summaryrefslogtreecommitdiffstats
path: root/sys/dev/bge
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>2006-12-22 02:59:58 +0000
committerjdp <jdp@FreeBSD.org>2006-12-22 02:59:58 +0000
commit3c8630bd2bc4c203424d1b8dd311eb53ca908bf3 (patch)
treed9deabebd6b8e26d251b09c02c951d210a614d91 /sys/dev/bge
parent7ca53bc609134958887cd2cf5b2e7161756c966d (diff)
downloadFreeBSD-src-3c8630bd2bc4c203424d1b8dd311eb53ca908bf3.zip
FreeBSD-src-3c8630bd2bc4c203424d1b8dd311eb53ca908bf3.tar.gz
Re-enable MSI support for those chips on which it is believed to work
properly.
Diffstat (limited to 'sys/dev/bge')
-rw-r--r--sys/dev/bge/if_bge.c120
-rw-r--r--sys/dev/bge/if_bgereg.h2
2 files changed, 88 insertions, 34 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index f58b281..75bff43 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -114,12 +114,6 @@ __FBSDID("$FreeBSD$");
#define BGE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP)
#define ETHER_MIN_NOPAD (ETHER_MIN_LEN - ETHER_CRC_LEN) /* i.e., 60 */
-/*
- * Disable the use of MSI until we sort out on which chip revisions support
- * it properly.
- */
-#define BGE_DISABLE_MSI 1
-
MODULE_DEPEND(bge, pci, 1, 1, 1);
MODULE_DEPEND(bge, ether, 1, 1, 1);
MODULE_DEPEND(bge, miibus, 1, 1, 1);
@@ -2108,6 +2102,54 @@ bge_dma_alloc(device_t dev)
return (0);
}
+/*
+ * Return true if this device has more than one port.
+ */
+static int
+bge_has_multiple_ports(struct bge_softc *sc)
+{
+ device_t dev = sc->bge_dev;
+ u_int b, s, f, fscan;
+
+ b = pci_get_bus(dev);
+ s = pci_get_slot(dev);
+ f = pci_get_function(dev);
+ for (fscan = 0; fscan <= PCI_FUNCMAX; fscan++)
+ if (fscan != f && pci_find_bsf(b, s, fscan) != NULL)
+ return (1);
+ return (0);
+}
+
+/*
+ * Return true if MSI can be used with this device.
+ */
+static int
+bge_can_use_msi(struct bge_softc *sc)
+{
+ int can_use_msi = 0;
+
+ switch (sc->bge_asicrev) {
+ case BGE_ASICREV_BCM5714:
+ /*
+ * Apparently, MSI doesn't work when this chip is configured
+ * in single-port mode.
+ */
+ if (bge_has_multiple_ports(sc))
+ can_use_msi = 1;
+ break;
+ case BGE_ASICREV_BCM5750:
+ if (sc->bge_chiprev != BGE_CHIPREV_5750_AX &&
+ sc->bge_chiprev != BGE_CHIPREV_5750_BX)
+ can_use_msi = 1;
+ break;
+ case BGE_ASICREV_BCM5752:
+ case BGE_ASICREV_BCM5780:
+ can_use_msi = 1;
+ break;
+ }
+ return (can_use_msi);
+}
+
static int
bge_attach(device_t dev)
{
@@ -2139,33 +2181,6 @@ bge_attach(device_t dev)
sc->bge_btag = rman_get_bustag(sc->bge_res);
sc->bge_bhandle = rman_get_bushandle(sc->bge_res);
- /*
- * Allocate the interrupt, using MSI if possible. These devices
- * support 8 MSI messages, but only the first one is used in
- * normal operation.
- */
- if ((msicount = pci_msi_count(dev)) > 1)
- msicount = 1;
-#ifdef BGE_DISABLE_MSI
- msicount = 0;
-#endif
- if (msicount == 1 && pci_alloc_msi(dev, &msicount) == 0) {
- rid = 1;
- sc->bge_flags |= BGE_FLAG_MSI;
- } else
- rid = 0;
-
- sc->bge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
-
- if (sc->bge_irq == NULL) {
- device_printf(sc->bge_dev, "couldn't map interrupt\n");
- error = ENXIO;
- goto fail;
- }
-
- BGE_LOCK_INIT(sc, device_get_nameunit(dev));
-
/* Save ASIC rev. */
sc->bge_chipid =
@@ -2233,6 +2248,34 @@ bge_attach(device_t dev)
}
#endif
+ /*
+ * Allocate the interrupt, using MSI if possible. These devices
+ * support 8 MSI messages, but only the first one is used in
+ * normal operation.
+ */
+ if (bge_can_use_msi(sc)) {
+ msicount = pci_msi_count(dev);
+ if (msicount > 1)
+ msicount = 1;
+ } else
+ msicount = 0;
+ if (msicount == 1 && pci_alloc_msi(dev, &msicount) == 0) {
+ rid = 1;
+ sc->bge_flags |= BGE_FLAG_MSI;
+ } else
+ rid = 0;
+
+ sc->bge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_SHAREABLE | RF_ACTIVE);
+
+ if (sc->bge_irq == NULL) {
+ device_printf(sc->bge_dev, "couldn't map interrupt\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ BGE_LOCK_INIT(sc, device_get_nameunit(dev));
+
/* Try to reset the chip. */
if (bge_reset(sc)) {
device_printf(sc->bge_dev, "chip reset failed\n");
@@ -2615,10 +2658,19 @@ bge_reset(struct bge_softc *sc)
pci_write_config(dev, BGE_PCI_CMD, command, 4);
write_op(sc, BGE_MISC_CFG, (65 << 1));
- /* Enable memory arbiter. */
+ /* Re-enable MSI, if neccesary, and enable the memory arbiter. */
if (BGE_IS_5714_FAMILY(sc)) {
uint32_t val;
+ /* This chip disables MSI on reset. */
+ if (sc->bge_flags & BGE_FLAG_MSI) {
+ val = pci_read_config(dev, BGE_PCI_MSI_CTL, 2);
+ pci_write_config(dev, BGE_PCI_MSI_CTL,
+ val | PCIM_MSICTRL_MSI_ENABLE, 2);
+ val = CSR_READ_4(sc, BGE_MSI_MODE);
+ CSR_WRITE_4(sc, BGE_MSI_MODE,
+ val | BGE_MSIMODE_ENABLE);
+ }
val = CSR_READ_4(sc, BGE_MARB_MODE);
CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE | val);
} else
diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h
index e2a039e..ec326d2 100644
--- a/sys/dev/bge/if_bgereg.h
+++ b/sys/dev/bge/if_bgereg.h
@@ -303,6 +303,8 @@
#define BGE_CHIPREV_5700_BX 0x71
#define BGE_CHIPREV_5700_CX 0x72
#define BGE_CHIPREV_5701_AX 0x00
+#define BGE_CHIPREV_5750_AX 0x40
+#define BGE_CHIPREV_5750_BX 0x41
/* PCI DMA Read/Write Control register */
#define BGE_PCIDMARWCTL_MINDMA 0x000000FF
OpenPOWER on IntegriCloud