diff options
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r-- | usr/src/uts/common/io/igb/igb.conf | 6 | ||||
-rw-r--r-- | usr/src/uts/common/io/igb/igb_gld.c | 10 | ||||
-rw-r--r-- | usr/src/uts/common/io/igb/igb_main.c | 159 | ||||
-rw-r--r-- | usr/src/uts/common/io/igb/igb_ndd.c | 19 | ||||
-rw-r--r-- | usr/src/uts/common/io/igb/igb_rx.c | 16 | ||||
-rw-r--r-- | usr/src/uts/common/io/igb/igb_stat.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/io/igb/igb_sw.h | 4 | ||||
-rw-r--r-- | usr/src/uts/common/io/igb/igb_tx.c | 12 |
8 files changed, 189 insertions, 43 deletions
diff --git a/usr/src/uts/common/io/igb/igb.conf b/usr/src/uts/common/io/igb/igb.conf index 93860209f0..8914b31189 100644 --- a/usr/src/uts/common/io/igb/igb.conf +++ b/usr/src/uts/common/io/igb/igb.conf @@ -19,9 +19,9 @@ # CDDL HEADER END # # -# Copyright(c) 2007-2008 Intel Corporation. All rights reserved. +# Copyright(c) 2007-2009 Intel Corporation. All rights reserved. # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # @@ -133,7 +133,7 @@ # mr_enable # Enable multiple rx queues and tx queues # Allowed values: 0, 1 -# Default value: 1 +# Default value: 0 # # rx_group_number # The number of the receive ring groups diff --git a/usr/src/uts/common/io/igb/igb_gld.c b/usr/src/uts/common/io/igb/igb_gld.c index 539b1992cc..9fddd30f61 100644 --- a/usr/src/uts/common/io/igb/igb_gld.c +++ b/usr/src/uts/common/io/igb/igb_gld.c @@ -427,8 +427,10 @@ igb_m_stat(void *arg, uint_t stat, uint64_t *val) mutex_exit(&igb->gen_lock); - if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) - ddi_fm_service_impact(igb->dip, DDI_SERVICE_UNAFFECTED); + if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { + ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + return (EIO); + } return (0); } @@ -454,7 +456,7 @@ igb_m_start(void *arg) return (EIO); } - igb->igb_state |= IGB_STARTED; + atomic_or_32(&igb->igb_state, IGB_STARTED); mutex_exit(&igb->gen_lock); @@ -482,7 +484,7 @@ igb_m_stop(void *arg) return; } - igb->igb_state &= ~IGB_STARTED; + atomic_and_32(&igb->igb_state, ~IGB_STARTED); igb_stop(igb); diff --git a/usr/src/uts/common/io/igb/igb_main.c b/usr/src/uts/common/io/igb/igb_main.c index e2137ae44c..5939625e28 100644 --- a/usr/src/uts/common/io/igb/igb_main.c +++ b/usr/src/uts/common/io/igb/igb_main.c @@ -29,7 +29,7 @@ #include "igb_sw.h" static char ident[] = "Intel 1Gb Ethernet"; -static char igb_version[] = "igb 1.1.9"; +static char igb_version[] = "igb 1.1.10"; /* * Local function protoypes @@ -67,10 +67,13 @@ static int igb_get_prop(igb_t *, char *, int, int, int); static boolean_t igb_is_link_up(igb_t *); static boolean_t igb_link_check(igb_t *); static void igb_local_timer(void *); +static void igb_link_timer(void *); static void igb_arm_watchdog_timer(igb_t *); static void igb_start_watchdog_timer(igb_t *); static void igb_restart_watchdog_timer(igb_t *); static void igb_stop_watchdog_timer(igb_t *); +static void igb_start_link_timer(igb_t *); +static void igb_stop_link_timer(igb_t *); static void igb_disable_adapter_interrupts(igb_t *); static void igb_enable_adapter_interrupts_82575(igb_t *); static void igb_enable_adapter_interrupts_82576(igb_t *); @@ -507,7 +510,7 @@ igb_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) igb->attach_progress |= ATTACH_PROGRESS_ENABLE_INTR; igb_log(igb, "%s", igb_version); - igb->igb_state |= IGB_INITIALIZED; + atomic_or_32(&igb->igb_state, IGB_INITIALIZED); return (DDI_SUCCESS); @@ -575,7 +578,7 @@ igb_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) */ mutex_enter(&igb->gen_lock); if (igb->igb_state & IGB_STARTED) { - igb->igb_state &= ~IGB_STARTED; + atomic_and_32(&igb->igb_state, ~IGB_STARTED); igb_stop(igb); mutex_exit(&igb->gen_lock); /* Disable and stop the watchdog timer */ @@ -1027,6 +1030,9 @@ igb_init_locks(igb_t *igb) mutex_init(&igb->watchdog_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(igb->intr_pri)); + + mutex_init(&igb->link_lock, NULL, + MUTEX_DRIVER, DDI_INTR_PRI(igb->intr_pri)); } /* @@ -1055,6 +1061,7 @@ igb_destroy_locks(igb_t *igb) mutex_destroy(&igb->gen_lock); mutex_destroy(&igb->watchdog_lock); + mutex_destroy(&igb->link_lock); } static int @@ -1080,7 +1087,7 @@ igb_resume(dev_info_t *devinfo) igb_enable_watchdog_timer(igb); } - igb->igb_state &= ~IGB_SUSPENDED; + atomic_and_32(&igb->igb_state, ~IGB_SUSPENDED); mutex_exit(&igb->gen_lock); @@ -1098,7 +1105,7 @@ igb_suspend(dev_info_t *devinfo) mutex_enter(&igb->gen_lock); - igb->igb_state |= IGB_SUSPENDED; + atomic_or_32(&igb->igb_state, IGB_SUSPENDED); if (!(igb->igb_state & IGB_STARTED)) { mutex_exit(&igb->gen_lock); @@ -1149,6 +1156,11 @@ igb_init(igb_t *igb) for (i = igb->num_rx_rings - 1; i >= 0; i--) mutex_exit(&igb->rx_rings[i].rx_lock); + if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { + ddi_fm_service_impact(igb->dip, DDI_SERVICE_LOST); + return (IGB_FAILURE); + } + mutex_exit(&igb->gen_lock); return (IGB_SUCCESS); @@ -1325,6 +1337,11 @@ igb_init_adapter(igb_t *igb) } /* + * Start the link setup timer + */ + igb_start_link_timer(igb); + + /* * Disable wakeup control by default */ E1000_WRITE_REG(hw, E1000_WUC, 0); @@ -1394,6 +1411,9 @@ igb_stop_adapter(igb_t *igb) ASSERT(mutex_owned(&igb->gen_lock)); + /* Stop the link setup timer */ + igb_stop_link_timer(igb); + /* Tell firmware driver is no longer in control */ igb_release_driver_control(hw); @@ -1424,6 +1444,7 @@ igb_reset(igb_t *igb) mutex_enter(&igb->gen_lock); ASSERT(igb->igb_state & IGB_STARTED); + atomic_and_32(&igb->igb_state, ~IGB_STARTED); /* * Disable the adapter interrupts to stop any rx/tx activities @@ -1464,6 +1485,8 @@ igb_reset(igb_t *igb) */ igb_setup_rings(igb); + atomic_and_32(&igb->igb_state, ~(IGB_ERROR | IGB_STALL)); + /* * Enable adapter interrupts * The interrupts must be enabled after the driver state is START @@ -1481,6 +1504,8 @@ igb_reset(igb_t *igb) for (i = igb->num_rx_rings - 1; i >= 0; i--) mutex_exit(&igb->rx_rings[i].rx_lock); + atomic_or_32(&igb->igb_state, IGB_STARTED); + mutex_exit(&igb->gen_lock); return (IGB_SUCCESS); @@ -1840,9 +1865,6 @@ igb_setup_rings(igb_t *igb) igb_setup_rx(igb); igb_setup_tx(igb); - - if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) - ddi_fm_service_impact(igb->dip, DDI_SERVICE_LOST); } static void @@ -2397,9 +2419,6 @@ igb_init_unicst(igb_t *igb) igb->unicst_addr[slot].mac.group_index); } } - - if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) - ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); } /* @@ -2982,8 +3001,10 @@ igb_link_check(igb_t *igb) igb->link_state = LINK_STATE_UP; igb->link_down_timeout = 0; link_changed = B_TRUE; + if (!igb->link_complete) + igb_stop_link_timer(igb); } - } else { + } else if (igb->link_complete) { if (igb->link_state != LINK_STATE_DOWN) { igb->link_speed = 0; igb->link_duplex = 0; @@ -3002,8 +3023,10 @@ igb_link_check(igb_t *igb) } } - if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) + if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + return (B_FALSE); + } return (link_changed); } @@ -3020,17 +3043,24 @@ igb_local_timer(void *arg) igb_t *igb = (igb_t *)arg; boolean_t link_changed = B_FALSE; - if (igb_stall_check(igb)) - igb->igb_state |= IGB_STALL; + if (igb->igb_state & IGB_ERROR) { + igb->reset_count++; + if (igb_reset(igb) == IGB_SUCCESS) + ddi_fm_service_impact(igb->dip, DDI_SERVICE_RESTORED); - if (igb->igb_state & IGB_STALL) { + igb_restart_watchdog_timer(igb); + return; + } + + if (igb_stall_check(igb) || (igb->igb_state & IGB_STALL)) { igb_fm_ereport(igb, DDI_FM_DEVICE_STALL); ddi_fm_service_impact(igb->dip, DDI_SERVICE_LOST); igb->reset_count++; - igb->igb_state &= ~IGB_STALL; if (igb_reset(igb) == IGB_SUCCESS) - ddi_fm_service_impact(igb->dip, - DDI_SERVICE_RESTORED); + ddi_fm_service_impact(igb->dip, DDI_SERVICE_RESTORED); + + igb_restart_watchdog_timer(igb); + return; } mutex_enter(&igb->gen_lock); @@ -3041,13 +3071,30 @@ igb_local_timer(void *arg) if (link_changed) mac_link_update(igb->mac_hdl, igb->link_state); - if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) - ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); - igb_restart_watchdog_timer(igb); } /* + * igb_link_timer - link setup timer function + * + * It is called when the timer for link setup is expired, which indicates + * the completion of the link setup. The link state will not be updated + * until the link setup is completed. And the link state will not be sent + * to the upper layer through mac_link_update() in this function. It will + * be updated in the local timer routine or the interrupts service routine + * after the interface is started (plumbed). + */ +static void +igb_link_timer(void *arg) +{ + igb_t *igb = (igb_t *)arg; + + mutex_enter(&igb->link_lock); + igb->link_complete = B_TRUE; + igb->link_tid = 0; + mutex_exit(&igb->link_lock); +} +/* * igb_stall_check - check for transmit stall * * This function checks if the adapter is stalled (in transmit). @@ -3302,6 +3349,50 @@ igb_stop_watchdog_timer(igb_t *igb) } /* + * igb_start_link_timer - Start the link setup timer + */ +static void +igb_start_link_timer(struct igb *igb) +{ + struct e1000_hw *hw = &igb->hw; + clock_t link_timeout; + + if (hw->mac.autoneg) + link_timeout = PHY_AUTO_NEG_LIMIT * + drv_usectohz(100000); + else + link_timeout = PHY_FORCE_LIMIT * drv_usectohz(100000); + + mutex_enter(&igb->link_lock); + if (hw->phy.autoneg_wait_to_complete) { + igb->link_complete = B_TRUE; + } else { + igb->link_complete = B_FALSE; + igb->link_tid = timeout(igb_link_timer, (void *)igb, + link_timeout); + } + mutex_exit(&igb->link_lock); +} + +/* + * igb_stop_link_timer - Stop the link setup timer + */ +static void +igb_stop_link_timer(struct igb *igb) +{ + timeout_id_t tid; + + mutex_enter(&igb->link_lock); + igb->link_complete = B_TRUE; + tid = igb->link_tid; + igb->link_tid = 0; + mutex_exit(&igb->link_lock); + + if (tid != 0) + (void) untimeout(tid); +} + +/* * igb_disable_adapter_interrupts - Clear/disable all hardware interrupts */ static void @@ -3829,6 +3920,12 @@ igb_intr_legacy(void *arg1, void *arg2) link_changed = B_FALSE; icr = E1000_READ_REG(&igb->hw, E1000_ICR); + if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { + ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + atomic_or_32(&igb->igb_state, IGB_ERROR); + return (DDI_INTR_UNCLAIMED); + } + if (icr & E1000_ICR_INT_ASSERTED) { /* * E1000_ICR_INT_ASSERTED bit was set: @@ -3872,7 +3969,7 @@ igb_intr_legacy(void *arg1, void *arg2) if (icr & E1000_ICR_DRSTA) { /* 82580 Full Device Reset needed */ - igb->igb_state |= IGB_STALL; + atomic_or_32(&igb->igb_state, IGB_STALL); } result = DDI_INTR_CLAIMED; @@ -3917,6 +4014,12 @@ igb_intr_msi(void *arg1, void *arg2) icr = E1000_READ_REG(&igb->hw, E1000_ICR); + if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { + ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + atomic_or_32(&igb->igb_state, IGB_ERROR); + return (DDI_INTR_CLAIMED); + } + /* Make sure all interrupt causes cleared */ (void) E1000_READ_REG(&igb->hw, E1000_EICR); @@ -3941,7 +4044,7 @@ igb_intr_msi(void *arg1, void *arg2) if (icr & E1000_ICR_DRSTA) { /* 82580 Full Device Reset needed */ - igb->igb_state |= IGB_STALL; + atomic_or_32(&igb->igb_state, IGB_STALL); } return (DDI_INTR_CLAIMED); @@ -3999,6 +4102,12 @@ igb_intr_tx_other(void *arg1, void *arg2) icr = E1000_READ_REG(&igb->hw, E1000_ICR); + if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { + ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + atomic_or_32(&igb->igb_state, IGB_ERROR); + return (DDI_INTR_CLAIMED); + } + /* * Look for tx reclaiming work first. Remember, in the * case of only interrupt sharing, only one tx ring is @@ -4027,7 +4136,7 @@ igb_intr_tx_other(void *arg1, void *arg2) if (icr & E1000_ICR_DRSTA) { /* 82580 Full Device Reset needed */ - igb->igb_state |= IGB_STALL; + atomic_or_32(&igb->igb_state, IGB_STALL); } return (DDI_INTR_CLAIMED); diff --git a/usr/src/uts/common/io/igb/igb_ndd.c b/usr/src/uts/common/io/igb/igb_ndd.c index 58ce0e77e5..3e00a82c89 100644 --- a/usr/src/uts/common/io/igb/igb_ndd.c +++ b/usr/src/uts/common/io/igb/igb_ndd.c @@ -33,7 +33,7 @@ static int igb_nd_get(queue_t *, mblk_t *, caddr_t, cred_t *); static int igb_nd_set(queue_t *, mblk_t *, char *, caddr_t, cred_t *); static int igb_nd_param_load(igb_t *); static void igb_nd_get_param_val(nd_param_t *); -static void igb_nd_set_param_val(nd_param_t *, uint32_t); +static int igb_nd_set_param_val(nd_param_t *, uint32_t); /* * Notes: @@ -146,7 +146,8 @@ igb_nd_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *credp) if (new_value < nd->min || new_value > nd->max) return (EINVAL); - igb_nd_set_param_val(nd, new_value); + if (igb_nd_set_param_val(nd, new_value) != IGB_SUCCESS) + return (EIO); return (0); } @@ -263,16 +264,17 @@ igb_nd_get_param_val(nd_param_t *nd) /* * igb_nd_set_param_val */ -static void +static int igb_nd_set_param_val(nd_param_t *nd, uint32_t value) { igb_t *igb = (igb_t *)nd->private; + int result = IGB_SUCCESS; mutex_enter(&igb->gen_lock); if (nd->val == value) { mutex_exit(&igb->gen_lock); - return; + return (IGB_SUCCESS); } switch (nd->info) { @@ -284,16 +286,19 @@ igb_nd_set_param_val(nd_param_t *nd, uint32_t value) case PARAM_ADV_10HDX_CAP: nd->val = value; (void) igb_setup_link(igb, B_TRUE); + if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { + ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + result = IGB_FAILURE; + } break; default: break; } - if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) - ddi_fm_service_impact(igb->dip, DDI_SERVICE_UNAFFECTED); - mutex_exit(&igb->gen_lock); + + return (result); } /* diff --git a/usr/src/uts/common/io/igb/igb_rx.c b/usr/src/uts/common/io/igb/igb_rx.c index d1f6368a8d..13265e8a28 100644 --- a/usr/src/uts/common/io/igb/igb_rx.c +++ b/usr/src/uts/common/io/igb/igb_rx.c @@ -112,6 +112,8 @@ igb_rx_copy(igb_rx_ring_t *rx_ring, uint32_t index, uint32_t pkt_len) if (igb_check_dma_handle( current_rcb->rx_buf.dma_handle) != DDI_FM_OK) { ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + atomic_or_32(&igb->igb_state, IGB_ERROR); + return (NULL); } /* @@ -184,6 +186,9 @@ igb_rx_bind(igb_rx_ring_t *rx_ring, uint32_t index, uint32_t pkt_len) if (igb_check_dma_handle( current_rcb->rx_buf.dma_handle) != DDI_FM_OK) { ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + atomic_or_32(&igb->igb_state, IGB_ERROR); + atomic_inc_32(&rx_ring->rcb_free); + return (NULL); } mp = current_rcb->mp; @@ -253,8 +258,9 @@ igb_rx_ring_poll(void *arg, int bytes) ASSERT(bytes >= 0); - if (bytes == 0) - return (mp); + if ((bytes == 0) || (rx_ring->igb->igb_state & IGB_SUSPENDED) || + !(rx_ring->igb->igb_state & IGB_STARTED)) + return (NULL); mutex_enter(&rx_ring->rx_lock); mp = igb_rx(rx_ring, bytes); @@ -290,6 +296,9 @@ igb_rx(igb_rx_ring_t *rx_ring, int poll_bytes) mblk_head = NULL; mblk_tail = &mblk_head; + if (igb->igb_state & IGB_ERROR) + return (NULL); + /* * Sync the receive descriptors before * accepting the packets @@ -299,6 +308,8 @@ igb_rx(igb_rx_ring_t *rx_ring, int poll_bytes) if (igb_check_dma_handle( rx_ring->rbd_area.dma_handle) != DDI_FM_OK) { ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + atomic_or_32(&igb->igb_state, IGB_ERROR); + return (NULL); } /* @@ -401,6 +412,7 @@ rx_discard: if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + atomic_or_32(&igb->igb_state, IGB_ERROR); } return (mblk_head); diff --git a/usr/src/uts/common/io/igb/igb_stat.c b/usr/src/uts/common/io/igb/igb_stat.c index a16d8bec3f..8edc4dbeed 100644 --- a/usr/src/uts/common/io/igb/igb_stat.c +++ b/usr/src/uts/common/io/igb/igb_stat.c @@ -136,8 +136,10 @@ igb_update_stats(kstat_t *ks, int rw) mutex_exit(&igb->gen_lock); - if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) - ddi_fm_service_impact(igb->dip, DDI_SERVICE_UNAFFECTED); + if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { + ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + return (EIO); + } return (0); } diff --git a/usr/src/uts/common/io/igb/igb_sw.h b/usr/src/uts/common/io/igb/igb_sw.h index 5744f148f0..483f3342b2 100644 --- a/usr/src/uts/common/io/igb/igb_sw.h +++ b/usr/src/uts/common/io/igb/igb_sw.h @@ -82,6 +82,7 @@ extern "C" { #define IGB_STARTED 0x02 #define IGB_SUSPENDED 0x04 #define IGB_STALL 0x08 +#define IGB_ERROR 0x80 #define IGB_INTR_NONE 0 #define IGB_INTR_MSIX 1 @@ -662,6 +663,8 @@ typedef struct igb { uint32_t link_speed; uint32_t link_duplex; uint32_t link_down_timeout; + boolean_t link_complete; + timeout_id_t link_tid; uint32_t reset_count; uint32_t attach_progress; @@ -715,6 +718,7 @@ typedef struct igb { kmutex_t gen_lock; /* General lock for device access */ kmutex_t watchdog_lock; + kmutex_t link_lock; boolean_t watchdog_enable; boolean_t watchdog_start; diff --git a/usr/src/uts/common/io/igb/igb_tx.c b/usr/src/uts/common/io/igb/igb_tx.c index a24010cd30..54bde3d330 100644 --- a/usr/src/uts/common/io/igb/igb_tx.c +++ b/usr/src/uts/common/io/igb/igb_tx.c @@ -56,6 +56,13 @@ igb_tx_ring_send(void *arg, mblk_t *mp) ASSERT(tx_ring != NULL); + if ((tx_ring->igb->igb_state & IGB_SUSPENDED) || + (tx_ring->igb->igb_state & IGB_ERROR) || + !(tx_ring->igb->igb_state & IGB_STARTED)) { + freemsg(mp); + return (NULL); + } + return ((igb_tx(tx_ring, mp)) ? NULL : mp); } @@ -1013,6 +1020,7 @@ igb_tx_fill_ring(igb_tx_ring_t *tx_ring, link_list_t *pending_list, if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) { ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + atomic_or_32(&igb->igb_state, IGB_ERROR); } return (desc_num); @@ -1081,6 +1089,8 @@ igb_tx_recycle_legacy(igb_tx_ring_t *tx_ring) if (igb_check_dma_handle( tx_ring->tbd_area.dma_handle) != DDI_FM_OK) { ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + atomic_or_32(&igb->igb_state, IGB_ERROR); + return (0); } LINK_LIST_INIT(&pending_list); @@ -1227,6 +1237,8 @@ igb_tx_recycle_head_wb(igb_tx_ring_t *tx_ring) if (igb_check_dma_handle( tx_ring->tbd_area.dma_handle) != DDI_FM_OK) { ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED); + atomic_or_32(&igb->igb_state, IGB_ERROR); + return (0); } LINK_LIST_INIT(&pending_list); |