/** * Poll for received packets * * @v netdev Network device */ static void nii_poll_rx ( struct net_device *netdev ) { struct nii_nic *nii = netdev->priv; PXE_CPB_RECEIVE cpb; PXE_DB_RECEIVE db; unsigned int quota; int stat; int rc; /* Retrieve up to NII_RX_QUOTA packets */ for ( quota = NII_RX_QUOTA ; quota ; quota-- ) { /* Allocate buffer, if required */ if ( ! nii->rxbuf ) { nii->rxbuf = alloc_iob ( nii->mtu ); if ( ! nii->rxbuf ) { /* Leave for next poll */ break; } } /* Construct parameter block */ memset ( &cpb, 0, sizeof ( cpb ) ); cpb.BufferAddr = virt_to_bus ( nii->rxbuf->data ); cpb.BufferLen = iob_tailroom ( nii->rxbuf ); /* Issue command */ if ( ( stat = nii_issue_cpb_db ( nii, PXE_OPCODE_RECEIVE, &cpb, sizeof ( cpb ), &db, sizeof ( db ) ) ) < 0 ) { /* PXE_STATCODE_NO_DATA is just the usual "no packet" * status indicator; ignore it. */ if ( stat == -PXE_STATCODE_NO_DATA ) break; /* Anything else is an error */ rc = -EIO_STAT ( stat ); DBGC ( nii, "NII %s could not receive: %s\n", nii->dev.name, strerror ( rc ) ); netdev_rx_err ( netdev, NULL, rc ); break; } /* Hand off to network stack */ iob_put ( nii->rxbuf, db.FrameLen ); netdev_rx ( netdev, nii->rxbuf ); nii->rxbuf = NULL; } }
/** * Poll for received packets * * @v netdev Network device */ static void snpnet_poll_rx ( struct net_device *netdev ) { struct snp_nic *snp = netdev->priv; UINTN len; unsigned int quota; EFI_STATUS efirc; int rc; /* Retrieve up to SNP_RX_QUOTA packets */ for ( quota = SNP_RX_QUOTA ; quota ; quota-- ) { /* Allocate buffer, if required */ if ( ! snp->rxbuf ) { snp->rxbuf = alloc_iob ( snp->mtu ); if ( ! snp->rxbuf ) { /* Leave for next poll */ break; } } /* Receive packet */ len = iob_tailroom ( snp->rxbuf ); if ( ( efirc = snp->snp->Receive ( snp->snp, NULL, &len, snp->rxbuf->data, NULL, NULL, NULL ) ) != 0 ) { /* EFI_NOT_READY is just the usual "no packet" * status indication; ignore it. */ if ( efirc == EFI_NOT_READY ) break; /* Anything else is an error */ rc = -EEFI ( efirc ); DBGC ( snp, "SNP %s could not receive: %s\n", netdev->name, strerror ( rc ) ); netdev_rx_err ( netdev, NULL, rc ); break; } /* Hand off to network stack */ iob_put ( snp->rxbuf, len ); netdev_rx ( netdev, snp->rxbuf ); snp->rxbuf = NULL; } }
/** * Refill receive descriptor ring * * @v netdev Network device */ static void netfront_refill_rx ( struct net_device *netdev ) { struct netfront_nic *netfront = netdev->priv; struct xen_device *xendev = netfront->xendev; struct io_buffer *iobuf; struct netif_rx_request *request; int notify; int rc; /* Do nothing if ring is already full */ if ( netfront_ring_is_full ( &netfront->rx ) ) return; /* Refill ring */ do { /* Allocate I/O buffer */ iobuf = alloc_iob ( PAGE_SIZE ); if ( ! iobuf ) { /* Wait for next refill */ break; } /* Add to descriptor ring */ request = RING_GET_REQUEST ( &netfront->rx_fring, netfront->rx_fring.req_prod_pvt ); if ( ( rc = netfront_push ( netfront, &netfront->rx, iobuf, &request->id, &request->gref ) ) != 0 ) { netdev_rx_err ( netdev, iobuf, rc ); break; } DBGC2 ( netfront, "NETFRONT %s RX id %d ref %d is %#08lx+%zx\n", xendev->key, request->id, request->gref, virt_to_phys ( iobuf->data ), iob_tailroom ( iobuf ) ); /* Move to next descriptor */ netfront->rx_fring.req_prod_pvt++; } while ( ! netfront_ring_is_full ( &netfront->rx ) ); /* Push new descriptors and notify backend if applicable */ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY ( &netfront->rx_fring, notify ); if ( notify ) netfront_send_event ( netfront ); }