Subject: kern/26807: BCM5701 does not work with AMD760MPX chipset
To: None <gnats-bugs@gnats.NetBSD.org>
From: HITOSHI Osada <QFH02545@nifty.com>
List: netbsd-bugs
Date: 08/30/2004 22:13:21
>Number:         26807
>Category:       kern
>Synopsis:       BCM5701 does not work with AMD760MPX chipset
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Aug 30 13:19:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator:     HITOSHI Osada
>Release:        NetBSD 2.0G (20040824)
>Organization:
>Environment:
System: NetBSD that 2.0G NetBSD 2.0G (TIGERMPX2) #10: Mon Aug 30 17:55:49 JST 2004 that@that:/sys/arch/i386/compile/TIGERMPX2 i386
Architecture: i386
Machine: i386
>Description:
	The Broadcom 5701 does not work with AMD760MPX(AMD 762+AMD768)
	chipset when using 64bit slot.(corrupt packets)
	Using 32bit slot works very well.
	
>How-To-Repeat:
	Put BCM5701 NIC into AMD760MPX 64bit slot.

>Fix:

*** if_bge.c	6 Jun 2004 11:09:39 -0000
--- if_bge.c	30 Aug 2004 08:54:08 -0000
***************
*** 246,251 ****
--- 246,255 ----
  void bge_dump_status(struct bge_softc *);
  void bge_dump_rxbd(struct bge_rx_bd *);
  
+ static int bge_amd762_match(struct pci_attach_args *);
+ static void bge_amd762_fix(struct bge_softc *);
+ 
+ 
  #define BGE_DEBUG
  #ifdef BGE_DEBUG
  #define DPRINTF(x)	if (bgedebug) printf x
***************
*** 276,281 ****
--- 280,286 ----
  #define	BGE_QUIRK_PCIX_DMA_ALIGN_BUG	0x00000040
  #define	BGE_QUIRK_5705_CORE		0x00000080
  #define	BGE_QUIRK_FEWER_MBUFS		0x00000100
+ #define	BGE_QUIRK_FLUSH_POSTED_WRITE	0x00000200
  
  /* following bugs are common to bcm5700 rev B, all flavours */
  #define BGE_QUIRK_5700_COMMON \
***************
*** 1002,1007 ****
--- 1007,1015 ----
  
  	sc->bge_std = i - 1;
  	CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
+ 	if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
+ 		(void)CSR_READ_4(sc, BGE_MBX_RX_STD_PROD_LO);
+ 
  
  	sc->bge_flags |= BGE_RXRING_VALID;
  
***************
*** 1054,1059 ****
--- 1062,1069 ----
  	CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags);
  
  	CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
+ 	if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
+ 		(void)CSR_READ_4(sc, BGE_MBX_RX_JUMBO_PROD_LO);
  
  	return(0);
  }
***************
*** 1129,1138 ****
  	CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, 0);
  	if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG)	/* 5700 b2 errata */
  		CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, 0);
  
  	CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
  	if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG)	/* 5700 b2 errata */
! 		CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, 0);
  
  	SLIST_INIT(&sc->txdma_list);
  	for (i = 0; i < BGE_RSLOTS; i++) {
--- 1139,1152 ----
  	CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, 0);
  	if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG)	/* 5700 b2 errata */
  		CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, 0);
+ 	if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
+ 		(void)CSR_READ_4(sc, BGE_MBX_TX_HOST_PROD0_LO);
  
  	CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
  	if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG)	/* 5700 b2 errata */
! 		CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
! 	if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
! 		(void)CSR_READ_4(sc, BGE_MBX_TX_NIC_PROD0_LO);
  
  	SLIST_INIT(&sc->txdma_list);
  	for (i = 0; i < BGE_RSLOTS; i++) {
***************
*** 1333,1345 ****
  		    BGE_MODECTL_TX_NO_PHDR_CSUM|BGE_MODECTL_RX_NO_PHDR_CSUM);
  
  	/* Get cache line size. */
! 	cachesize = pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_CACHESZ);
  
  	/*
  	 * Avoid violating PCI spec on certain chip revs.
  	 */
! 	if (pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_CMD) &
! 	    PCIM_CMD_MWIEN) {
  		switch(cachesize) {
  		case 1:
  			PCI_SETBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL,
--- 1347,1358 ----
  		    BGE_MODECTL_TX_NO_PHDR_CSUM|BGE_MODECTL_RX_NO_PHDR_CSUM);
  
  	/* Get cache line size. */
! 	cachesize = pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_CACHESZ) & 0xff;
  
  	/*
  	 * Avoid violating PCI spec on certain chip revs.
  	 */
! 	if (pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_CMD) & PCIM_CMD_MWIEN) {
  		switch(cachesize) {
  		case 1:
  			PCI_SETBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL,
***************
*** 1383,1395 ****
  		}
  	}
  
  	/*
  	 * Disable memory write invalidate.  Apparently it is not supported
  	 * properly by these devices.
  	 */
  	PCI_CLRBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_CMD, PCIM_CMD_MWIEN);
  
