# HG changeset patch # User zh199473 # Date 1175067973 25200 # Node ID 06a70d1289cb1ae3a7366c0ee26d39e9a31a854f # Parent 6bf37835020135a1eb6c8eb6c65b08af39f24b4c 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 diff -r 6bf378350201 -r 06a70d1289cb usr/src/uts/common/io/bge/bge.conf --- 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; ######################################################################### # diff -r 6bf378350201 -r 06a70d1289cb usr/src/uts/common/io/bge/bge_chip2.c --- 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; diff -r 6bf378350201 -r 06a70d1289cb usr/src/uts/common/io/bge/bge_hw.h --- 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 diff -r 6bf378350201 -r 06a70d1289cb usr/src/uts/common/io/bge/bge_impl.h --- 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 */ diff -r 6bf378350201 -r 06a70d1289cb usr/src/uts/common/io/bge/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 diff -r 6bf378350201 -r 06a70d1289cb usr/src/uts/common/io/bge/bge_main2.c --- 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 */