X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fnet%2Fcpmac.c;h=c85194f2cd2dc2b8a9bf5628e63b9189db0ec2cd;hb=b01368291926b30abc702dee35c688408b54d422;hp=ae419736158eda973e556c81fa1be8c586947503;hpb=f09cc910fe3af7e63298105bc0482653eb534c3c;p=linux-2.6-omap-h63xx.git diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index ae419736158..c85194f2cd2 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -53,12 +54,6 @@ MODULE_PARM_DESC(debug_level, "Number of NETIF_MSG bits to enable"); MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus"); #define CPMAC_VERSION "0.5.0" -/* stolen from net/ieee80211.h */ -#ifndef MAC_FMT -#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" -#define MAC_ARG(x) ((u8*)(x))[0], ((u8*)(x))[1], ((u8*)(x))[2], \ - ((u8*)(x))[3], ((u8*)(x))[4], ((u8*)(x))[5] -#endif /* frame size + 802.1q tag */ #define CPMAC_SKB_SIZE (ETH_FRAME_LEN + 4) #define CPMAC_QUEUES 8 @@ -211,6 +206,7 @@ struct cpmac_priv { struct net_device *dev; struct work_struct reset_work; struct platform_device *pdev; + struct napi_struct napi; }; static irqreturn_t cpmac_irq(int, void *); @@ -362,47 +358,48 @@ static void cpmac_set_multicast_list(struct net_device *dev) } } -static struct sk_buff *cpmac_rx_one(struct net_device *dev, - struct cpmac_priv *priv, +static struct sk_buff *cpmac_rx_one(struct cpmac_priv *priv, struct cpmac_desc *desc) { struct sk_buff *skb, *result = NULL; if (unlikely(netif_msg_hw(priv))) - cpmac_dump_desc(dev, desc); + cpmac_dump_desc(priv->dev, desc); cpmac_write(priv->regs, CPMAC_RX_ACK(0), (u32)desc->mapping); if (unlikely(!desc->datalen)) { if (netif_msg_rx_err(priv) && net_ratelimit()) printk(KERN_WARNING "%s: rx: spurious interrupt\n", - dev->name); + priv->dev->name); return NULL; } - skb = netdev_alloc_skb(dev, CPMAC_SKB_SIZE); + skb = netdev_alloc_skb(priv->dev, CPMAC_SKB_SIZE); if (likely(skb)) { skb_reserve(skb, 2); skb_put(desc->skb, desc->datalen); - desc->skb->protocol = eth_type_trans(desc->skb, dev); + desc->skb->protocol = eth_type_trans(desc->skb, priv->dev); desc->skb->ip_summed = CHECKSUM_NONE; - dev->stats.rx_packets++; - dev->stats.rx_bytes += desc->datalen; + priv->dev->stats.rx_packets++; + priv->dev->stats.rx_bytes += desc->datalen; result = desc->skb; - dma_unmap_single(&dev->dev, desc->data_mapping, CPMAC_SKB_SIZE, - DMA_FROM_DEVICE); + dma_unmap_single(&priv->dev->dev, desc->data_mapping, + CPMAC_SKB_SIZE, DMA_FROM_DEVICE); desc->skb = skb; - desc->data_mapping = dma_map_single(&dev->dev, skb->data, + desc->data_mapping = dma_map_single(&priv->dev->dev, skb->data, CPMAC_SKB_SIZE, DMA_FROM_DEVICE); desc->hw_data = (u32)desc->data_mapping; if (unlikely(netif_msg_pktdata(priv))) { - printk(KERN_DEBUG "%s: received packet:\n", dev->name); - cpmac_dump_skb(dev, result); + printk(KERN_DEBUG "%s: received packet:\n", + priv->dev->name); + cpmac_dump_skb(priv->dev, result); } } else { if (netif_msg_rx_err(priv) && net_ratelimit()) printk(KERN_WARNING - "%s: low on skbs, dropping packet\n", dev->name); - dev->stats.rx_dropped++; + "%s: low on skbs, dropping packet\n", + priv->dev->name); + priv->dev->stats.rx_dropped++; } desc->buflen = CPMAC_SKB_SIZE; @@ -411,25 +408,25 @@ static struct sk_buff *cpmac_rx_one(struct net_device *dev, return result; } -static int cpmac_poll(struct net_device *dev, int *budget) +static int cpmac_poll(struct napi_struct *napi, int budget) { struct sk_buff *skb; struct cpmac_desc *desc; - int received = 0, quota = min(dev->quota, *budget); - struct cpmac_priv *priv = netdev_priv(dev); + int received = 0; + struct cpmac_priv *priv = container_of(napi, struct cpmac_priv, napi); spin_lock(&priv->rx_lock); if (unlikely(!priv->rx_head)) { if (netif_msg_rx_err(priv) && net_ratelimit()) printk(KERN_WARNING "%s: rx: polling, but no queue\n", - dev->name); - netif_rx_complete(dev); + priv->dev->name); + netif_rx_complete(priv->dev, napi); return 0; } desc = priv->rx_head; - while ((received < quota) && ((desc->dataflags & CPMAC_OWN) == 0)) { - skb = cpmac_rx_one(dev, priv, desc); + while (((desc->dataflags & CPMAC_OWN) == 0) && (received < budget)) { + skb = cpmac_rx_one(priv, desc); if (likely(skb)) { netif_receive_skb(skb); received++; @@ -439,13 +436,11 @@ static int cpmac_poll(struct net_device *dev, int *budget) priv->rx_head = desc; spin_unlock(&priv->rx_lock); - *budget -= received; - dev->quota -= received; if (unlikely(netif_msg_rx_status(priv))) - printk(KERN_DEBUG "%s: poll processed %d packets\n", dev->name, - received); + printk(KERN_DEBUG "%s: poll processed %d packets\n", + priv->dev->name, received); if (desc->dataflags & CPMAC_OWN) { - netif_rx_complete(dev); + netif_rx_complete(priv->dev, napi); cpmac_write(priv->regs, CPMAC_RX_PTR(0), (u32)desc->mapping); cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1); return 0; @@ -460,15 +455,8 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) struct cpmac_desc *desc; struct cpmac_priv *priv = netdev_priv(dev); - if (unlikely(skb_padto(skb, ETH_ZLEN))) { - if (netif_msg_tx_err(priv) && net_ratelimit()) - printk(KERN_WARNING - "%s: tx: padding failed, dropping\n", dev->name); - spin_lock(&priv->lock); - dev->stats.tx_dropped++; - spin_unlock(&priv->lock); - return -ENOMEM; - } + if (unlikely(skb_padto(skb, ETH_ZLEN))) + return NETDEV_TX_OK; len = max(skb->len, ETH_ZLEN); queue = skb_get_queue_mapping(skb); @@ -481,13 +469,9 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) desc = &priv->desc_ring[queue]; if (unlikely(desc->dataflags & CPMAC_OWN)) { if (netif_msg_tx_err(priv) && net_ratelimit()) - printk(KERN_WARNING "%s: tx dma ring full, dropping\n", + printk(KERN_WARNING "%s: tx dma ring full\n", dev->name); - spin_lock(&priv->lock); - dev->stats.tx_dropped++; - spin_unlock(&priv->lock); - dev_kfree_skb_any(skb); - return -ENOMEM; + return NETDEV_TX_BUSY; } spin_lock(&priv->lock); @@ -509,7 +493,7 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) cpmac_dump_skb(dev, skb); cpmac_write(priv->regs, CPMAC_TX_PTR(queue), (u32)desc->mapping); - return 0; + return NETDEV_TX_OK; } static void cpmac_end_xmit(struct net_device *dev, int queue) @@ -646,12 +630,14 @@ static void cpmac_clear_tx(struct net_device *dev) int i; if (unlikely(!priv->desc_ring)) return; - for (i = 0; i < CPMAC_QUEUES; i++) + for (i = 0; i < CPMAC_QUEUES; i++) { + priv->desc_ring[i].dataflags = 0; if (priv->desc_ring[i].skb) { dev_kfree_skb_any(priv->desc_ring[i].skb); if (netif_subqueue_stopped(dev, i)) netif_wake_subqueue(dev, i); } + } } static void cpmac_hw_error(struct work_struct *work) @@ -664,6 +650,7 @@ static void cpmac_hw_error(struct work_struct *work) spin_unlock(&priv->rx_lock); cpmac_clear_tx(priv->dev); cpmac_hw_start(priv->dev); + napi_enable(&priv->napi); netif_start_queue(priv->dev); } @@ -674,9 +661,6 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id) int queue; u32 status; - if (!dev) - return IRQ_NONE; - priv = netdev_priv(dev); status = cpmac_read(priv->regs, CPMAC_MAC_INT_VECTOR); @@ -690,8 +674,10 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id) if (status & MAC_INT_RX) { queue = (status >> 8) & 7; - netif_rx_schedule(dev); - cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue); + if (netif_rx_schedule_prep(dev, &priv->napi)) { + cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue); + __netif_rx_schedule(dev, &priv->napi); + } } cpmac_write(priv->regs, CPMAC_MAC_EOI_VECTOR, 0); @@ -701,6 +687,7 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id) printk(KERN_ERR "%s: hw error, resetting...\n", dev->name); netif_stop_queue(dev); + napi_disable(&priv->napi); cpmac_hw_stop(dev); schedule_work(&priv->reset_work); if (unlikely(netif_msg_hw(priv))) @@ -727,11 +714,13 @@ static void cpmac_tx_timeout(struct net_device *dev) #ifdef CONFIG_NETDEVICES_MULTIQUEUE for (i = 0; i < CPMAC_QUEUES; i++) if (priv->desc_ring[i].skb) { + priv->desc_ring[i].dataflags = 0; dev_kfree_skb_any(priv->desc_ring[i].skb); netif_wake_subqueue(dev, i); break; } #else + priv->desc_ring[0].dataflags = 0; if (priv->desc_ring[0].skb) dev_kfree_skb_any(priv->desc_ring[0].skb); netif_wake_queue(dev); @@ -794,7 +783,7 @@ static int cpmac_set_ringparam(struct net_device *dev, struct ethtool_ringparam* { struct cpmac_priv *priv = netdev_priv(dev); - if (dev->flags && IFF_UP) + if (netif_running(dev)) return -EBUSY; priv->ring_size = ring->rx_pending; return 0; @@ -864,15 +853,6 @@ static int cpmac_open(struct net_device *dev) struct cpmac_desc *desc; struct sk_buff *skb; - priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, - 0, PHY_INTERFACE_MODE_MII); - if (IS_ERR(priv->phy)) { - if (netif_msg_drv(priv)) - printk(KERN_ERR "%s: Could not attach to PHY\n", - dev->name); - return PTR_ERR(priv->phy); - } - mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs"); if (!request_mem_region(mem->start, mem->end - mem->start, dev->name)) { if (netif_msg_drv(priv)) @@ -934,6 +914,7 @@ static int cpmac_open(struct net_device *dev) INIT_WORK(&priv->reset_work, cpmac_hw_error); cpmac_hw_start(dev); + napi_enable(&priv->napi); priv->phy->state = PHY_CHANGELINK; phy_start(priv->phy); @@ -958,8 +939,6 @@ fail_remap: release_mem_region(mem->start, mem->end - mem->start); fail_reserve: - phy_disconnect(priv->phy); - return res; } @@ -972,9 +951,8 @@ static int cpmac_stop(struct net_device *dev) netif_stop_queue(dev); cancel_work_sync(&priv->reset_work); + napi_disable(&priv->napi); phy_stop(priv->phy); - phy_disconnect(priv->phy); - priv->phy = NULL; cpmac_hw_stop(dev); @@ -1008,11 +986,13 @@ static int external_switch; static int __devinit cpmac_probe(struct platform_device *pdev) { - int rc, phy_id; + int rc, phy_id, i; + int mdio_bus_id = cpmac_mii.id; struct resource *mem; struct cpmac_priv *priv; struct net_device *dev; struct plat_cpmac_data *pdata; + DECLARE_MAC_BUF(mac); pdata = pdev->dev.platform_data; @@ -1025,9 +1005,23 @@ static int __devinit cpmac_probe(struct platform_device *pdev) } if (phy_id == PHY_MAX_ADDR) { - if (external_switch || dumb_switch) + if (external_switch || dumb_switch) { + struct fixed_phy_status status = {}; + + mdio_bus_id = 0; + + /* + * FIXME: this should be in the platform code! + * Since there is not platform code at all (that is, + * no mainline users of that driver), place it here + * for now. + */ phy_id = 0; - else { + status.link = 1; + status.duplex = 1; + status.speed = 100; + fixed_phy_add(PHY_POLL, phy_id, &status); + } else { printk(KERN_ERR "cpmac: no PHY present\n"); return -ENODEV; } @@ -1060,21 +1054,27 @@ static int __devinit cpmac_probe(struct platform_device *pdev) dev->set_multicast_list = cpmac_set_multicast_list; dev->tx_timeout = cpmac_tx_timeout; dev->ethtool_ops = &cpmac_ethtool_ops; - dev->poll = cpmac_poll; - dev->weight = 64; dev->features |= NETIF_F_MULTI_QUEUE; + netif_napi_add(dev, &priv->napi, cpmac_poll, 64); + spin_lock_init(&priv->lock); spin_lock_init(&priv->rx_lock); priv->dev = dev; priv->ring_size = 64; priv->msg_enable = netif_msg_init(debug_level, 0xff); memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); - if (phy_id == 31) { - snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, - cpmac_mii.id, phy_id); - } else - snprintf(priv->phy_name, BUS_ID_SIZE, "fixed@%d:%d", 100, 1); + + snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); + + priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, + PHY_INTERFACE_MODE_MII); + if (IS_ERR(priv->phy)) { + if (netif_msg_drv(priv)) + printk(KERN_ERR "%s: Could not attach to PHY\n", + dev->name); + return PTR_ERR(priv->phy); + } if ((rc = register_netdev(dev))) { printk(KERN_ERR "cpmac: error %i registering device %s\n", rc, @@ -1084,9 +1084,9 @@ static int __devinit cpmac_probe(struct platform_device *pdev) if (netif_msg_probe(priv)) { printk(KERN_INFO - "cpmac: device %s (regs: %p, irq: %d, phy: %s, mac: " - MAC_FMT ")\n", dev->name, (void *)mem->start, dev->irq, - priv->phy_name, MAC_ARG(dev->dev_addr)); + "cpmac: device %s (regs: %p, irq: %d, phy: %s, " + "mac: %s)\n", dev->name, (void *)mem->start, dev->irq, + priv->phy_name, print_mac(mac, dev->dev_addr)); } return 0;