changeset 3907:06a70d1289cb

6424735 bge driver should support relaxed ordering 6426339 boston bge hardware reporting critical issue through fma. 6462563 Broadcom 5703 needs to be added to /etc/driver_aliases & /kernel/drv/bge.conf for GRUB with HP BL20p
author zh199473
date Wed, 28 Mar 2007 00:46:13 -0700
parents 6bf378350201
children 211a66d0821f
files usr/src/uts/common/io/bge/bge.conf usr/src/uts/common/io/bge/bge_chip2.c usr/src/uts/common/io/bge/bge_hw.h usr/src/uts/common/io/bge/bge_impl.h usr/src/uts/common/io/bge/bge_kstats.c usr/src/uts/common/io/bge/bge_main2.c
diffstat 6 files changed, 175 insertions(+), 143 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/bge/bge.conf	Tue Mar 27 22:00:10 2007 -0700
+++ b/usr/src/uts/common/io/bge/bge.conf	Wed Mar 28 00:46:13 2007 -0700
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
 #
 #########################################################################
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -165,6 +164,7 @@
 			  0x10280109,
 			  0x1028865d,
 			  0x0e11005a,
+			  0x0e1100cb,
 			  0x103c12bc;
 #########################################################################
 #
--- a/usr/src/uts/common/io/bge/bge_chip2.c	Tue Mar 27 22:00:10 2007 -0700
+++ b/usr/src/uts/common/io/bge/bge_chip2.c	Wed Mar 28 00:46:13 2007 -0700
@@ -52,6 +52,11 @@
 #endif
 
 /*
+ * PCI-X/PCI-E relaxed ordering tunable for OS/Nexus driver
+ */
+boolean_t bge_relaxed_ordering = B_TRUE;
+
+/*
  * Property names
  */
 static char knownids_propname[] = "bge-known-subsystems";
@@ -3212,7 +3217,7 @@
 	/* Enable MSI code */
 	if (bgep->intr_type == DDI_INTR_TYPE_MSI)
 		bge_reg_set32(bgep, MSI_MODE_REG,
-		    MSI_PRI_HIGHEST|MSI_MSI_ENABLE);
+		    MSI_PRI_HIGHEST|MSI_MSI_ENABLE|MSI_ERROR_ATTENTION);
 
 	/*
 	 * On the first time through, save the factory-set MAC address
@@ -3835,7 +3840,7 @@
 	bge_t *bgep = (bge_t *)arg1;		/* private device info	*/
 	bge_status_t *bsp;
 	uint64_t flags;
-	uint32_t mlcr = 0;
+	uint32_t regval;
 	uint_t result;
 	int retval;
 
@@ -3848,158 +3853,169 @@
 	 */
 	ASSERT(bgep->progress & PROGRESS_HWINT);
 
-	/*
-	 * Check whether chip's says it's asserting #INTA;
-	 * if not, don't process or claim the interrupt.
-	 *
-	 * Note that the PCI signal is active low, so the
-	 * bit is *zero* when the interrupt is asserted.
-	 */
 	result = DDI_INTR_UNCLAIMED;
 	mutex_enter(bgep->genlock);
 
