diff options
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/bge/if_bge.c | 120 | ||||
| -rw-r--r-- | sys/dev/bge/if_bgereg.h | 2 | 
2 files changed, 88 insertions, 34 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index f58b281fc8c5..75bff43c6068 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 e2a039e57ffc..ec326d2a2f3c 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  | 
