--- //depot/yahoo/ybsd_6/src/sys/dev/em/if_em.c 2006/09/26 14:59:47 +++ //depot/jhb/bsd6/src/sys/dev/em/if_em.c 2006/10/30 09:54:13 @@ -211,7 +211,7 @@ static void em_local_timer(void *); static int em_hardware_init(struct adapter *); static void em_setup_interface(device_t, struct adapter *); -static int em_setup_transmit_structures(struct adapter *); +static void em_setup_transmit_structures(struct adapter *); static void em_initialize_transmit_unit(struct adapter *); static int em_setup_receive_structures(struct adapter *); static void em_initialize_receive_unit(struct adapter *); @@ -245,7 +245,6 @@ static void em_82547_update_fifo_head(struct adapter *, int); static int em_82547_tx_fifo_reset(struct adapter *); static void em_82547_move_tail(void *arg); -static void em_82547_move_tail_locked(struct adapter *); static int em_dma_malloc(struct adapter *, bus_size_t, struct em_dma_alloc *, int); static void em_dma_free(struct adapter *, struct em_dma_alloc *); @@ -416,8 +415,8 @@ OID_AUTO, "stats", CTLTYPE_INT|CTLFLAG_RW, adapter, 0, em_sysctl_stats, "I", "Statistics"); - callout_init(&adapter->timer, CALLOUT_MPSAFE); - callout_init(&adapter->tx_fifo_timer, CALLOUT_MPSAFE); + callout_init_mtx(&adapter->timer, &adapter->mtx, 0); + callout_init_mtx(&adapter->tx_fifo_timer, &adapter->mtx, 0); /* Determine hardware revision */ em_identify_hardware(adapter); @@ -552,6 +551,20 @@ goto err_hw_init; } + /* Allocate transmit descriptors and buffers */ + if (em_allocate_transmit_structures(adapter)) { + device_printf(dev, "Could not setup transmit structures\n"); + error = ENOMEM; + goto err_tx_struct; + } + + /* Allocate receive descriptors and buffers */ + if (em_allocate_receive_structures(adapter)) { + device_printf(dev, "Could not setup receive structures\n"); + error = ENOMEM; + goto err_rx_struct; + } + /* Setup OS specific network interface */ em_setup_interface(dev, adapter); @@ -579,6 +592,9 @@ return (0); +err_rx_struct: + em_free_transmit_structures(adapter); +err_tx_struct: err_hw_init: em_dma_free(adapter, &adapter->rxdma); err_rx_desc: @@ -623,10 +639,16 @@ EM_UNLOCK(adapter); ether_ifdetach(adapter->ifp); + callout_drain(&adapter->timer); + callout_drain(&adapter->tx_fifo_timer); + em_free_pci_resources(adapter); bus_generic_detach(dev); if_free(ifp); + em_free_transmit_structures(adapter); + em_free_receive_structures(adapter); + /* Free Transmit Descriptor ring */ if (adapter->tx_desc_base) { em_dma_free(adapter, &adapter->txdma); @@ -1044,11 +1066,7 @@ em_enable_vlans(adapter); /* Prepare transmit descriptors and buffers */ - if (em_setup_transmit_structures(adapter)) { - device_printf(dev, "Could not setup transmit structures\n"); - em_stop(adapter); - return; - } + em_setup_transmit_structures(adapter); em_initialize_transmit_unit(adapter); /* Setup Multicast table */ @@ -1213,6 +1231,10 @@ ifp = adapter->ifp; EM_LOCK(adapter); + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + EM_UNLOCK(adapter); + return; + } callout_stop(&adapter->timer); adapter->hw.get_link_status = 1; @@ -1239,14 +1261,20 @@ if (em_rxeof(adapter, adapter->rx_process_limit) != 0) taskqueue_enqueue(adapter->tq, &adapter->rxtx_task); EM_LOCK(adapter); + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + EM_UNLOCK(adapter); + goto out; + } em_txeof(adapter); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) em_start_locked(ifp); + + em_enable_intr(adapter); EM_UNLOCK(adapter); } - em_enable_intr(adapter); +out: NET_UNLOCK_GIANT(); } @@ -1625,7 +1653,7 @@ bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); if (adapter->hw.mac_type == em_82547 && adapter->link_duplex == HALF_DUPLEX) - em_82547_move_tail_locked(adapter); + em_82547_move_tail(adapter); else { E1000_WRITE_REG(&adapter->hw, TDT, i); if (adapter->hw.mac_type == em_82547) @@ -1644,8 +1672,9 @@ * **********************************************************************/ static void -em_82547_move_tail_locked(struct adapter *adapter) +em_82547_move_tail(void *arg) { + struct adapter *adapter = arg; uint16_t hw_tdt; uint16_t sw_tdt; struct em_tx_desc *tx_desc; @@ -1678,16 +1707,6 @@ } } -static void -em_82547_move_tail(void *arg) -{ - struct adapter *adapter = arg; - - EM_LOCK(adapter); - em_82547_move_tail_locked(adapter); - EM_UNLOCK(adapter); -} - static int em_82547_fifo_workaround(struct adapter *adapter, int len) { @@ -1873,7 +1892,7 @@ struct adapter *adapter = arg; struct ifnet *ifp = adapter->ifp; - EM_LOCK(adapter); + EM_LOCK_ASSERT(adapter); em_check_for_link(&adapter->hw); em_update_link_status(adapter); @@ -1883,8 +1902,6 @@ em_smartspeed(adapter); callout_reset(&adapter->timer, hz, em_local_timer, adapter); - - EM_UNLOCK(adapter); } static void @@ -1947,14 +1964,19 @@ INIT_DEBUGOUT("em_stop: begin"); em_disable_intr(adapter); - em_reset_hw(&adapter->hw); callout_stop(&adapter->timer); callout_stop(&adapter->tx_fifo_timer); - em_free_transmit_structures(adapter); - em_free_receive_structures(adapter); /* Tell the stack that the interface is no longer active */ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + + /* Unlock so that the defered contexts can drain without blocking */ + EM_UNLOCK(adapter); + taskqueue_drain(adapter->tq, &adapter->rxtx_task); + taskqueue_drain(taskqueue_fast, &adapter->link_task); + + EM_LOCK(adapter); + em_reset_hw(&adapter->hw); } @@ -2469,26 +2491,6 @@ static int em_allocate_transmit_structures(struct adapter *adapter) { - adapter->tx_buffer_area = malloc(sizeof(struct em_buffer) * - adapter->num_tx_desc, M_DEVBUF, M_NOWAIT); - if (adapter->tx_buffer_area == NULL) { - device_printf(adapter->dev, "Unable to allocate tx_buffer memory\n"); - return (ENOMEM); - } - - bzero(adapter->tx_buffer_area, sizeof(struct em_buffer) * adapter->num_tx_desc); - - return (0); -} - -/********************************************************************* - * - * Allocate and initialize transmit structures. - * - **********************************************************************/ -static int -em_setup_transmit_structures(struct adapter *adapter) -{ device_t dev = adapter->dev; struct em_buffer *tx_buffer; bus_size_t size; @@ -2514,10 +2516,14 @@ goto fail; } - if ((error = em_allocate_transmit_structures(adapter)) != 0) + adapter->tx_buffer_area = malloc(sizeof(struct em_buffer) * + adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO); + if (adapter->tx_buffer_area == NULL) { + device_printf(dev, "Unable to allocate tx_buffer memory\n"); + error = ENOMEM; goto fail; + } - bzero(adapter->tx_desc_base, (sizeof(struct em_tx_desc)) * adapter->num_tx_desc); tx_buffer = adapter->tx_buffer_area; for (i = 0; i < adapter->num_tx_desc; i++) { error = bus_dmamap_create(adapter->txtag, 0, &tx_buffer->map); @@ -2528,9 +2534,41 @@ tx_buffer++; } + return (0); + +fail: + em_free_transmit_structures(adapter); + return (error); +} + +/********************************************************************* + * + * Initialize transmit structures. + * + **********************************************************************/ +static void +em_setup_transmit_structures(struct adapter *adapter) +{ + struct em_buffer *tx_buffer; + int i; + + bzero(adapter->tx_desc_base, (sizeof(struct em_tx_desc)) * adapter->num_tx_desc); + adapter->next_avail_tx_desc = 0; adapter->oldest_used_tx_desc = 0; + /* Free any existing tx buffers. */ + tx_buffer = adapter->tx_buffer_area; + for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) { + if (tx_buffer->m_head != NULL) { + bus_dmamap_sync(adapter->txtag, tx_buffer->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(adapter->txtag, tx_buffer->map); + m_freem(tx_buffer->m_head); + tx_buffer->m_head = NULL; + } + } + /* Set number of descriptors available */ adapter->num_tx_desc_avail = adapter->num_tx_desc; @@ -2538,12 +2576,6 @@ adapter->active_checksum_context = OFFLOAD_NONE; bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - - return (0); - -fail: - em_free_transmit_structures(adapter); - return (error); } /********************************************************************* @@ -2946,14 +2978,6 @@ } } - for (i = 0; i < adapter->num_rx_desc; i++) { - error = em_get_buf(adapter, i); - if (error) - goto fail; - } - bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - return (0); fail: @@ -2969,15 +2993,34 @@ static int em_setup_receive_structures(struct adapter *adapter) { - int error; + struct em_buffer *rx_buffer; + int i, error; bzero(adapter->rx_desc_base, (sizeof(struct em_rx_desc)) * adapter->num_rx_desc); - if ((error = em_allocate_receive_structures(adapter)) != 0) - return (error); + /* Free current RX buffers. */ + rx_buffer = adapter->rx_buffer_area; + for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) { + if (rx_buffer->m_head != NULL) { + bus_dmamap_sync(adapter->rxtag, rx_buffer->map, + BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(adapter->rxtag, rx_buffer->map); + m_freem(rx_buffer->m_head); + rx_buffer->m_head = NULL; + } + } + + /* Allocate new ones. */ + for (i = 0; i < adapter->num_rx_desc; i++) { + error = em_get_buf(adapter, i); + if (error) + return (error); + } /* Setup our descriptor pointers */ adapter->next_rx_desc_to_check = 0; + bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); return (0); }