/* In case dst is not aligned we need an intermediate buffer */ if (dst_is_aligned) {
ioread32_rep(priv->regs_base + NPS_ENET_REG_RX_BUF, reg, len);
reg += len;
} else { /* !dst_is_aligned */ for (i = 0; i < len; i++, reg++) {
u32 buf = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF);
put_unaligned_be32(buf, reg);
}
} /* copy last bytes (if any) */ if (last) {
u32 buf;
if (netif_queue_stopped(ndev))
netif_wake_queue(ndev);
}
/** * nps_enet_poll - NAPI poll handler. * @napi: Pointer to napi_struct structure. * @budget: How many frames to process on one call. * * returns: Number of processed frames
*/ staticint nps_enet_poll(struct napi_struct *napi, int budget)
{ struct net_device *ndev = napi->dev; struct nps_enet_priv *priv = netdev_priv(ndev);
u32 work_done;
/* in case we will get a tx interrupt while interrupts * are masked, we will lose it since the tx is edge interrupt. * specifically, while executing the code section above, * between nps_enet_tx_handler and the interrupts enable, all * tx requests will be stuck until we will get an rx interrupt. * the two code lines below will solve this situation by * re-adding ourselves to the poll list.
*/ if (nps_enet_is_tx_pending(priv)) {
nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, 0);
napi_schedule(napi);
}
}
return work_done;
}
/** * nps_enet_irq_handler - Global interrupt handler for ENET. * @irq: irq number. * @dev_instance: device instance. * * returns: IRQ_HANDLED for all cases. * * EZchip ENET has 2 interrupt causes, and depending on bits raised in * CTRL registers we may tell what is a reason for interrupt to fire up. * We got one for RX and the other for TX (completion).
*/ static irqreturn_t nps_enet_irq_handler(s32 irq, void *dev_instance)
{ struct net_device *ndev = dev_instance; struct nps_enet_priv *priv = netdev_priv(ndev);
u32 rx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_RX_CTL);
u32 rx_ctrl_cr = (rx_ctrl_value & RX_CTL_CR_MASK) >> RX_CTL_CR_SHIFT;
if (nps_enet_is_tx_pending(priv) || rx_ctrl_cr) if (likely(napi_schedule_prep(&priv->napi))) {
nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, 0);
__napi_schedule(&priv->napi);
}
/** * nps_enet_hw_reset - Reset the network device. * @ndev: Pointer to the network device. * * This function reset the PCS and TX fifo. * The programming model is to set the relevant reset bits * wait for some time for this to propagate and then unset * the reset bits. This way we ensure that reset procedure * is done successfully by device.
*/ staticvoid nps_enet_hw_reset(struct net_device *ndev)
{ struct nps_enet_priv *priv = netdev_priv(ndev);
u32 ge_rst_value = 0, phase_fifo_ctl_value = 0;
/* In case src is not aligned we need an intermediate buffer */ if (src_is_aligned)
iowrite32_rep(priv->regs_base + NPS_ENET_REG_TX_BUF, src, len); else/* !src_is_aligned */ for (i = 0; i < len; i++, src++)
nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF,
get_unaligned_be32(src));
/* Write the length of the Frame */
tx_ctrl_value |= length << TX_CTL_NT_SHIFT;
/** * nps_enet_set_mac_address - Set the MAC address for this device. * @ndev: Pointer to net_device structure. * @p: 6 byte Address to be written as MAC address. * * This function copies the HW address from the sockaddr structure to the * net_device structure and updates the address in HW. * * returns: -EBUSY if the net device is busy or 0 if the address is set * successfully.
*/ static s32 nps_enet_set_mac_address(struct net_device *ndev, void *p)
{ struct sockaddr *addr = p;
s32 res;
if (netif_running(ndev)) return -EBUSY;
res = eth_mac_addr(ndev, p); if (!res) {
eth_hw_addr_set(ndev, addr->sa_data);
nps_enet_set_hw_mac_address(ndev);
}
return res;
}
/** * nps_enet_set_rx_mode - Change the receive filtering mode. * @ndev: Pointer to the network device. * * This function enables/disables promiscuous mode
*/ staticvoid nps_enet_set_rx_mode(struct net_device *ndev)
{ struct nps_enet_priv *priv = netdev_priv(ndev);
u32 ge_mac_cfg_2_value = priv->ge_mac_cfg_2_value;
/** * nps_enet_open - Open the network device. * @ndev: Pointer to the network device. * * returns: 0, on success or non-zero error value on failure. * * This function sets the MAC address, requests and enables an IRQ * for the ENET device and starts the Tx queue.
*/ static s32 nps_enet_open(struct net_device *ndev)
{ struct nps_enet_priv *priv = netdev_priv(ndev);
s32 err;
/** * nps_enet_stop - Close the network device. * @ndev: Pointer to the network device. * * This function stops the Tx queue, disables interrupts for the ENET device.
*/ static s32 nps_enet_stop(struct net_device *ndev)
{ struct nps_enet_priv *priv = netdev_priv(ndev);
/** * nps_enet_start_xmit - Starts the data transmission. * @skb: sk_buff pointer that contains data to be Transmitted. * @ndev: Pointer to net_device structure. * * returns: NETDEV_TX_OK, on success * NETDEV_TX_BUSY, if any of the descriptors are not free. * * This function is invoked from upper layers to initiate transmission.
*/ static netdev_tx_t nps_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{ struct nps_enet_priv *priv = netdev_priv(ndev);
/* This driver handles one frame at a time */
netif_stop_queue(ndev);
priv->tx_skb = skb;
/* make sure tx_skb is actually written to the memory * before the HW is informed and the IRQ is fired.
*/
wmb();
/* The EZ NET specific entries in the device structure. */
ndev->netdev_ops = &nps_netdev_ops;
ndev->watchdog_timeo = (400 * HZ / 1000); /* FIXME :: no multicast support yet */
ndev->flags &= ~IFF_MULTICAST;
priv->regs_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->regs_base)) {
err = PTR_ERR(priv->regs_base); goto out_netdev;
}
dev_dbg(dev, "Registers base address is 0x%p\n", priv->regs_base);
/* set kernel MAC address to dev */
err = of_get_ethdev_address(dev->of_node, ndev); if (err)
eth_hw_addr_random(ndev);
/* Get IRQ number */
priv->irq = platform_get_irq(pdev, 0); if (priv->irq < 0) {
err = -ENODEV; goto out_netdev;
}
/* Register the driver. Should be the last thing in probe */
err = register_netdev(ndev); if (err) {
dev_err(dev, "Failed to register ndev for %s, err = 0x%08x\n",
ndev->name, (s32)err); goto out_netif_api;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.