diff options
author | gallatin <gallatin@FreeBSD.org> | 2006-11-22 16:33:40 +0000 |
---|---|---|
committer | gallatin <gallatin@FreeBSD.org> | 2006-11-22 16:33:40 +0000 |
commit | bcc8dcd383b99785d2df7ca26b8c621d166e6b82 (patch) | |
tree | e4b9b69422f4552decacbb22d913e16562d9fc0a /sys | |
parent | ec3e058a757e1f0ca8b0be0c5376387d7228e84f (diff) | |
download | FreeBSD-src-bcc8dcd383b99785d2df7ca26b8c621d166e6b82.zip FreeBSD-src-bcc8dcd383b99785d2df7ca26b8c621d166e6b82.tar.gz |
Initialization bugfixes and enhancements:
- Fix bug preventing adoption of running firmware
- Set PCIe max read request size to 4KB
- Read PCIe link width from config space
- Assume aligned completions from the southbridge ports
of intel E5000 chips
- Use aligned firmware when link width is x4 or less
- Add hw.mxge.force_firmware tunable to allow user to force
selection of aligned (or unaligned) firmware
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/mxge/if_mxge.c | 56 | ||||
-rw-r--r-- | sys/dev/mxge/if_mxge_var.h | 1 |
2 files changed, 51 insertions, 6 deletions
diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index c4d3e6b..fb7dbae 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$"); /* tunable params */ static int mxge_nvidia_ecrc_enable = 1; +static int mxge_force_firmware = 0; static int mxge_max_intr_slots = 1024; static int mxge_intr_coal_delay = 30; static int mxge_deassert_wait = 1; @@ -403,6 +404,29 @@ mxge_select_firmware(mxge_softc_t *sc) device_t pdev; uint16_t pvend, pdid; + + if (mxge_force_firmware != 0) { + if (mxge_force_firmware == 1) + aligned = 1; + else + aligned = 0; + if (mxge_verbose) + device_printf(sc->dev, + "Assuming %s completions (forced)\n", + aligned ? "aligned" : "unaligned"); + goto abort; + } + + /* if the PCIe link width is 4 or less, we can use the aligned + firmware and skip any checks */ + if (sc->link_width != 0 && sc->link_width <= 4) { + device_printf(sc->dev, + "PCIe x%d Link, expect reduced performance\n", + sc->link_width); + aligned = 1; + goto abort; + } + pdev = device_get_parent(device_get_parent(sc->dev)); if (pdev == NULL) { device_printf(sc->dev, "could not find parent?\n"); @@ -428,8 +452,10 @@ mxge_select_firmware(mxge_softc_t *sc) provided aligned completions */ if (/* HT2000 */ (pvend == 0x1166 && pdid == 0x0132) || /* PLX */ (pvend == 0x10b5 && pdid == 0x8532) || - /* Intel */ (pvend == 0x8086 && - /* E5000 */(pdid >= 0x25f7 && pdid <= 0x25fa))) { + /* Intel */ (pvend == 0x8086 && + /* E5000 NorthBridge*/((pdid >= 0x25f7 && pdid <= 0x25fa) || + /* E5000 SouthBridge*/ (pdid >= 0x3510 && pdid <= 0x351b)))) { + aligned = 1; if (mxge_verbose) device_printf(sc->dev, "Assuming aligned completions " @@ -722,7 +748,9 @@ mxge_load_firmware(mxge_softc_t *sc) "performance consider loading optimized " "firmware\n"); } - + sc->fw_name = mxge_fw_unaligned; + sc->tx.boundary = 2048; + return 0; } /* clear confirmation addr */ confirm = (volatile uint32_t *)sc->cmd; @@ -1093,6 +1121,10 @@ mxge_add_sysctls(mxge_softc_t *sc) CTLFLAG_RD, &sc->product_code_string, 0, "product_code"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "pcie_link_width", + CTLFLAG_RD, &sc->link_width, + 0, "tx_boundary"); + SYSCTL_ADD_INT(ctx, children, OID_AUTO, "tx_boundary", CTLFLAG_RD, &sc->tx.boundary, 0, "tx_boundary"); @@ -2669,6 +2701,8 @@ mxge_fetch_tunables(mxge_softc_t *sc) &mxge_intr_coal_delay); TUNABLE_INT_FETCH("hw.mxge.nvidia_ecrc_enable", &mxge_nvidia_ecrc_enable); + TUNABLE_INT_FETCH("hw.mxge.force_firmware", + &mxge_force_firmware); TUNABLE_INT_FETCH("hw.mxge.deassert_wait", &mxge_deassert_wait); TUNABLE_INT_FETCH("hw.mxge.verbose", @@ -2687,8 +2721,8 @@ mxge_attach(device_t dev) mxge_softc_t *sc = device_get_softc(dev); struct ifnet *ifp; size_t bytes; - int count, rid, err; - uint16_t cmd; + int count, rid, err, reg; + uint16_t cmd, pectl, lnk; sc->dev = dev; mxge_fetch_tunables(sc); @@ -2724,6 +2758,16 @@ mxge_attach(device_t dev) 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, ®) == 0) { + lnk = pci_read_config(dev, reg + 0x12, 2); + sc->link_width = (lnk >> 4) & 0x3f; + + pectl = pci_read_config(dev, reg + 0x8, 2); + pectl = (pectl & ~0x7000) | (5 << 12); + pci_write_config(dev, reg + 0x8, 2, pectl); + } + /* Enable DMA and Memory space access */ pci_enable_busmaster(dev); cmd = pci_read_config(dev, PCIR_COMMAND, 2); @@ -2802,7 +2846,7 @@ mxge_attach(device_t dev) device_printf(dev, "could not alloc interrupt\n"); goto abort_with_rx_done; } - if (bootverbose) + if (mxge_verbose) device_printf(dev, "using %s irq %ld\n", sc->msi_enabled ? "MSI" : "INTx", rman_get_start(sc->irq_res)); diff --git a/sys/dev/mxge/if_mxge_var.h b/sys/dev/mxge/if_mxge_var.h index 2360424..f8c284f 100644 --- a/sys/dev/mxge/if_mxge_var.h +++ b/sys/dev/mxge/if_mxge_var.h @@ -156,6 +156,7 @@ typedef struct { int write_dma; int read_write_dma; int fw_multicast_support; + int link_width; char *mac_addr_string; char product_code_string[64]; char serial_number_string[64]; |