summaryrefslogtreecommitdiffstats
path: root/sys/dev/cxgb/cxgb_main.c
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2008-02-23 01:06:17 +0000
committerkmacy <kmacy@FreeBSD.org>2008-02-23 01:06:17 +0000
commit48fe676ff5ddc104ebc346eebf48c7c0e285f833 (patch)
tree02a3e854ca5eb4caea80ce68a9a12f620befb52d /sys/dev/cxgb/cxgb_main.c
parentdf26e399aa077b14fb965be866012bccf2847bae (diff)
downloadFreeBSD-src-48fe676ff5ddc104ebc346eebf48c7c0e285f833.zip
FreeBSD-src-48fe676ff5ddc104ebc346eebf48c7c0e285f833.tar.gz
- update firmware to 5.0
- add support for T3C - add DDP support (zero-copy receive) - fix TOE transmit of large requests - fix shutdown so that sockets don't remain in CLOSING state indefinitely - register listeners when an interface is brought up after tom is loaded - fix setting of multicast filter - enable link at device attach - exit tick handler if shutdown is in progress - add helper for logging TCB - add sysctls for dumping transmit queues - note that TOE wxill not be MFC'd until after 7.0 has been finalized MFC after: 3 days
Diffstat (limited to 'sys/dev/cxgb/cxgb_main.c')
-rw-r--r--sys/dev/cxgb/cxgb_main.c316
1 files changed, 226 insertions, 90 deletions
diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c
index 581370b..9db5256 100644
--- a/sys/dev/cxgb/cxgb_main.c
+++ b/sys/dev/cxgb/cxgb_main.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus_dma.h>
+#include <sys/ktr.h>
#include <sys/rman.h>
#include <sys/ioccom.h>
#include <sys/mbuf.h>
@@ -119,6 +120,7 @@ static int cxgb_get_regs_len(void);
static int offload_open(struct port_info *pi);
static void touch_bars(device_t dev);
static int offload_close(struct t3cdev *tdev);
+static void cxgb_link_start(struct port_info *p);
static device_method_t cxgb_controller_methods[] = {
DEVMETHOD(device_probe, cxgb_controller_probe),
@@ -281,6 +283,32 @@ struct cxgb_ident {
static int set_eeprom(struct port_info *pi, const uint8_t *data, int len, int offset);
+
+void
+cxgb_log_tcb(struct adapter *sc, unsigned int tid)
+{
+ char buf[TCB_SIZE];
+ uint64_t *tcb = (uint64_t *)buf;
+ int i, error;
+ struct mc7 *mem = &sc->cm;
+
+ error = t3_mc7_bd_read(mem, tid*TCB_SIZE/8, TCB_SIZE/8, tcb);
+ if (error)
+ printf("cxgb_tcb_log failed\n");
+
+ CTR1(KTR_CXGB, "TCB tid=%u", tid);
+ for (i = 0; i < TCB_SIZE / 32; i++) {
+ CTR5(KTR_CXGB, "%1d: %08x %08x %08x %08x",
+ i, (uint32_t)tcb[1], (uint32_t)(tcb[1] >> 32),
+ (uint32_t)tcb[0], (uint32_t)(tcb[0] >> 32));
+ tcb += 2;
+ CTR4(KTR_CXGB, " %08x %08x %08x %08x",
+ (uint32_t)tcb[1], (uint32_t)(tcb[1] >> 32),
+ (uint32_t)tcb[0], (uint32_t)(tcb[0] >> 32));
+ tcb += 2;
+ }
+}
+
static __inline char
t3rev2char(struct adapter *adapter)
{
@@ -397,7 +425,8 @@ cxgb_controller_attach(device_t dev)
int port_qsets = 1;
#ifdef MSI_SUPPORTED
int msi_needed, reg;
-#endif
+#endif
+ int must_load = 0;
sc = device_get_softc(dev);
sc->dev = dev;
sc->msi_count = 0;
@@ -434,9 +463,16 @@ cxgb_controller_attach(device_t dev)
sc->regs_rid = PCIR_BAR(0);
if ((sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->regs_rid, RF_ACTIVE)) == NULL) {
- device_printf(dev, "Cannot allocate BAR\n");
+ device_printf(dev, "Cannot allocate BAR region 0\n");
return (ENXIO);
}
+ sc->udbs_rid = PCIR_BAR(2);
+ if ((sc->udbs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->udbs_rid, RF_ACTIVE)) == NULL) {
+ device_printf(dev, "Cannot allocate BAR region 1\n");
+ error = ENXIO;
+ goto out;
+ }
snprintf(sc->lockbuf, ADAPTER_LOCK_NAME_LEN, "cxgb controller lock %d",
device_get_unit(dev));
@@ -449,7 +485,7 @@ cxgb_controller_attach(device_t dev)
snprintf(sc->elmerlockbuf, ADAPTER_LOCK_NAME_LEN, "cxgb elmer lock %d",
device_get_unit(dev));
- MTX_INIT(&sc->sge.reg_lock, sc->reglockbuf, NULL, MTX_DEF);
+ MTX_INIT(&sc->sge.reg_lock, sc->reglockbuf, NULL, MTX_SPIN);
MTX_INIT(&sc->mdio_lock, sc->mdiolockbuf, NULL, MTX_DEF);
MTX_INIT(&sc->elmer_lock, sc->elmerlockbuf, NULL, MTX_DEF);
@@ -534,7 +570,7 @@ cxgb_controller_attach(device_t dev)
/* Create a periodic callout for checking adapter status */
callout_init(&sc->cxgb_tick_ch, TRUE);
- if (t3_check_fw_version(sc) != 0) {
+ if (t3_check_fw_version(sc, &must_load) != 0 && must_load) {
/*
* Warn user that a firmware update will be attempted in init.
*/
@@ -545,7 +581,7 @@ cxgb_controller_attach(device_t dev)
sc->flags |= FW_UPTODATE;
}
- if (t3_check_tpsram_version(sc) != 0) {
+ if (t3_check_tpsram_version(sc, &must_load) != 0 && must_load) {
/*
* Warn user that a firmware update will be attempted in init.
*/
@@ -609,6 +645,8 @@ cxgb_controller_attach(device_t dev)
G_FW_VERSION_MAJOR(vers), G_FW_VERSION_MINOR(vers),
G_FW_VERSION_MICRO(vers));
+ device_printf(sc->dev, "Firmware Version %s\n", &sc->fw_version[0]);
+ callout_reset(&sc->cxgb_tick_ch, hz, cxgb_tick, sc);
t3_add_attach_sysctls(sc);
out:
if (error)
@@ -634,9 +672,12 @@ cxgb_free(struct adapter *sc)
{
int i;
-
+ ADAPTER_LOCK(sc);
+ sc->flags |= CXGB_SHUTDOWN;
+ ADAPTER_UNLOCK(sc);
cxgb_pcpu_shutdown_threads(sc);
ADAPTER_LOCK(sc);
+
/*
* drops the lock
*/
@@ -654,11 +695,7 @@ cxgb_free(struct adapter *sc)
bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->msix_regs_rid,
sc->msix_regs_res);
}
-
- if (sc->tq != NULL) {
- taskqueue_drain(sc->tq, &sc->ext_intr_task);
- taskqueue_drain(sc->tq, &sc->tick_task);
- }
+
t3_sge_deinit_sw(sc);
/*
* Wait for last callout
@@ -672,8 +709,11 @@ cxgb_free(struct adapter *sc)
}
bus_generic_detach(sc->dev);
- if (sc->tq != NULL)
+ if (sc->tq != NULL) {
taskqueue_free(sc->tq);
+ sc->tq = NULL;
+ }
+
if (is_offload(sc)) {
cxgb_adapter_unofld(sc);
if (isset(&sc->open_device_map, OFFLOAD_DEVMAP_BIT))
@@ -682,11 +722,18 @@ cxgb_free(struct adapter *sc)
printf("cxgb_free: DEVMAP_BIT not set\n");
} else
printf("not offloading set\n");
+
+ if (sc->flags & CXGB_OFLD_INIT)
+ cxgb_offload_deactivate(sc);
free(sc->filters, M_DEVBUF);
t3_sge_free(sc);
cxgb_offload_exit();
-
+
+ if (sc->udbs_res != NULL)
+ bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->udbs_rid,
+ sc->udbs_res);
+
if (sc->regs_res != NULL)
bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->regs_rid,
sc->regs_res);
@@ -797,8 +844,6 @@ cxgb_setup_msix(adapter_t *sc, int msix_count)
return (EINVAL);
}
sc->msix_irq_rid[k] = rid;
- printf("setting up interrupt for port=%d\n",
- qs->port->port_id);
if (bus_setup_intr(sc->dev, sc->msix_irq_res[k],
INTR_MPSAFE|INTR_TYPE_NET,
#ifdef INTR_FILTERS
@@ -828,10 +873,11 @@ cxgb_port_probe(device_t dev)
{
struct port_info *p;
char buf[80];
-
+ const char *desc;
+
p = device_get_softc(dev);
-
- snprintf(buf, sizeof(buf), "Port %d %s", p->port_id, p->port_type->desc);
+ desc = p->phy.desc;
+ snprintf(buf, sizeof(buf), "Port %d %s", p->port_id, desc);
device_set_desc_copy(dev, buf);
return (0);
}
@@ -873,9 +919,11 @@ cxgb_port_attach(device_t dev)
struct port_info *p;
struct ifnet *ifp;
int err, media_flags;
+ struct adapter *sc;
+
p = device_get_softc(dev);
-
+ sc = p->adapter;
snprintf(p->lockbuf, PORT_NAME_LEN, "cxgb port lock %d:%d",
device_get_unit(device_get_parent(dev)), p->port_id);
PORT_LOCK_INIT(p, p->lockbuf);
@@ -897,11 +945,12 @@ cxgb_port_attach(device_t dev)
ifp->if_ioctl = cxgb_ioctl;
ifp->if_start = cxgb_start;
+#if 0
#ifdef IFNET_MULTIQUEUE
ifp->if_flags |= IFF_MULTIQ;
ifp->if_mq_start = cxgb_pcpu_start;
#endif
-
+#endif
ifp->if_timer = 0; /* Disable ifnet watchdog */
ifp->if_watchdog = NULL;
@@ -934,14 +983,14 @@ cxgb_port_attach(device_t dev)
}
ifmedia_init(&p->media, IFM_IMASK, cxgb_media_change,
cxgb_media_status);
-
- if (!strcmp(p->port_type->desc, "10GBASE-CX4")) {
+
+ if (!strcmp(p->phy.desc, "10GBASE-CX4")) {
media_flags = IFM_ETHER | IFM_10G_CX4 | IFM_FDX;
- } else if (!strcmp(p->port_type->desc, "10GBASE-SR")) {
+ } else if (!strcmp(p->phy.desc, "10GBASE-SR")) {
media_flags = IFM_ETHER | IFM_10G_SR | IFM_FDX;
- } else if (!strcmp(p->port_type->desc, "10GBASE-XR")) {
+ } else if (!strcmp(p->phy.desc, "10GBASE-XR")) {
media_flags = IFM_ETHER | IFM_10G_LR | IFM_FDX;
- } else if (!strcmp(p->port_type->desc, "10/100/1000BASE-T")) {
+ } else if (!strcmp(p->phy.desc, "10/100/1000BASE-T")) {
ifmedia_add(&p->media, IFM_ETHER | IFM_10_T, 0, NULL);
ifmedia_add(&p->media, IFM_ETHER | IFM_10_T | IFM_FDX,
0, NULL);
@@ -953,7 +1002,7 @@ cxgb_port_attach(device_t dev)
0, NULL);
media_flags = 0;
} else {
- printf("unsupported media type %s\n", p->port_type->desc);
+ printf("unsupported media type %s\n", p->phy.desc);
return (ENXIO);
}
if (media_flags) {
@@ -976,7 +1025,8 @@ cxgb_port_attach(device_t dev)
taskqueue_thread_enqueue, &p->tq);
#endif
t3_sge_init_port(p);
-
+ cxgb_link_start(p);
+ t3_link_changed(sc, p->port_id);
return (0);
}
@@ -1119,17 +1169,14 @@ t3_os_link_changed(adapter_t *adapter, int port_id, int link_status, int speed,
struct port_info *pi = &adapter->port[port_id];
struct cmac *mac = &adapter->port[port_id].mac;
- if ((pi->ifp->if_flags & IFF_UP) == 0)
- return;
-
if (link_status) {
t3_mac_enable(mac, MAC_DIRECTION_RX);
if_link_state_change(pi->ifp, LINK_STATE_UP);
} else {
- if_link_state_change(pi->ifp, LINK_STATE_DOWN);
pi->phy.ops->power_down(&pi->phy, 1);
t3_mac_disable(mac, MAC_DIRECTION_RX);
t3_link_start(&pi->phy, mac, &pi->link_config);
+ if_link_state_change(pi->ifp, LINK_STATE_DOWN);
}
}
@@ -1195,6 +1242,84 @@ cxgb_link_start(struct port_info *p)
t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
}
+
+static int
+await_mgmt_replies(struct adapter *adap, unsigned long init_cnt,
+ unsigned long n)
+{
+ int attempts = 5;
+
+ while (adap->sge.qs[0].rspq.offload_pkts < init_cnt + n) {
+ if (!--attempts)
+ return (ETIMEDOUT);
+ t3_os_sleep(10);
+ }
+ return 0;
+}
+
+static int
+init_tp_parity(struct adapter *adap)
+{
+ int i;
+ struct mbuf *m;
+ struct cpl_set_tcb_field *greq;
+ unsigned long cnt = adap->sge.qs[0].rspq.offload_pkts;
+
+ t3_tp_set_offload_mode(adap, 1);
+
+ for (i = 0; i < 16; i++) {
+ struct cpl_smt_write_req *req;
+
+ m = m_gethdr(M_WAITOK, MT_DATA);
+ req = mtod(m, struct cpl_smt_write_req *);
+ m->m_len = m->m_pkthdr.len = sizeof(*req);
+ memset(req, 0, sizeof(*req));
+ req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, i));
+ req->iff = i;
+ t3_mgmt_tx(adap, m);
+ }
+
+ for (i = 0; i < 2048; i++) {
+ struct cpl_l2t_write_req *req;
+
+ m = m_gethdr(M_WAITOK, MT_DATA);
+ req = mtod(m, struct cpl_l2t_write_req *);
+ m->m_len = m->m_pkthdr.len = sizeof(*req);
+ memset(req, 0, sizeof(*req));
+ req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, i));
+ req->params = htonl(V_L2T_W_IDX(i));
+ t3_mgmt_tx(adap, m);
+ }
+
+ for (i = 0; i < 2048; i++) {
+ struct cpl_rte_write_req *req;
+
+ m = m_gethdr(M_WAITOK, MT_DATA);
+ req = mtod(m, struct cpl_rte_write_req *);
+ m->m_len = m->m_pkthdr.len = sizeof(*req);
+ memset(req, 0, sizeof(*req));
+ req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RTE_WRITE_REQ, i));
+ req->l2t_idx = htonl(V_L2T_W_IDX(i));
+ t3_mgmt_tx(adap, m);
+ }
+
+ m = m_gethdr(M_WAITOK, MT_DATA);
+ greq = mtod(m, struct cpl_set_tcb_field *);
+ m->m_len = m->m_pkthdr.len = sizeof(*greq);
+ memset(greq, 0, sizeof(*greq));
+ greq->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+ OPCODE_TID(greq) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, 0));
+ greq->mask = htobe64(1);
+ t3_mgmt_tx(adap, m);
+
+ i = await_mgmt_replies(adap, cnt, 16 + 2048 + 2048 + 1);
+ t3_tp_set_offload_mode(adap, 0);
+ return (i);
+}
+
/**
* setup_rss - configure Receive Side Steering (per-queue connection demux)
* @adap: the adapter
@@ -1224,11 +1349,9 @@ setup_rss(adapter_t *adap)
nq[pi->tx_chan] += pi->nqsets;
}
- nq[0] = max(nq[0], 1U);
- nq[1] = max(nq[1], 1U);
for (i = 0; i < RSS_TABLE_SIZE / 2; ++i) {
- rspq_map[i] = i % nq[0];
- rspq_map[i + RSS_TABLE_SIZE / 2] = (i % nq[1]) + nq[0];
+ rspq_map[i] = nq[0] ? i % nq[0] : 0;
+ rspq_map[i + RSS_TABLE_SIZE / 2] = nq[1] ? i % nq[1] + nq[0] : 0;
}
/* Calculate the reverse RSS map table */
for (i = 0; i < RSS_TABLE_SIZE; ++i)
@@ -1237,7 +1360,8 @@ setup_rss(adapter_t *adap)
t3_config_rss(adap, F_RQFEEDBACKENABLE | F_TNLLKPEN | F_TNLMAPEN |
F_TNLPRTEN | F_TNL2TUPEN | F_TNL4TUPEN | F_OFDMAPEN |
- V_RRCPLCPUSIZE(6), cpus, rspq_map);
+ F_RRCPLMAPEN | V_RRCPLCPUSIZE(6) | F_HASHTOEPLITZ,
+ cpus, rspq_map);
}
@@ -1470,6 +1594,7 @@ cxgb_up(struct adapter *sc)
if (err)
goto out;
+ t3_set_reg_field(sc, A_TP_PARA_REG5, 0, F_RXDDPOFFINIT);
t3_write_reg(sc, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12));
err = setup_sge_qsets(sc);
@@ -1510,8 +1635,18 @@ cxgb_up(struct adapter *sc)
t3_sge_start(sc);
t3_intr_enable(sc);
+ if (sc->params.rev >= T3_REV_C && !(sc->flags & TP_PARITY_INIT) &&
+ is_offload(sc) && init_tp_parity(sc) == 0)
+ sc->flags |= TP_PARITY_INIT;
+
+ if (sc->flags & TP_PARITY_INIT) {
+ t3_write_reg(sc, A_TP_INT_CAUSE,
+ F_CMCACHEPERR | F_ARPLUTPERR);
+ t3_write_reg(sc, A_TP_INT_ENABLE, 0x7fbfffff);
+ }
+
+
if (!(sc->flags & QUEUES_BOUND)) {
- printf("bind qsets\n");
bind_qsets(sc);
sc->flags |= QUEUES_BOUND;
}
@@ -1529,7 +1664,6 @@ irq_err:
static void
cxgb_down_locked(struct adapter *sc)
{
- int i;
t3_sge_stop(sc);
t3_intr_disable(sc);
@@ -1546,20 +1680,24 @@ cxgb_down_locked(struct adapter *sc)
sc->irq_res = NULL;
}
- if (sc->flags & USING_MSIX)
+ if (sc->flags & USING_MSIX)
cxgb_teardown_msix(sc);
- ADAPTER_UNLOCK(sc);
-
+
callout_stop(&sc->cxgb_tick_ch);
callout_stop(&sc->sge_timer_ch);
callout_drain(&sc->cxgb_tick_ch);
callout_drain(&sc->sge_timer_ch);
if (sc->tq != NULL) {
+ printf("draining slow intr\n");
+
taskqueue_drain(sc->tq, &sc->slow_intr_task);
- for (i = 0; i < sc->params.nports; i++)
- taskqueue_drain(sc->tq, &sc->port[i].timer_reclaim_task);
+ printf("draining ext intr\n");
+ taskqueue_drain(sc->tq, &sc->ext_intr_task);
+ printf("draining tick task\n");
+ taskqueue_drain(sc->tq, &sc->tick_task);
}
+ ADAPTER_UNLOCK(sc);
}
static int
@@ -1573,7 +1711,7 @@ offload_open(struct port_info *pi)
int adap_up = adapter->open_device_map & PORT_MASK;
int err = 0;
- printf("device_map=0x%x\n", adapter->open_device_map);
+ CTR1(KTR_CXGB, "device_map=0x%x", adapter->open_device_map);
if (atomic_cmpset_int(&adapter->open_device_map,
(adapter->open_device_map & ~(1<<OFFLOAD_DEVMAP_BIT)),
(adapter->open_device_map | (1<<OFFLOAD_DEVMAP_BIT))) == 0)
@@ -1620,11 +1758,8 @@ offload_close(struct t3cdev *tdev)
{
struct adapter *adapter = tdev2adap(tdev);
- if (!isset(&adapter->open_device_map, OFFLOAD_DEVMAP_BIT)) {
- printf("offload_close: DEVMAP_BIT not set\n");
-
+ if (!isset(&adapter->open_device_map, OFFLOAD_DEVMAP_BIT))
return (0);
- }
/* Call back all registered clients */
cxgb_remove_clients(tdev);
@@ -1638,7 +1773,6 @@ offload_close(struct t3cdev *tdev)
cxgb_down_locked(adapter);
else
ADAPTER_UNLOCK(adapter);
- cxgb_offload_deactivate(adapter);
return (0);
}
@@ -1680,17 +1814,12 @@ cxgb_init_locked(struct port_info *p)
if (err)
log(LOG_WARNING,
"Could not initialize offload capabilities\n");
- else
- printf("offload opened\n");
}
- cxgb_link_start(p);
- t3_link_changed(sc, p->port_id);
ifp->if_baudrate = p->link_config.speed * 1000000;
device_printf(sc->dev, "enabling interrupts on port=%d\n", p->port_id);
t3_port_intr_enable(sc, p->port_id);
- callout_reset(&sc->cxgb_tick_ch, hz, cxgb_tick, sc);
t3_sge_reset_adapter(sc);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -1703,10 +1832,10 @@ cxgb_set_rxmode(struct port_info *p)
struct t3_rx_mode rm;
struct cmac *mac = &p->mac;
- PORT_LOCK_ASSERT_OWNED(p);
-
t3_init_rx_mode(&rm, p);
+ mtx_lock(&p->adapter->mdio_lock);
t3_mac_set_rx_mode(mac, &rm);
+ mtx_unlock(&p->adapter->mdio_lock);
}
static void
@@ -1745,7 +1874,6 @@ cxgb_set_mtu(struct port_info *p, int mtu)
PORT_LOCK(p);
ifp->if_mtu = mtu;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- callout_stop(&p->adapter->cxgb_tick_ch);
cxgb_stop_locked(p);
cxgb_init_locked(p);
}
@@ -1771,19 +1899,18 @@ cxgb_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data)
error = cxgb_set_mtu(p, ifr->ifr_mtu);
break;
case SIOCSIFADDR:
- case SIOCGIFADDR:
if (ifa->ifa_addr->sa_family == AF_INET) {
- PORT_LOCK(p);
ifp->if_flags |= IFF_UP;
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ PORT_LOCK(p);
cxgb_init_locked(p);
+ PORT_UNLOCK(p);
+ }
arp_ifinit(ifp, ifa);
- PORT_UNLOCK(p);
} else
error = ether_ioctl(ifp, command, data);
break;
case SIOCSIFFLAGS:
- callout_drain(&p->adapter->cxgb_tick_ch);
PORT_LOCK(p);
if (ifp->if_flags & IFF_UP) {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
@@ -1797,12 +1924,13 @@ cxgb_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data)
} else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
cxgb_stop_locked(p);
+ PORT_UNLOCK(p);
+ break;
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- adapter_t *sc = p->adapter;
- callout_reset(&sc->cxgb_tick_ch, hz,
- cxgb_tick, sc);
+ cxgb_set_rxmode(p);
}
- PORT_UNLOCK(p);
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
@@ -1929,7 +2057,7 @@ check_link_status(adapter_t *sc)
for (i = 0; i < (sc)->params.nports; ++i) {
struct port_info *p = &sc->port[i];
- if (!(p->port_type->caps & SUPPORTED_IRQ))
+ if (!(p->phy.caps & SUPPORTED_IRQ))
t3_link_changed(sc, i);
p->ifp->if_baudrate = p->link_config.speed * 1000000;
}
@@ -1940,11 +2068,17 @@ check_t3b2_mac(struct adapter *adapter)
{
int i;
+ if(adapter->flags & CXGB_SHUTDOWN)
+ return;
+
for_each_port(adapter, i) {
struct port_info *p = &adapter->port[i];
struct ifnet *ifp = p->ifp;
int status;
-
+
+ if(adapter->flags & CXGB_SHUTDOWN)
+ return;
+
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
continue;
@@ -1974,26 +2108,12 @@ static void
cxgb_tick(void *arg)
{
adapter_t *sc = (adapter_t *)arg;
- int i, running = 0;
-
- for_each_port(sc, i) {
-
- struct port_info *p = &sc->port[i];
- struct ifnet *ifp = p->ifp;
- PORT_LOCK(p);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING))
- running = 1;
- PORT_UNLOCK(p);
- }
-
- if (running == 0)
+ if(sc->flags & CXGB_SHUTDOWN)
return;
-
+
taskqueue_enqueue(sc->tq, &sc->tick_task);
-
- if (sc->open_device_map != 0)
- callout_reset(&sc->cxgb_tick_ch, hz, cxgb_tick, sc);
+ callout_reset(&sc->cxgb_tick_ch, hz, cxgb_tick, sc);
}
static void
@@ -2002,17 +2122,20 @@ cxgb_tick_handler(void *arg, int count)
adapter_t *sc = (adapter_t *)arg;
const struct adapter_params *p = &sc->params;
+ if(sc->flags & CXGB_SHUTDOWN)
+ return;
+
ADAPTER_LOCK(sc);
if (p->linkpoll_period)
check_link_status(sc);
/*
- * adapter lock can currently only be acquire after the
+ * adapter lock can currently only be acquired after the
* port lock
*/
ADAPTER_UNLOCK(sc);
- if (p->rev == T3_REV_B2 && p->nports < 4)
+ if (p->rev == T3_REV_B2 && p->nports < 4 && sc->open_device_map)
check_t3b2_mac(sc);
}
@@ -2180,7 +2303,7 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
}
case CHELSIO_GET_SGE_CONTEXT: {
struct ch_cntxt *ecntxt = (struct ch_cntxt *)data;
- mtx_lock(&sc->sge.reg_lock);
+ mtx_lock_spin(&sc->sge.reg_lock);
switch (ecntxt->cntxt_type) {
case CNTXT_TYPE_EGRESS:
error = t3_sge_read_ecntxt(sc, ecntxt->cntxt_id,
@@ -2202,7 +2325,7 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
error = EINVAL;
break;
}
- mtx_unlock(&sc->sge.reg_lock);
+ mtx_unlock_spin(&sc->sge.reg_lock);
break;
}
case CHELSIO_GET_SGE_DESC: {
@@ -2220,7 +2343,8 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
case CHELSIO_SET_QSET_PARAMS: {
struct qset_params *q;
struct ch_qset_params *t = (struct ch_qset_params *)data;
-
+ int i;
+
if (t->qset_idx >= SGE_QSETS)
return (EINVAL);
if (!in_range(t->intr_lat, 0, M_NEWTIMER) ||
@@ -2236,6 +2360,18 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
MAX_RX_JUMBO_BUFFERS) ||
!in_range(t->rspq_size, MIN_RSPQ_ENTRIES, MAX_RSPQ_ENTRIES))
return (EINVAL);
+
+ if ((sc->flags & FULL_INIT_DONE) && t->lro > 0)
+ for_each_port(sc, i) {
+ pi = adap2pinfo(sc, i);
+ if (t->qset_idx >= pi->first_qset &&
+ t->qset_idx < pi->first_qset + pi->nqsets
+#if 0
+ && !pi->rx_csum_offload
+#endif
+ )
+ return -EINVAL;
+ }
if ((sc->flags & FULL_INIT_DONE) &&
(t->rspq_size >= 0 || t->fl_size[0] >= 0 ||
t->fl_size[1] >= 0 || t->txq_size[0] >= 0 ||
OpenPOWER on IntegriCloud