- 
  #ifdef __brokenalpha__
  	/*
  	 * Must insure that we do not cross an 8K (bytes) boundary
--- 1396,1417 ----
  		}
  	}
  
+ 	if ((BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5700) ||
+ 	    (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5701)) {
+ 		/* XXX
+ 		 * At my TigerMPX, 64bit-slot requires this fix, but 32bit does not.
+ 		 */
+ 		if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)
+ 			pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL, 
+ 				       (dma_rw_ctl | BGE_PCI_WRITE_BNDRY_16BYTES));
+ 	}
+ 
  	/*
  	 * Disable memory write invalidate.  Apparently it is not supported
  	 * properly by these devices.
  	 */
  	PCI_CLRBIT(pa->pa_pc, pa->pa_tag, BGE_PCI_CMD, PCIM_CMD_MWIEN);
  
  #ifdef __brokenalpha__
  	/*
  	 * Must insure that we do not cross an 8K (bytes) boundary
***************
*** 2179,2184 ****
--- 2201,2236 ----
  	return (0);
  }
  
+ /* find AMD762 chipset. */
+ static int
+ bge_amd762_match(struct pci_attach_args *pa)
+ {
+ 	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_SC762_NB) 
+ 		return (1);
+ 	return 0;
+ }
+ 
+ /* fix for AMD762 chipset. */
+ static void
+ bge_amd762_fix(struct bge_softc *sc)
+ {
+ 	struct pci_attach_args amd762_pa;
+ 	u_int32_t val;
+ 
+ 	if (pci_find_device(&amd762_pa, bge_amd762_match) == 0)
+ 		return;
+ 
+ 	sc->bge_quirks |= BGE_QUIRK_FLUSH_POSTED_WRITE;
+ 
+ 	val = pci_conf_read(amd762_pa.pa_pc, amd762_pa.pa_tag, 0x4c);
+ 	if ((val & 0x02) == 0) {
+ 		printf("%s: Setting AMD762 Northbridge to enable PCI ordering compliance\n",
+ 		       sc->bge_dev.dv_xname);
+ 		pci_conf_write(amd762_pa.pa_pc, amd762_pa.pa_tag, 0x4c, (val | 0x02));
+ 	}
+ }
+ 
+ 
  void
  bge_attach(parent, self, aux)
  	struct device *parent, *self;
***************
*** 2212,2217 ****
--- 2264,2272 ----
  	aprint_naive(": Ethernet controller\n");
  	aprint_normal(": %s\n", bp->bp_name);
  
+ 	/* Fix for AMD762 */
+ 	bge_amd762_fix(sc);
+ 
  	/*
  	 * Map control/status registers.
  	 */
***************
*** 2493,2499 ****
  		if ((pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_PCISTATE) &
                      (BGE_PCISTATE_PCI_BUSMODE | BGE_PCISTATE_PCI_BUSSPEED)) ==
                           BGE_PCISTATE_PCI_BUSSPEED)
! 		sc->bge_rx_alignment_bug = 1;
          }
  
  	/*
--- 2548,2554 ----
  		if ((pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_PCISTATE) &
                      (BGE_PCISTATE_PCI_BUSMODE | BGE_PCISTATE_PCI_BUSSPEED)) ==
                           BGE_PCISTATE_PCI_BUSSPEED)
! 			sc->bge_rx_alignment_bug = 1;
          }
  
  	/*
***************
*** 2801,2810 ****
  	}
  
  	CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx);
! 	if (stdcnt)
  		CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
! 	if (jumbocnt)
  		CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
  }
  
  void
--- 2856,2874 ----
  	}
  
  	CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx);
! 	if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
! 		(void)CSR_READ_4(sc, BGE_MBX_RX_CONS0_LO);
! 
! 	if (stdcnt) {
  		CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
! 		if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
! 			(void)CSR_READ_4(sc, BGE_MBX_RX_STD_PROD_LO);
! 	}
! 	if (jumbocnt) {
  		CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
+ 		if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
+ 			(void)CSR_READ_4(sc, BGE_MBX_RX_JUMBO_PROD_LO);
+ 	}
  }
  
  void
***************
*** 2895,2900 ****
--- 2959,2966 ----
  #endif
  	/* Ack interrupt and stop others from occuring. */
  	CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
+ 	if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
+ 		(void)CSR_READ_4(sc, BGE_MBX_IRQ0_LO);
  
  	BGE_EVCNT_INCR(sc->bge_ev_intr);
  
***************
*** 2965,2970 ****
--- 3031,3038 ----
  
  	/* Re-enable interrupts. */
  	CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
+ 	if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
+ 		(void)CSR_READ_4(sc, BGE_MBX_IRQ0_LO);
  
  	if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
  		bge_start(ifp);
***************
*** 3450,3455 ****
--- 3518,3525 ----
  	CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
  	if (sc->bge_quirks & BGE_QUIRK_PRODUCER_BUG)	/* 5700 b2 errata */
  		CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
+ 	if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
+ 		(void)CSR_READ_4(sc, BGE_MBX_TX_HOST_PROD0_LO);
  
  	/*
  	 * Set a timeout in case the chip goes out to lunch.
***************
*** 3535,3540 ****
--- 3605,3612 ----
  	BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA);
  	BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
  	CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
+ 	if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
+ 		(void)CSR_READ_4(sc, BGE_MBX_IRQ0_LO);
  
  	bge_ifmedia_upd(ifp);
  
***************
*** 3800,3805 ****
--- 3872,3879 ----
  	/* Disable host interrupts. */
  	BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
  	CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
+ 	if (sc->bge_quirks & BGE_QUIRK_FLUSH_POSTED_WRITE)	/* fix for AMD762 */
+ 		(void)CSR_READ_4(sc, BGE_MBX_IRQ0_LO);
  
  	/*
  	 * Tell firmware we're shutting down.
>Release-Note:
>Audit-Trail:
>Unformatted: