/** * Close network device * * @v netdev Network device */ static void snpnet_close ( struct net_device *netdev ) { struct snp_nic *snp = netdev->priv; EFI_STATUS efirc; int rc; /* Shut down NIC */ if ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) { rc = -EEFI ( efirc ); DBGC ( snp, "SNP %s could not shut down: %s\n", netdev->name, strerror ( rc ) ); /* Nothing we can do about this */ } /* Discard transmit buffer, if applicable */ if ( snp->txbuf ) { netdev_tx_complete_err ( netdev, snp->txbuf, -ECANCELED ); snp->txbuf = NULL; } /* Discard receive buffer, if applicable */ if ( snp->rxbuf ) { free_iob ( snp->rxbuf ); snp->rxbuf = NULL; } }
/* * vxge_xmit_compl * * If an interrupt was raised to indicate DMA complete of the Tx packet, * this function is called. It identifies the last TxD whose buffer was * freed and frees all skbs whose data have already DMA'ed into the NICs * internal memory. */ enum vxge_hw_status vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, struct vxge_hw_fifo_txd *txdp, enum vxge_hw_fifo_tcode tcode) { struct net_device *netdev; struct io_buffer *tx_iob = NULL; vxge_trace(); netdev = fifo_hw->vpathh->hldev->ndev; tx_iob = (struct io_buffer *)(intptr_t)txdp->host_control; if (tcode == VXGE_HW_FIFO_T_CODE_OK) { netdev_tx_complete(netdev, tx_iob); } else { netdev_tx_complete_err(netdev, tx_iob, -EINVAL); vxge_debug(VXGE_ERR, "%s: transmit failed, tcode %d\n", netdev->name, tcode); } memset(txdp, 0, sizeof(struct vxge_hw_fifo_txd)); return VXGE_HW_OK; }
/** * Poll for completed packets * * @v netdev Network device */ static void netfront_poll_tx ( struct net_device *netdev ) { struct netfront_nic *netfront = netdev->priv; struct xen_device *xendev = netfront->xendev; struct netif_tx_response *response; struct io_buffer *iobuf; unsigned int status; int rc; /* Consume any unconsumed responses */ while ( RING_HAS_UNCONSUMED_RESPONSES ( &netfront->tx_fring ) ) { /* Get next response */ response = RING_GET_RESPONSE ( &netfront->tx_fring, netfront->tx_fring.rsp_cons++ ); /* Retrieve from descriptor ring */ iobuf = netfront_pull ( netfront, &netfront->tx, response->id ); status = response->status; if ( status == NETIF_RSP_OKAY ) { DBGC2 ( netfront, "NETFRONT %s TX id %d complete\n", xendev->key, response->id ); netdev_tx_complete ( netdev, iobuf ); } else { rc = -EIO_NETIF_RSP ( status ); DBGC2 ( netfront, "NETFRONT %s TX id %d error %d: %s\n", xendev->key, response->id, status, strerror ( rc ) ); netdev_tx_complete_err ( netdev, iobuf, rc ); } } }
/** * Complete bulk OUT transfer * * @v ep USB endpoint * @v iobuf I/O buffer * @v rc Completion status code */ static void smsc95xx_out_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf, int rc ) { struct smsc95xx_device *smsc95xx = container_of ( ep, struct smsc95xx_device, usbnet.out ); struct net_device *netdev = smsc95xx->netdev; /* Report TX completion */ netdev_tx_complete_err ( netdev, iobuf, rc ); }
/** * e1000_process_tx_packets - process transmitted packets * * @v netdev network interface device structure **/ static void e1000e_process_tx_packets ( struct net_device *netdev ) { struct e1000_adapter *adapter = netdev_priv ( netdev ); uint32_t i; uint32_t tx_status; struct e1000_tx_desc *tx_curr_desc; /* Check status of transmitted packets */ DBG ( "process_tx_packets: tx_head = %d, tx_tail = %d\n", adapter->tx_head, adapter->tx_tail ); while ( ( i = adapter->tx_head ) != adapter->tx_tail ) { tx_curr_desc = ( void * ) ( adapter->tx_base ) + ( i * sizeof ( *adapter->tx_base ) ); tx_status = tx_curr_desc->upper.data; DBG ( " tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) ); DBG ( " tx_status = %#08x\n", tx_status ); /* if the packet at tx_head is not owned by hardware it is for us */ if ( ! ( tx_status & E1000_TXD_STAT_DD ) ) break; DBG ( "Sent packet. tx_head: %d tx_tail: %d tx_status: %#08x\n", adapter->tx_head, adapter->tx_tail, tx_status ); if ( tx_status & ( E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU ) ) { netdev_tx_complete_err ( netdev, adapter->tx_iobuf[i], -EINVAL ); DBG ( "Error transmitting packet, tx_status: %#08x\n", tx_status ); } else { netdev_tx_complete ( netdev, adapter->tx_iobuf[i] ); DBG ( "Success transmitting packet, tx_status: %#08x\n", tx_status ); } /* Decrement count of used descriptors, clear this descriptor */ adapter->tx_fill_ctr--; memset ( tx_curr_desc, 0, sizeof ( *tx_curr_desc ) ); adapter->tx_head = ( adapter->tx_head + 1 ) % NUM_TX_DESC; } }
/** * Close network device * * @v netdev Network device */ static void nii_close ( struct net_device *netdev ) { struct nii_nic *nii = netdev->priv; /* Shut down NIC */ nii_shutdown ( nii ); /* Discard transmit buffer, if applicable */ if ( nii->txbuf ) { netdev_tx_complete_err ( netdev, nii->txbuf, -ECANCELED ); nii->txbuf = NULL; } /* Discard receive buffer, if applicable */ if ( nii->rxbuf ) { free_iob ( nii->rxbuf ); nii->rxbuf = NULL; } }
/** * e1000_poll - Poll for received packets * * @v netdev Network device */ static void e1000_poll ( struct net_device *netdev ) { struct e1000_adapter *adapter = netdev_priv( netdev ); struct e1000_hw *hw = &adapter->hw; uint32_t icr; uint32_t tx_status; uint32_t rx_status; uint32_t rx_len; uint32_t rx_err; struct e1000_tx_desc *tx_curr_desc; struct e1000_rx_desc *rx_curr_desc; uint32_t i; DBGP ( "e1000_poll\n" ); /* Acknowledge interrupts */ icr = E1000_READ_REG ( hw, ICR ); if ( ! icr ) return; DBG ( "e1000_poll: intr_status = %#08x\n", icr ); /* Check status of transmitted packets */ while ( ( i = adapter->tx_head ) != adapter->tx_tail ) { tx_curr_desc = ( void * ) ( adapter->tx_base ) + ( i * sizeof ( *adapter->tx_base ) ); tx_status = tx_curr_desc->upper.data; /* if the packet at tx_head is not owned by hardware it is for us */ if ( ! ( tx_status & E1000_TXD_STAT_DD ) ) break; DBG ( "Sent packet. tx_head: %d tx_tail: %d tx_status: %#08x\n", adapter->tx_head, adapter->tx_tail, tx_status ); if ( tx_status & ( E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU ) ) { netdev_tx_complete_err ( netdev, adapter->tx_iobuf[i], -EINVAL ); DBG ( "Error transmitting packet, tx_status: %#08x\n", tx_status ); } else { netdev_tx_complete ( netdev, adapter->tx_iobuf[i] ); DBG ( "Success transmitting packet, tx_status: %#08x\n", tx_status ); } /* Decrement count of used descriptors, clear this descriptor */ adapter->tx_fill_ctr--; memset ( tx_curr_desc, 0, sizeof ( *tx_curr_desc ) ); adapter->tx_head = ( adapter->tx_head + 1 ) % NUM_TX_DESC; } /* Process received packets */ while ( 1 ) { i = adapter->rx_curr; rx_curr_desc = ( void * ) ( adapter->rx_base ) + ( i * sizeof ( *adapter->rx_base ) ); rx_status = rx_curr_desc->status; DBG2 ( "Before DD Check RX_status: %#08x\n", rx_status ); if ( ! ( rx_status & E1000_RXD_STAT_DD ) ) break; if ( adapter->rx_iobuf[i] == NULL ) break; DBG ( "RCTL = %#08x\n", E1000_READ_REG ( &adapter->hw, RCTL ) ); rx_len = rx_curr_desc->length; DBG ( "Received packet, rx_curr: %d rx_status: %#08x rx_len: %d\n", i, rx_status, rx_len ); rx_err = rx_curr_desc->errors; iob_put ( adapter->rx_iobuf[i], rx_len ); if ( rx_err & E1000_RXD_ERR_FRAME_ERR_MASK ) { netdev_rx_err ( netdev, adapter->rx_iobuf[i], -EINVAL ); DBG ( "e1000_poll: Corrupted packet received!" " rx_err: %#08x\n", rx_err ); } else { /* Add this packet to the receive queue. */ netdev_rx ( netdev, adapter->rx_iobuf[i] ); } adapter->rx_iobuf[i] = NULL; memset ( rx_curr_desc, 0, sizeof ( *rx_curr_desc ) ); adapter->rx_curr = ( adapter->rx_curr + 1 ) % NUM_RX_DESC; } e1000_refill_rx_ring(adapter); }