Allocate receive and transmit data structures during attach() and free them

during detach() similar to other NIC drivers rather than allocating them
during init() and freeing them during stop():
- Move creation of tx bus_dma tag amd maps and tx_buffer_area from
  em_setup_transmit_structures() to em_allocate_transmit_structures().
- Call em_allocate_xxx_structures() in em_attach().
- Only call em_free_xxx_structures() in em_detach().
- Change em_setup_xxx_structures() to free any existing tx or rx buffers
  and in the case of rx repopulate the ring with newer buffers.

Reviewed by:	jfv
This commit is contained in:
jhb 2006-10-31 17:21:14 +00:00
parent 9f9db205d0
commit 624b4884d8

View File

@ -219,7 +219,7 @@ static void em_free_pci_resources(struct adapter *);
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 *);
@ -556,6 +556,20 @@ em_attach(device_t dev)
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);
@ -583,6 +597,9 @@ em_attach(device_t dev)
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:
@ -634,6 +651,9 @@ em_detach(device_t dev)
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);
@ -1089,11 +1109,7 @@ em_init_locked(struct adapter *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 */
@ -2088,8 +2104,6 @@ em_stop(void *arg)
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);
@ -2599,26 +2613,6 @@ em_dma_free(struct adapter *adapter, struct em_dma_alloc *dma)
**********************************************************************/
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)
{
struct ifnet *ifp = adapter->ifp;
device_t dev = adapter->dev;
@ -2653,10 +2647,14 @@ em_setup_transmit_structures(struct adapter *adapter)
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);
@ -2667,9 +2665,41 @@ em_setup_transmit_structures(struct adapter *adapter)
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->next_tx_to_clean = 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;
@ -2677,12 +2707,6 @@ em_setup_transmit_structures(struct adapter *adapter)
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);
}
/*********************************************************************
@ -3310,14 +3334,6 @@ em_allocate_receive_structures(struct adapter *adapter)
}
}
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:
@ -3333,15 +3349,34 @@ fail:
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);
}