-	if (bgep->intr_type == DDI_INTR_TYPE_FIXED)
-		mlcr = bge_reg_get32(bgep, MISC_LOCAL_CONTROL_REG);
-
-	BGE_DEBUG(("bge_intr($%p) ($%p) mlcr 0x%08x", arg1, arg2, mlcr));
-
-	if ((mlcr & MLCR_INTA_STATE) == 0) {
+	if (bgep->intr_type == DDI_INTR_TYPE_FIXED) {
 		/*
-		 * Block further PCI interrupts ...
+		 * Check whether chip's says it's asserting #INTA;
+		 * if not, don't process or claim the interrupt.
+		 *
+		 * Note that the PCI signal is active low, so the
+		 * bit is *zero* when the interrupt is asserted.
 		 */
-		result = DDI_INTR_CLAIMED;
-
-		if (bgep->intr_type == DDI_INTR_TYPE_FIXED) {
-			bge_reg_set32(bgep, PCI_CONF_BGE_MHCR,
-				MHCR_MASK_PCI_INT_OUTPUT);
-			if (bge_check_acc_handle(bgep, bgep->cfg_handle) !=
-			    DDI_FM_OK)
+		regval = bge_reg_get32(bgep, MISC_LOCAL_CONTROL_REG);
+		if (regval & MLCR_INTA_STATE) {
+			if (bge_check_acc_handle(bgep, bgep->io_handle)
+			    != DDI_FM_OK)
 				goto chip_stop;
+			mutex_exit(bgep->genlock);
+			return (result);
 		}
 
 		/*
-		 * Sync the status block and grab the flags-n-tag from it.
-		 * We count the number of interrupts where there doesn't
-		 * seem to have been a DMA update of the status block; if
-		 * it *has* been updated, the counter will be cleared in
-		 * the while() loop below ...
+		 * Block further PCI interrupts ...
+		 */
+		bge_reg_set32(bgep, PCI_CONF_BGE_MHCR,
+		    MHCR_MASK_PCI_INT_OUTPUT);
+
+	} else {
+		/*
+		 * Check MSI status
 		 */
-		bgep->missed_dmas += 1;
-		bsp = DMA_VPTR(bgep->status_block);
-		for (;;) {
-			if (bgep->bge_chip_state != BGE_CHIP_RUNNING) {
-				/*
-				 * bge_chip_stop() may have freed dma area etc
-				 * while we were in this interrupt handler -
-				 * better not call bge_status_sync()
-				 */
-				(void) bge_check_acc_handle(bgep,
-				    bgep->io_handle);
-				mutex_exit(bgep->genlock);
-				return (DDI_INTR_CLAIMED);
-			}
-			retval = bge_status_sync(bgep, STATUS_FLAG_UPDATED,
-			    &flags);
-			if (retval != DDI_FM_OK) {
-				bgep->bge_dma_error = B_TRUE;
-				goto chip_stop;
-			}
-
-			if (!(flags & STATUS_FLAG_UPDATED))
-				break;
-
+		regval = bge_reg_get32(bgep, MSI_STATUS_REG);
+		if (regval & MSI_ERROR_ATTENTION) {
+			BGE_REPORT((bgep, "msi error attention,"
+			    " status=0x%x", regval));
+			bge_reg_put32(bgep, MSI_STATUS_REG, regval);
+		}
+	}
+
+	result = DDI_INTR_CLAIMED;
+
+	BGE_DEBUG(("bge_intr($%p) ($%p) regval 0x%08x", arg1, arg2, regval));
+
+	/*
+	 * Sync the status block and grab the flags-n-tag from it.
+	 * We count the number of interrupts where there doesn't
+	 * seem to have been a DMA update of the status block; if
+	 * it *has* been updated, the counter will be cleared in
+	 * the while() loop below ...
+	 */
+	bgep->missed_dmas += 1;
+	bsp = DMA_VPTR(bgep->status_block);
+	for (;;) {
+		if (bgep->bge_chip_state != BGE_CHIP_RUNNING) {
 			/*
-			 * Tell the chip that we're processing the interrupt
+			 * bge_chip_stop() may have freed dma area etc
+			 * while we were in this interrupt handler -
+			 * better not call bge_status_sync()
 			 */
-			bge_mbx_put(bgep, INTERRUPT_MBOX_0_REG,
-				INTERRUPT_MBOX_DISABLE(flags));
-			if (bge_check_acc_handle(bgep, bgep->io_handle) !=
-			    DDI_FM_OK)
-				goto chip_stop;
-
-			/*
-			 * Drop the mutex while we:
-			 * 	Receive any newly-arrived packets
-			 *	Recycle any newly-finished send buffers
-			 */
-			bgep->bge_intr_running = B_TRUE;
+			(void) bge_check_acc_handle(bgep,
+			    bgep->io_handle);
 			mutex_exit(bgep->genlock);
-			bge_receive(bgep, bsp);
-			bge_recycle(bgep, bsp);
-			mutex_enter(bgep->genlock);
-			bgep->bge_intr_running = B_FALSE;
-
-			/*
-			 * Tell the chip we've finished processing, and
-			 * give it the tag that we got from the status
-			 * block earlier, so that it knows just how far
-			 * we've gone.  If it's got more for us to do,
-			 * it will now update the status block and try
-			 * to assert an interrupt (but we've got the
-			 * #INTA blocked at present).  If we see the
-			 * update, we'll loop around to do some more.
-			 * Eventually we'll get out of here ...
-			 */
-			bge_mbx_put(bgep, INTERRUPT_MBOX_0_REG,
-				INTERRUPT_MBOX_ENABLE(flags));
-			bgep->missed_dmas = 0;
+			return (DDI_INTR_CLAIMED);
+		}
+		retval = bge_status_sync(bgep, STATUS_FLAG_UPDATED,
+		    &flags);
+		if (retval != DDI_FM_OK) {
+			bgep->bge_dma_error = B_TRUE;
+			goto chip_stop;
 		}
 
+		if (!(flags & STATUS_FLAG_UPDATED))
+			break;
+
+		/*
+		 * Tell the chip that we're processing the interrupt
+		 */
+		bge_mbx_put(bgep, INTERRUPT_MBOX_0_REG,
+		    INTERRUPT_MBOX_DISABLE(flags));
+		if (bge_check_acc_handle(bgep, bgep->io_handle) !=
+		    DDI_FM_OK)
+			goto chip_stop;
+
 		/*
-		 * Check for exceptional conditions that we need to handle
-		 *
-		 * Link status changed
-		 * Status block not updated
+		 * Drop the mutex while we:
+		 * 	Receive any newly-arrived packets
+		 *	Recycle any newly-finished send buffers
 		 */
-		if (flags & STATUS_FLAG_LINK_CHANGED)
-			bge_wake_factotum(bgep);
-
-		if (bgep->missed_dmas) {
-			/*
-			 * Probably due to the internal status tag not
-			 * being reset.  Force a status block update now;
-			 * this should ensure that we get an update and
-			 * a new interrupt.  After that, we should be in
-			 * sync again ...
-			 */
-			BGE_REPORT((bgep, "interrupt: flags 0x%llx - "
-				"not updated?", flags));
-			bge_reg_set32(bgep, HOST_COALESCE_MODE_REG,
-				COALESCE_NOW);
-
-			if (bgep->missed_dmas >= bge_dma_miss_limit) {
-				/*
-				 * If this happens multiple times in a row,
-				 * it means DMA is just not working.  Maybe
-				 * the chip's failed, or maybe there's a
-				 * problem on the PCI bus or in the host-PCI
-				 * bridge (Tomatillo).
-				 *
-				 * At all events, we want to stop further
-				 * interrupts and let the recovery code take
-				 * over to see whether anything can be done
-				 * about it ...
-				 */
-				bge_fm_ereport(bgep,
-				    DDI_FM_DEVICE_BADINT_LIMIT);
-				goto chip_stop;
-			}
-		}
+		bgep->bge_intr_running = B_TRUE;
+		mutex_exit(bgep->genlock);
+		bge_receive(bgep, bsp);
+		bge_recycle(bgep, bsp);
+		mutex_enter(bgep->genlock);
+		bgep->bge_intr_running = B_FALSE;
 
 		/*
-		 * Reenable assertion of #INTA, unless there's a DMA fault
+		 * Tell the chip we've finished processing, and
+		 * give it the tag that we got from the status
+		 * block earlier, so that it knows just how far
+		 * we've gone.  If it's got more for us to do,
+		 * it will now update the status block and try
+		 * to assert an interrupt (but we've got the
+		 * #INTA blocked at present).  If we see the
+		 * update, we'll loop around to do some more.
+		 * Eventually we'll get out of here ...
+		 */
+		bge_mbx_put(bgep, INTERRUPT_MBOX_0_REG,
+		    INTERRUPT_MBOX_ENABLE(flags));
+		bgep->missed_dmas = 0;
+	}
+
+	/*
+	 * Check for exceptional conditions that we need to handle
+	 *
+	 * Link status changed
+	 * Status block not updated
+	 */
+	if (flags & STATUS_FLAG_LINK_CHANGED)
+		bge_wake_factotum(bgep);
+
+	if (bgep->missed_dmas) {
+		/*
+		 * Probably due to the internal status tag not
+		 * being reset.  Force a status block update now;
+		 * this should ensure that we get an update and
+		 * a new interrupt.  After that, we should be in
+		 * sync again ...
 		 */
-		if (result == DDI_INTR_CLAIMED) {
-			if (bgep->intr_type == DDI_INTR_TYPE_FIXED) {
-				bge_reg_clr32(bgep, PCI_CONF_BGE_MHCR,
-					MHCR_MASK_PCI_INT_OUTPUT);
-				if (bge_check_acc_handle(bgep,
-				    bgep->cfg_handle) != DDI_FM_OK)
-					goto chip_stop;
-			}
+		BGE_REPORT((bgep, "interrupt: flags 0x%llx - "
+		    "not updated?", flags));
+		bgep->missed_updates++;
+		bge_reg_set32(bgep, HOST_COALESCE_MODE_REG,
+		    COALESCE_NOW);
+
+		if (bgep->missed_dmas >= bge_dma_miss_limit) {
+			/*
+			 * If this happens multiple times in a row,
+			 * it means DMA is just not working.  Maybe
+			 * the chip's failed, or maybe there's a
+			 * problem on the PCI bus or in the host-PCI
+			 * bridge (Tomatillo).
+			 *
+			 * At all events, we want to stop further
+			 * interrupts and let the recovery code take
+			 * over to see whether anything can be done
+			 * about it ...
+			 */
+			bge_fm_ereport(bgep,
+			    DDI_FM_DEVICE_BADINT_LIMIT);
+			goto chip_stop;
 		}
 	}
 
+	/*
+	 * Reenable assertion of #INTA, unless there's a DMA fault
+	 */
+	if (bgep->intr_type == DDI_INTR_TYPE_FIXED) {
+		bge_reg_clr32(bgep, PCI_CONF_BGE_MHCR,
+		    MHCR_MASK_PCI_INT_OUTPUT);
+		if (bge_check_acc_handle(bgep, bgep->cfg_handle) !=
+		    DDI_FM_OK)
+			goto chip_stop;
+	}
+
 	if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK)
 		goto chip_stop;
 
--- a/usr/src/uts/common/io/bge/bge_hw.h	Tue Mar 27 22:00:10 2007 -0700
+++ b/usr/src/uts/common/io/bge/bge_hw.h	Wed Mar 28 00:46:13 2007 -0700
@@ -1065,6 +1065,9 @@
 #define	MSI_MODE_REG			0x6000
 #define	MSI_PRI_HIGHEST			0xc0000000
 #define	MSI_MSI_ENABLE			0x00000002
+#define	MSI_ERROR_ATTENTION		0x0000001c
+
+#define	MSI_STATUS_REG			0x6004
 
 #define	MODE_CONTROL_REG		0x6800
 #define	MODE_ROUTE_MCAST_TO_RX_RISC	0x40000000
--- a/usr/src/uts/common/io/bge/bge_impl.h	Tue Mar 27 22:00:10 2007 -0700
+++ b/usr/src/uts/common/io/bge/bge_impl.h	Wed Mar 28 00:46:13 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -924,6 +924,7 @@
 	 */
 	uint64_t		chip_resets;	/* # of chip RESETs	*/
 	uint64_t		missed_dmas;	/* # of missed DMAs	*/
+	uint64_t		missed_updates;	/* # of missed updates	*/
 	enum bge_mac_state	bge_mac_state;	/* definitions above	*/
 	enum bge_chip_state	bge_chip_state;	/* definitions above	*/
 	boolean_t		send_hw_tcp_csum;
@@ -1234,6 +1235,8 @@
 extern uint32_t bge_rx_count_norm;
 extern uint32_t bge_tx_count_norm;
 extern boolean_t bge_jumbo_enable;
+extern boolean_t bge_relaxed_ordering;
+
 void   bge_chip_msi_trig(bge_t *bgep);
 
 /* bge_kstats.c */
--- a/usr/src/uts/common/io/bge/bge_kstats.c	Tue Mar 27 22:00:10 2007 -0700
+++ b/usr/src/uts/common/io/bge/bge_kstats.c	Wed Mar 28 00:46:13 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -404,13 +404,14 @@
 	{ 18,				"watchdog"		},
 	{ 19,				"chip_resets"		},
 	{ 20,				"dma_misses"		},
+	{ 21,				"update_misses"		},
 
-	{ 21,				"misc_host_config"	},
-	{ 22,				"dma_rw_control"	},
-	{ 23,				"pci_bus_info"		},
+	{ 22,				"misc_host_config"	},
+	{ 23,				"dma_rw_control"	},
+	{ 24,				"pci_bus_info"		},
 
-	{ 24,				"buff_mgr_status"	},
-	{ 25,				"rcv_init_status"	},
+	{ 25,				"buff_mgr_status"	},
+	{ 26,				"rcv_init_status"	},
 
 	{ -1,				NULL 			}
 };
@@ -455,6 +456,7 @@
 	(knp++)->value.ui64 = bgep->watchdog;
 	(knp++)->value.ui64 = bgep->chip_resets;
 	(knp++)->value.ui64 = bgep->missed_dmas;
+	(knp++)->value.ui64 = bgep->missed_updates;
 
 	/*
 	 * Hold the mutex while accessing the chip registers
--- a/usr/src/uts/common/io/bge/bge_main2.c	Tue Mar 27 22:00:10 2007 -0700
+++ b/usr/src/uts/common/io/bge/bge_main2.c	Wed Mar 28 00:46:13 2007 -0700
@@ -33,7 +33,7 @@
  * This is the string displayed by modinfo, etc.
  * Make sure you keep the version ID up to date!
  */
-static char bge_ident[] = "Broadcom Gb Ethernet v0.55";
+static char bge_ident[] = "Broadcom Gb Ethernet v0.56";
 
 /*
  * Property names
@@ -1975,6 +1975,12 @@
 	txdescsize += BGE_STATUS_PADDING;
 
 	/*
+	 * Enable PCI relaxed ordering only for RX/TX data buffers
+	 */
+	if (bge_relaxed_ordering)
+		dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING;
+
+	/*
 	 * Allocate memory & handles for RX buffers
 	 */
 	ASSERT((rxbuffsize % BGE_SPLIT) == 0);
@@ -1998,6 +2004,8 @@
 			return (DDI_FAILURE);
 	}
 
+	dma_attr.dma_attr_flags &= ~DDI_DMA_RELAXED_ORDERING;
+
 	/*
 	 * Allocate memory & handles for receive return rings
 	 */