summaryrefslogtreecommitdiffstats
path: root/sys/dev/mxge
diff options
context:
space:
mode:
authorgallatin <gallatin@FreeBSD.org>2007-01-31 15:29:31 +0000
committergallatin <gallatin@FreeBSD.org>2007-01-31 15:29:31 +0000
commit60e3c7067047cbb6c9f0fa5bfcb0ad9d19fe721d (patch)
tree6ce4bf2ae8cb1509cf925d3640cbcc0162fc36d8 /sys/dev/mxge
parent3bd3bcc77909873a2c6ae0e8f139126642e309d4 (diff)
downloadFreeBSD-src-60e3c7067047cbb6c9f0fa5bfcb0ad9d19fe721d.zip
FreeBSD-src-60e3c7067047cbb6c9f0fa5bfcb0ad9d19fe721d.tar.gz
Abandon using sleepable locks in favor of mutexes for mxge's if_ioctl
locking in preparation for adding a watchdog handler (callouts must not use sleepable locks). This required shuffling memory and interrupt allocation to the attach routine rather than if_ioctl so as to avoid potential sleeps while bringing up the interface.
Diffstat (limited to 'sys/dev/mxge')
-rw-r--r--sys/dev/mxge/if_mxge.c145
-rw-r--r--sys/dev/mxge/if_mxge_var.h10
2 files changed, 83 insertions, 72 deletions
diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c
index fc274b5..c5c84a0 100644
--- a/sys/dev/mxge/if_mxge.c
+++ b/sys/dev/mxge/if_mxge.c
@@ -648,7 +648,7 @@ mxge_send_cmd(mxge_softc_t *sc, uint32_t cmd, mxge_cmd_t *data)
buf->response_addr.low = htobe32(dma_low);
buf->response_addr.high = htobe32(dma_high);
- mtx_lock(&sc->cmd_lock);
+ mtx_lock(&sc->cmd_mtx);
response->result = 0xffffffff;
mb();
mxge_pio_copy((volatile void *)cmd_addr, buf, sizeof (*buf));
@@ -661,20 +661,20 @@ mxge_send_cmd(mxge_softc_t *sc, uint32_t cmd, mxge_cmd_t *data)
if (response->result != 0xffffffff) {
if (response->result == 0) {
data->data0 = be32toh(response->data);
- mtx_unlock(&sc->cmd_lock);
+ mtx_unlock(&sc->cmd_mtx);
return 0;
} else {
device_printf(sc->dev,
"mxge: command %d "
"failed, result = %d\n",
cmd, be32toh(response->result));
- mtx_unlock(&sc->cmd_lock);
+ mtx_unlock(&sc->cmd_mtx);
return ENXIO;
}
}
DELAY(1000);
}
- mtx_unlock(&sc->cmd_lock);
+ mtx_unlock(&sc->cmd_mtx);
device_printf(sc->dev, "mxge: command %d timed out"
"result = %d\n",
cmd, be32toh(response->result));
@@ -927,7 +927,6 @@ mxge_reset(mxge_softc_t *sc)
{
mxge_cmd_t cmd;
- mxge_dma_t dmabench_dma;
size_t bytes;
int status;
@@ -975,13 +974,10 @@ mxge_reset(mxge_softc_t *sc)
/* run a DMA benchmark */
sc->read_dma = sc->write_dma = sc->read_write_dma = 0;
- status = mxge_dma_alloc(sc, &dmabench_dma, 4096, 4096);
- if (status)
- goto dmabench_fail;
/* Read DMA */
- cmd.data0 = MXGE_LOWPART_TO_U32(dmabench_dma.bus_addr);
- cmd.data1 = MXGE_HIGHPART_TO_U32(dmabench_dma.bus_addr);
+ cmd.data0 = MXGE_LOWPART_TO_U32(sc->dmabench_dma.bus_addr);
+ cmd.data1 = MXGE_HIGHPART_TO_U32(sc->dmabench_dma.bus_addr);
cmd.data2 = sc->tx.boundary * 0x10000;
status = mxge_send_cmd(sc, MXGEFW_DMA_TEST, &cmd);
@@ -992,8 +988,8 @@ mxge_reset(mxge_softc_t *sc)
(cmd.data0 & 0xffff);
/* Write DMA */
- cmd.data0 = MXGE_LOWPART_TO_U32(dmabench_dma.bus_addr);
- cmd.data1 = MXGE_HIGHPART_TO_U32(dmabench_dma.bus_addr);
+ cmd.data0 = MXGE_LOWPART_TO_U32(sc->dmabench_dma.bus_addr);
+ cmd.data1 = MXGE_HIGHPART_TO_U32(sc->dmabench_dma.bus_addr);
cmd.data2 = sc->tx.boundary * 0x1;
status = mxge_send_cmd(sc, MXGEFW_DMA_TEST, &cmd);
if (status != 0)
@@ -1002,8 +998,8 @@ mxge_reset(mxge_softc_t *sc)
sc->write_dma = ((cmd.data0>>16) * sc->tx.boundary * 2) /
(cmd.data0 & 0xffff);
/* Read/Write DMA */
- cmd.data0 = MXGE_LOWPART_TO_U32(dmabench_dma.bus_addr);
- cmd.data1 = MXGE_HIGHPART_TO_U32(dmabench_dma.bus_addr);
+ cmd.data0 = MXGE_LOWPART_TO_U32(sc->dmabench_dma.bus_addr);
+ cmd.data1 = MXGE_HIGHPART_TO_U32(sc->dmabench_dma.bus_addr);
cmd.data2 = sc->tx.boundary * 0x10001;
status = mxge_send_cmd(sc, MXGEFW_DMA_TEST, &cmd);
if (status != 0)
@@ -1013,9 +1009,6 @@ mxge_reset(mxge_softc_t *sc)
((cmd.data0>>16) * sc->tx.boundary * 2 * 2) /
(cmd.data0 & 0xffff);
- mxge_dma_free(&dmabench_dma);
-
-dmabench_fail:
/* reset mcp/driver shared state back to 0 */
bzero(sc->rx_done.entry, bytes);
sc->rx_done.idx = 0;
@@ -1028,6 +1021,8 @@ dmabench_fail:
sc->rx_big.cnt = 0;
sc->rx_small.cnt = 0;
sc->rdma_tags_available = 15;
+ sc->fw_stats->valid = 0;
+ sc->fw_stats->send_done_count = 0;
status = mxge_update_mac_address(sc);
mxge_change_promisc(sc, 0);
mxge_change_pause(sc, sc->pause);
@@ -1054,11 +1049,11 @@ mxge_change_intr_coal(SYSCTL_HANDLER_ARGS)
if (intr_coal_delay == 0 || intr_coal_delay > 1000*1000)
return EINVAL;
- sx_xlock(&sc->driver_lock);
+ mtx_lock(&sc->driver_mtx);
*sc->intr_coal_delay_ptr = htobe32(intr_coal_delay);
sc->intr_coal_delay = intr_coal_delay;
- sx_xunlock(&sc->driver_lock);
+ mtx_unlock(&sc->driver_mtx);
return err;
}
@@ -1078,9 +1073,9 @@ mxge_change_flow_control(SYSCTL_HANDLER_ARGS)
if (enabled == sc->pause)
return 0;
- sx_xlock(&sc->driver_lock);
+ mtx_lock(&sc->driver_mtx);
err = mxge_change_pause(sc, enabled);
- sx_xunlock(&sc->driver_lock);
+ mtx_unlock(&sc->driver_mtx);
return err;
}
@@ -1698,9 +1693,9 @@ mxge_start(struct ifnet *ifp)
mxge_softc_t *sc = ifp->if_softc;
- mtx_lock(&sc->tx_lock);
+ mtx_lock(&sc->tx_mtx);
mxge_start_locked(sc);
- mtx_unlock(&sc->tx_lock);
+ mtx_unlock(&sc->tx_mtx);
}
/*
@@ -2032,11 +2027,11 @@ mxge_tx_done(mxge_softc_t *sc, uint32_t mcp_idx)
if (ifp->if_drv_flags & IFF_DRV_OACTIVE &&
tx->req - tx->done < (tx->mask + 1)/4) {
- mtx_lock(&sc->tx_lock);
+ mtx_lock(&sc->tx_mtx);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
sc->tx.wake++;
mxge_start_locked(sc);
- mtx_unlock(&sc->tx_lock);
+ mtx_unlock(&sc->tx_mtx);
}
}
@@ -2406,25 +2401,15 @@ mxge_open(mxge_softc_t *sc)
device_printf(sc->dev, "failed to reset\n");
return EIO;
}
-
+ bzero(sc->rx_done.entry,
+ mxge_max_intr_slots * sizeof(*sc->rx_done.entry));
+
if (MCLBYTES >=
sc->ifp->if_mtu + ETHER_HDR_LEN + MXGEFW_PAD)
sc->big_bytes = MCLBYTES;
else
sc->big_bytes = MJUMPAGESIZE;
- err = mxge_alloc_rings(sc);
- if (err != 0) {
- device_printf(sc->dev, "failed to allocate rings\n");
- return err;
- }
-
- err = bus_setup_intr(sc->dev, sc->irq_res,
- INTR_TYPE_NET | INTR_MPSAFE,
- mxge_intr, sc, &sc->ih);
- if (err != 0) {
- goto abort_with_rings;
- }
/* get the lanai pointers to the send and receive rings */
@@ -2442,8 +2427,7 @@ mxge_open(mxge_softc_t *sc)
if (err != 0) {
device_printf(sc->dev,
"failed to get ring sizes or locations\n");
- err = EIO;
- goto abort_with_irq;
+ return EIO;
}
if (sc->wc) {
@@ -2532,10 +2516,7 @@ mxge_open(mxge_softc_t *sc)
abort:
mxge_free_mbufs(sc);
-abort_with_irq:
- bus_teardown_intr(sc->dev, sc->irq_res, sc->ih);
-abort_with_rings:
- mxge_free_rings(sc);
+
return err;
}
@@ -2554,15 +2535,14 @@ mxge_close(mxge_softc_t *sc)
}
if (old_down_cnt == sc->down_cnt) {
/* wait for down irq */
- (void)tsleep(&sc->down_cnt, PWAIT, "down mxge", hz);
+ DELAY(2 * sc->intr_coal_delay);
}
if (old_down_cnt == sc->down_cnt) {
device_printf(sc->dev, "never got down irq\n");
}
- if (sc->ih != NULL)
- bus_teardown_intr(sc->dev, sc->irq_res, sc->ih);
+
mxge_free_mbufs(sc);
- mxge_free_rings(sc);
+
return 0;
}
@@ -2585,7 +2565,7 @@ mxge_change_mtu(mxge_softc_t *sc, int mtu)
if ((real_mtu > MXGE_MAX_ETHER_MTU) ||
real_mtu < 60)
return EINVAL;
- sx_xlock(&sc->driver_lock);
+ mtx_lock(&sc->driver_mtx);
old_mtu = ifp->if_mtu;
ifp->if_mtu = mtu;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
@@ -2597,7 +2577,7 @@ mxge_change_mtu(mxge_softc_t *sc, int mtu)
(void) mxge_open(sc);
}
}
- sx_xunlock(&sc->driver_lock);
+ mtx_unlock(&sc->driver_mtx);
return err;
}
@@ -2634,7 +2614,7 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
break;
case SIOCSIFFLAGS:
- sx_xlock(&sc->driver_lock);
+ mtx_lock(&sc->driver_mtx);
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
err = mxge_open(sc);
@@ -2649,18 +2629,18 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
mxge_close(sc);
}
- sx_xunlock(&sc->driver_lock);
+ mtx_unlock(&sc->driver_mtx);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
- sx_xlock(&sc->driver_lock);
+ mtx_lock(&sc->driver_mtx);
mxge_set_multicast_list(sc);
- sx_xunlock(&sc->driver_lock);
+ mtx_unlock(&sc->driver_mtx);
break;
case SIOCSIFCAP:
- sx_xlock(&sc->driver_lock);
+ mtx_lock(&sc->driver_mtx);
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
if (mask & IFCAP_TXCSUM) {
if (IFCAP_TXCSUM & ifp->if_capenable) {
@@ -2693,7 +2673,7 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
err = EINVAL;
}
}
- sx_xunlock(&sc->driver_lock);
+ mtx_unlock(&sc->driver_mtx);
break;
case SIOCGIFMEDIA:
@@ -2768,11 +2748,16 @@ mxge_attach(device_t dev)
err = ENOSPC;
goto abort_with_parent_dmat;
}
- mtx_init(&sc->cmd_lock, NULL,
- MTX_NETWORK_LOCK, MTX_DEF);
- mtx_init(&sc->tx_lock, device_get_nameunit(dev),
+ snprintf(sc->cmd_mtx_name, sizeof(sc->cmd_mtx_name), "%s:cmd",
+ device_get_nameunit(dev));
+ mtx_init(&sc->cmd_mtx, sc->cmd_mtx_name, NULL, MTX_DEF);
+ snprintf(sc->tx_mtx_name, sizeof(sc->tx_mtx_name), "%s:tx",
+ device_get_nameunit(dev));
+ mtx_init(&sc->tx_mtx, sc->tx_mtx_name, NULL, MTX_DEF);
+ snprintf(sc->driver_mtx_name, sizeof(sc->driver_mtx_name),
+ "%s:drv", device_get_nameunit(dev));
+ mtx_init(&sc->driver_mtx, sc->driver_mtx_name,
MTX_NETWORK_LOCK, MTX_DEF);
- sx_init(&sc->driver_lock, device_get_nameunit(dev));
/* find the PCIe link width and set max read request to 4KB*/
if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
@@ -2839,12 +2824,15 @@ mxge_attach(device_t dev)
goto abort_with_zeropad_dma;
sc->fw_stats = (mcp_irq_data_t *)sc->fw_stats_dma.addr;
+ err = mxge_dma_alloc(sc, &sc->dmabench_dma, 4096, 4096);
+ if (err != 0)
+ goto abort_with_fw_stats;
/* allocate interrupt queues */
bytes = mxge_max_intr_slots * sizeof (*sc->rx_done.entry);
err = mxge_dma_alloc(sc, &sc->rx_done.dma, bytes, 4096);
if (err != 0)
- goto abort_with_fw_stats;
+ goto abort_with_dmabench;
sc->rx_done.entry = sc->rx_done.dma.addr;
bzero(sc->rx_done.entry, bytes);
@@ -2877,6 +2865,18 @@ mxge_attach(device_t dev)
if (err != 0)
goto abort_with_irq_res;
+ err = mxge_alloc_rings(sc);
+ if (err != 0) {
+ device_printf(sc->dev, "failed to allocate rings\n");
+ goto abort_with_irq_res;
+ }
+
+ err = bus_setup_intr(sc->dev, sc->irq_res,
+ INTR_TYPE_NET | INTR_MPSAFE,
+ mxge_intr, sc, &sc->ih);
+ if (err != 0) {
+ goto abort_with_rings;
+ }
/* hook into the network stack */
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_baudrate = 100000000;
@@ -2902,6 +2902,8 @@ mxge_attach(device_t dev)
mxge_add_sysctls(sc);
return 0;
+abort_with_rings:
+ mxge_free_rings(sc);
abort_with_irq_res:
bus_release_resource(dev, SYS_RES_IRQ,
sc->msi_enabled ? 1 : 0, sc->irq_res);
@@ -2910,6 +2912,8 @@ abort_with_irq_res:
abort_with_rx_done:
sc->rx_done.entry = NULL;
mxge_dma_free(&sc->rx_done.dma);
+abort_with_dmabench:
+ mxge_dma_free(&sc->dmabench_dma);
abort_with_fw_stats:
mxge_dma_free(&sc->fw_stats_dma);
abort_with_zeropad_dma:
@@ -2920,9 +2924,9 @@ abort_with_mem_res:
bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BARS, sc->mem_res);
abort_with_lock:
pci_disable_busmaster(dev);
- mtx_destroy(&sc->cmd_lock);
- mtx_destroy(&sc->tx_lock);
- sx_destroy(&sc->driver_lock);
+ mtx_destroy(&sc->cmd_mtx);
+ mtx_destroy(&sc->tx_mtx);
+ mtx_destroy(&sc->driver_mtx);
if_free(ifp);
abort_with_parent_dmat:
bus_dma_tag_destroy(sc->parent_dmat);
@@ -2936,12 +2940,14 @@ mxge_detach(device_t dev)
{
mxge_softc_t *sc = device_get_softc(dev);
- sx_xlock(&sc->driver_lock);
+ mtx_lock(&sc->driver_mtx);
if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING)
mxge_close(sc);
- sx_xunlock(&sc->driver_lock);
+ mtx_unlock(&sc->driver_mtx);
ether_ifdetach(sc->ifp);
mxge_dummy_rdma(sc, 0);
+ bus_teardown_intr(sc->dev, sc->irq_res, sc->ih);
+ mxge_free_rings(sc);
bus_release_resource(dev, SYS_RES_IRQ,
sc->msi_enabled ? 1 : 0, sc->irq_res);
if (sc->msi_enabled)
@@ -2950,13 +2956,14 @@ mxge_detach(device_t dev)
sc->rx_done.entry = NULL;
mxge_dma_free(&sc->rx_done.dma);
mxge_dma_free(&sc->fw_stats_dma);
+ mxge_dma_free(&sc->dmabench_dma);
mxge_dma_free(&sc->zeropad_dma);
mxge_dma_free(&sc->cmd_dma);
bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BARS, sc->mem_res);
pci_disable_busmaster(dev);
- mtx_destroy(&sc->cmd_lock);
- mtx_destroy(&sc->tx_lock);
- sx_destroy(&sc->driver_lock);
+ mtx_destroy(&sc->cmd_mtx);
+ mtx_destroy(&sc->tx_mtx);
+ mtx_destroy(&sc->driver_mtx);
if_free(sc->ifp);
bus_dma_tag_destroy(sc->parent_dmat);
return 0;
diff --git a/sys/dev/mxge/if_mxge_var.h b/sys/dev/mxge/if_mxge_var.h
index 82beda1..cf3c0d4 100644
--- a/sys/dev/mxge/if_mxge_var.h
+++ b/sys/dev/mxge/if_mxge_var.h
@@ -114,7 +114,7 @@ typedef struct
typedef struct {
struct ifnet* ifp;
int big_bytes;
- struct mtx tx_lock;
+ struct mtx tx_mtx;
int csum_flag; /* rx_csums? */
uint8_t mac_addr[6]; /* eeprom mac address */
mxge_tx_buf_t tx; /* transmit ring */
@@ -138,8 +138,8 @@ typedef struct {
int intr_coal_delay;
volatile uint32_t *intr_coal_delay_ptr;
int wc;
- struct mtx cmd_lock;
- struct sx driver_lock;
+ struct mtx cmd_mtx;
+ struct mtx driver_mtx;
int wake_queue;
int stop_queue;
int down_cnt;
@@ -159,10 +159,14 @@ typedef struct {
int read_write_dma;
int fw_multicast_support;
int link_width;
+ mxge_dma_t dmabench_dma;
char *mac_addr_string;
char product_code_string[64];
char serial_number_string[64];
char scratch[256];
+ char tx_mtx_name[16];
+ char cmd_mtx_name[16];
+ char driver_mtx_name[16];
} mxge_softc_t;
#define MXGE_PCI_VENDOR_MYRICOM 0x14c1
OpenPOWER on IntegriCloud