/** * Poll for completed and received packets * * @v netdev Network device */ static void intelxvf_poll ( struct net_device *netdev ) { struct intel_nic *intel = netdev->priv; uint32_t eicr; int rc; /* Check for and acknowledge interrupts */ eicr = readl ( intel->regs + INTELXVF_EICR ); if ( ! eicr ) return; /* Poll for TX completions, if applicable */ if ( eicr & INTELXVF_EIRQ_TX0 ) intel_poll_tx ( netdev ); /* Poll for RX completions, if applicable */ if ( eicr & INTELXVF_EIRQ_RX0 ) intel_poll_rx ( netdev ); /* Poll for mailbox messages, if applicable */ if ( eicr & INTELXVF_EIRQ_MBOX ) { /* Poll mailbox */ if ( ( rc = intelvf_mbox_poll ( intel ) ) != 0 ) { DBGC ( intel, "INTEL %p mailbox poll failed!\n", intel ); netdev_rx_err ( netdev, NULL, rc ); } /* Update link state */ intelxvf_check_link ( netdev ); } /* Refill RX ring */ intel_refill_rx ( intel ); }
/** * Poll for completed and received packets * * @v netdev Network device */ static void intelx_poll ( struct net_device *netdev ) { struct intel_nic *intel = netdev->priv; uint32_t eicr; /* Check for and acknowledge interrupts */ eicr = readl ( intel->regs + INTELX_EICR ); if ( ! eicr ) return; /* Poll for TX completions, if applicable */ if ( eicr & INTELX_EIRQ_TX0 ) intel_poll_tx ( netdev ); /* Poll for RX completions, if applicable */ if ( eicr & ( INTELX_EIRQ_RX0 | INTELX_EIRQ_RXO ) ) intel_poll_rx ( netdev ); /* Report receive overruns */ if ( eicr & INTELX_EIRQ_RXO ) netdev_rx_err ( netdev, NULL, -ENOBUFS ); /* Check link state, if applicable */ if ( eicr & INTELX_EIRQ_LSC ) intelx_check_link ( netdev ); /* Refill RX ring */ intel_refill_rx ( intel ); }
/** * Open network device * * @v netdev Network device * @ret rc Return status code */ static int intelxvf_open ( struct net_device *netdev ) { struct intel_nic *intel = netdev->priv; uint32_t rxdctl; uint32_t srrctl; uint32_t dca_rxctrl; unsigned int i; int vlan_thing; int rc; /* Reset the function */ intelxvf_reset ( intel ); /* Notify PF that reset is complete */ if ( ( rc = intelvf_mbox_reset ( intel, NULL ) ) != 0 ) { DBGC ( intel, "INTEL %p could not reset: %s\n", intel, strerror ( rc ) ); goto err_mbox_reset; } /* Negotiate API version 1.1. If we do not negotiate at least * this version, then the RX datapath will remain disabled if * the PF has jumbo frames enabled. * * Ignore failures, since the host may not actually support * v1.1. */ intelxvf_mbox_version ( intel, INTELXVF_MSG_VERSION_1_1 ); /* Set MAC address */ if ( ( rc = intelvf_mbox_set_mac ( intel, netdev->ll_addr ) ) != 0 ) { DBGC ( intel, "INTEL %p could not set MAC address: %s\n", intel, strerror ( rc ) ); goto err_mbox_set_mac; } /* Set MTU */ if ( ( rc = intelvf_mbox_set_mtu ( intel, netdev->max_pkt_len ) ) != 0){ DBGC ( intel, "INTEL %p could not set MTU %zd: %s\n", intel, netdev->max_pkt_len, strerror ( rc ) ); goto err_mbox_set_mtu; } /* Reset all descriptor rings */ for ( i = 0 ; i < INTELXVF_NUM_RINGS ; i++ ) { intel_reset_ring ( intel, INTELXVF_TD ( i ) ); intel_reset_ring ( intel, INTELXVF_RD ( i ) ); } /* Reset packet split receive type register */ writel ( 0, intel->regs + INTELXVF_PSRTYPE ); /* Get queue configuration. Ignore failures, since the host * may not support this message. */ vlan_thing = 0; intelxvf_mbox_queues ( intel, &vlan_thing ); if ( vlan_thing ) { DBGC ( intel, "INTEL %p stripping VLAN tags (thing=%d)\n", intel, vlan_thing ); rxdctl = readl ( intel->regs + INTELXVF_RD(0) + INTEL_xDCTL ); rxdctl |= INTELX_RXDCTL_VME; writel ( rxdctl, intel->regs + INTELXVF_RD(0) + INTEL_xDCTL ); } /* Create transmit descriptor ring */ if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 ) goto err_create_tx; /* Create receive descriptor ring */ if ( ( rc = intel_create_ring ( intel, &intel->rx ) ) != 0 ) goto err_create_rx; /* Allocate interrupt vectors */ writel ( ( INTELXVF_IVAR_RX0_DEFAULT | INTELXVF_IVAR_RX0_VALID | INTELXVF_IVAR_TX0_DEFAULT | INTELXVF_IVAR_TX0_VALID ), intel->regs + INTELXVF_IVAR ); writel ( ( INTELXVF_IVARM_MBOX_DEFAULT | INTELXVF_IVARM_MBOX_VALID ), intel->regs + INTELXVF_IVARM ); /* Configure receive buffer sizes and set receive descriptor type */ srrctl = readl ( intel->regs + INTELXVF_SRRCTL ); srrctl &= ~( INTELXVF_SRRCTL_BSIZE_MASK | INTELXVF_SRRCTL_BHDRSIZE_MASK | INTELXVF_SRRCTL_DESCTYPE_MASK ); srrctl |= ( INTELXVF_SRRCTL_BSIZE_DEFAULT | INTELXVF_SRRCTL_BHDRSIZE_DEFAULT | INTELXVF_SRRCTL_DESCTYPE_DEFAULT | INTELXVF_SRRCTL_DROP_EN ); writel ( srrctl, intel->regs + INTELXVF_SRRCTL ); /* Clear "must-be-zero" bit for direct cache access (DCA). We * leave DCA disabled anyway, but if we do not clear this bit * then the received packets contain garbage data. */ dca_rxctrl = readl ( intel->regs + INTELXVF_DCA_RXCTRL ); dca_rxctrl &= ~INTELXVF_DCA_RXCTRL_MUST_BE_ZERO; writel ( dca_rxctrl, intel->regs + INTELXVF_DCA_RXCTRL ); /* Fill receive ring */ intel_refill_rx ( intel ); /* Update link state */ intelxvf_check_link ( netdev ); return 0; intel_destroy_ring ( intel, &intel->rx ); err_create_rx: intel_destroy_ring ( intel, &intel->tx ); err_create_tx: err_mbox_set_mtu: err_mbox_set_mac: err_mbox_reset: intelxvf_reset ( intel ); return rc; }
/** * Open network device * * @v netdev Network device * @ret rc Return status code */ static int intelx_open ( struct net_device *netdev ) { struct intel_nic *intel = netdev->priv; union intel_receive_address mac; uint32_t ral0; uint32_t rah0; uint32_t dmatxctl; uint32_t fctrl; uint32_t srrctl; uint32_t hlreg0; uint32_t maxfrs; uint32_t rdrxctl; uint32_t rxctrl; uint32_t dca_rxctrl; int rc; /* Create transmit descriptor ring */ if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 ) goto err_create_tx; /* Create receive descriptor ring */ if ( ( rc = intel_create_ring ( intel, &intel->rx ) ) != 0 ) goto err_create_rx; /* Program MAC address */ memset ( &mac, 0, sizeof ( mac ) ); memcpy ( mac.raw, netdev->ll_addr, sizeof ( mac.raw ) ); ral0 = le32_to_cpu ( mac.reg.low ); rah0 = ( le32_to_cpu ( mac.reg.high ) | INTELX_RAH0_AV ); writel ( ral0, intel->regs + INTELX_RAL0 ); writel ( rah0, intel->regs + INTELX_RAH0 ); writel ( ral0, intel->regs + INTELX_RAL0_ALT ); writel ( rah0, intel->regs + INTELX_RAH0_ALT ); /* Allocate interrupt vectors */ writel ( ( INTELX_IVAR_RX0_DEFAULT | INTELX_IVAR_RX0_VALID | INTELX_IVAR_TX0_DEFAULT | INTELX_IVAR_TX0_VALID ), intel->regs + INTELX_IVAR ); /* Enable transmitter */ dmatxctl = readl ( intel->regs + INTELX_DMATXCTL ); dmatxctl |= INTELX_DMATXCTL_TE; writel ( dmatxctl, intel->regs + INTELX_DMATXCTL ); /* Configure receive filter */ fctrl = readl ( intel->regs + INTELX_FCTRL ); fctrl |= ( INTELX_FCTRL_BAM | INTELX_FCTRL_UPE | INTELX_FCTRL_MPE ); writel ( fctrl, intel->regs + INTELX_FCTRL ); /* Configure receive buffer sizes */ srrctl = readl ( intel->regs + INTELX_SRRCTL ); srrctl &= ~INTELX_SRRCTL_BSIZE_MASK; srrctl |= INTELX_SRRCTL_BSIZE_DEFAULT; writel ( srrctl, intel->regs + INTELX_SRRCTL ); /* Configure jumbo frames. Required to allow the extra 4-byte * headroom for VLANs, since we don't use the hardware's * native VLAN offload. */ hlreg0 = readl ( intel->regs + INTELX_HLREG0 ); hlreg0 |= INTELX_HLREG0_JUMBOEN; writel ( hlreg0, intel->regs + INTELX_HLREG0 ); /* Configure frame size */ maxfrs = readl ( intel->regs + INTELX_MAXFRS ); maxfrs &= ~INTELX_MAXFRS_MFS_MASK; maxfrs |= INTELX_MAXFRS_MFS_DEFAULT; writel ( maxfrs, intel->regs + INTELX_MAXFRS ); /* Configure receive DMA */ rdrxctl = readl ( intel->regs + INTELX_RDRXCTL ); rdrxctl |= INTELX_RDRXCTL_SECRC; writel ( rdrxctl, intel->regs + INTELX_RDRXCTL ); /* Clear "must-be-zero" bit for direct cache access (DCA). We * leave DCA disabled anyway, but if we do not clear this bit * then the received packets contain garbage data. */ dca_rxctrl = readl ( intel->regs + INTELX_DCA_RXCTRL ); dca_rxctrl &= ~INTELX_DCA_RXCTRL_MUST_BE_ZERO; writel ( dca_rxctrl, intel->regs + INTELX_DCA_RXCTRL ); /* Enable receiver */ rxctrl = readl ( intel->regs + INTELX_RXCTRL ); rxctrl |= INTELX_RXCTRL_RXEN; writel ( rxctrl, intel->regs + INTELX_RXCTRL ); /* Fill receive ring */ intel_refill_rx ( intel ); /* Update link state */ intelx_check_link ( netdev ); return 0; intel_destroy_ring ( intel, &intel->rx ); err_create_rx: intel_destroy_ring ( intel, &intel->tx ); err_create_tx: return rc; }