Example #1
0
File: nii.c Project: baloo/ipxe
/**
 * 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;
	}
}
Example #2
0
/**
 * 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;
    }
}
Example #3
0
/**
 * 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 );
}