diff options
Diffstat (limited to 'drivers/net/ethernet')
307 files changed, 10632 insertions, 5200 deletions
diff --git a/drivers/net/ethernet/3com/3c501.c b/drivers/net/ethernet/3com/3c501.c index 68da81d476f3..bf73e1a02293 100644 --- a/drivers/net/ethernet/3com/3c501.c +++ b/drivers/net/ethernet/3com/3c501.c @@ -702,7 +702,7 @@ static void el_receive(struct net_device *dev) */ outb(AX_SYS, AX_CMD); - skb = dev_alloc_skb(pkt_len+2); + skb = netdev_alloc_skb(dev, pkt_len + 2); /* * Start of frame diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c index 92053e6fc980..41719da2e178 100644 --- a/drivers/net/ethernet/3com/3c509.c +++ b/drivers/net/ethernet/3com/3c509.c @@ -1066,7 +1066,7 @@ el3_rx(struct net_device *dev) short pkt_len = rx_status & 0x7ff; struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len+5); + skb = netdev_alloc_skb(dev, pkt_len + 5); if (el3_debug > 4) pr_debug("Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); diff --git a/drivers/net/ethernet/3com/3c515.c b/drivers/net/ethernet/3com/3c515.c index f67a5d3a200c..59e1e001bc3f 100644 --- a/drivers/net/ethernet/3com/3c515.c +++ b/drivers/net/ethernet/3com/3c515.c @@ -826,11 +826,10 @@ static int corkscrew_open(struct net_device *dev) vp->rx_ring[i].next = 0; vp->rx_ring[i].status = 0; /* Clear complete bit. */ vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000; - skb = dev_alloc_skb(PKT_BUF_SZ); + skb = netdev_alloc_skb(dev, PKT_BUF_SZ); vp->rx_skbuff[i] = skb; if (skb == NULL) break; /* Bad news! */ - skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ vp->rx_ring[i].addr = isa_virt_to_bus(skb->data); } @@ -1295,7 +1294,7 @@ static int corkscrew_rx(struct net_device *dev) short pkt_len = rx_status & 0x1fff; struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len + 5 + 2); + skb = netdev_alloc_skb(dev, pkt_len + 5 + 2); if (corkscrew_debug > 4) pr_debug("Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); @@ -1368,7 +1367,7 @@ static int boomerang_rx(struct net_device *dev) /* Check if the packet is long enough to just accept without copying to a properly sized skbuff. */ if (pkt_len < rx_copybreak && - (skb = dev_alloc_skb(pkt_len + 4)) != NULL) { + (skb = netdev_alloc_skb(dev, pkt_len + 4)) != NULL) { skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ /* 'skb_put()' points to the start of sk_buff data area. */ memcpy(skb_put(skb, pkt_len), @@ -1403,10 +1402,9 @@ static int boomerang_rx(struct net_device *dev) struct sk_buff *skb; entry = vp->dirty_rx % RX_RING_SIZE; if (vp->rx_skbuff[entry] == NULL) { - skb = dev_alloc_skb(PKT_BUF_SZ); + skb = netdev_alloc_skb(dev, PKT_BUF_SZ); if (skb == NULL) break; /* Bad news! */ - skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ vp->rx_ring[entry].addr = isa_virt_to_bus(skb->data); vp->rx_skbuff[entry] = skb; diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c index 9c01bc9235b3..e61b2f82ba3a 100644 --- a/drivers/net/ethernet/3com/3c574_cs.c +++ b/drivers/net/ethernet/3com/3c574_cs.c @@ -1012,7 +1012,7 @@ static int el3_rx(struct net_device *dev, int worklimit) short pkt_len = rx_status & 0x7ff; struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len+5); + skb = netdev_alloc_skb(dev, pkt_len + 5); pr_debug(" Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); diff --git a/drivers/net/ethernet/3com/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c index da410f036869..b23253b9f742 100644 --- a/drivers/net/ethernet/3com/3c589_cs.c +++ b/drivers/net/ethernet/3com/3c589_cs.c @@ -819,7 +819,7 @@ static int el3_rx(struct net_device *dev) short pkt_len = rx_status & 0x7ff; struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len+5); + skb = netdev_alloc_skb(dev, pkt_len + 5); netdev_dbg(dev, " Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 8153a3e0a1a4..1282f048dfad 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -1121,10 +1121,9 @@ static int __devinit vortex_probe1(struct device *gendev, dev = alloc_etherdev(sizeof(*vp)); retval = -ENOMEM; - if (!dev) { - pr_err(PFX "unable to allocate etherdev, aborting\n"); + if (!dev) goto out; - } + SET_NETDEV_DEV(dev, gendev); vp = netdev_priv(dev); @@ -2500,7 +2499,7 @@ static int vortex_rx(struct net_device *dev) int pkt_len = rx_status & 0x1fff; struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len + 5); + skb = netdev_alloc_skb(dev, pkt_len + 5); if (vortex_debug > 4) pr_debug("Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); @@ -2579,7 +2578,8 @@ boomerang_rx(struct net_device *dev) /* Check if the packet is long enough to just accept without copying to a properly sized skbuff. */ - if (pkt_len < rx_copybreak && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + if (pkt_len < rx_copybreak && + (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) { skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ pci_dma_sync_single_for_cpu(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); /* 'skb_put()' points to the start of sk_buff data area. */ diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig index a8bb30cf512d..bad4fa6815c5 100644 --- a/drivers/net/ethernet/3com/Kconfig +++ b/drivers/net/ethernet/3com/Kconfig @@ -97,7 +97,7 @@ config VORTEX available from <http://www.tldp.org/docs.html#howto>. More specific information is in <file:Documentation/networking/vortex.txt> and in the comments at - the beginning of <file:drivers/net/3c59x.c>. + the beginning of <file:drivers/net/ethernet/3com/3c59x.c>. To compile this support as a module, choose M here. diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c index 6d6bc754b1a8..f7d622eed203 100644 --- a/drivers/net/ethernet/3com/typhoon.c +++ b/drivers/net/ethernet/3com/typhoon.c @@ -1607,7 +1607,7 @@ typhoon_alloc_rx_skb(struct typhoon *tp, u32 idx) le32_to_cpu(indexes->rxBuffCleared)) return -ENOMEM; - skb = dev_alloc_skb(PKT_BUF_SZ); + skb = netdev_alloc_skb(tp->dev, PKT_BUF_SZ); if(!skb) return -ENOMEM; @@ -1618,7 +1618,6 @@ typhoon_alloc_rx_skb(struct typhoon *tp, u32 idx) skb_reserve(skb, 2); #endif - skb->dev = tp->dev; dma_addr = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); @@ -1673,7 +1672,7 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile __le32 * read pkt_len = le16_to_cpu(rx->frameLen); if(pkt_len < rx_copybreak && - (new_skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + (new_skb = netdev_alloc_skb(tp->dev, pkt_len + 2)) != NULL) { skb_reserve(new_skb, 2); pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, PKT_BUF_SZ, diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c index 0f92e3567f68..c30adcc9828a 100644 --- a/drivers/net/ethernet/8390/ax88796.c +++ b/drivers/net/ethernet/8390/ax88796.c @@ -1,4 +1,4 @@ -/* drivers/net/ax88796.c +/* drivers/net/ethernet/8390/ax88796.c * * Copyright 2005,2007 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c index bba51cdc74a1..c5bd8eb7a9f5 100644 --- a/drivers/net/ethernet/8390/axnet_cs.c +++ b/drivers/net/ethernet/8390/axnet_cs.c @@ -192,7 +192,7 @@ static int get_prom(struct pcmcia_device *link) unsigned int ioaddr = dev->base_addr; int i, j; - /* This is based on drivers/net/ne.c */ + /* This is based on drivers/net/ethernet/8390/ne.c */ struct { u_char value, offset; } program_seq[] = { @@ -1408,7 +1408,7 @@ static void ei_receive(struct net_device *dev) { struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len+2); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { if (ei_debug > 1) diff --git a/drivers/net/ethernet/8390/lib8390.c b/drivers/net/ethernet/8390/lib8390.c index 05ae21435bfd..e77f624e8194 100644 --- a/drivers/net/ethernet/8390/lib8390.c +++ b/drivers/net/ethernet/8390/lib8390.c @@ -717,7 +717,7 @@ static void ei_receive(struct net_device *dev) } else if ((pkt_stat & 0x0F) == ENRSR_RXOK) { struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len+2); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { if (ei_debug > 1) netdev_dbg(dev, "Couldn't allocate a sk_buff of size %d\n", diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c index 053b2551a72d..f2a4e5de18c4 100644 --- a/drivers/net/ethernet/8390/pcnet_cs.c +++ b/drivers/net/ethernet/8390/pcnet_cs.c @@ -326,7 +326,7 @@ static hw_info_t *get_prom(struct pcmcia_device *link) u_char prom[32]; int i, j; - /* This is lifted straight from drivers/net/ne.c */ + /* This is lifted straight from drivers/net/ethernet/8390/ne.c */ struct { u_char value, offset; } program_seq[] = { diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c index cb4f38a17f20..d896816512ca 100644 --- a/drivers/net/ethernet/adaptec/starfire.c +++ b/drivers/net/ethernet/adaptec/starfire.c @@ -686,10 +686,9 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, } dev = alloc_etherdev(sizeof(*np)); - if (!dev) { - printk(KERN_ERR DRV_NAME " %d: cannot alloc etherdev, aborting\n", card_idx); + if (!dev) return -ENOMEM; - } + SET_NETDEV_DEV(dev, &pdev->dev); irq = pdev->irq; @@ -1180,12 +1179,11 @@ static void init_ring(struct net_device *dev) /* Fill in the Rx buffers. Handle allocation failure gracefully. */ for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz); + struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz); np->rx_info[i].skb = skb; if (skb == NULL) break; np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); - skb->dev = dev; /* Mark as being used by this device. */ /* Grrr, we cannot offset to correctly align the IP header. */ np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid); } @@ -1473,7 +1471,7 @@ static int __netdev_rx(struct net_device *dev, int *quota) /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < rx_copybreak && - (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) { skb_reserve(skb, 2); /* 16 byte align the IP header */ pci_dma_sync_single_for_cpu(np->pci_dev, np->rx_info[entry].mapping, @@ -1597,13 +1595,12 @@ static void refill_rx_ring(struct net_device *dev) for (; np->cur_rx - np->dirty_rx > 0; np->dirty_rx++) { entry = np->dirty_rx % RX_RING_SIZE; if (np->rx_info[entry].skb == NULL) { - skb = dev_alloc_skb(np->rx_buf_sz); + skb = netdev_alloc_skb(dev, np->rx_buf_sz); np->rx_info[entry].skb = skb; if (skb == NULL) break; /* Better luck next round. */ np->rx_info[entry].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); - skb->dev = dev; /* Mark as being used by this device. */ np->rx_ring[entry].rxaddr = cpu_to_dma(np->rx_info[entry].mapping | RxDescValid); } diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c index d812a103e032..49733696703a 100644 --- a/drivers/net/ethernet/adi/bfin_mac.c +++ b/drivers/net/ethernet/adi/bfin_mac.c @@ -113,7 +113,7 @@ static void desc_list_free(void) } } -static int desc_list_init(void) +static int desc_list_init(struct net_device *dev) { int i; struct sk_buff *new_skb; @@ -187,7 +187,7 @@ static int desc_list_init(void) struct dma_descriptor *b = &(r->desc_b); /* allocate a new skb for next time receive */ - new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN); + new_skb = netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN); if (!new_skb) { pr_notice("init: low on mem - packet dropped\n"); goto init_error; @@ -1090,7 +1090,7 @@ static void bfin_mac_rx(struct net_device *dev) /* allocate a new skb for next time receive */ skb = current_rx_ptr->skb; - new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN); + new_skb = netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN); if (!new_skb) { netdev_notice(dev, "rx: low on mem - packet dropped\n"); dev->stats.rx_dropped++; @@ -1397,7 +1397,7 @@ static int bfin_mac_open(struct net_device *dev) } /* initial rx and tx list */ - ret = desc_list_init(); + ret = desc_list_init(dev); if (ret) return ret; @@ -1467,10 +1467,8 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) int rc; ndev = alloc_etherdev(sizeof(struct bfin_mac_local)); - if (!ndev) { - dev_err(&pdev->dev, "Cannot allocate net device!\n"); + if (!ndev) return -ENOMEM; - } SET_NETDEV_DEV(ndev, &pdev->dev); platform_set_drvdata(pdev, ndev); diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c index c885aa905dec..b23751e683c8 100644 --- a/drivers/net/ethernet/aeroflex/greth.c +++ b/drivers/net/ethernet/aeroflex/greth.c @@ -785,7 +785,6 @@ static int greth_rx(struct net_device *dev, int limit) } else { skb_reserve(skb, NET_IP_ALIGN); - skb->dev = dev; dma_sync_single_for_cpu(greth->dev, dma_addr, diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c index f872748ab4e6..6c3b1c0adaa0 100644 --- a/drivers/net/ethernet/alteon/acenic.c +++ b/drivers/net/ethernet/alteon/acenic.c @@ -463,11 +463,8 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev, static int boards_found; dev = alloc_etherdev(sizeof(struct ace_private)); - if (dev == NULL) { - printk(KERN_ERR "acenic: Unable to allocate " - "net_device structure!\n"); + if (dev == NULL) return -ENOMEM; - } SET_NETDEV_DEV(dev, &pdev->dev); diff --git a/drivers/net/ethernet/amd/7990.c b/drivers/net/ethernet/amd/7990.c index 60b35fb5f524..1b046f58d58f 100644 --- a/drivers/net/ethernet/amd/7990.c +++ b/drivers/net/ethernet/amd/7990.c @@ -316,7 +316,7 @@ static int lance_rx (struct net_device *dev) if (bits & LE_R1_EOP) dev->stats.rx_errors++; } else { int len = (rd->mblength & 0xfff) - 4; - struct sk_buff *skb = dev_alloc_skb (len+2); + struct sk_buff *skb = netdev_alloc_skb(dev, len + 2); if (!skb) { printk ("%s: Memory squeeze, deferring packet.\n", diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig index 238b537b68fe..8350f4b37a8a 100644 --- a/drivers/net/ethernet/amd/Kconfig +++ b/drivers/net/ethernet/amd/Kconfig @@ -113,7 +113,7 @@ config DEPCA If you have a network (Ethernet) card of this type, say Y and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto> as well as - <file:drivers/net/depca.c>. + <file:drivers/net/ethernet/amd/depca.c>. To compile this driver as a module, choose M here. The module will be called depca. diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c index 825e5d4ef4c3..689dfcafc6d4 100644 --- a/drivers/net/ethernet/amd/a2065.c +++ b/drivers/net/ethernet/amd/a2065.c @@ -290,7 +290,7 @@ static int lance_rx(struct net_device *dev) dev->stats.rx_errors++; } else { int len = (rd->mblength & 0xfff) - 4; - struct sk_buff *skb = dev_alloc_skb(len + 2); + struct sk_buff *skb = netdev_alloc_skb(dev, len + 2); if (!skb) { netdev_warn(dev, "Memory squeeze, deferring packet\n"); diff --git a/drivers/net/ethernet/amd/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c index 7d5ded80d2d7..cc7b9e46780c 100644 --- a/drivers/net/ethernet/amd/am79c961a.c +++ b/drivers/net/ethernet/amd/am79c961a.c @@ -1,5 +1,5 @@ /* - * linux/drivers/net/am79c961.c + * linux/drivers/net/ethernet/amd/am79c961a.c * * by Russell King <rmk@arm.linux.org.uk> 1995-2001. * @@ -516,7 +516,7 @@ am79c961_rx(struct net_device *dev, struct dev_priv *priv) } len = am_readword(dev, hdraddr + 6); - skb = dev_alloc_skb(len + 2); + skb = netdev_alloc_skb(dev, len + 2); if (skb) { skb_reserve(skb, 2); diff --git a/drivers/net/ethernet/amd/am79c961a.h b/drivers/net/ethernet/amd/am79c961a.h index fd634d32756b..9f384b79507b 100644 --- a/drivers/net/ethernet/amd/am79c961a.h +++ b/drivers/net/ethernet/amd/am79c961a.h @@ -1,5 +1,5 @@ /* - * linux/drivers/net/arm/am79c961a.h + * linux/drivers/net/ethernet/amd/am79c961a.h * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index 33e0a8c20f6b..9f62504d0086 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c @@ -336,7 +336,8 @@ static int amd8111e_init_ring(struct net_device *dev) /* Allocating receive skbs */ for (i = 0; i < NUM_RX_BUFFERS; i++) { - if (!(lp->rx_skbuff[i] = dev_alloc_skb(lp->rx_buff_len))) { + lp->rx_skbuff[i] = netdev_alloc_skb(dev, lp->rx_buff_len); + if (!lp->rx_skbuff[i]) { /* Release previos allocated skbs */ for(--i; i >= 0 ;i--) dev_kfree_skb(lp->rx_skbuff[i]); @@ -768,7 +769,8 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget) } if(--rx_pkt_limit < 0) goto rx_not_empty; - if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){ + new_skb = netdev_alloc_skb(dev, lp->rx_buff_len); + if (!new_skb) { /* if allocation fail, ignore that pkt and go to next one */ lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; @@ -1859,7 +1861,6 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, dev = alloc_etherdev(sizeof(struct amd8111e_priv)); if (!dev) { - printk(KERN_ERR "amd8111e: Etherdev alloc failed, exiting.\n"); err = -ENOMEM; goto err_free_reg; } diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c index eb18e1fe65c8..f4c228e4d76c 100644 --- a/drivers/net/ethernet/amd/ariadne.c +++ b/drivers/net/ethernet/amd/ariadne.c @@ -191,7 +191,7 @@ static int ariadne_rx(struct net_device *dev) short pkt_len = swapw(priv->rx_ring[entry]->RMD3); struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len + 2); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { netdev_warn(dev, "Memory squeeze, deferring packet\n"); for (i = 0; i < RX_RING_SIZE; i++) diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c index 15bfa28d6c53..70ed79c46245 100644 --- a/drivers/net/ethernet/amd/atarilance.c +++ b/drivers/net/ethernet/amd/atarilance.c @@ -997,7 +997,7 @@ static int lance_rx( struct net_device *dev ) dev->stats.rx_errors++; } else { - skb = dev_alloc_skb( pkt_len+2 ); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n", dev->name )); diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index 8b95dd314253..c1dfdc8b7079 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -725,7 +725,7 @@ static int au1000_rx(struct net_device *dev) /* good frame */ frmlen = (status & RX_FRAME_LEN_MASK); frmlen -= 4; /* Remove FCS */ - skb = dev_alloc_skb(frmlen + 2); + skb = netdev_alloc_skb(dev, frmlen + 2); if (skb == NULL) { netdev_err(dev, "Memory squeeze, dropping packet.\n"); dev->stats.rx_dropped++; @@ -1077,7 +1077,6 @@ static int __devinit au1000_probe(struct platform_device *pdev) dev = alloc_etherdev(sizeof(struct au1000_private)); if (!dev) { - dev_err(&pdev->dev, "alloc_etherdev failed\n"); err = -ENOMEM; goto err_alloc; } diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c index 73f8d4fa682d..7dc508e5c72e 100644 --- a/drivers/net/ethernet/amd/declance.c +++ b/drivers/net/ethernet/amd/declance.c @@ -605,7 +605,7 @@ static int lance_rx(struct net_device *dev) dev->stats.rx_errors++; } else { len = (*rds_ptr(rd, mblength, lp->type) & 0xfff) - 4; - skb = dev_alloc_skb(len + 2); + skb = netdev_alloc_skb(dev, len + 2); if (skb == 0) { printk("%s: Memory squeeze, deferring packet.\n", @@ -1052,8 +1052,6 @@ static int __devinit dec_lance_probe(struct device *bdev, const int type) dev = alloc_etherdev(sizeof(struct lance_private)); if (!dev) { - printk(KERN_ERR "%s: Unable to allocate etherdev, aborting.\n", - name); ret = -ENOMEM; goto err_out; } diff --git a/drivers/net/ethernet/amd/depca.c b/drivers/net/ethernet/amd/depca.c index 681970c07f22..86dd95766a64 100644 --- a/drivers/net/ethernet/amd/depca.c +++ b/drivers/net/ethernet/amd/depca.c @@ -1042,7 +1042,7 @@ static int depca_rx(struct net_device *dev) short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4; struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len + 2); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb != NULL) { unsigned char *buf; skb_reserve(skb, 2); /* 16 byte align the IP header */ diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c index 6e6aa7213aab..013b65108536 100644 --- a/drivers/net/ethernet/amd/ni65.c +++ b/drivers/net/ethernet/amd/ni65.c @@ -621,10 +621,8 @@ static void *ni65_alloc_mem(struct net_device *dev,char *what,int size,int type) } else { ret = ptr = kmalloc(T_BUF_SIZE,GFP_KERNEL | GFP_DMA); - if(!ret) { - printk(KERN_WARNING "%s: unable to allocate %s memory.\n",dev->name,what); + if(!ret) return NULL; - } } if( (u32) virt_to_phys(ptr+size) > 0x1000000) { printk(KERN_WARNING "%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what); @@ -1091,7 +1089,7 @@ static void ni65_recv_intr(struct net_device *dev,int csr0) if (skb) skb_reserve(skb,16); #else - struct sk_buff *skb = dev_alloc_skb(len+2); + struct sk_buff *skb = netdev_alloc_skb(dev, len + 2); #endif if(skb) { diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c index 6be0dd67631a..ebdb9e238a8d 100644 --- a/drivers/net/ethernet/amd/nmclan_cs.c +++ b/drivers/net/ethernet/amd/nmclan_cs.c @@ -1104,7 +1104,7 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt) pr_debug(" receiving packet size 0x%X rx_status" " 0x%X.\n", pkt_len, rx_status); - skb = dev_alloc_skb(pkt_len+2); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb != NULL) { skb_reserve(skb, 2); diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index 20e6dab0186c..86b6d8e4e6cd 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c @@ -588,11 +588,11 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, /* now allocate any new buffers needed */ for (; new < size; new++) { struct sk_buff *rx_skbuff; - new_skb_list[new] = dev_alloc_skb(PKT_BUF_SKB); + new_skb_list[new] = netdev_alloc_skb(dev, PKT_BUF_SKB); rx_skbuff = new_skb_list[new]; if (!rx_skbuff) { /* keep the original lists and buffers */ - netif_err(lp, drv, dev, "%s dev_alloc_skb failed\n", + netif_err(lp, drv, dev, "%s netdev_alloc_skb failed\n", __func__); goto free_all_new; } @@ -909,7 +909,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) /* Initialize Transmit buffers. */ size = data_len + 15; for (x = 0; x < numbuffs; x++) { - skb = dev_alloc_skb(size); + skb = netdev_alloc_skb(dev, size); if (!skb) { netif_printk(lp, hw, KERN_DEBUG, dev, "Cannot allocate skb at line: %d!\n", @@ -1152,7 +1152,7 @@ static void pcnet32_rx_entry(struct net_device *dev, if (pkt_len > rx_copybreak) { struct sk_buff *newskb; - newskb = dev_alloc_skb(PKT_BUF_SKB); + newskb = netdev_alloc_skb(dev, PKT_BUF_SKB); if (newskb) { skb_reserve(newskb, NET_IP_ALIGN); skb = lp->rx_skbuff[entry]; @@ -1172,7 +1172,7 @@ static void pcnet32_rx_entry(struct net_device *dev, } else skb = NULL; } else - skb = dev_alloc_skb(pkt_len + NET_IP_ALIGN); + skb = netdev_alloc_skb(dev, pkt_len + NET_IP_ALIGN); if (skb == NULL) { netif_err(lp, drv, dev, "Memory squeeze, dropping packet\n"); @@ -1649,8 +1649,6 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) dev = alloc_etherdev(sizeof(*lp)); if (!dev) { - if (pcnet32_debug & NETIF_MSG_PROBE) - pr_err("Memory allocation failed\n"); ret = -ENOMEM; goto err_release_region; } @@ -2273,11 +2271,11 @@ static int pcnet32_init_ring(struct net_device *dev) for (i = 0; i < lp->rx_ring_size; i++) { struct sk_buff *rx_skbuff = lp->rx_skbuff[i]; if (rx_skbuff == NULL) { - lp->rx_skbuff[i] = dev_alloc_skb(PKT_BUF_SKB); + lp->rx_skbuff[i] = netdev_alloc_skb(dev, PKT_BUF_SKB); rx_skbuff = lp->rx_skbuff[i]; if (!rx_skbuff) { /* there is not much we can do at this point */ - netif_err(lp, drv, dev, "%s dev_alloc_skb failed\n", + netif_err(lp, drv, dev, "%s netdev_alloc_skb failed\n", __func__); return -1; } diff --git a/drivers/net/ethernet/amd/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c index 080b71fcc683..74b3891b6483 100644 --- a/drivers/net/ethernet/amd/sun3lance.c +++ b/drivers/net/ethernet/amd/sun3lance.c @@ -810,7 +810,7 @@ static int lance_rx( struct net_device *dev ) dev->stats.rx_errors++; } else { - skb = dev_alloc_skb( pkt_len+2 ); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n", dev->name )); diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c index 7ea16d32a5f5..e3fe3504e198 100644 --- a/drivers/net/ethernet/amd/sunlance.c +++ b/drivers/net/ethernet/amd/sunlance.c @@ -534,7 +534,7 @@ static void lance_rx_dvma(struct net_device *dev) if (bits & LE_R1_EOP) dev->stats.rx_errors++; } else { len = (rd->mblength & 0xfff) - 4; - skb = dev_alloc_skb(len + 2); + skb = netdev_alloc_skb(dev, len + 2); if (skb == NULL) { printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n", @@ -706,7 +706,7 @@ static void lance_rx_pio(struct net_device *dev) if (bits & LE_R1_EOP) dev->stats.rx_errors++; } else { len = (sbus_readw(&rd->mblength) & 0xfff) - 4; - skb = dev_alloc_skb(len + 2); + skb = netdev_alloc_skb(dev, len + 2); if (skb == NULL) { printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n", diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c index d070b229dbf7..855bdafb1a87 100644 --- a/drivers/net/ethernet/apple/bmac.c +++ b/drivers/net/ethernet/apple/bmac.c @@ -607,8 +607,9 @@ bmac_init_tx_ring(struct bmac_data *bp) } static int -bmac_init_rx_ring(struct bmac_data *bp) +bmac_init_rx_ring(struct net_device *dev) { + struct bmac_data *bp = netdev_priv(dev); volatile struct dbdma_regs __iomem *rd = bp->rx_dma; int i; struct sk_buff *skb; @@ -618,7 +619,7 @@ bmac_init_rx_ring(struct bmac_data *bp) (N_RX_RING + 1) * sizeof(struct dbdma_cmd)); for (i = 0; i < N_RX_RING; i++) { if ((skb = bp->rx_bufs[i]) == NULL) { - bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2); + bp->rx_bufs[i] = skb = netdev_alloc_skb(dev, RX_BUFLEN + 2); if (skb != NULL) skb_reserve(skb, 2); } @@ -722,7 +723,7 @@ static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id) ++dev->stats.rx_dropped; } if ((skb = bp->rx_bufs[i]) == NULL) { - bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2); + bp->rx_bufs[i] = skb = netdev_alloc_skb(dev, RX_BUFLEN + 2); if (skb != NULL) skb_reserve(bp->rx_bufs[i], 2); } @@ -1208,7 +1209,7 @@ static void bmac_reset_and_enable(struct net_device *dev) spin_lock_irqsave(&bp->lock, flags); bmac_enable_and_reset_chip(dev); bmac_init_tx_ring(bp); - bmac_init_rx_ring(bp); + bmac_init_rx_ring(dev); bmac_init_chip(dev); bmac_start_chip(dev); bmwrite(dev, INTDISABLE, EnableNormal); @@ -1218,7 +1219,7 @@ static void bmac_reset_and_enable(struct net_device *dev) * It seems that the bmac can't receive until it's transmitted * a packet. So we give it a dummy packet to transmit. */ - skb = dev_alloc_skb(ETHERMINPACKET); + skb = netdev_alloc_skb(dev, ETHERMINPACKET); if (skb != NULL) { data = skb_put(skb, ETHERMINPACKET); memset(data, 0, ETHERMINPACKET); @@ -1269,10 +1270,8 @@ static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_i memcpy(addr, prop_addr, sizeof(addr)); dev = alloc_etherdev(PRIV_BYTES); - if (!dev) { - printk(KERN_ERR "BMAC: alloc_etherdev failed, out of memory\n"); + if (!dev) return -ENOMEM; - } bp = netdev_priv(dev); SET_NETDEV_DEV(dev, &mdev->ofdev.dev); @@ -1660,10 +1659,8 @@ static int __init bmac_init(void) { if (bmac_emergency_rxbuf == NULL) { bmac_emergency_rxbuf = kmalloc(RX_BUFLEN, GFP_KERNEL); - if (bmac_emergency_rxbuf == NULL) { - printk(KERN_ERR "BMAC: can't allocate emergency RX buffer\n"); + if (bmac_emergency_rxbuf == NULL) return -ENOMEM; - } } return macio_register_driver(&bmac_driver); diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c index bec87bd9195c..e1df4b76c885 100644 --- a/drivers/net/ethernet/apple/mace.c +++ b/drivers/net/ethernet/apple/mace.c @@ -136,10 +136,8 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i */ if (dummy_buf == NULL) { dummy_buf = kmalloc(RX_BUFLEN+2, GFP_KERNEL); - if (dummy_buf == NULL) { - printk(KERN_ERR "MACE: couldn't allocate dummy buffer\n"); + if (dummy_buf == NULL) return -ENOMEM; - } } if (macio_request_resources(mdev, "mace")) { @@ -149,7 +147,6 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i dev = alloc_etherdev(PRIV_BYTES); if (!dev) { - printk(KERN_ERR "MACE: can't allocate ethernet device !\n"); rc = -ENOMEM; goto err_release; } @@ -447,7 +444,7 @@ static int mace_open(struct net_device *dev) memset((char *)mp->rx_cmds, 0, N_RX_RING * sizeof(struct dbdma_cmd)); cp = mp->rx_cmds; for (i = 0; i < N_RX_RING - 1; ++i) { - skb = dev_alloc_skb(RX_BUFLEN + 2); + skb = netdev_alloc_skb(dev, RX_BUFLEN + 2); if (!skb) { data = dummy_buf; } else { @@ -959,7 +956,7 @@ static irqreturn_t mace_rxdma_intr(int irq, void *dev_id) cp = mp->rx_cmds + i; skb = mp->rx_bufs[i]; if (!skb) { - skb = dev_alloc_skb(RX_BUFLEN + 2); + skb = netdev_alloc_skb(dev, RX_BUFLEN + 2); if (skb) { skb_reserve(skb, 2); mp->rx_bufs[i] = skb; diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c index 7cf81bbffe0e..ab7ff8645ab1 100644 --- a/drivers/net/ethernet/apple/macmace.c +++ b/drivers/net/ethernet/apple/macmace.c @@ -661,7 +661,7 @@ static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf) } else { unsigned int frame_length = mf->rcvcnt + ((frame_status & 0x0F) << 8 ); - skb = dev_alloc_skb(frame_length + 2); + skb = netdev_alloc_skb(dev, frame_length + 2); if (!skb) { dev->stats.rx_dropped++; return; diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index b8591246eb4c..2c8ed70704aa 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -1765,7 +1765,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid while (next_info->flags & ATL1C_BUFFER_FREE) { rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use); - skb = dev_alloc_skb(adapter->rx_buffer_len); + skb = netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len); if (unlikely(!skb)) { if (netif_msg_rx_err(adapter)) dev_warn(&pdev->dev, "alloc rx buffer failed\n"); @@ -2689,7 +2689,6 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, netdev = alloc_etherdev(sizeof(struct atl1c_adapter)); if (netdev == NULL) { err = -ENOMEM; - dev_err(&pdev->dev, "etherdev alloc failed\n"); goto err_alloc_etherdev; } diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index c915c0873810..93ff2b231284 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -2300,7 +2300,6 @@ static int __devinit atl1e_probe(struct pci_dev *pdev, netdev = alloc_etherdev(sizeof(struct atl1e_adapter)); if (netdev == NULL) { err = -ENOMEM; - dev_err(&pdev->dev, "etherdev alloc failed\n"); goto err_alloc_etherdev; } diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 3fb66d09ece5..66f53c797e3a 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -2138,7 +2138,6 @@ static int __devinit b44_init_one(struct ssb_device *sdev, dev = alloc_etherdev(sizeof(*bp)); if (!dev) { - dev_err(sdev->dev, "Etherdev alloc failed, aborting\n"); err = -ENOMEM; goto out; } diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 021fb818007a..7105989ba658 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -2625,10 +2625,8 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp) u32 val; good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL); - if (good_mbuf == NULL) { - pr_err("Failed to allocate memory in %s\n", __func__); + if (good_mbuf == NULL) return -ENOMEM; - } REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE); @@ -6248,7 +6246,16 @@ static int bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi) { int cpus = num_online_cpus(); - int msix_vecs = min(cpus + 1, RX_MAX_RINGS); + int msix_vecs; + + if (!bp->num_req_rx_rings) + msix_vecs = max(cpus + 1, bp->num_req_tx_rings); + else if (!bp->num_req_tx_rings) + msix_vecs = max(cpus, bp->num_req_rx_rings); + else + msix_vecs = max(bp->num_req_rx_rings, bp->num_req_tx_rings); + + msix_vecs = min(msix_vecs, RX_MAX_RINGS); bp->irq_tbl[0].handler = bnx2_interrupt; strcpy(bp->irq_tbl[0].name, bp->dev->name); @@ -6272,10 +6279,18 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi) } } - bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs); + if (!bp->num_req_tx_rings) + bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs); + else + bp->num_tx_rings = min(bp->irq_nvecs, bp->num_req_tx_rings); + + if (!bp->num_req_rx_rings) + bp->num_rx_rings = bp->irq_nvecs; + else + bp->num_rx_rings = min(bp->irq_nvecs, bp->num_req_rx_rings); + netif_set_real_num_tx_queues(bp->dev, bp->num_tx_rings); - bp->num_rx_rings = bp->irq_nvecs; return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings); } @@ -6550,6 +6565,9 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) } txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END; + /* Sync BD data before updating TX mailbox */ + wmb(); + netdev_tx_sent_queue(txq, skb->len); prod = NEXT_TX_BD(prod); @@ -7164,7 +7182,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) } static int -bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) +bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx, bool reset_irq) { if (netif_running(bp->dev)) { /* Reset will erase chipset stats; save them */ @@ -7172,7 +7190,12 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) bnx2_netif_stop(bp, true); bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); - __bnx2_free_irq(bp); + if (reset_irq) { + bnx2_free_irq(bp); + bnx2_del_napi(bp); + } else { + __bnx2_free_irq(bp); + } bnx2_free_skbs(bp); bnx2_free_mem(bp); } @@ -7181,9 +7204,16 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) bp->tx_ring_size = tx; if (netif_running(bp->dev)) { - int rc; + int rc = 0; + + if (reset_irq) { + rc = bnx2_setup_int_mode(bp, disable_msi); + bnx2_init_napi(bp); + } + + if (!rc) + rc = bnx2_alloc_mem(bp); - rc = bnx2_alloc_mem(bp); if (!rc) rc = bnx2_request_irq(bp); @@ -7219,7 +7249,8 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) return -EINVAL; } - rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending); + rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending, + false); return rc; } @@ -7607,6 +7638,54 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features) return 0; } +static void bnx2_get_channels(struct net_device *dev, + struct ethtool_channels *channels) +{ + struct bnx2 *bp = netdev_priv(dev); + u32 max_rx_rings = 1; + u32 max_tx_rings = 1; + + if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) { + max_rx_rings = RX_MAX_RINGS; + max_tx_rings = TX_MAX_RINGS; + } + + channels->max_rx = max_rx_rings; + channels->max_tx = max_tx_rings; + channels->max_other = 0; + channels->max_combined = 0; + channels->rx_count = bp->num_rx_rings; + channels->tx_count = bp->num_tx_rings; + channels->other_count = 0; + channels->combined_count = 0; +} + +static int bnx2_set_channels(struct net_device *dev, + struct ethtool_channels *channels) +{ + struct bnx2 *bp = netdev_priv(dev); + u32 max_rx_rings = 1; + u32 max_tx_rings = 1; + int rc = 0; + + if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) { + max_rx_rings = RX_MAX_RINGS; + max_tx_rings = TX_MAX_RINGS; + } + if (channels->rx_count > max_rx_rings || + channels->tx_count > max_tx_rings) + return -EINVAL; + + bp->num_req_rx_rings = channels->rx_count; + bp->num_req_tx_rings = channels->tx_count; + + if (netif_running(dev)) + rc = bnx2_change_ring_size(bp, bp->rx_ring_size, + bp->tx_ring_size, true); + + return rc; +} + static const struct ethtool_ops bnx2_ethtool_ops = { .get_settings = bnx2_get_settings, .set_settings = bnx2_set_settings, @@ -7631,6 +7710,8 @@ static const struct ethtool_ops bnx2_ethtool_ops = { .set_phys_id = bnx2_set_phys_id, .get_ethtool_stats = bnx2_get_ethtool_stats, .get_sset_count = bnx2_get_sset_count, + .get_channels = bnx2_get_channels, + .set_channels = bnx2_set_channels, }; /* Called with rtnl_lock */ @@ -7712,7 +7793,8 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu) return -EINVAL; dev->mtu = new_mtu; - return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size); + return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size, + false); } #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h index 1db2d51ba3f1..dc06bda73be7 100644 --- a/drivers/net/ethernet/broadcom/bnx2.h +++ b/drivers/net/ethernet/broadcom/bnx2.h @@ -6933,6 +6933,9 @@ struct bnx2 { u8 num_tx_rings; u8 num_rx_rings; + int num_req_tx_rings; + int num_req_rx_rings; + u32 leds_save; u32 idle_chk_status_idx; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 8c73d34b2ff1..7d184fbffaf6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1,6 +1,6 @@ /* bnx2x.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +23,8 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ -#define DRV_MODULE_VERSION "1.70.35-0" -#define DRV_MODULE_RELDATE "2011/11/10" +#define DRV_MODULE_VERSION "1.72.00-0" +#define DRV_MODULE_RELDATE "2012/01/26" #define BNX2X_BC_VER 0x040200 #if defined(CONFIG_DCB) @@ -1088,7 +1088,8 @@ enum bnx2x_recovery_state { BNX2X_RECOVERY_DONE, BNX2X_RECOVERY_INIT, BNX2X_RECOVERY_WAIT, - BNX2X_RECOVERY_FAILED + BNX2X_RECOVERY_FAILED, + BNX2X_RECOVERY_NIC_LOADING }; /* diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 7aee46983be4..518ec5c6872d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1,6 +1,6 @@ /* bnx2x_cmn.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1766,12 +1766,27 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bnx2x_napi_enable(bp); + /* set pf load just before approaching the MCP */ + bnx2x_set_pf_load(bp); + /* Send LOAD_REQUEST command to MCP * Returns the type of LOAD command: * if it is the first port to be initialized * common blocks should be initialized, otherwise - not */ if (!BP_NOMCP(bp)) { + /* init fw_seq */ + bp->fw_seq = + (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) & + DRV_MSG_SEQ_NUMBER_MASK); + BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq); + + /* Get current FW pulse sequence */ + bp->fw_drv_pulse_wr_seq = + (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb) & + DRV_PULSE_SEQ_MASK); + BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq); + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0); if (!load_code) { BNX2X_ERR("MCP response failure, aborting\n"); @@ -1782,6 +1797,29 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) rc = -EBUSY; /* other port in diagnostic mode */ LOAD_ERROR_EXIT(bp, load_error1); } + if (load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP && + load_code != FW_MSG_CODE_DRV_LOAD_COMMON) { + /* build FW version dword */ + u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) + + (BCM_5710_FW_MINOR_VERSION << 8) + + (BCM_5710_FW_REVISION_VERSION << 16) + + (BCM_5710_FW_ENGINEERING_VERSION << 24); + + /* read loaded FW from chip */ + u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM); + + DP(BNX2X_MSG_SP, "loaded fw %x, my fw %x", + loaded_fw, my_fw); + + /* abort nic load if version mismatch */ + if (my_fw != loaded_fw) { + BNX2X_ERR("bnx2x with FW %x already loaded, " + "which mismatches my %x FW. aborting", + loaded_fw, my_fw); + rc = -EBUSY; + LOAD_ERROR_EXIT(bp, load_error2); + } + } } else { int path = BP_PATH(bp); @@ -1948,7 +1986,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) if (bp->state == BNX2X_STATE_OPEN) bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD); #endif - bnx2x_inc_load_cnt(bp); /* Wait for all pending SP commands to complete */ if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) { @@ -1988,6 +2025,8 @@ load_error2: bp->port.pmf = 0; load_error1: bnx2x_napi_disable(bp); + /* clear pf_load status, as it was already set */ + bnx2x_clear_pf_load(bp); load_error0: bnx2x_free_mem(bp); @@ -2108,7 +2147,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) /* The last driver must disable a "close the gate" if there is no * parity attention or "process kill" pending. */ - if (!bnx2x_dec_load_cnt(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp))) + if (!bnx2x_clear_pf_load(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp))) bnx2x_disable_close_the_gate(bp); return 0; @@ -3414,7 +3453,7 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu) struct bnx2x *bp = netdev_priv(dev); if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - pr_err("Handling parity error recovery. Try again later\n"); + netdev_err(dev, "Handling parity error recovery. Try again later\n"); return -EAGAIN; } @@ -3541,7 +3580,7 @@ int bnx2x_resume(struct pci_dev *pdev) bp = netdev_priv(dev); if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - pr_err("Handling parity error recovery. Try again later\n"); + netdev_err(dev, "Handling parity error recovery. Try again later\n"); return -EAGAIN; } @@ -3557,8 +3596,6 @@ int bnx2x_resume(struct pci_dev *pdev) bnx2x_set_power_state(bp, PCI_D0); netif_device_attach(dev); - /* Since the chip was reset, clear the FW sequence number */ - bp->fw_seq = 0; rc = bnx2x_nic_load(bp, LOAD_OPEN); rtnl_unlock(); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index bf27c54ff2e0..c7c7bf1e573a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -1,6 +1,6 @@ /* bnx2x_cmn.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -379,8 +379,8 @@ void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id, unsigned long ramrod_flags); /* Parity errors related */ -void bnx2x_inc_load_cnt(struct bnx2x *bp); -u32 bnx2x_dec_load_cnt(struct bnx2x *bp); +void bnx2x_set_pf_load(struct bnx2x *bp); +bool bnx2x_clear_pf_load(struct bnx2x *bp); bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print); bool bnx2x_reset_is_done(struct bnx2x *bp, int engine); void bnx2x_set_reset_in_progress(struct bnx2x *bp); @@ -984,10 +984,11 @@ static inline int bnx2x_func_start(struct bnx2x *bp) /* Function parameters */ start_params->mf_mode = bp->mf_mode; start_params->sd_vlan_tag = bp->mf_ov; - if (CHIP_IS_E1x(bp)) - start_params->network_cos_mode = OVERRIDE_COS; - else + + if (CHIP_IS_E2(bp) || CHIP_IS_E3(bp)) start_params->network_cos_mode = STATIC_COS; + else /* CHIP_IS_E1X */ + start_params->network_cos_mode = FW_WRR; return bnx2x_func_state_change(bp, &func_params); } @@ -1539,7 +1540,7 @@ static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set) { if (SHMEM2_HAS(bp, drv_flags)) { u32 drv_flags; - bnx2x_acquire_hw_lock(bp, HW_LOCK_DRV_FLAGS); + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_DRV_FLAGS); drv_flags = SHMEM2_RD(bp, drv_flags); if (set) @@ -1549,7 +1550,7 @@ static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set) SHMEM2_WR(bp, drv_flags, drv_flags); DP(NETIF_MSG_HW, "drv_flags 0x%08x\n", drv_flags); - bnx2x_release_hw_lock(bp, HW_LOCK_DRV_FLAGS); + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_DRV_FLAGS); } } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c index 5051cf3deb20..9a9bd3ab4793 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c @@ -1,6 +1,6 @@ /* bnx2x_dcb.c: Broadcom Everest network driver. * - * Copyright 2009-2011 Broadcom Corporation + * Copyright 2009-2012 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h index 2ab9254e2d5e..06c7a0435948 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h @@ -1,6 +1,6 @@ /* bnx2x_dcb.h: Broadcom Everest network driver. * - * Copyright 2009-2011 Broadcom Corporation + * Copyright 2009-2012 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h index b983825d0ee9..3e4cff9b1ebe 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h @@ -1,6 +1,6 @@ /* bnx2x_dump.h: Broadcom Everest network driver. * - * Copyright (c) 2011 Broadcom Corporation + * Copyright (c) 2012 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 31a8b38ab15e..137968d33d1e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1,6 +1,6 @@ /* bnx2x_ethtool.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -175,7 +175,11 @@ static const struct { { STATS_OFFSET32(total_tpa_aggregated_frames_hi), 8, STATS_FLAGS_FUNC, "tpa_aggregated_frames"}, { STATS_OFFSET32(total_tpa_bytes_hi), - 8, STATS_FLAGS_FUNC, "tpa_bytes"} + 8, STATS_FLAGS_FUNC, "tpa_bytes"}, + { STATS_OFFSET32(recoverable_error), + 4, STATS_FLAGS_FUNC, "recoverable_errors" }, + { STATS_OFFSET32(unrecoverable_error), + 4, STATS_FLAGS_FUNC, "unrecoverable_errors" }, }; #define BNX2X_NUM_STATS ARRAY_SIZE(bnx2x_stats_arr) @@ -882,11 +886,27 @@ static int bnx2x_get_eeprom_len(struct net_device *dev) return bp->common.flash_size; } +/* Per pf misc lock must be aquired before the per port mcp lock. Otherwise, had + * we done things the other way around, if two pfs from the same port would + * attempt to access nvram at the same time, we could run into a scenario such + * as: + * pf A takes the port lock. + * pf B succeeds in taking the same lock since they are from the same port. + * pf A takes the per pf misc lock. Performs eeprom access. + * pf A finishes. Unlocks the per pf misc lock. + * Pf B takes the lock and proceeds to perform it's own access. + * pf A unlocks the per port lock, while pf B is still working (!). + * mcp takes the per port lock and corrupts pf B's access (and/or has it's own + * acess corrupted by pf B).* + */ static int bnx2x_acquire_nvram_lock(struct bnx2x *bp) { int port = BP_PORT(bp); int count, i; - u32 val = 0; + u32 val; + + /* acquire HW lock: protect against other PFs in PF Direct Assignment */ + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_NVRAM); /* adjust timeout for emulation/FPGA */ count = BNX2X_NVRAM_TIMEOUT_COUNT; @@ -917,7 +937,7 @@ static int bnx2x_release_nvram_lock(struct bnx2x *bp) { int port = BP_PORT(bp); int count, i; - u32 val = 0; + u32 val; /* adjust timeout for emulation/FPGA */ count = BNX2X_NVRAM_TIMEOUT_COUNT; @@ -941,6 +961,8 @@ static int bnx2x_release_nvram_lock(struct bnx2x *bp) return -EBUSY; } + /* release HW lock: protect against other PFs in PF Direct Assignment */ + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_NVRAM); return 0; } @@ -1370,7 +1392,8 @@ static int bnx2x_set_ringparam(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - pr_err("Handling parity error recovery. Try again later\n"); + netdev_err(dev, "Handling parity error recovery. " + "Try again later\n"); return -EAGAIN; } @@ -2024,7 +2047,8 @@ static void bnx2x_self_test(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); u8 is_serdes; if (bp->recovery_state != BNX2X_RECOVERY_DONE) { - pr_err("Handling parity error recovery. Try again later\n"); + netdev_err(bp->dev, "Handling parity error recovery. " + "Try again later\n"); etest->flags |= ETH_TEST_FL_FAILED; return; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h index 998652a1b858..e5c5982ae06d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h @@ -1,6 +1,6 @@ /* bnx2x_fw_defs.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h index f4a07fbaed05..4bed52ba300d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h @@ -1,6 +1,6 @@ /* bnx2x_fw_file_hdr.h: FW binary file header structure. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h index 3e30c8642c26..78b77de728b0 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h @@ -1,6 +1,6 @@ /* bnx2x_hsi.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h index 4d748e77d1ac..29f5c3cca31a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h @@ -1,7 +1,7 @@ /* bnx2x_init.h: Broadcom Everest network driver. * Structures and macroes needed during the initialization. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h index 7ec1724753ad..fe66d902dc62 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h @@ -2,7 +2,7 @@ * Static functions needed during the initialization. * This file is "included" in bnx2x_main.c. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,12 +69,12 @@ static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len, { if (bp->dmae_ready) bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len); - else if (wb) - /* - * Wide bus registers with no dmae need to be written - * using indirect write. - */ + + /* in E1 chips BIOS initiated ZLR may interrupt widebus writes */ + else if (wb && CHIP_IS_E1(bp)) bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len); + + /* in later chips PXP root complex handles BIOS ZLR w/o interrupting */ else bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len); } @@ -99,8 +99,14 @@ static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len) { if (bp->dmae_ready) bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len); - else + + /* in E1 chips BIOS initiated ZLR may interrupt widebus writes */ + else if (CHIP_IS_E1(bp)) bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len); + + /* in later chips PXP root complex handles BIOS ZLR w/o interrupting */ + else + bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len); } static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr, @@ -177,8 +183,14 @@ static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, { if (bp->dmae_ready) VIRT_WR_DMAE_LEN(bp, data, addr, len, 0); - else + + /* in E1 chips BIOS initiated ZLR may interrupt widebus writes */ + else if (CHIP_IS_E1(bp)) bnx2x_init_ind_wr(bp, addr, data, len); + + /* in later chips PXP root complex handles BIOS ZLR w/o interrupting */ + else + bnx2x_init_str_wr(bp, addr, data, len); } static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo, @@ -840,25 +852,15 @@ static void bnx2x_qm_init_cid_count(struct bnx2x *bp, int qm_cid_count, } } -static void bnx2x_qm_set_ptr_table(struct bnx2x *bp, int qm_cid_count) +static void bnx2x_qm_set_ptr_table(struct bnx2x *bp, int qm_cid_count, + u32 base_reg, u32 reg) { int i; - u32 wb_data[2]; - - wb_data[0] = wb_data[1] = 0; - + u32 wb_data[2] = {0, 0}; for (i = 0; i < 4 * QM_QUEUES_PER_FUNC; i++) { - REG_WR(bp, QM_REG_BASEADDR + i*4, + REG_WR(bp, base_reg + i*4, qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC)); - bnx2x_init_ind_wr(bp, QM_REG_PTRTBL + i*8, - wb_data, 2); - - if (CHIP_IS_E1H(bp)) { - REG_WR(bp, QM_REG_BASEADDR_EXT_A + i*4, - qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC)); - bnx2x_init_ind_wr(bp, QM_REG_PTRTBL_EXT_A + i*8, - wb_data, 2); - } + bnx2x_init_wr_wb(bp, reg + i*8, wb_data, 2); } } @@ -873,7 +875,12 @@ static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count, case INITOP_INIT: /* set in the init-value array */ case INITOP_SET: - bnx2x_qm_set_ptr_table(bp, qm_cid_count); + bnx2x_qm_set_ptr_table(bp, qm_cid_count, + QM_REG_BASEADDR, QM_REG_PTRTBL); + if (CHIP_IS_E1H(bp)) + bnx2x_qm_set_ptr_table(bp, qm_cid_count, + QM_REG_BASEADDR_EXT_A, + QM_REG_PTRTBL_EXT_A); break; case INITOP_CLEAR: break; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 2091e5dbbcdd..2102ad593c14 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -1,4 +1,4 @@ -/* Copyright 2008-2011 Broadcom Corporation +/* Copyright 2008-2012 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h index e02a68a7fb85..9cc7bafb3dfe 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h @@ -1,4 +1,4 @@ -/* Copyright 2008-2011 Broadcom Corporation +/* Copyright 2008-2012 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 1e3f978ee6da..ff19c3cf4409 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -1,6 +1,6 @@ /* bnx2x_main.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -468,7 +468,9 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, while ((*wb_comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) { DP(BNX2X_MSG_OFF, "wb_comp 0x%08x\n", *wb_comp); - if (!cnt) { + if (!cnt || + (bp->recovery_state != BNX2X_RECOVERY_DONE && + bp->recovery_state != BNX2X_RECOVERY_NIC_LOADING)) { BNX2X_ERR("DMAE timeout!\n"); rc = DMAE_TIMEOUT; goto unlock; @@ -498,9 +500,13 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr, if (!bp->dmae_ready) { u32 *data = bnx2x_sp(bp, wb_data[0]); - DP(BNX2X_MSG_OFF, "DMAE is not ready (dst_addr %08x len32 %d)" - " using indirect\n", dst_addr, len32); - bnx2x_init_ind_wr(bp, dst_addr, data, len32); + DP(BNX2X_MSG_OFF, + "DMAE is not ready (dst_addr %08x len32 %d) using indirect\n", + dst_addr, len32); + if (CHIP_IS_E1(bp)) + bnx2x_init_ind_wr(bp, dst_addr, data, len32); + else + bnx2x_init_str_wr(bp, dst_addr, data, len32); return; } @@ -528,10 +534,16 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32) u32 *data = bnx2x_sp(bp, wb_data[0]); int i; - DP(BNX2X_MSG_OFF, "DMAE is not ready (src_addr %08x len32 %d)" - " using indirect\n", src_addr, len32); - for (i = 0; i < len32; i++) - data[i] = bnx2x_reg_rd_ind(bp, src_addr + i*4); + if (CHIP_IS_E1(bp)) { + DP(BNX2X_MSG_OFF, + "DMAE is not ready (src_addr %08x len32 %d) using indirect\n", + src_addr, len32); + for (i = 0; i < len32; i++) + data[i] = bnx2x_reg_rd_ind(bp, src_addr + i*4); + } else + for (i = 0; i < len32; i++) + data[i] = REG_RD(bp, src_addr + i*4); + return; } @@ -772,6 +784,7 @@ void bnx2x_panic_dump(struct bnx2x *bp) #endif bp->stats_state = STATS_STATE_DISABLED; + bp->eth_stats.unrecoverable_error++; DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n"); BNX2X_ERR("begin crash dump -----------------\n"); @@ -1007,8 +1020,8 @@ void bnx2x_panic_dump(struct bnx2x *bp) * initialization. */ #define FLR_WAIT_USEC 10000 /* 10 miliseconds */ -#define FLR_WAIT_INTERAVAL 50 /* usec */ -#define FLR_POLL_CNT (FLR_WAIT_USEC/FLR_WAIT_INTERAVAL) /* 200 */ +#define FLR_WAIT_INTERVAL 50 /* usec */ +#define FLR_POLL_CNT (FLR_WAIT_USEC/FLR_WAIT_INTERVAL) /* 200 */ struct pbf_pN_buf_regs { int pN; @@ -1041,7 +1054,7 @@ static void bnx2x_pbf_pN_buf_flushed(struct bnx2x *bp, while ((crd != init_crd) && ((u32)SUB_S32(crd_freed, crd_freed_start) < (init_crd - crd_start))) { if (cur_cnt--) { - udelay(FLR_WAIT_INTERAVAL); + udelay(FLR_WAIT_INTERVAL); crd = REG_RD(bp, regs->crd); crd_freed = REG_RD(bp, regs->crd_freed); } else { @@ -1055,7 +1068,7 @@ static void bnx2x_pbf_pN_buf_flushed(struct bnx2x *bp, } } DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF tx buffer[%d]\n", - poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN); + poll_count-cur_cnt, FLR_WAIT_INTERVAL, regs->pN); } static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp, @@ -1073,7 +1086,7 @@ static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp, while (occup && ((u32)SUB_S32(freed, freed_start) < to_free)) { if (cur_cnt--) { - udelay(FLR_WAIT_INTERAVAL); + udelay(FLR_WAIT_INTERVAL); occup = REG_RD(bp, regs->lines_occup); freed = REG_RD(bp, regs->lines_freed); } else { @@ -1087,7 +1100,7 @@ static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp, } } DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF cmd queue[%d]\n", - poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN); + poll_count-cur_cnt, FLR_WAIT_INTERVAL, regs->pN); } static inline u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg, @@ -1097,7 +1110,7 @@ static inline u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg, u32 val; while ((val = REG_RD(bp, reg)) != expected && cur_cnt--) - udelay(FLR_WAIT_INTERAVAL); + udelay(FLR_WAIT_INTERVAL); return val; } @@ -1210,7 +1223,7 @@ static inline int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func, int ret = 0; if (REG_RD(bp, comp_addr)) { - BNX2X_ERR("Cleanup complete is not 0\n"); + BNX2X_ERR("Cleanup complete was not 0 before sending\n"); return 1; } @@ -1219,7 +1232,7 @@ static inline int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func, op_gen.command |= OP_GEN_AGG_VECT(clnup_func); op_gen.command |= 1 << SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT; - DP(BNX2X_MSG_SP, "FW Final cleanup\n"); + DP(BNX2X_MSG_SP, "sending FW Final cleanup\n"); REG_WR(bp, XSDM_REG_OPERATION_GEN, op_gen.command); if (bnx2x_flr_clnup_reg_poll(bp, comp_addr, 1, poll_cnt) != 1) { @@ -1334,6 +1347,7 @@ static int bnx2x_pf_flr_clnup(struct bnx2x *bp) REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); /* Poll HW usage counters */ + DP(BNX2X_MSG_SP, "Polling usage counters\n"); if (bnx2x_poll_hw_usage_counters(bp, poll_cnt)) return -EBUSY; @@ -3713,11 +3727,11 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) */ void bnx2x_set_reset_global(struct bnx2x *bp) { - u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); - + u32 val; + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); + val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val | BNX2X_GLOBAL_RESET_BIT); - barrier(); - mmiowb(); + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); } /* @@ -3727,11 +3741,11 @@ void bnx2x_set_reset_global(struct bnx2x *bp) */ static inline void bnx2x_clear_reset_global(struct bnx2x *bp) { - u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); - + u32 val; + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); + val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~BNX2X_GLOBAL_RESET_BIT)); - barrier(); - mmiowb(); + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); } /* @@ -3754,15 +3768,17 @@ static inline bool bnx2x_reset_is_global(struct bnx2x *bp) */ static inline void bnx2x_set_reset_done(struct bnx2x *bp) { - u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); + u32 val; u32 bit = BP_PATH(bp) ? BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT; + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); + val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); /* Clear the bit */ val &= ~bit; REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); - barrier(); - mmiowb(); + + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); } /* @@ -3772,15 +3788,16 @@ static inline void bnx2x_set_reset_done(struct bnx2x *bp) */ void bnx2x_set_reset_in_progress(struct bnx2x *bp) { - u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); + u32 val; u32 bit = BP_PATH(bp) ? BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT; + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); + val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); /* Set the bit */ val |= bit; REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); - barrier(); - mmiowb(); + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); } /* @@ -3798,25 +3815,28 @@ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine) } /* - * Increment the load counter for the current engine. + * set pf load for the current pf. * * should be run under rtnl lock */ -void bnx2x_inc_load_cnt(struct bnx2x *bp) +void bnx2x_set_pf_load(struct bnx2x *bp) { - u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); + u32 val1, val; u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : BNX2X_PATH0_LOAD_CNT_MASK; u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT : BNX2X_PATH0_LOAD_CNT_SHIFT; + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); + val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); + DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val); /* get the current counter value */ val1 = (val & mask) >> shift; - /* increment... */ - val1++; + /* set bit of that PF */ + val1 |= (1 << bp->pf_num); /* clear the old value */ val &= ~mask; @@ -3825,34 +3845,35 @@ void bnx2x_inc_load_cnt(struct bnx2x *bp) val |= ((val1 << shift) & mask); REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); - barrier(); - mmiowb(); + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); } /** - * bnx2x_dec_load_cnt - decrement the load counter + * bnx2x_clear_pf_load - clear pf load mark * * @bp: driver handle * * Should be run under rtnl lock. * Decrements the load counter for the current engine. Returns - * the new counter value. + * whether other functions are still loaded */ -u32 bnx2x_dec_load_cnt(struct bnx2x *bp) +bool bnx2x_clear_pf_load(struct bnx2x *bp) { - u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); + u32 val1, val; u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : BNX2X_PATH0_LOAD_CNT_MASK; u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT : BNX2X_PATH0_LOAD_CNT_SHIFT; + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); + val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val); /* get the current counter value */ val1 = (val & mask) >> shift; - /* decrement... */ - val1--; + /* clear bit of that PF */ + val1 &= ~(1 << bp->pf_num); /* clear the old value */ val &= ~mask; @@ -3861,18 +3882,16 @@ u32 bnx2x_dec_load_cnt(struct bnx2x *bp) val |= ((val1 << shift) & mask); REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); - barrier(); - mmiowb(); - - return val1; + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); + return val1 != 0; } /* - * Read the load counter for the current engine. + * Read the load status for the current engine. * * should be run under rtnl lock */ -static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine) +static inline bool bnx2x_get_load_status(struct bnx2x *bp, int engine) { u32 mask = (engine ? BNX2X_PATH1_LOAD_CNT_MASK : BNX2X_PATH0_LOAD_CNT_MASK); @@ -3884,23 +3903,23 @@ static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine) val = (val & mask) >> shift; - DP(NETIF_MSG_HW, "load_cnt for engine %d = %d\n", engine, val); + DP(NETIF_MSG_HW, "load mask for engine %d = 0x%x\n", engine, val); - return val; + return val != 0; } /* - * Reset the load counter for the current engine. - * - * should be run under rtnl lock + * Reset the load status for the current engine. */ -static inline void bnx2x_clear_load_cnt(struct bnx2x *bp) +static inline void bnx2x_clear_load_status(struct bnx2x *bp) { - u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); + u32 val; u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : - BNX2X_PATH0_LOAD_CNT_MASK); - + BNX2X_PATH0_LOAD_CNT_MASK); + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); + val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~mask)); + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); } static inline void _print_next_block(int idx, const char *blk) @@ -5423,6 +5442,7 @@ static void bnx2x_init_eth_fp(struct bnx2x *bp, int fp_idx) /* init shortcut */ fp->ustorm_rx_prods_offset = bnx2x_rx_ustorm_prods_offset(fp); + /* Setup SB indicies */ fp->rx_cons_sb = BNX2X_RX_SB_INDEX; @@ -6687,13 +6707,16 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) u16 cdu_ilt_start; u32 addr, val; u32 main_mem_base, main_mem_size, main_mem_prty_clr; - int i, main_mem_width; + int i, main_mem_width, rc; DP(BNX2X_MSG_MCP, "starting func init func %d\n", func); /* FLR cleanup - hmmm */ - if (!CHIP_IS_E1x(bp)) - bnx2x_pf_flr_clnup(bp); + if (!CHIP_IS_E1x(bp)) { + rc = bnx2x_pf_flr_clnup(bp); + if (rc) + return rc; + } /* set MSI reconfigure capability */ if (bp->common.int_block == INT_BLOCK_HC) { @@ -8458,13 +8481,38 @@ int bnx2x_leader_reset(struct bnx2x *bp) { int rc = 0; bool global = bnx2x_reset_is_global(bp); + u32 load_code; + + /* if not going to reset MCP - load "fake" driver to reset HW while + * driver is owner of the HW + */ + if (!global && !BP_NOMCP(bp)) { + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0); + if (!load_code) { + BNX2X_ERR("MCP response failure, aborting\n"); + rc = -EAGAIN; + goto exit_leader_reset; + } + if ((load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) && + (load_code != FW_MSG_CODE_DRV_LOAD_COMMON)) { + BNX2X_ERR("MCP unexpected resp, aborting\n"); + rc = -EAGAIN; + goto exit_leader_reset2; + } + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0); + if (!load_code) { + BNX2X_ERR("MCP response failure, aborting\n"); + rc = -EAGAIN; + goto exit_leader_reset2; + } + } /* Try to recover after the failure */ if (bnx2x_process_kill(bp, global)) { netdev_err(bp->dev, "Something bad had happen on engine %d! " "Aii!\n", BP_PATH(bp)); rc = -EAGAIN; - goto exit_leader_reset; + goto exit_leader_reset2; } /* @@ -8475,6 +8523,12 @@ int bnx2x_leader_reset(struct bnx2x *bp) if (global) bnx2x_clear_reset_global(bp); +exit_leader_reset2: + /* unload "fake driver" if it was loaded */ + if (!global && !BP_NOMCP(bp)) { + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); + } exit_leader_reset: bp->is_leader = 0; bnx2x_release_leader_lock(bp); @@ -8511,13 +8565,16 @@ static inline void bnx2x_recovery_failed(struct bnx2x *bp) static void bnx2x_parity_recover(struct bnx2x *bp) { bool global = false; + u32 error_recovered, error_unrecovered; + bool is_parity; DP(NETIF_MSG_HW, "Handling parity\n"); while (1) { switch (bp->recovery_state) { case BNX2X_RECOVERY_INIT: DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_INIT\n"); - bnx2x_chk_parity_attn(bp, &global, false); + is_parity = bnx2x_chk_parity_attn(bp, &global, false); + WARN_ON(!is_parity); /* Try to get a LEADER_LOCK HW lock */ if (bnx2x_trylock_leader_lock(bp)) { @@ -8541,15 +8598,6 @@ static void bnx2x_parity_recover(struct bnx2x *bp) bp->recovery_state = BNX2X_RECOVERY_WAIT; - /* - * Reset MCP command sequence number and MCP mail box - * sequence as we are going to reset the MCP. - */ - if (global) { - bp->fw_seq = 0; - bp->fw_drv_pulse_wr_seq = 0; - } - /* Ensure "is_leader", MCP command sequence and * "recovery_state" update values are seen on other * CPUs. @@ -8561,10 +8609,10 @@ static void bnx2x_parity_recover(struct bnx2x *bp) DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_WAIT\n"); if (bp->is_leader) { int other_engine = BP_PATH(bp) ? 0 : 1; - u32 other_load_counter = - bnx2x_get_load_cnt(bp, other_engine); - u32 load_counter = - bnx2x_get_load_cnt(bp, BP_PATH(bp)); + bool other_load_status = + bnx2x_get_load_status(bp, other_engine); + bool load_status = + bnx2x_get_load_status(bp, BP_PATH(bp)); global = bnx2x_reset_is_global(bp); /* @@ -8575,8 +8623,8 @@ static void bnx2x_parity_recover(struct bnx2x *bp) * the the gates will remain closed for that * engine. */ - if (load_counter || - (global && other_load_counter)) { + if (load_status || + (global && other_load_status)) { /* Wait until all other functions get * down. */ @@ -8633,13 +8681,34 @@ static void bnx2x_parity_recover(struct bnx2x *bp) return; } - if (bnx2x_nic_load(bp, LOAD_NORMAL)) - bnx2x_recovery_failed(bp); - else { + error_recovered = + bp->eth_stats.recoverable_error; + error_unrecovered = + bp->eth_stats.unrecoverable_error; + bp->recovery_state = + BNX2X_RECOVERY_NIC_LOADING; + if (bnx2x_nic_load(bp, LOAD_NORMAL)) { + error_unrecovered++; + netdev_err(bp->dev, + "Recovery failed. " + "Power cycle " + "needed\n"); + /* Disconnect this device */ + netif_device_detach(bp->dev); + /* Shut down the power */ + bnx2x_set_power_state( + bp, PCI_D3hot); + smp_mb(); + } else { bp->recovery_state = BNX2X_RECOVERY_DONE; + error_recovered++; smp_mb(); } + bp->eth_stats.recoverable_error = + error_recovered; + bp->eth_stats.unrecoverable_error = + error_unrecovered; return; } @@ -8795,11 +8864,13 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) { u32 val; - /* Check if there is any driver already loaded */ - val = REG_RD(bp, MISC_REG_UNPREPARED); - if (val == 0x1) { + /* possibly another driver is trying to reset the chip */ + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET); + + /* check if doorbell queue is reset */ + if (REG_RD(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET) + & MISC_REGISTERS_RESET_REG_1_RST_DORQ) { - bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET); /* * Check if it is the UNDI driver * UNDI driver initializes CID offset for normal bell to 0x7 @@ -8887,14 +8958,11 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) /* restore our func and fw_seq */ bp->pf_num = orig_pf_num; - bp->fw_seq = - (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) & - DRV_MSG_SEQ_NUMBER_MASK); } - - /* now it's safe to release the lock */ - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET); } + + /* now it's safe to release the lock */ + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET); } static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) @@ -9915,16 +9983,6 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) bnx2x_get_cnic_info(bp); - /* Get current FW pulse sequence */ - if (!BP_NOMCP(bp)) { - int mb_idx = BP_FW_MB_IDX(bp); - - bp->fw_drv_pulse_wr_seq = - (SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) & - DRV_PULSE_SEQ_MASK); - BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq); - } - return rc; } @@ -10094,14 +10152,6 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) if (!BP_NOMCP(bp)) bnx2x_undi_unload(bp); - /* init fw_seq after undi_unload! */ - if (!BP_NOMCP(bp)) { - bp->fw_seq = - (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) & - DRV_MSG_SEQ_NUMBER_MASK); - BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq); - } - if (CHIP_REV_IS_FPGA(bp)) dev_err(&bp->pdev->dev, "FPGA detected\n"); @@ -10183,14 +10233,14 @@ static int bnx2x_open(struct net_device *dev) struct bnx2x *bp = netdev_priv(dev); bool global = false; int other_engine = BP_PATH(bp) ? 0 : 1; - u32 other_load_counter, load_counter; + bool other_load_status, load_status; netif_carrier_off(dev); bnx2x_set_power_state(bp, PCI_D0); - other_load_counter = bnx2x_get_load_cnt(bp, other_engine); - load_counter = bnx2x_get_load_cnt(bp, BP_PATH(bp)); + other_load_status = bnx2x_get_load_status(bp, other_engine); + load_status = bnx2x_get_load_status(bp, BP_PATH(bp)); /* * If parity had happen during the unload, then attentions @@ -10216,8 +10266,8 @@ static int bnx2x_open(struct net_device *dev) * global blocks only the first in the chip should try * to recover. */ - if ((!load_counter && - (!global || !other_load_counter)) && + if ((!load_status && + (!global || !other_load_status)) && bnx2x_trylock_leader_lock(bp) && !bnx2x_leader_reset(bp)) { netdev_info(bp->dev, "Recovered in open\n"); @@ -10536,6 +10586,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, { struct bnx2x *bp; int rc; + u32 pci_cfg_dword; bool chip_is_e1x = (board_type == BCM57710 || board_type == BCM57711 || board_type == BCM57711E); @@ -10546,7 +10597,6 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, bp->dev = dev; bp->pdev = pdev; bp->flags = 0; - bp->pf_num = PCI_FUNC(pdev->devfn); rc = pci_enable_device(pdev); if (rc) { @@ -10613,6 +10663,21 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, goto err_out_release; } + /* In E1/E1H use pci device function given by kernel. + * In E2/E3 read physical function from ME register since these chips + * support Physical Device Assignment where kernel BDF maybe arbitrary + * (depending on hypervisor). + */ + if (chip_is_e1x) + bp->pf_num = PCI_FUNC(pdev->devfn); + else {/* chip is E2/3*/ + pci_read_config_dword(bp->pdev, + PCICFG_ME_REGISTER, &pci_cfg_dword); + bp->pf_num = (u8)((pci_cfg_dword & ME_REG_ABS_PF_NUM) >> + ME_REG_ABS_PF_NUM_SHIFT); + } + DP(BNX2X_MSG_SP, "me reg PF num: %d\n", bp->pf_num); + bnx2x_set_power_state(bp, PCI_D0); /* clean indirect addresses */ @@ -10642,7 +10707,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); /* Reset the load counter */ - bnx2x_clear_load_cnt(bp); + bnx2x_clear_load_status(bp); dev->watchdog_timeo = TX_TIMEOUT; @@ -10829,10 +10894,8 @@ static inline void be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n) do { \ u32 len = be32_to_cpu(fw_hdr->arr.len); \ bp->arr = kmalloc(len, GFP_KERNEL); \ - if (!bp->arr) { \ - pr_err("Failed to allocate %d bytes for "#arr"\n", len); \ + if (!bp->arr) \ goto lbl; \ - } \ func(bp->firmware->data + be32_to_cpu(fw_hdr->arr.offset), \ (u8 *)bp->arr, len); \ } while (0) @@ -11070,10 +11133,8 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, /* dev zeroed in init_etherdev */ dev = alloc_etherdev_mqs(sizeof(*bp), tx_count, rx_count); - if (!dev) { - dev_err(&pdev->dev, "Cannot allocate net device\n"); + if (!dev) return -ENOMEM; - } bp = netdev_priv(dev); @@ -11295,13 +11356,6 @@ static void bnx2x_eeh_recover(struct bnx2x *bp) if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) BNX2X_ERR("BAD MCP validity signature\n"); - - if (!BP_NOMCP(bp)) { - bp->fw_seq = - (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) & - DRV_MSG_SEQ_NUMBER_MASK); - BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq); - } } /** @@ -11557,6 +11611,13 @@ static int bnx2x_cnic_sp_queue(struct net_device *dev, return -EIO; #endif + if ((bp->recovery_state != BNX2X_RECOVERY_DONE) && + (bp->recovery_state != BNX2X_RECOVERY_NIC_LOADING)) { + netdev_err(dev, "Handling parity error recovery. Try again " + "later\n"); + return -EAGAIN; + } + spin_lock_bh(&bp->spq_lock); for (i = 0; i < count; i++) { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index dddbcf6e154e..c95d9dcac6df 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h @@ -1,6 +1,6 @@ /* bnx2x_reg.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -5731,6 +5731,7 @@ #define MISC_REGISTERS_GPIO_PORT_SHIFT 4 #define MISC_REGISTERS_GPIO_SET_POS 8 #define MISC_REGISTERS_RESET_REG_1_CLEAR 0x588 +#define MISC_REGISTERS_RESET_REG_1_RST_DORQ (0x1<<19) #define MISC_REGISTERS_RESET_REG_1_RST_HC (0x1<<29) #define MISC_REGISTERS_RESET_REG_1_RST_NIG (0x1<<7) #define MISC_REGISTERS_RESET_REG_1_RST_PXP (0x1<<26) @@ -5783,15 +5784,17 @@ #define MISC_REGISTERS_SPIO_OUTPUT_HIGH 1 #define MISC_REGISTERS_SPIO_OUTPUT_LOW 0 #define MISC_REGISTERS_SPIO_SET_POS 8 -#define HW_LOCK_DRV_FLAGS 10 #define HW_LOCK_MAX_RESOURCE_VALUE 31 +#define HW_LOCK_RESOURCE_DRV_FLAGS 10 #define HW_LOCK_RESOURCE_GPIO 1 #define HW_LOCK_RESOURCE_MDIO 0 +#define HW_LOCK_RESOURCE_NVRAM 12 #define HW_LOCK_RESOURCE_PORT0_ATT_MASK 3 #define HW_LOCK_RESOURCE_RECOVERY_LEADER_0 8 #define HW_LOCK_RESOURCE_RECOVERY_LEADER_1 9 -#define HW_LOCK_RESOURCE_SPIO 2 +#define HW_LOCK_RESOURCE_RECOVERY_REG 11 #define HW_LOCK_RESOURCE_RESET 5 +#define HW_LOCK_RESOURCE_SPIO 2 #define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT (0x1<<4) #define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR (0x1<<5) #define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR (0x1<<18) @@ -6023,7 +6026,8 @@ #define PCICFG_MSI_CONTROL_64_BIT_ADDR_CAP (0x1<<23) #define PCICFG_MSI_CONTROL_MSI_PVMASK_CAPABLE (0x1<<24) #define PCICFG_GRC_ADDRESS 0x78 -#define PCICFG_GRC_DATA 0x80 +#define PCICFG_GRC_DATA 0x80 +#define PCICFG_ME_REGISTER 0x98 #define PCICFG_MSIX_CAP_ID_OFFSET 0xa0 #define PCICFG_MSIX_CONTROL_TABLE_SIZE (0x7ff<<16) #define PCICFG_MSIX_CONTROL_RESERVED (0x7<<27) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index cb6339c35571..ac15f747f8da 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -1,6 +1,6 @@ /* bnx2x_sp.c: Broadcom Everest network driver. * - * Copyright 2011 Broadcom Corporation + * Copyright (c) 2011-2012 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you @@ -1836,6 +1836,7 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp, rc = exeq->remove(bp, exeq->owner, exeq_pos); if (rc) { BNX2X_ERR("Failed to remove command\n"); + spin_unlock_bh(&exeq->lock); return rc; } list_del(&exeq_pos->link); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index 66da39f0c84a..71e039b618a7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h @@ -1,6 +1,6 @@ /* bnx2x_sp.h: Broadcom Everest network driver. * - * Copyright 2011 Broadcom Corporation + * Copyright (c) 2011-2012 Broadcom Corporation * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you @@ -803,10 +803,10 @@ enum bnx2x_q_type { }; #define BNX2X_PRIMARY_CID_INDEX 0 -#define BNX2X_MULTI_TX_COS_E1X 1 +#define BNX2X_MULTI_TX_COS_E1X 3 /* QM only */ #define BNX2X_MULTI_TX_COS_E2_E3A0 2 #define BNX2X_MULTI_TX_COS_E3B0 3 -#define BNX2X_MULTI_TX_COS BNX2X_MULTI_TX_COS_E3B0 +#define BNX2X_MULTI_TX_COS 3 /* Maximum possible */ struct bnx2x_queue_init_params { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index bc0121ac291e..7b9b304b9107 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -1,6 +1,6 @@ /* bnx2x_stats.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h index 683deb053109..7e979686cd68 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h @@ -1,6 +1,6 @@ /* bnx2x_stats.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2011 Broadcom Corporation + * Copyright (c) 2007-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -199,6 +199,10 @@ struct bnx2x_eth_stats { u32 pfc_frames_received_lo; u32 pfc_frames_sent_hi; u32 pfc_frames_sent_lo; + + /* Recovery */ + u32 recoverable_error; + u32 unrecoverable_error; }; diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index dd3a0a232ea0..df429959abdd 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c @@ -1,6 +1,6 @@ /* cnic.c: Broadcom CNIC core network driver. * - * Copyright (c) 2006-2011 Broadcom Corporation + * Copyright (c) 2006-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -380,6 +380,8 @@ static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type, if (cnic_in_use(csk) && test_bit(SK_F_CONNECT_START, &csk->flags)) { + csk->vlan_id = path_resp->vlan_id; + memcpy(csk->ha, path_resp->mac_addr, 6); if (test_bit(SK_F_IPV6, &csk->flags)) memcpy(&csk->src_ip[0], &path_resp->src.v6_addr, @@ -2521,12 +2523,35 @@ static void cnic_bnx2x_kwqe_err(struct cnic_dev *dev, struct kwqe *kwqe) u32 cid; u32 opcode = KWQE_OPCODE(kwqe->kwqe_op_flag); u32 layer_code = kwqe->kwqe_op_flag & KWQE_LAYER_MASK; + u32 kcqe_op; int ulp_type; cid = kwqe->kwqe_info0; memset(&kcqe, 0, sizeof(kcqe)); - if (layer_code == KWQE_FLAGS_LAYER_MASK_L5_ISCSI) { + if (layer_code == KWQE_FLAGS_LAYER_MASK_L5_FCOE) { + u32 l5_cid = 0; + + ulp_type = CNIC_ULP_FCOE; + if (opcode == FCOE_KWQE_OPCODE_DISABLE_CONN) { + struct fcoe_kwqe_conn_enable_disable *req; + + req = (struct fcoe_kwqe_conn_enable_disable *) kwqe; + kcqe_op = FCOE_KCQE_OPCODE_DISABLE_CONN; + cid = req->context_id; + l5_cid = req->conn_id; + } else if (opcode == FCOE_KWQE_OPCODE_DESTROY) { + kcqe_op = FCOE_KCQE_OPCODE_DESTROY_FUNC; + } else { + return; + } + kcqe.kcqe_op_flag = kcqe_op << KCQE_FLAGS_OPCODE_SHIFT; + kcqe.kcqe_op_flag |= KCQE_FLAGS_LAYER_MASK_L5_FCOE; + kcqe.kcqe_info1 = FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR; + kcqe.kcqe_info2 = cid; + kcqe.kcqe_info0 = l5_cid; + + } else if (layer_code == KWQE_FLAGS_LAYER_MASK_L5_ISCSI) { ulp_type = CNIC_ULP_ISCSI; if (opcode == ISCSI_KWQE_OPCODE_UPDATE_CONN) cid = kwqe->kwqe_info1; @@ -2539,7 +2564,6 @@ static void cnic_bnx2x_kwqe_err(struct cnic_dev *dev, struct kwqe *kwqe) } else if (layer_code == KWQE_FLAGS_LAYER_MASK_L4) { struct l4_kcq *l4kcqe = (struct l4_kcq *) &kcqe; - u32 kcqe_op; ulp_type = CNIC_ULP_L4; if (opcode == L4_KWQE_OPCODE_VALUE_CONNECT1) @@ -2686,9 +2710,17 @@ static int cnic_submit_bnx2x_fcoe_kwqes(struct cnic_dev *dev, opcode); break; } - if (ret < 0) + if (ret < 0) { netdev_err(dev->netdev, "KWQE(0x%x) failed\n", opcode); + + /* Possibly bnx2x parity error, send completion + * to ulp drivers with error code to speed up + * cleanup and reset recovery. + */ + if (ret == -EIO || ret == -EAGAIN) + cnic_bnx2x_kwqe_err(dev, kwqe); + } i += work; } return 0; @@ -3897,6 +3929,8 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe) case L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE: if (l4kcqe->status == 0) set_bit(SK_F_OFFLD_COMPLETE, &csk->flags); + else if (l4kcqe->status == L4_KCQE_COMPLETION_STATUS_NIC_ERROR) + set_bit(SK_F_HW_ERR, &csk->flags); smp_mb__before_clear_bit(); clear_bit(SK_F_OFFLD_SCHED, &csk->flags); diff --git a/drivers/net/ethernet/broadcom/cnic_defs.h b/drivers/net/ethernet/broadcom/cnic_defs.h index 86936f6b6dbc..7271f14bda3b 100644 --- a/drivers/net/ethernet/broadcom/cnic_defs.h +++ b/drivers/net/ethernet/broadcom/cnic_defs.h @@ -1,7 +1,7 @@ /* cnic.c: Broadcom CNIC core network driver. * - * Copyright (c) 2006-2009 Broadcom Corporation + * Copyright (c) 2006-2012 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,6 +69,7 @@ #define FCOE_KCQE_COMPLETION_STATUS_ERROR (0x1) #define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE (0x3) +#define FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR (0x5) /* KCQ (kernel completion queue) response op codes */ #define L4_KCQE_OPCODE_VALUE_CLOSE_COMP (53) diff --git a/drivers/net/ethernet/broadcom/cnic_if.h b/drivers/net/ethernet/broadcom/cnic_if.h index 1517763d4e55..60deb84d36bd 100644 --- a/drivers/net/ethernet/broadcom/cnic_if.h +++ b/drivers/net/ethernet/broadcom/cnic_if.h @@ -12,8 +12,8 @@ #ifndef CNIC_IF_H #define CNIC_IF_H -#define CNIC_MODULE_VERSION "2.5.8" -#define CNIC_MODULE_RELDATE "Jan 3, 2012" +#define CNIC_MODULE_VERSION "2.5.9" +#define CNIC_MODULE_RELDATE "Feb 8, 2012" #define CNIC_ULP_RDMA 0 #define CNIC_ULP_ISCSI 1 diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c index 084904ceaa30..49e7a258da8a 100644 --- a/drivers/net/ethernet/broadcom/sb1250-mac.c +++ b/drivers/net/ethernet/broadcom/sb1250-mac.c @@ -2623,8 +2623,6 @@ static int __devinit sbmac_probe(struct platform_device *pldev) */ dev = alloc_etherdev(sizeof(struct sbmac_softc)); if (!dev) { - printk(KERN_ERR "%s: unable to allocate etherdev\n", - dev_name(&pldev->dev)); err = -ENOMEM; goto out_unmap; } diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index a1f2e0fed78b..3bf3adca3695 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -15471,7 +15471,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS); if (!dev) { - dev_err(&pdev->dev, "Etherdev alloc failed, aborting\n"); err = -ENOMEM; goto err_out_power_down; } diff --git a/drivers/net/ethernet/brocade/bna/bfa_defs.h b/drivers/net/ethernet/brocade/bna/bfa_defs.h index 871c6309334c..48f877337390 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_defs.h +++ b/drivers/net/ethernet/brocade/bna/bfa_defs.h @@ -297,6 +297,7 @@ enum bfa_mode { #define BFA_FLASH_PART_ENTRY_SIZE 32 /* partition entry size */ #define BFA_FLASH_PART_MAX 32 /* maximal # of partitions */ #define BFA_TOTAL_FLASH_SIZE 0x400000 +#define BFA_FLASH_PART_FWIMG 2 #define BFA_FLASH_PART_MFG 7 /* diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index be7d91e4b785..ff78f770dec9 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -3284,7 +3284,6 @@ bnad_pci_probe(struct pci_dev *pdev, */ netdev = alloc_etherdev(sizeof(struct bnad)); if (!netdev) { - dev_err(&pdev->dev, "netdev allocation failed\n"); err = -ENOMEM; return err; } diff --git a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c index 592ad3929f53..c9fdceb135f3 100644 --- a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c +++ b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c @@ -62,8 +62,6 @@ bnad_debugfs_open_fwtrc(struct inode *inode, struct file *file) if (!fw_debug->debug_buffer) { kfree(fw_debug); fw_debug = NULL; - pr_warn("bna %s: Failed to allocate fwtrc buffer\n", - pci_name(bnad->pcidev)); return -ENOMEM; } @@ -105,8 +103,6 @@ bnad_debugfs_open_fwsave(struct inode *inode, struct file *file) if (!fw_debug->debug_buffer) { kfree(fw_debug); fw_debug = NULL; - pr_warn("bna %s: Failed to allocate fwsave buffer\n", - pci_name(bnad->pcidev)); return -ENOMEM; } @@ -208,8 +204,6 @@ bnad_debugfs_open_drvinfo(struct inode *inode, struct file *file) if (!drv_info->debug_buffer) { kfree(drv_info); drv_info = NULL; - pr_warn("bna %s: Failed to allocate drv info buffer\n", - pci_name(bnad->pcidev)); return -ENOMEM; } @@ -348,11 +342,8 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf, /* Allocate memory to store the user space buf */ kern_buf = kzalloc(nbytes, GFP_KERNEL); - if (!kern_buf) { - pr_warn("bna %s: Failed to allocate user buffer\n", - pci_name(bnad->pcidev)); + if (!kern_buf) return -ENOMEM; - } if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) { kfree(kern_buf); @@ -373,11 +364,8 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf, bnad->reglen = 0; bnad->regdata = kzalloc(len << 2, GFP_KERNEL); - if (!bnad->regdata) { - pr_warn("bna %s: Failed to allocate regrd buffer\n", - pci_name(bnad->pcidev)); + if (!bnad->regdata) return -ENOMEM; - } bnad->reglen = len << 2; rb = bfa_ioc_bar0(ioc); @@ -421,11 +409,8 @@ bnad_debugfs_write_regwr(struct file *file, const char __user *buf, /* Allocate memory to store the user space buf */ kern_buf = kzalloc(nbytes, GFP_KERNEL); - if (!kern_buf) { - pr_warn("bna %s: Failed to allocate user buffer\n", - pci_name(bnad->pcidev)); + if (!kern_buf) return -ENOMEM; - } if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) { kfree(kern_buf); diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c index 803ea32aa99d..ab753d7334a6 100644 --- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c +++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c @@ -1070,6 +1070,47 @@ done: return ret; } +static int +bnad_flash_device(struct net_device *netdev, struct ethtool_flash *eflash) +{ + struct bnad *bnad = netdev_priv(netdev); + struct bnad_iocmd_comp fcomp; + const struct firmware *fw; + int ret = 0; + + ret = request_firmware(&fw, eflash->data, &bnad->pcidev->dev); + if (ret) { + pr_err("BNA: Can't locate firmware %s\n", eflash->data); + goto out; + } + + fcomp.bnad = bnad; + fcomp.comp_status = 0; + + init_completion(&fcomp.comp); + spin_lock_irq(&bnad->bna_lock); + ret = bfa_nw_flash_update_part(&bnad->bna.flash, BFA_FLASH_PART_FWIMG, + bnad->id, (u8 *)fw->data, fw->size, 0, + bnad_cb_completion, &fcomp); + if (ret != BFA_STATUS_OK) { + pr_warn("BNA: Flash update failed with err: %d\n", ret); + ret = -EIO; + spin_unlock_irq(&bnad->bna_lock); + goto out; + } + + spin_unlock_irq(&bnad->bna_lock); + wait_for_completion(&fcomp.comp); + if (fcomp.comp_status != BFA_STATUS_OK) { + ret = -EIO; + pr_warn("BNA: Firmware image update to flash failed with: %d\n", + fcomp.comp_status); + } +out: + release_firmware(fw); + return ret; +} + static const struct ethtool_ops bnad_ethtool_ops = { .get_settings = bnad_get_settings, .set_settings = bnad_set_settings, @@ -1088,6 +1129,7 @@ static const struct ethtool_ops bnad_ethtool_ops = { .get_eeprom_len = bnad_get_eeprom_len, .get_eeprom = bnad_get_eeprom, .set_eeprom = bnad_set_eeprom, + .flash_device = bnad_flash_device, }; void diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c index 1a5b6efa0120..906117016fc4 100644 --- a/drivers/net/ethernet/cadence/at91_ether.c +++ b/drivers/net/ethernet/cadence/at91_ether.c @@ -886,7 +886,7 @@ static void at91ether_rx(struct net_device *dev) while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) { p_recv = dlist->recv_buf[lp->rxBuffIndex]; pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */ - skb = dev_alloc_skb(pktlen + 2); + skb = netdev_alloc_skb(dev, pktlen + 2); if (skb != NULL) { skb_reserve(skb, 2); memcpy(skb_put(skb, pktlen), p_recv, pktlen); diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 23200680d4c1..85e044567f68 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -397,7 +397,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, netdev_dbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n", first_frag, last_frag, len); - skb = dev_alloc_skb(len + RX_OFFSET); + skb = netdev_alloc_skb(bp->dev, len + RX_OFFSET); if (!skb) { bp->stats.rx_dropped++; for (frag = first_frag; ; frag = NEXT_RX(frag)) { @@ -1308,10 +1308,8 @@ static int __init macb_probe(struct platform_device *pdev) err = -ENOMEM; dev = alloc_etherdev(sizeof(*bp)); - if (!dev) { - dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n"); + if (!dev) goto err_out; - } SET_NETDEV_DEV(dev, &pdev->dev); diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index e53365a71484..9045a451d4a9 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -2596,8 +2596,6 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, netdev = alloc_etherdev_mq(sizeof(struct port_info), MAX_PORT_QSETS); if (netdev == NULL) { - dev_err(&pdev->dev, "cannot allocate netdev for" - " port %d\n", port_id); t4vf_free_vi(adapter, viid); err = -ENOMEM; goto err_free_dev; diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c index f328da24c8fa..d5ff93653e4c 100644 --- a/drivers/net/ethernet/cirrus/cs89x0.c +++ b/drivers/net/ethernet/cirrus/cs89x0.c @@ -911,7 +911,7 @@ dma_rx(struct net_device *dev) } /* Malloc up new buffer. */ - skb = dev_alloc_skb(length + 2); + skb = netdev_alloc_skb(dev, length + 2); if (skb == NULL) { if (net_debug) /* I don't think we want to do this to a stressed system */ printk("%s: Memory squeeze, dropping packet.\n", dev->name); @@ -1616,7 +1616,7 @@ net_rx(struct net_device *dev) } /* Malloc up new buffer. */ - skb = dev_alloc_skb(length + 2); + skb = netdev_alloc_skb(dev, length + 2); if (skb == NULL) { #if 0 /* Again, this seems a cruel thing to do */ printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c index 4317af8d2f0a..c21e5ab8d1ef 100644 --- a/drivers/net/ethernet/cirrus/ep93xx_eth.c +++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c @@ -282,7 +282,7 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget) if (rstat0 & RSTAT0_CRCI) length -= 4; - skb = dev_alloc_skb(length + 2); + skb = netdev_alloc_skb(dev, length + 2); if (likely(skb != NULL)) { struct ep93xx_rdesc *rxd = &ep->descs->rdesc[entry]; skb_reserve(skb, 2); diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h index ee93a2087fe6..54fd9c314b38 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -32,13 +32,13 @@ #define DRV_NAME "enic" #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" -#define DRV_VERSION "2.1.1.31" +#define DRV_VERSION "2.1.1.33" #define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc" #define ENIC_BARS_MAX 6 #define ENIC_WQ_MAX 1 -#define ENIC_RQ_MAX 1 +#define ENIC_RQ_MAX 8 #define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX) #define ENIC_INTR_MAX (ENIC_CQ_MAX + 2) diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index ab3f67f980d8..2838891a94ee 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -2280,10 +2280,8 @@ static int __devinit enic_probe(struct pci_dev *pdev, */ netdev = alloc_etherdev(sizeof(struct enic)); - if (!netdev) { - pr_err("Etherdev alloc failed, aborting\n"); + if (!netdev) return -ENOMEM; - } pci_set_drvdata(pdev, netdev); @@ -2388,7 +2386,6 @@ static int __devinit enic_probe(struct pci_dev *pdev, /* Allocate structure for port profiles */ enic->pp = kcalloc(num_pps, sizeof(*enic->pp), GFP_KERNEL); if (!enic->pp) { - pr_err("port profile alloc failed, aborting\n"); err = -ENOMEM; goto err_out_disable_sriov_pp; } diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c index 31e7f9bc2067..298ad6f865be 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_dev.c +++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c @@ -439,11 +439,12 @@ int vnic_dev_fw_info(struct vnic_dev *vdev, a1 = sizeof(struct vnic_devcmd_fw_info); /* only get fw_info once and cache it */ - err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, &a0, &a1, wait); - if (err == ERR_ECMDUNKNOWN) { + if (vnic_dev_capable(vdev, CMD_MCPU_FW_INFO)) + err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, + &a0, &a1, wait); + else err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO_OLD, &a0, &a1, wait); - } } *fw_info = vdev->fw_info; @@ -504,13 +505,11 @@ int vnic_dev_enable_wait(struct vnic_dev *vdev) { u64 a0 = 0, a1 = 0; int wait = 1000; - int err; - err = vnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait); - if (err == ERR_ECMDUNKNOWN) + if (vnic_dev_capable(vdev, CMD_ENABLE_WAIT)) + return vnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait); + else return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait); - - return err; } int vnic_dev_disable(struct vnic_dev *vdev) @@ -574,16 +573,15 @@ int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg) int wait = 1000; int err; - err = vnic_dev_cmd(vdev, CMD_HANG_RESET, &a0, &a1, wait); - if (err == ERR_ECMDUNKNOWN) { + if (vnic_dev_capable(vdev, CMD_HANG_RESET)) { + return vnic_dev_cmd(vdev, CMD_HANG_RESET, + &a0, &a1, wait); + } else { err = vnic_dev_soft_reset(vdev, arg); if (err) return err; - return vnic_dev_init(vdev, 0); } - - return err; } int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done) @@ -594,11 +592,13 @@ int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done) *done = 0; - err = vnic_dev_cmd(vdev, CMD_HANG_RESET_STATUS, &a0, &a1, wait); - if (err) { - if (err == ERR_ECMDUNKNOWN) - return vnic_dev_soft_reset_done(vdev, done); - return err; + if (vnic_dev_capable(vdev, CMD_HANG_RESET_STATUS)) { + err = vnic_dev_cmd(vdev, CMD_HANG_RESET_STATUS, + &a0, &a1, wait); + if (err) + return err; + } else { + return vnic_dev_soft_reset_done(vdev, done); } *done = (a0 == 0); @@ -691,13 +691,12 @@ int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev, { u64 a0 = ig_vlan_rewrite_mode, a1 = 0; int wait = 1000; - int err; - err = vnic_dev_cmd(vdev, CMD_IG_VLAN_REWRITE_MODE, &a0, &a1, wait); - if (err == ERR_ECMDUNKNOWN) + if (vnic_dev_capable(vdev, CMD_IG_VLAN_REWRITE_MODE)) + return vnic_dev_cmd(vdev, CMD_IG_VLAN_REWRITE_MODE, + &a0, &a1, wait); + else return 0; - - return err; } static int vnic_dev_notify_setcmd(struct vnic_dev *vdev, @@ -835,7 +834,10 @@ int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev) memset(vdev->args, 0, sizeof(vdev->args)); - err = _vnic_dev_cmd(vdev, CMD_INTR_COAL_CONVERT, wait); + if (vnic_dev_capable(vdev, CMD_INTR_COAL_CONVERT)) + err = _vnic_dev_cmd(vdev, CMD_INTR_COAL_CONVERT, wait); + else + err = ERR_ECMDUNKNOWN; /* Use defaults when firmware doesn't support the devcmd at all or * supports it for only specific hardware @@ -848,9 +850,11 @@ int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev) return 0; } - vdev->intr_coal_timer_info.mul = (u32) vdev->args[0]; - vdev->intr_coal_timer_info.div = (u32) vdev->args[1]; - vdev->intr_coal_timer_info.max_usec = (u32) vdev->args[2]; + if (!err) { + vdev->intr_coal_timer_info.mul = (u32) vdev->args[0]; + vdev->intr_coal_timer_info.div = (u32) vdev->args[1]; + vdev->intr_coal_timer_info.max_usec = (u32) vdev->args[2]; + } return err; } diff --git a/drivers/net/ethernet/cisco/enic/vnic_rq.c b/drivers/net/ethernet/cisco/enic/vnic_rq.c index 34105e0951a5..7e1488fc8ab2 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_rq.c +++ b/drivers/net/ethernet/cisco/enic/vnic_rq.c @@ -38,10 +38,8 @@ static int vnic_rq_alloc_bufs(struct vnic_rq *rq) for (i = 0; i < blks; i++) { rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ(count), GFP_ATOMIC); - if (!rq->bufs[i]) { - pr_err("Failed to alloc rq_bufs\n"); + if (!rq->bufs[i]) return -ENOMEM; - } } for (i = 0; i < blks; i++) { diff --git a/drivers/net/ethernet/cisco/enic/vnic_wq.c b/drivers/net/ethernet/cisco/enic/vnic_wq.c index df61bd932ea6..5e0d7a2be9bc 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_wq.c +++ b/drivers/net/ethernet/cisco/enic/vnic_wq.c @@ -38,10 +38,8 @@ static int vnic_wq_alloc_bufs(struct vnic_wq *wq) for (i = 0; i < blks; i++) { wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ(count), GFP_ATOMIC); - if (!wq->bufs[i]) { - pr_err("Failed to alloc wq_bufs\n"); + if (!wq->bufs[i]) return -ENOMEM; - } } for (i = 0; i < blks; i++) { diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index f801754c71a7..42383ab5227e 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -1028,7 +1028,7 @@ dm9000_rx(struct net_device *dev) /* Move data from DM9000 */ if (GoodPacket && - ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) { + ((skb = netdev_alloc_skb(dev, RxLen + 4)) != NULL)) { skb_reserve(skb, 2); rdptr = (u8 *) skb_put(skb, RxLen - 4); @@ -1373,10 +1373,8 @@ dm9000_probe(struct platform_device *pdev) /* Init network device */ ndev = alloc_etherdev(sizeof(struct board_info)); - if (!ndev) { - dev_err(&pdev->dev, "could not allocate device.\n"); + if (!ndev) return -ENOMEM; - } SET_NETDEV_DEV(ndev, &pdev->dev); diff --git a/drivers/net/ethernet/dec/ewrk3.c b/drivers/net/ethernet/dec/ewrk3.c index f9df5e4d0341..1879f84a25a3 100644 --- a/drivers/net/ethernet/dec/ewrk3.c +++ b/drivers/net/ethernet/dec/ewrk3.c @@ -986,8 +986,10 @@ static int ewrk3_rx(struct net_device *dev) dev->stats.rx_fifo_errors++; } else { struct sk_buff *skb; + skb = netdev_alloc_skb(dev, + pkt_len + 2); - if ((skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + if (skb != NULL) { unsigned char *p; skb_reserve(skb, 2); /* Align to 16 bytes */ p = skb_put(skb, pkt_len); diff --git a/drivers/net/ethernet/dec/tulip/21142.c b/drivers/net/ethernet/dec/tulip/21142.c index 25b8deedbef8..369858272650 100644 --- a/drivers/net/ethernet/dec/tulip/21142.c +++ b/drivers/net/ethernet/dec/tulip/21142.c @@ -1,5 +1,5 @@ /* - drivers/net/tulip/21142.c + drivers/net/ethernet/dec/tulip/21142.c Copyright 2000,2001 The Linux Kernel Team Written/copyright 1994-2001 by Donald Becker. diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c index 1eb46a0bb488..68f1c39184df 100644 --- a/drivers/net/ethernet/dec/tulip/de2104x.c +++ b/drivers/net/ethernet/dec/tulip/de2104x.c @@ -439,7 +439,7 @@ static void de_rx (struct de_private *de) rx_tail, status, len, copying_skb); buflen = copying_skb ? (len + RX_OFFSET) : de->rx_buf_sz; - copy_skb = dev_alloc_skb (buflen); + copy_skb = netdev_alloc_skb(de->dev, buflen); if (unlikely(!copy_skb)) { de->net_stats.rx_dropped++; drop = 1; @@ -1283,12 +1283,10 @@ static int de_refill_rx (struct de_private *de) for (i = 0; i < DE_RX_RING_SIZE; i++) { struct sk_buff *skb; - skb = dev_alloc_skb(de->rx_buf_sz); + skb = netdev_alloc_skb(de->dev, de->rx_buf_sz); if (!skb) goto err_out; - skb->dev = de->dev; - de->rx_skb[i].mapping = pci_map_single(de->pdev, skb->data, de->rx_buf_sz, PCI_DMA_FROMDEVICE); de->rx_skb[i].skb = skb; diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c index 4d71f5ae20c8..93583408a325 100644 --- a/drivers/net/ethernet/dec/tulip/de4x5.c +++ b/drivers/net/ethernet/dec/tulip/de4x5.c @@ -3598,7 +3598,7 @@ de4x5_alloc_rx_buff(struct net_device *dev, int index, int len) struct sk_buff *ret; u_long i=0, tmp; - p = dev_alloc_skb(IEEE802_3_SZ + DE4X5_ALIGN + 2); + p = netdev_alloc_skb(dev, IEEE802_3_SZ + DE4X5_ALIGN + 2); if (!p) return NULL; tmp = virt_to_bus(p->data); @@ -3618,7 +3618,7 @@ de4x5_alloc_rx_buff(struct net_device *dev, int index, int len) #else if (lp->state != OPEN) return (struct sk_buff *)1; /* Fake out the open */ - p = dev_alloc_skb(len + 2); + p = netdev_alloc_skb(dev, len + 2); if (!p) return NULL; skb_reserve(p, 2); /* Align */ diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c index 51f7542eb451..1eccf4945485 100644 --- a/drivers/net/ethernet/dec/tulip/dmfe.c +++ b/drivers/net/ethernet/dec/tulip/dmfe.c @@ -325,8 +325,8 @@ static irqreturn_t dmfe_interrupt(int , void *); #ifdef CONFIG_NET_POLL_CONTROLLER static void poll_dmfe (struct net_device *dev); #endif -static void dmfe_descriptor_init(struct dmfe_board_info *, unsigned long); -static void allocate_rx_buffer(struct dmfe_board_info *); +static void dmfe_descriptor_init(struct net_device *, unsigned long); +static void allocate_rx_buffer(struct net_device *); static void update_cr6(u32, unsigned long); static void send_filter_frame(struct DEVICE *); static void dm9132_id_table(struct DEVICE *); @@ -649,7 +649,7 @@ static void dmfe_init_dm910x(struct DEVICE *dev) db->op_mode = db->media_mode; /* Force Mode */ /* Initialize Transmit/Receive decriptor and CR3/4 */ - dmfe_descriptor_init(db, ioaddr); + dmfe_descriptor_init(dev, ioaddr); /* Init CR6 to program DM910x operation */ update_cr6(db->cr6_data, ioaddr); @@ -828,7 +828,7 @@ static irqreturn_t dmfe_interrupt(int irq, void *dev_id) /* reallocate rx descriptor buffer */ if (db->rx_avail_cnt<RX_DESC_CNT) - allocate_rx_buffer(db); + allocate_rx_buffer(dev); /* Free the transmitted descriptor */ if ( db->cr5_data & 0x01) @@ -1008,7 +1008,7 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db) /* Good packet, send to upper layer */ /* Shorst packet used new SKB */ if ((rxlen < RX_COPY_SIZE) && - ((newskb = dev_alloc_skb(rxlen + 2)) + ((newskb = netdev_alloc_skb(dev, rxlen + 2)) != NULL)) { skb = newskb; @@ -1364,8 +1364,9 @@ static void dmfe_reuse_skb(struct dmfe_board_info *db, struct sk_buff * skb) * Using Chain structure, and allocate Tx/Rx buffer */ -static void dmfe_descriptor_init(struct dmfe_board_info *db, unsigned long ioaddr) +static void dmfe_descriptor_init(struct net_device *dev, unsigned long ioaddr) { + struct dmfe_board_info *db = netdev_priv(dev); struct tx_desc *tmp_tx; struct rx_desc *tmp_rx; unsigned char *tmp_buf; @@ -1421,7 +1422,7 @@ static void dmfe_descriptor_init(struct dmfe_board_info *db, unsigned long ioadd tmp_rx->next_rx_desc = db->first_rx_desc; /* pre-allocate Rx buffer */ - allocate_rx_buffer(db); + allocate_rx_buffer(dev); } @@ -1551,15 +1552,16 @@ static void send_filter_frame(struct DEVICE *dev) * As possible as allocate maxiumn Rx buffer */ -static void allocate_rx_buffer(struct dmfe_board_info *db) +static void allocate_rx_buffer(struct net_device *dev) { + struct dmfe_board_info *db = netdev_priv(dev); struct rx_desc *rxptr; struct sk_buff *skb; rxptr = db->rx_insert_ptr; while(db->rx_avail_cnt < RX_DESC_CNT) { - if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL ) + if ( ( skb = netdev_alloc_skb(dev, RX_ALLOC_SIZE) ) == NULL ) break; rxptr->rx_skb_ptr = skb; /* FIXME (?) */ rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data, diff --git a/drivers/net/ethernet/dec/tulip/eeprom.c b/drivers/net/ethernet/dec/tulip/eeprom.c index 14d5b611783d..ed7d1dcd9566 100644 --- a/drivers/net/ethernet/dec/tulip/eeprom.c +++ b/drivers/net/ethernet/dec/tulip/eeprom.c @@ -1,5 +1,5 @@ /* - drivers/net/tulip/eeprom.c + drivers/net/ethernet/dec/tulip/eeprom.c Copyright 2000,2001 The Linux Kernel Team Written/copyright 1994-2001 by Donald Becker. diff --git a/drivers/net/ethernet/dec/tulip/interrupt.c b/drivers/net/ethernet/dec/tulip/interrupt.c index 4fb8c8c0a420..28a5e425fecf 100644 --- a/drivers/net/ethernet/dec/tulip/interrupt.c +++ b/drivers/net/ethernet/dec/tulip/interrupt.c @@ -1,5 +1,5 @@ /* - drivers/net/tulip/interrupt.c + drivers/net/ethernet/dec/tulip/interrupt.c Copyright 2000,2001 The Linux Kernel Team Written/copyright 1994-2001 by Donald Becker. @@ -69,7 +69,8 @@ int tulip_refill_rx(struct net_device *dev) struct sk_buff *skb; dma_addr_t mapping; - skb = tp->rx_buffers[entry].skb = dev_alloc_skb(PKT_BUF_SZ); + skb = tp->rx_buffers[entry].skb = + netdev_alloc_skb(dev, PKT_BUF_SZ); if (skb == NULL) break; @@ -77,7 +78,6 @@ int tulip_refill_rx(struct net_device *dev) PCI_DMA_FROMDEVICE); tp->rx_buffers[entry].mapping = mapping; - skb->dev = dev; /* Mark as being used by this device. */ tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping); refilled++; } @@ -202,7 +202,7 @@ int tulip_poll(struct napi_struct *napi, int budget) /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < tulip_rx_copybreak && - (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) { skb_reserve(skb, 2); /* 16 byte align the IP header */ pci_dma_sync_single_for_cpu(tp->pdev, tp->rx_buffers[entry].mapping, @@ -428,7 +428,7 @@ static int tulip_rx(struct net_device *dev) /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < tulip_rx_copybreak && - (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) { skb_reserve(skb, 2); /* 16 byte align the IP header */ pci_dma_sync_single_for_cpu(tp->pdev, tp->rx_buffers[entry].mapping, diff --git a/drivers/net/ethernet/dec/tulip/media.c b/drivers/net/ethernet/dec/tulip/media.c index beeb17b52ad4..ae937c6749e7 100644 --- a/drivers/net/ethernet/dec/tulip/media.c +++ b/drivers/net/ethernet/dec/tulip/media.c @@ -1,5 +1,5 @@ /* - drivers/net/tulip/media.c + drivers/net/ethernet/dec/tulip/media.c Copyright 2000,2001 The Linux Kernel Team Written/copyright 1994-2001 by Donald Becker. diff --git a/drivers/net/ethernet/dec/tulip/pnic.c b/drivers/net/ethernet/dec/tulip/pnic.c index 9c16e4ad02a6..5364563c4378 100644 --- a/drivers/net/ethernet/dec/tulip/pnic.c +++ b/drivers/net/ethernet/dec/tulip/pnic.c @@ -1,5 +1,5 @@ /* - drivers/net/tulip/pnic.c + drivers/net/ethernet/dec/tulip/pnic.c Copyright 2000,2001 The Linux Kernel Team Written/copyright 1994-2001 by Donald Becker. diff --git a/drivers/net/ethernet/dec/tulip/pnic2.c b/drivers/net/ethernet/dec/tulip/pnic2.c index 04a7e477eaff..5895fc43f6e0 100644 --- a/drivers/net/ethernet/dec/tulip/pnic2.c +++ b/drivers/net/ethernet/dec/tulip/pnic2.c @@ -1,5 +1,5 @@ /* - drivers/net/tulip/pnic2.c + drivers/net/ethernet/dec/tulip/pnic2.c Copyright 2000,2001 The Linux Kernel Team Written/copyright 1994-2001 by Donald Becker. diff --git a/drivers/net/ethernet/dec/tulip/timer.c b/drivers/net/ethernet/dec/tulip/timer.c index 19078d28ffb9..768379b8aee9 100644 --- a/drivers/net/ethernet/dec/tulip/timer.c +++ b/drivers/net/ethernet/dec/tulip/timer.c @@ -1,5 +1,5 @@ /* - drivers/net/tulip/timer.c + drivers/net/ethernet/dec/tulip/timer.c Copyright 2000,2001 The Linux Kernel Team Written/copyright 1994-2001 by Donald Becker. diff --git a/drivers/net/ethernet/dec/tulip/tulip.h b/drivers/net/ethernet/dec/tulip/tulip.h index fb3887c18dc6..38431a155f09 100644 --- a/drivers/net/ethernet/dec/tulip/tulip.h +++ b/drivers/net/ethernet/dec/tulip/tulip.h @@ -1,5 +1,5 @@ /* - drivers/net/tulip/tulip.h + drivers/net/ethernet/dec/tulip/tulip.h Copyright 2000,2001 The Linux Kernel Team Written/copyright 1994-2001 by Donald Becker. diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c index 4eb0d76145c2..fea3641d9398 100644 --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c @@ -636,16 +636,15 @@ static void tulip_init_ring(struct net_device *dev) dma_addr_t mapping; /* Note the receive buffer must be longword aligned. - dev_alloc_skb() provides 16 byte alignment. But do *not* + netdev_alloc_skb() provides 16 byte alignment. But do *not* use skb_reserve() to align the IP header! */ - struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ); + struct sk_buff *skb = netdev_alloc_skb(dev, PKT_BUF_SZ); tp->rx_buffers[i].skb = skb; if (skb == NULL) break; mapping = pci_map_single(tp->pdev, skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); tp->rx_buffers[i].mapping = mapping; - skb->dev = dev; /* Mark as being used by this device. */ tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */ tp->rx_ring[i].buffer1 = cpu_to_le32(mapping); } @@ -1424,10 +1423,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, /* alloc_etherdev ensures aligned and zeroed private structures */ dev = alloc_etherdev (sizeof (*tp)); - if (!dev) { - pr_err("ether device alloc failed, aborting\n"); + if (!dev) return -ENOMEM; - } SET_NETDEV_DEV(dev, &pdev->dev); if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) { diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c index 48b0b6566eef..fc4001f6a5e4 100644 --- a/drivers/net/ethernet/dec/tulip/uli526x.c +++ b/drivers/net/ethernet/dec/tulip/uli526x.c @@ -232,8 +232,8 @@ static irqreturn_t uli526x_interrupt(int, void *); #ifdef CONFIG_NET_POLL_CONTROLLER static void uli526x_poll(struct net_device *dev); #endif -static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long); -static void allocate_rx_buffer(struct uli526x_board_info *); +static void uli526x_descriptor_init(struct net_device *, unsigned long); +static void allocate_rx_buffer(struct net_device *); static void update_cr6(u32, unsigned long); static void send_filter_frame(struct net_device *, int); static u16 phy_read(unsigned long, u8, u8, u32); @@ -549,7 +549,7 @@ static void uli526x_init(struct net_device *dev) db->op_mode = db->media_mode; /* Force Mode */ /* Initialize Transmit/Receive decriptor and CR3/4 */ - uli526x_descriptor_init(db, ioaddr); + uli526x_descriptor_init(dev, ioaddr); /* Init CR6 to program M526X operation */ update_cr6(db->cr6_data, ioaddr); @@ -711,7 +711,7 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id) /* reallocate rx descriptor buffer */ if (db->rx_avail_cnt<RX_DESC_CNT) - allocate_rx_buffer(db); + allocate_rx_buffer(dev); /* Free the transmitted descriptor */ if ( db->cr5_data & 0x01) @@ -844,7 +844,7 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info /* Good packet, send to upper layer */ /* Shorst packet used new SKB */ if ((rxlen < RX_COPY_SIZE) && - (((new_skb = dev_alloc_skb(rxlen + 2)) != NULL))) { + (((new_skb = netdev_alloc_skb(dev, rxlen + 2)) != NULL))) { skb = new_skb; /* size less than COPY_SIZE, allocate a rxlen SKB */ skb_reserve(skb, 2); /* 16byte align */ @@ -1289,8 +1289,9 @@ static void uli526x_reuse_skb(struct uli526x_board_info *db, struct sk_buff * sk * Using Chain structure, and allocate Tx/Rx buffer */ -static void uli526x_descriptor_init(struct uli526x_board_info *db, unsigned long ioaddr) +static void uli526x_descriptor_init(struct net_device *dev, unsigned long ioaddr) { + struct uli526x_board_info *db = netdev_priv(dev); struct tx_desc *tmp_tx; struct rx_desc *tmp_rx; unsigned char *tmp_buf; @@ -1343,7 +1344,7 @@ static void uli526x_descriptor_init(struct uli526x_board_info *db, unsigned long tmp_rx->next_rx_desc = db->first_rx_desc; /* pre-allocate Rx buffer */ - allocate_rx_buffer(db); + allocate_rx_buffer(dev); } @@ -1433,15 +1434,17 @@ static void send_filter_frame(struct net_device *dev, int mc_cnt) * As possible as allocate maxiumn Rx buffer */ -static void allocate_rx_buffer(struct uli526x_board_info *db) +static void allocate_rx_buffer(struct net_device *dev) { + struct uli526x_board_info *db = netdev_priv(dev); struct rx_desc *rxptr; struct sk_buff *skb; rxptr = db->rx_insert_ptr; while(db->rx_avail_cnt < RX_DESC_CNT) { - if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL ) + skb = netdev_alloc_skb(dev, RX_ALLOC_SIZE); + if (skb == NULL) break; rxptr->rx_skb_ptr = skb; /* FIXME (?) */ rxptr->rdes2 = cpu_to_le32(pci_map_single(db->pdev, diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c index 52da7b2fe3b6..2ac6fff0363a 100644 --- a/drivers/net/ethernet/dec/tulip/winbond-840.c +++ b/drivers/net/ethernet/dec/tulip/winbond-840.c @@ -815,7 +815,7 @@ static void init_rxtx_rings(struct net_device *dev) /* Fill in the Rx buffers. Handle allocation failure gracefully. */ for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz); + struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz); np->rx_skbuff[i] = skb; if (skb == NULL) break; @@ -1231,7 +1231,7 @@ static int netdev_rx(struct net_device *dev) /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < rx_copybreak && - (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) { skb_reserve(skb, 2); /* 16 byte align the IP header */ pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, @@ -1270,7 +1270,7 @@ static int netdev_rx(struct net_device *dev) struct sk_buff *skb; entry = np->dirty_rx % RX_RING_SIZE; if (np->rx_skbuff[entry] == NULL) { - skb = dev_alloc_skb(np->rx_buf_sz); + skb = netdev_alloc_skb(dev, np->rx_buf_sz); np->rx_skbuff[entry] = skb; if (skb == NULL) break; /* Better luck next round. */ diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c index 988b8eb24d37..fdb329fe6e8e 100644 --- a/drivers/net/ethernet/dec/tulip/xircom_cb.c +++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c @@ -222,10 +222,9 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ is available. */ dev = alloc_etherdev(sizeof(struct xircom_private)); - if (!dev) { - pr_err("%s: failed to allocate etherdev\n", __func__); + if (!dev) goto device_fail; - } + private = netdev_priv(dev); /* Allocate the send/receive buffers */ @@ -1085,7 +1084,7 @@ investigate_read_descriptor(struct net_device *dev, struct xircom_private *card, pkt_len = 1518; } - skb = dev_alloc_skb(pkt_len + 2); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { dev->stats.rx_dropped++; goto out; diff --git a/drivers/net/ethernet/dlink/de600.c b/drivers/net/ethernet/dlink/de600.c index c24fab1e9cbe..682750c052c8 100644 --- a/drivers/net/ethernet/dlink/de600.c +++ b/drivers/net/ethernet/dlink/de600.c @@ -335,7 +335,7 @@ static void de600_rx_intr(struct net_device *dev) return; } - skb = dev_alloc_skb(size+2); + skb = netdev_alloc_skb(dev, size + 2); if (skb == NULL) { printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size); return; diff --git a/drivers/net/ethernet/dlink/de620.c b/drivers/net/ethernet/dlink/de620.c index 3b934ab784d3..afc5aaac6b60 100644 --- a/drivers/net/ethernet/dlink/de620.c +++ b/drivers/net/ethernet/dlink/de620.c @@ -650,7 +650,7 @@ static int de620_rx_intr(struct net_device *dev) printk(KERN_WARNING "%s: Illegal packet size: %d!\n", dev->name, size); } else { /* Good packet? */ - skb = dev_alloc_skb(size+2); + skb = netdev_alloc_skb(dev, size + 2); if (skb == NULL) { /* Yeah, but no place to put it... */ printk(KERN_WARNING "%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size); dev->stats.rx_dropped++; diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c index 28a3a9b50b8b..7227f29ee2ee 100644 --- a/drivers/net/ethernet/dlink/sundance.c +++ b/drivers/net/ethernet/dlink/sundance.c @@ -1020,11 +1020,11 @@ static void init_ring(struct net_device *dev) /* Fill in the Rx buffers. Handle allocation failure gracefully. */ for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + 2); + struct sk_buff *skb = + netdev_alloc_skb(dev, np->rx_buf_sz + 2); np->rx_skbuff[i] = skb; if (skb == NULL) break; - skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* 16 byte align the IP header. */ np->rx_ring[i].frag[0].addr = cpu_to_le32( dma_map_single(&np->pci_dev->dev, skb->data, @@ -1358,7 +1358,7 @@ static void rx_poll(unsigned long data) /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < rx_copybreak && - (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) { skb_reserve(skb, 2); /* 16 byte align the IP header */ dma_sync_single_for_cpu(&np->pci_dev->dev, le32_to_cpu(desc->frag[0].addr), @@ -1411,11 +1411,10 @@ static void refill_rx (struct net_device *dev) struct sk_buff *skb; entry = np->dirty_rx % RX_RING_SIZE; if (np->rx_skbuff[entry] == NULL) { - skb = dev_alloc_skb(np->rx_buf_sz + 2); + skb = netdev_alloc_skb(dev, np->rx_buf_sz + 2); np->rx_skbuff[entry] = skb; if (skb == NULL) break; /* Better luck next round. */ - skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ np->rx_ring[entry].frag[0].addr = cpu_to_le32( dma_map_single(&np->pci_dev->dev, skb->data, diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c index 925c9bafc9b9..8536e376555a 100644 --- a/drivers/net/ethernet/dnet.c +++ b/drivers/net/ethernet/dnet.c @@ -421,7 +421,7 @@ static int dnet_poll(struct napi_struct *napi, int budget) printk(KERN_ERR "%s packet receive error %x\n", __func__, cmd_word); - skb = dev_alloc_skb(pkt_len + 5); + skb = netdev_alloc_skb(dev, pkt_len + 5); if (skb != NULL) { /* Align IP on 16 byte boundaries */ skb_reserve(skb, 2); @@ -854,10 +854,8 @@ static int __devinit dnet_probe(struct platform_device *pdev) err = -ENOMEM; dev = alloc_etherdev(sizeof(*bp)); - if (!dev) { - dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n"); + if (!dev) goto err_out_release_mem; - } /* TODO: Actually, we have some interesting features... */ dev->features |= 0; diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index cbdec2536da6..74aa14811977 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -74,6 +74,9 @@ static inline char *nic_name(struct pci_dev *pdev) /* Number of bytes of an RX frame that are copied to skb->data */ #define BE_HDR_LEN ((u16) 64) +/* allocate extra space to allow tunneling decapsulation without head reallocation */ +#define BE_RX_SKB_ALLOC_SIZE (BE_HDR_LEN + 64) + #define BE_MAX_JUMBO_FRAME_SIZE 9018 #define BE_MIN_MTU 256 @@ -262,7 +265,6 @@ struct be_drv_stats { u32 rx_drops_no_erx_descr; u32 rx_drops_no_tpre_descr; u32 rx_drops_too_many_frags; - u32 rx_drops_invalid_ring; u32 forwarded_packets; u32 rx_drops_mtu; u32 rx_crc_errors; @@ -273,7 +275,7 @@ struct be_drv_stats { u32 rx_in_range_errors; u32 rx_out_range_errors; u32 rx_frame_too_long; - u32 rx_address_match_errors; + u32 rx_address_mismatch_drops; u32 rx_dropped_too_small; u32 rx_dropped_too_short; u32 rx_dropped_header_too_small; diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 0fcb45624796..29dff7de66b6 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1257,11 +1257,13 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, } req = embedded_payload(wrb); + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL); + if (adapter->generation == BE_GEN3 || lancer_chip(adapter)) req->hdr.version = 1; - be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, - OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL); + req->hdr.domain = dom; status = be_mcc_notify_wait(adapter); if (!status) { @@ -2298,52 +2300,81 @@ err: /* Uses synchronous MCCQ */ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, - u32 *pmac_id) + bool *pmac_id_active, u32 *pmac_id, u8 *mac) { struct be_mcc_wrb *wrb; struct be_cmd_req_get_mac_list *req; int status; int mac_count; + struct be_dma_mem get_mac_list_cmd; + int i; + + memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem)); + get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list); + get_mac_list_cmd.va = pci_alloc_consistent(adapter->pdev, + get_mac_list_cmd.size, + &get_mac_list_cmd.dma); + + if (!get_mac_list_cmd.va) { + dev_err(&adapter->pdev->dev, + "Memory allocation failure during GET_MAC_LIST\n"); + return -ENOMEM; + } spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { status = -EBUSY; - goto err; + goto out; } - req = embedded_payload(wrb); + + req = get_mac_list_cmd.va; be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_GET_MAC_LIST, sizeof(*req), - wrb, NULL); + wrb, &get_mac_list_cmd); req->hdr.domain = domain; + req->mac_type = MAC_ADDRESS_TYPE_NETWORK; + req->perm_override = 1; status = be_mcc_notify_wait(adapter); if (!status) { struct be_cmd_resp_get_mac_list *resp = - embedded_payload(wrb); - int i; - u8 *ctxt = &resp->context[0][0]; - status = -EIO; - mac_count = resp->mac_count; - be_dws_le_to_cpu(&resp->context, sizeof(resp->context)); + get_mac_list_cmd.va; + mac_count = resp->true_mac_count + resp->pseudo_mac_count; + /* Mac list returned could contain one or more active mac_ids + * or one or more pseudo permanant mac addresses. If an active + * mac_id is present, return first active mac_id found + */ for (i = 0; i < mac_count; i++) { - if (!AMAP_GET_BITS(struct amap_get_mac_list_context, - act, ctxt)) { - *pmac_id = AMAP_GET_BITS - (struct amap_get_mac_list_context, - macid, ctxt); - status = 0; - break; + struct get_list_macaddr *mac_entry; + u16 mac_addr_size; + u32 mac_id; + + mac_entry = &resp->macaddr_list[i]; + mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size); + /* mac_id is a 32 bit value and mac_addr size + * is 6 bytes + */ + if (mac_addr_size == sizeof(u32)) { + *pmac_id_active = true; + mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id; + *pmac_id = le32_to_cpu(mac_id); + goto out; } - ctxt += sizeof(struct amap_get_mac_list_context) / 8; } + /* If no active mac_id found, return first pseudo mac addr */ + *pmac_id_active = false; + memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr, + ETH_ALEN); } -err: +out: spin_unlock_bh(&adapter->mcc_lock); + pci_free_consistent(adapter->pdev, get_mac_list_cmd.size, + get_mac_list_cmd.va, get_mac_list_cmd.dma); return status; } diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index dca89249088f..5bb66c80f05e 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -592,8 +592,8 @@ struct be_port_rxf_stats_v0 { u32 rx_in_range_errors; /* dword 10*/ u32 rx_out_range_errors; /* dword 11*/ u32 rx_frame_too_long; /* dword 12*/ - u32 rx_address_match_errors; /* dword 13*/ - u32 rx_vlan_mismatch; /* dword 14*/ + u32 rx_address_mismatch_drops; /* dword 13*/ + u32 rx_vlan_mismatch_drops; /* dword 14*/ u32 rx_dropped_too_small; /* dword 15*/ u32 rx_dropped_too_short; /* dword 16*/ u32 rx_dropped_header_too_small; /* dword 17*/ @@ -799,8 +799,8 @@ struct lancer_pport_stats { u32 rx_control_frames_unknown_opcode_hi; u32 rx_in_range_errors; u32 rx_out_of_range_errors; - u32 rx_address_match_errors; - u32 rx_vlan_mismatch_errors; + u32 rx_address_mismatch_drops; + u32 rx_vlan_mismatch_drops; u32 rx_dropped_too_small; u32 rx_dropped_too_short; u32 rx_dropped_header_too_small; @@ -1346,22 +1346,36 @@ struct be_cmd_resp_set_func_cap { /******************** GET/SET_MACLIST **************************/ #define BE_MAX_MAC 64 -struct amap_get_mac_list_context { - u8 macid[31]; - u8 act; -} __packed; - struct be_cmd_req_get_mac_list { struct be_cmd_req_hdr hdr; - u32 rsvd; + u8 mac_type; + u8 perm_override; + u16 iface_id; + u32 mac_id; + u32 rsvd[3]; +} __packed; + +struct get_list_macaddr { + u16 mac_addr_size; + union { + u8 macaddr[6]; + struct { + u8 rsvd[2]; + u32 mac_id; + } __packed s_mac_id; + } __packed mac_addr_id; } __packed; struct be_cmd_resp_get_mac_list { struct be_cmd_resp_hdr hdr; - u8 mac_count; - u8 rsvd1; - u16 rsvd2; - u8 context[sizeof(struct amap_get_mac_list_context) / 8][BE_MAX_MAC]; + struct get_list_macaddr fd_macaddr; /* Factory default mac */ + struct get_list_macaddr macid_macaddr; /* soft mac */ + u8 true_mac_count; + u8 pseudo_mac_count; + u8 mac_list_size; + u8 rsvd; + /* perm override mac */ + struct get_list_macaddr macaddr_list[BE_MAX_MAC]; } __packed; struct be_cmd_req_set_mac_list { @@ -1384,7 +1398,7 @@ struct be_port_rxf_stats_v1 { u32 rx_in_range_errors; u32 rx_out_range_errors; u32 rx_frame_too_long; - u32 rx_address_match_errors; + u32 rx_address_mismatch_drops; u32 rx_dropped_too_small; u32 rx_dropped_too_short; u32 rx_dropped_header_too_small; @@ -1575,7 +1589,7 @@ extern int be_cmd_req_native_mode(struct be_adapter *adapter); extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size); extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf); extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, - u32 *pmac_id); + bool *pmac_id_active, u32 *pmac_id, u8 *mac); extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, u8 mac_count, u32 domain); diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 802e5ddef8a8..dc1383c396c0 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -42,15 +42,42 @@ static const struct be_ethtool_stat et_stats[] = { {DRVSTAT_INFO(rx_alignment_symbol_errors)}, {DRVSTAT_INFO(rx_pause_frames)}, {DRVSTAT_INFO(rx_control_frames)}, + /* Received packets dropped when the Ethernet length field + * is not equal to the actual Ethernet data length. + */ {DRVSTAT_INFO(rx_in_range_errors)}, + /* Received packets dropped when their length field is >= 1501 bytes + * and <= 1535 bytes. + */ {DRVSTAT_INFO(rx_out_range_errors)}, + /* Received packets dropped when they are longer than 9216 bytes */ {DRVSTAT_INFO(rx_frame_too_long)}, - {DRVSTAT_INFO(rx_address_match_errors)}, + /* Received packets dropped when they don't pass the unicast or + * multicast address filtering. + */ + {DRVSTAT_INFO(rx_address_mismatch_drops)}, + /* Received packets dropped when IP packet length field is less than + * the IP header length field. + */ {DRVSTAT_INFO(rx_dropped_too_small)}, + /* Received packets dropped when IP length field is greater than + * the actual packet length. + */ {DRVSTAT_INFO(rx_dropped_too_short)}, + /* Received packets dropped when the IP header length field is less + * than 5. + */ {DRVSTAT_INFO(rx_dropped_header_too_small)}, + /* Received packets dropped when the TCP header length field is less + * than 5 or the TCP header length + IP header length is more + * than IP packet length. + */ {DRVSTAT_INFO(rx_dropped_tcp_length)}, {DRVSTAT_INFO(rx_dropped_runt)}, + /* Number of received packets dropped when a fifo for descriptors going + * into the packet demux block overflows. In normal operation, this + * fifo must never overflow. + */ {DRVSTAT_INFO(rxpp_fifo_overflow_drop)}, {DRVSTAT_INFO(rx_input_fifo_overflow_drop)}, {DRVSTAT_INFO(rx_ip_checksum_errs)}, @@ -59,16 +86,35 @@ static const struct be_ethtool_stat et_stats[] = { {DRVSTAT_INFO(tx_pauseframes)}, {DRVSTAT_INFO(tx_controlframes)}, {DRVSTAT_INFO(rx_priority_pause_frames)}, + /* Received packets dropped when an internal fifo going into + * main packet buffer tank (PMEM) overflows. + */ {DRVSTAT_INFO(pmem_fifo_overflow_drop)}, {DRVSTAT_INFO(jabber_events)}, + /* Received packets dropped due to lack of available HW packet buffers + * used to temporarily hold the received packets. + */ {DRVSTAT_INFO(rx_drops_no_pbuf)}, - {DRVSTAT_INFO(rx_drops_no_txpb)}, + /* Received packets dropped due to input receive buffer + * descriptor fifo overflowing. + */ {DRVSTAT_INFO(rx_drops_no_erx_descr)}, + /* Packets dropped because the internal FIFO to the offloaded TCP + * receive processing block is full. This could happen only for + * offloaded iSCSI or FCoE trarffic. + */ {DRVSTAT_INFO(rx_drops_no_tpre_descr)}, + /* Received packets dropped when they need more than 8 + * receive buffers. This cannot happen as the driver configures + * 2048 byte receive buffers. + */ {DRVSTAT_INFO(rx_drops_too_many_frags)}, - {DRVSTAT_INFO(rx_drops_invalid_ring)}, {DRVSTAT_INFO(forwarded_packets)}, + /* Received packets dropped when the frame length + * is more than 9018 bytes + */ {DRVSTAT_INFO(rx_drops_mtu)}, + /* Number of packets dropped due to random early drop function */ {DRVSTAT_INFO(eth_red_drops)}, {DRVSTAT_INFO(be_on_die_temperature)} }; @@ -84,8 +130,15 @@ static const struct be_ethtool_stat et_rx_stats[] = { {DRVSTAT_RX_INFO(rx_events)}, {DRVSTAT_RX_INFO(rx_compl)}, {DRVSTAT_RX_INFO(rx_mcast_pkts)}, + /* Number of page allocation failures while posting receive buffers + * to HW. + */ {DRVSTAT_RX_INFO(rx_post_fail)}, + /* Recevied packets dropped due to skb allocation failure */ {DRVSTAT_RX_INFO(rx_drops_no_skbs)}, + /* Received packets dropped due to lack of available fetched buffers + * posted by the driver. + */ {DRVSTAT_RX_INFO(rx_drops_no_frags)} }; #define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats)) @@ -97,9 +150,14 @@ static const struct be_ethtool_stat et_tx_stats[] = { {DRVSTAT_TX_INFO(tx_compl)}, /* If moving this member see above note */ {DRVSTAT_TX_INFO(tx_bytes)}, {DRVSTAT_TX_INFO(tx_pkts)}, + /* Number of skbs queued for trasmission by the driver */ {DRVSTAT_TX_INFO(tx_reqs)}, + /* Number of TX work request blocks DMAed to HW */ {DRVSTAT_TX_INFO(tx_wrbs)}, {DRVSTAT_TX_INFO(tx_compl)}, + /* Number of times the TX queue was stopped due to lack + * of spaces in the TXQ. + */ {DRVSTAT_TX_INFO(tx_stops)} }; #define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats)) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index e703d64434f8..780498784d8e 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -286,7 +286,9 @@ static void populate_be2_stats(struct be_adapter *adapter) drvs->rx_input_fifo_overflow_drop = port_stats->rx_input_fifo_overflow; drvs->rx_dropped_header_too_small = port_stats->rx_dropped_header_too_small; - drvs->rx_address_match_errors = port_stats->rx_address_match_errors; + drvs->rx_address_mismatch_drops = + port_stats->rx_address_mismatch_drops + + port_stats->rx_vlan_mismatch_drops; drvs->rx_alignment_symbol_errors = port_stats->rx_alignment_symbol_errors; @@ -298,9 +300,7 @@ static void populate_be2_stats(struct be_adapter *adapter) else drvs->jabber_events = rxf_stats->port0_jabber_events; drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; - drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; - drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; drvs->forwarded_packets = rxf_stats->forwarded_packets; drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu; drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr; @@ -337,7 +337,7 @@ static void populate_be3_stats(struct be_adapter *adapter) port_stats->rx_dropped_header_too_small; drvs->rx_input_fifo_overflow_drop = port_stats->rx_input_fifo_overflow_drop; - drvs->rx_address_match_errors = port_stats->rx_address_match_errors; + drvs->rx_address_mismatch_drops = port_stats->rx_address_mismatch_drops; drvs->rx_alignment_symbol_errors = port_stats->rx_alignment_symbol_errors; drvs->rxpp_fifo_overflow_drop = port_stats->rxpp_fifo_overflow_drop; @@ -345,9 +345,7 @@ static void populate_be3_stats(struct be_adapter *adapter) drvs->tx_controlframes = port_stats->tx_controlframes; drvs->jabber_events = port_stats->jabber_events; drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; - drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; - drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; drvs->forwarded_packets = rxf_stats->forwarded_packets; drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu; drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr; @@ -380,13 +378,14 @@ static void populate_lancer_stats(struct be_adapter *adapter) drvs->rx_dropped_header_too_small = pport_stats->rx_dropped_header_too_small; drvs->rx_input_fifo_overflow_drop = pport_stats->rx_fifo_overflow; - drvs->rx_address_match_errors = pport_stats->rx_address_match_errors; + drvs->rx_address_mismatch_drops = + pport_stats->rx_address_mismatch_drops + + pport_stats->rx_vlan_mismatch_drops; drvs->rx_alignment_symbol_errors = pport_stats->rx_symbol_errors_lo; drvs->rxpp_fifo_overflow_drop = pport_stats->rx_fifo_overflow; drvs->tx_pauseframes = pport_stats->tx_pause_frames_lo; drvs->tx_controlframes = pport_stats->tx_control_frames_lo; drvs->jabber_events = pport_stats->rx_jabbers; - drvs->rx_drops_invalid_ring = pport_stats->rx_drops_invalid_queue; drvs->forwarded_packets = pport_stats->num_forwards_lo; drvs->rx_drops_mtu = pport_stats->rx_drops_mtu_lo; drvs->rx_drops_too_many_frags = @@ -1189,7 +1188,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, struct net_device *netdev = adapter->netdev; struct sk_buff *skb; - skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN); + skb = netdev_alloc_skb_ip_align(netdev, BE_RX_SKB_ALLOC_SIZE); if (unlikely(!skb)) { rx_stats(rxo)->rx_drops_no_skbs++; be_rx_compl_discard(adapter, rxo, rxcp); @@ -2609,19 +2608,28 @@ static void be_setup_init(struct be_adapter *adapter) adapter->eq_next_idx = 0; } -static int be_configure_mac_from_list(struct be_adapter *adapter, u8 *mac) +static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac) { u32 pmac_id; - int status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id); - if (status != 0) - goto do_none; - status = be_cmd_mac_addr_query(adapter, mac, - MAC_ADDRESS_TYPE_NETWORK, - false, adapter->if_handle, pmac_id); + int status; + bool pmac_id_active; + + status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id_active, + &pmac_id, mac); if (status != 0) goto do_none; - status = be_cmd_pmac_add(adapter, mac, adapter->if_handle, - &adapter->pmac_id, 0); + + if (pmac_id_active) { + status = be_cmd_mac_addr_query(adapter, mac, + MAC_ADDRESS_TYPE_NETWORK, + false, adapter->if_handle, pmac_id); + + if (!status) + adapter->pmac_id = pmac_id; + } else { + status = be_cmd_pmac_add(adapter, mac, + adapter->if_handle, &adapter->pmac_id, 0); + } do_none: return status; } @@ -2686,7 +2694,7 @@ static int be_setup(struct be_adapter *adapter) */ if (!be_physfn(adapter)) { if (lancer_chip(adapter)) - status = be_configure_mac_from_list(adapter, mac); + status = be_add_mac_from_list(adapter, mac); else status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK, false, diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 60f0e788cc25..0b723ff2294b 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -1,5 +1,5 @@ /* - * linux/drivers/net/ethoc.c + * linux/drivers/net/ethernet/ethoc.c * * Copyright (C) 2007-2008 Avionic Design Development GmbH * Copyright (C) 2008-2009 Avionic Design GmbH @@ -913,7 +913,6 @@ static int __devinit ethoc_probe(struct platform_device *pdev) /* allocate networking device */ netdev = alloc_etherdev(sizeof(struct ethoc)); if (!netdev) { - dev_err(&pdev->dev, "cannot allocate network device\n"); ret = -ENOMEM; goto out; } diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c index c82d444b582d..1637b9862292 100644 --- a/drivers/net/ethernet/fealnx.c +++ b/drivers/net/ethernet/fealnx.c @@ -1070,14 +1070,13 @@ static void allocate_rx_buffers(struct net_device *dev) while (np->really_rx_count != RX_RING_SIZE) { struct sk_buff *skb; - skb = dev_alloc_skb(np->rx_buf_sz); + skb = netdev_alloc_skb(dev, np->rx_buf_sz); if (skb == NULL) break; /* Better luck next round. */ while (np->lack_rxbuf->skbuff) np->lack_rxbuf = np->lack_rxbuf->next_desc_logical; - skb->dev = dev; /* Mark as being used by this device. */ np->lack_rxbuf->skbuff = skb; np->lack_rxbuf->buffer = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); @@ -1265,7 +1264,7 @@ static void init_ring(struct net_device *dev) /* allocate skb for rx buffers */ for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz); + struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz); if (skb == NULL) { np->lack_rxbuf = &np->rx_ring[i]; @@ -1274,7 +1273,6 @@ static void init_ring(struct net_device *dev) ++np->really_rx_count; np->rx_ring[i].skbuff = skb; - skb->dev = dev; /* Mark as being used by this device. */ np->rx_ring[i].buffer = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); np->rx_ring[i].status = RXOWN; @@ -1704,7 +1702,7 @@ static int netdev_rx(struct net_device *dev) /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < rx_copybreak && - (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) { skb_reserve(skb, 2); /* 16 byte align the IP header */ pci_dma_sync_single_for_cpu(np->pci_dev, np->cur_rx->buffer, diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index 1c7aad8fa19c..0ee2ca7baaf3 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c @@ -711,7 +711,7 @@ fec_enet_rx(struct net_device *ndev) * include that when passing upstream as it messes up * bridging applications. */ - skb = dev_alloc_skb(pkt_len - 4 + NET_IP_ALIGN); + skb = netdev_alloc_skb(ndev, pkt_len - 4 + NET_IP_ALIGN); if (unlikely(!skb)) { printk("%s: Memory squeeze, dropping packet.\n", @@ -1210,7 +1210,7 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) bdp = fep->rx_bd_base; for (i = 0; i < RX_RING_SIZE; i++) { - skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE); + skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE); if (!skb) { fec_enet_free_buffers(ndev); return -ENOMEM; @@ -1739,21 +1739,6 @@ static struct platform_driver fec_driver = { .remove = __devexit_p(fec_drv_remove), }; -static int __init -fec_enet_module_init(void) -{ - printk(KERN_INFO "FEC Ethernet Driver\n"); - - return platform_driver_register(&fec_driver); -} - -static void __exit -fec_enet_cleanup(void) -{ - platform_driver_unregister(&fec_driver); -} - -module_exit(fec_enet_cleanup); -module_init(fec_enet_module_init); +module_platform_driver(fec_driver); MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index 30745b56fe5d..7b34d8c698da 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c @@ -160,7 +160,7 @@ static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task struct sk_buff *skb; while (!bcom_queue_full(rxtsk)) { - skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE); + skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE); if (!skb) return -EAGAIN; @@ -416,7 +416,7 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) /* skbs are allocated on open, so now we allocate a new one, * and remove the old (with the packet) */ - skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE); + skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE); if (!skb) { /* Can't get a new one : reuse the same & drop pkt */ dev_notice(&dev->dev, "Low memory - dropped packet.\n"); diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.h b/drivers/net/ethernet/freescale/fec_mpc52xx.h index 41d2dffde55b..10afa54dd062 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.h +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.h @@ -1,5 +1,5 @@ /* - * drivers/drivers/net/fec_mpc52xx/fec.h + * drivers/net/ethernet/freescale/fec_mpc52xx.h * * Driver for the MPC5200 Fast Ethernet Controller * diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index 910a8e18a9ae..999638a7c851 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -154,7 +154,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget) if (pkt_len <= fpi->rx_copybreak) { /* +2 to make IP header L1 cache aligned */ - skbn = dev_alloc_skb(pkt_len + 2); + skbn = netdev_alloc_skb(dev, pkt_len + 2); if (skbn != NULL) { skb_reserve(skbn, 2); /* align IP header */ skb_copy_from_linear_data(skb, @@ -165,7 +165,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget) skbn = skbt; } } else { - skbn = dev_alloc_skb(ENET_RX_FRSIZE); + skbn = netdev_alloc_skb(dev, ENET_RX_FRSIZE); if (skbn) skb_align(skbn, ENET_RX_ALIGN); @@ -286,7 +286,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev) if (pkt_len <= fpi->rx_copybreak) { /* +2 to make IP header L1 cache aligned */ - skbn = dev_alloc_skb(pkt_len + 2); + skbn = netdev_alloc_skb(dev, pkt_len + 2); if (skbn != NULL) { skb_reserve(skbn, 2); /* align IP header */ skb_copy_from_linear_data(skb, @@ -297,7 +297,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev) skbn = skbt; } } else { - skbn = dev_alloc_skb(ENET_RX_FRSIZE); + skbn = netdev_alloc_skb(dev, ENET_RX_FRSIZE); if (skbn) skb_align(skbn, ENET_RX_ALIGN); @@ -504,7 +504,7 @@ void fs_init_bds(struct net_device *dev) * Initialize the receive buffer descriptors. */ for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) { - skb = dev_alloc_skb(ENET_RX_FRSIZE); + skb = netdev_alloc_skb(dev, ENET_RX_FRSIZE); if (skb == NULL) { dev_warn(fep->dev, "Memory squeeze, unable to allocate skb\n"); @@ -592,7 +592,7 @@ static struct sk_buff *tx_skb_align_workaround(struct net_device *dev, struct fs_enet_private *fep = netdev_priv(dev); /* Alloc new skb */ - new_skb = dev_alloc_skb(skb->len + 4); + new_skb = netdev_alloc_skb(dev, skb->len + 4); if (!new_skb) { if (net_ratelimit()) { dev_warn(fep->dev, diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 39d160d353a4..adb0ae4e4195 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1,5 +1,5 @@ /* - * drivers/net/gianfar.c + * drivers/net/ethernet/freescale/gianfar.c * * Gianfar Ethernet Driver * This driver is designed for the non-CPM ethernet controllers diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index 40c33a7554c0..4fe0f342acec 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -1,5 +1,5 @@ /* - * drivers/net/gianfar.h + * drivers/net/ethernet/freescale/gianfar.h * * Gianfar Ethernet Driver * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560 diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 5a3b2e5b2880..5a78d55f46e7 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -1,5 +1,5 @@ /* - * drivers/net/gianfar_ethtool.c + * drivers/net/ethernet/freescale/gianfar_ethtool.c * * Gianfar Ethernet Driver * Ethtool support for Gianfar Enet diff --git a/drivers/net/ethernet/freescale/gianfar_sysfs.c b/drivers/net/ethernet/freescale/gianfar_sysfs.c index 64f4094ac7f1..cd14a4d449c2 100644 --- a/drivers/net/ethernet/freescale/gianfar_sysfs.c +++ b/drivers/net/ethernet/freescale/gianfar_sysfs.c @@ -1,5 +1,5 @@ /* - * drivers/net/gianfar_sysfs.c + * drivers/net/ethernet/freescale/gianfar_sysfs.c * * Gianfar Ethernet Driver * This driver is designed for the non-CPM ethernet controllers diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index ba2dc083bfc0..ec0905461312 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -214,8 +214,9 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, skb = __skb_dequeue(&ugeth->rx_recycle); if (!skb) - skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length + - UCC_GETH_RX_DATA_BUF_ALIGNMENT); + skb = netdev_alloc_skb(ugeth->ndev, + ugeth->ug_info->uf_info.max_rx_buf_length + + UCC_GETH_RX_DATA_BUF_ALIGNMENT); if (skb == NULL) return NULL; @@ -227,8 +228,6 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT - 1))); - skb->dev = ugeth->ndev; - out_be32(&((struct qe_bd __iomem *)bd)->buf, dma_map_single(ugeth->dev, skb->data, diff --git a/drivers/net/ethernet/fujitsu/at1700.c b/drivers/net/ethernet/fujitsu/at1700.c index 7c6c908bdf02..586b46fd4eed 100644 --- a/drivers/net/ethernet/fujitsu/at1700.c +++ b/drivers/net/ethernet/fujitsu/at1700.c @@ -757,7 +757,7 @@ net_rx(struct net_device *dev) dev->stats.rx_errors++; break; } - skb = dev_alloc_skb(pkt_len+3); + skb = netdev_alloc_skb(dev, pkt_len + 3); if (skb == NULL) { printk("%s: Memory squeeze, dropping packet (len %d).\n", dev->name, pkt_len); diff --git a/drivers/net/ethernet/fujitsu/eth16i.c b/drivers/net/ethernet/fujitsu/eth16i.c index b0e2313af3d1..c3f0178fb5cb 100644 --- a/drivers/net/ethernet/fujitsu/eth16i.c +++ b/drivers/net/ethernet/fujitsu/eth16i.c @@ -1164,7 +1164,7 @@ static void eth16i_rx(struct net_device *dev) else { /* Ok so now we should have a good packet */ struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len + 3); + skb = netdev_alloc_skb(dev, pkt_len + 3); if( skb == NULL ) { printk(KERN_WARNING "%s: Could'n allocate memory for packet (len %d)\n", dev->name, pkt_len); diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c index ee84b472cee6..0230319ddb59 100644 --- a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c +++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c @@ -1002,7 +1002,7 @@ static void fjn_rx(struct net_device *dev) dev->stats.rx_errors++; break; } - skb = dev_alloc_skb(pkt_len+2); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { netdev_notice(dev, "Memory squeeze, dropping packet (len %d)\n", pkt_len); diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c index 6a5ee0776b28..d496673f0908 100644 --- a/drivers/net/ethernet/hp/hp100.c +++ b/drivers/net/ethernet/hp/hp100.c @@ -1274,7 +1274,7 @@ static int hp100_build_rx_pdl(hp100_ring_t * ringptr, /* Note: This depends on the alloc_skb functions allocating more * space than requested, i.e. aligning to 16bytes */ - ringptr->skb = dev_alloc_skb(roundup(MAX_ETHER_SIZE + 2, 4)); + ringptr->skb = netdev_alloc_skb(dev, roundup(MAX_ETHER_SIZE + 2, 4)); if (NULL != ringptr->skb) { /* @@ -1284,7 +1284,6 @@ static int hp100_build_rx_pdl(hp100_ring_t * ringptr, */ skb_reserve(ringptr->skb, 2); - ringptr->skb->dev = dev; ringptr->skb->data = (u_char *) skb_put(ringptr->skb, MAX_ETHER_SIZE); /* ringptr->pdl points to the beginning of the PDL, i.e. the PDH */ @@ -1817,7 +1816,7 @@ static void hp100_rx(struct net_device *dev) #endif /* Now we allocate the skb and transfer the data into it. */ - skb = dev_alloc_skb(pkt_len+2); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { /* Not enough memory->drop packet */ #ifdef HP100_DEBUG printk("hp100: %s: rx: couldn't allocate a sk_buff of size %d\n", @@ -2992,7 +2991,6 @@ static int __init hp100_isa_init(void) for (i = 0; i < HP100_DEVICES && hp100_port[i] != -1; ++i) { dev = alloc_etherdev(sizeof(struct hp100_private)); if (!dev) { - printk(KERN_WARNING "hp100: no memory for network device\n"); while (cards > 0) cleanup_dev(hp100_devlist[--cards]); diff --git a/drivers/net/ethernet/i825xx/3c505.c b/drivers/net/ethernet/i825xx/3c505.c index ba82a266051d..6a5c21b82c51 100644 --- a/drivers/net/ethernet/i825xx/3c505.c +++ b/drivers/net/ethernet/i825xx/3c505.c @@ -583,7 +583,7 @@ static void receive_packet(struct net_device *dev, int len) unsigned long flags; rlen = (len + 1) & ~1; - skb = dev_alloc_skb(rlen + 2); + skb = netdev_alloc_skb(dev, rlen + 2); if (!skb) { pr_warning("%s: memory squeeze, dropping packet\n", dev->name); diff --git a/drivers/net/ethernet/i825xx/3c507.c b/drivers/net/ethernet/i825xx/3c507.c index 1e945551c144..ed6925f11479 100644 --- a/drivers/net/ethernet/i825xx/3c507.c +++ b/drivers/net/ethernet/i825xx/3c507.c @@ -851,7 +851,7 @@ static void el16_rx(struct net_device *dev) struct sk_buff *skb; pkt_len &= 0x3fff; - skb = dev_alloc_skb(pkt_len+2); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { pr_err("%s: Memory squeeze, dropping packet.\n", dev->name); diff --git a/drivers/net/ethernet/i825xx/3c523.c b/drivers/net/ethernet/i825xx/3c523.c index d70d3df4c985..8451ecd4c1ec 100644 --- a/drivers/net/ethernet/i825xx/3c523.c +++ b/drivers/net/ethernet/i825xx/3c523.c @@ -983,7 +983,7 @@ static void elmc_rcv_int(struct net_device *dev) if ((totlen = rbd->status) & RBD_LAST) { /* the first and the last buffer? */ totlen &= RBD_MASK; /* length of this frame */ rbd->status = 0; - skb = (struct sk_buff *) dev_alloc_skb(totlen + 2); + skb = netdev_alloc_skb(dev, totlen + 2); if (skb != NULL) { skb_reserve(skb, 2); /* 16 byte alignment */ skb_put(skb,totlen); diff --git a/drivers/net/ethernet/i825xx/3c527.c b/drivers/net/ethernet/i825xx/3c527.c index 474b5e71a53a..ef43f3e951c5 100644 --- a/drivers/net/ethernet/i825xx/3c527.c +++ b/drivers/net/ethernet/i825xx/3c527.c @@ -1169,7 +1169,7 @@ static void mc32_rx_ring(struct net_device *dev) /* Try to save time by avoiding a copy on big frames */ if ((length > RX_COPYBREAK) && - ((newskb=dev_alloc_skb(1532)) != NULL)) + ((newskb = netdev_alloc_skb(dev, 1532)) != NULL)) { skb=lp->rx_ring[rx_ring_tail].skb; skb_put(skb, length); @@ -1180,7 +1180,7 @@ static void mc32_rx_ring(struct net_device *dev) } else { - skb=dev_alloc_skb(length+2); + skb = netdev_alloc_skb(dev, length + 2); if(skb==NULL) { dev->stats.rx_dropped++; diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c index f2408a4d5d9c..6aa927af382c 100644 --- a/drivers/net/ethernet/i825xx/82596.c +++ b/drivers/net/ethernet/i825xx/82596.c @@ -549,14 +549,13 @@ static inline int init_rx_bufs(struct net_device *dev) /* First build the Receive Buffer Descriptor List */ for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) { - struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ); + struct sk_buff *skb = netdev_alloc_skb(dev, PKT_BUF_SZ); if (skb == NULL) { remove_rx_bufs(dev); return -ENOMEM; } - skb->dev = dev; rbd->v_next = rbd+1; rbd->b_next = WSWAPrbd(virt_to_bus(rbd+1)); rbd->b_addr = WSWAPrbd(virt_to_bus(rbd)); @@ -810,7 +809,7 @@ static inline int i596_rx(struct net_device *dev) struct sk_buff *newskb; /* Get fresh skbuff to replace filled one. */ - newskb = dev_alloc_skb(PKT_BUF_SZ); + newskb = netdev_alloc_skb(dev, PKT_BUF_SZ); if (newskb == NULL) { skb = NULL; /* drop pkt */ goto memory_squeeze; @@ -819,7 +818,6 @@ static inline int i596_rx(struct net_device *dev) skb_put(skb, pkt_len); rx_in_place = 1; rbd->skb = newskb; - newskb->dev = dev; rbd->v_data = newskb->data; rbd->b_data = WSWAPchar(virt_to_bus(newskb->data)); #ifdef __mc68000__ @@ -827,7 +825,7 @@ static inline int i596_rx(struct net_device *dev) #endif } else - skb = dev_alloc_skb(pkt_len + 2); + skb = netdev_alloc_skb(dev, pkt_len + 2); memory_squeeze: if (skb == NULL) { /* XXX tulip.c can defer packets here!! */ diff --git a/drivers/net/ethernet/i825xx/eepro.c b/drivers/net/ethernet/i825xx/eepro.c index 114cda7721fe..7a4ad4a07917 100644 --- a/drivers/net/ethernet/i825xx/eepro.c +++ b/drivers/net/ethernet/i825xx/eepro.c @@ -1563,7 +1563,7 @@ eepro_rx(struct net_device *dev) dev->stats.rx_bytes+=rcv_size; rcv_size &= 0x3fff; - skb = dev_alloc_skb(rcv_size+5); + skb = netdev_alloc_skb(dev, rcv_size + 5); if (skb == NULL) { printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); dev->stats.rx_dropped++; diff --git a/drivers/net/ethernet/i825xx/eexpress.c b/drivers/net/ethernet/i825xx/eexpress.c index 3a9580f3d4dd..3fc649e54a32 100644 --- a/drivers/net/ethernet/i825xx/eexpress.c +++ b/drivers/net/ethernet/i825xx/eexpress.c @@ -955,7 +955,7 @@ static void eexp_hw_rx_pio(struct net_device *dev) { struct sk_buff *skb; pkt_len &= 0x3fff; - skb = dev_alloc_skb(pkt_len+16); + skb = netdev_alloc_skb(dev, pkt_len + 16); if (skb == NULL) { printk(KERN_WARNING "%s: Memory squeeze, dropping packet\n",dev->name); diff --git a/drivers/net/ethernet/i825xx/ether1.c b/drivers/net/ethernet/i825xx/ether1.c index 42e90a97c7a5..406a12b46404 100644 --- a/drivers/net/ethernet/i825xx/ether1.c +++ b/drivers/net/ethernet/i825xx/ether1.c @@ -867,7 +867,7 @@ ether1_recv_done (struct net_device *dev) struct sk_buff *skb; length = (length + 1) & ~1; - skb = dev_alloc_skb (length + 2); + skb = netdev_alloc_skb(dev, length + 2); if (skb) { skb_reserve (skb, 2); diff --git a/drivers/net/ethernet/i825xx/lp486e.c b/drivers/net/ethernet/i825xx/lp486e.c index 414044b3cb11..6c2952c8ea15 100644 --- a/drivers/net/ethernet/i825xx/lp486e.c +++ b/drivers/net/ethernet/i825xx/lp486e.c @@ -454,8 +454,6 @@ init_rx_bufs(struct net_device *dev, int num) { } rfd->rbd = rbd; - } else { - printk("Could not kmalloc rbd\n"); } } lp->rbd_tail->next = rfd->rbd; @@ -658,7 +656,7 @@ i596_rx_one(struct net_device *dev, struct i596_private *lp, if (rfd->stat & RFD_STAT_OK) { /* a good frame */ int pkt_len = (rfd->count & 0x3fff); - struct sk_buff *skb = dev_alloc_skb(pkt_len); + struct sk_buff *skb = netdev_alloc_skb(dev, pkt_len); (*frames)++; diff --git a/drivers/net/ethernet/i825xx/ni52.c b/drivers/net/ethernet/i825xx/ni52.c index c0893715ef47..272976e1bb0f 100644 --- a/drivers/net/ethernet/i825xx/ni52.c +++ b/drivers/net/ethernet/i825xx/ni52.c @@ -964,7 +964,7 @@ static void ni52_rcv_int(struct net_device *dev) /* the first and the last buffer? */ totlen &= RBD_MASK; /* length of this frame */ writew(0x00, &rbd->status); - skb = (struct sk_buff *)dev_alloc_skb(totlen+2); + skb = netdev_alloc_skb(dev, totlen + 2); if (skb != NULL) { skb_reserve(skb, 2); skb_put(skb, totlen); diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c index 6ef5e11d1c84..cae17f4bc93e 100644 --- a/drivers/net/ethernet/i825xx/sun3_82586.c +++ b/drivers/net/ethernet/i825xx/sun3_82586.c @@ -28,7 +28,6 @@ static int automatic_resume = 0; /* experimental .. better should be zero */ static int rfdadd = 0; /* rfdadd=1 may be better for 8K MEM cards */ static int fifo=0x8; /* don't change */ -#include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/errno.h> @@ -779,7 +778,7 @@ static void sun3_82586_rcv_int(struct net_device *dev) { totlen &= RBD_MASK; /* length of this frame */ rbd->status = 0; - skb = (struct sk_buff *) dev_alloc_skb(totlen+2); + skb = netdev_alloc_skb(dev, totlen + 2); if(skb != NULL) { skb_reserve(skb,2); @@ -1151,28 +1150,6 @@ static void set_multicast_list(struct net_device *dev) netif_wake_queue(dev); } -#ifdef MODULE -#error This code is not currently supported as a module -static struct net_device *dev_sun3_82586; - -int init_module(void) -{ - dev_sun3_82586 = sun3_82586_probe(-1); - if (IS_ERR(dev_sun3_82586)) - return PTR_ERR(dev_sun3_82586); - return 0; -} - -void cleanup_module(void) -{ - unsigned long ioaddr = dev_sun3_82586->base_addr; - unregister_netdev(dev_sun3_82586); - release_region(ioaddr, SUN3_82586_TOTAL_SIZE); - iounmap((void *)ioaddr); - free_netdev(dev_sun3_82586); -} -#endif /* MODULE */ - #if 0 /* * DUMP .. we expect a not running CMD unit and enough space @@ -1209,5 +1186,3 @@ void sun3_82586_dump(struct net_device *dev,void *ptr) printk("\n"); } #endif - -MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/i825xx/znet.c b/drivers/net/ethernet/i825xx/znet.c index 962b4c421f3f..a43649735a04 100644 --- a/drivers/net/ethernet/i825xx/znet.c +++ b/drivers/net/ethernet/i825xx/znet.c @@ -762,7 +762,7 @@ static void znet_rx(struct net_device *dev) /* Malloc up new buffer. */ struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len); + skb = netdev_alloc_skb(dev, pkt_len); if (skb == NULL) { if (znet_debug) printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); diff --git a/drivers/net/ethernet/ibm/ehea/ehea.h b/drivers/net/ethernet/ibm/ehea/ehea.h index 6650068c996c..b8e46cc31e53 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea.h +++ b/drivers/net/ethernet/ibm/ehea/ehea.h @@ -1,5 +1,5 @@ /* - * linux/drivers/net/ehea/ehea.h + * linux/drivers/net/ethernet/ibm/ehea/ehea.h * * eHEA ethernet device driver for IBM eServer System p * diff --git a/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c index 6bdd8e36e564..95837b99a464 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c @@ -1,5 +1,5 @@ /* - * linux/drivers/net/ehea/ehea_ethtool.c + * linux/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c * * eHEA ethernet device driver for IBM eServer System p * diff --git a/drivers/net/ethernet/ibm/ehea/ehea_hw.h b/drivers/net/ethernet/ibm/ehea/ehea_hw.h index 1a2fe4dc3eb3..180d4128a711 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_hw.h +++ b/drivers/net/ethernet/ibm/ehea/ehea_hw.h @@ -1,5 +1,5 @@ /* - * linux/drivers/net/ehea/ehea_hw.h + * linux/drivers/net/ethernet/ibm/ehea/ehea_hw.h * * eHEA ethernet device driver for IBM eServer System p * diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 5d5fb2627184..8b73dd472475 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -1,5 +1,5 @@ /* - * linux/drivers/net/ehea/ehea_main.c + * linux/drivers/net/ethernet/ibm/ehea/ehea_main.c * * eHEA ethernet device driver for IBM eServer System p * @@ -2980,7 +2980,6 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, dev = alloc_etherdev_mq(sizeof(struct ehea_port), EHEA_MAX_PORT_RES); if (!dev) { - pr_err("no mem for net_device\n"); ret = -ENOMEM; goto out_err; } diff --git a/drivers/net/ethernet/ibm/ehea/ehea_phyp.c b/drivers/net/ethernet/ibm/ehea/ehea_phyp.c index 0506967b9044..30f903332e92 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_phyp.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_phyp.c @@ -1,5 +1,5 @@ /* - * linux/drivers/net/ehea/ehea_phyp.c + * linux/drivers/net/ethernet/ibm/ehea/ehea_phyp.c * * eHEA ethernet device driver for IBM eServer System p * diff --git a/drivers/net/ethernet/ibm/ehea/ehea_phyp.h b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h index 2f8174c248bc..52c456ec4d6c 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_phyp.h +++ b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h @@ -1,5 +1,5 @@ /* - * linux/drivers/net/ehea/ehea_phyp.h + * linux/drivers/net/ethernet/ibm/ehea/ehea_phyp.h * * eHEA ethernet device driver for IBM eServer System p * diff --git a/drivers/net/ethernet/ibm/ehea/ehea_qmr.c b/drivers/net/ethernet/ibm/ehea/ehea_qmr.c index c25b05b94daa..4fb47f14dbfe 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_qmr.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_qmr.c @@ -1,5 +1,5 @@ /* - * linux/drivers/net/ehea/ehea_qmr.c + * linux/drivers/net/ethernet/ibm/ehea/ehea_qmr.c * * eHEA ethernet device driver for IBM eServer System p * diff --git a/drivers/net/ethernet/ibm/ehea/ehea_qmr.h b/drivers/net/ethernet/ibm/ehea/ehea_qmr.h index 337a47ecf4aa..8e4a70c20ab7 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_qmr.h +++ b/drivers/net/ethernet/ibm/ehea/ehea_qmr.h @@ -1,5 +1,5 @@ /* - * linux/drivers/net/ehea/ehea_qmr.h + * linux/drivers/net/ethernet/ibm/ehea/ehea_qmr.h * * eHEA ethernet device driver for IBM eServer System p * diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 2abce965c7bd..dac7ffb4eaf1 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/core.c + * drivers/net/ethernet/ibm/emac/core.c * * Driver for PowerPC 4xx on-chip ethernet controller. * @@ -2706,11 +2706,9 @@ static int __devinit emac_probe(struct platform_device *ofdev) /* Allocate our net_device structure */ err = -ENOMEM; ndev = alloc_etherdev(sizeof(struct emac_instance)); - if (!ndev) { - printk(KERN_ERR "%s: could not allocate ethernet device!\n", - np->full_name); + if (!ndev) goto err_gone; - } + dev = netdev_priv(ndev); dev->ndev = ndev; dev->ofdev = ofdev; diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h index fa3ec57935fa..bade29690c71 100644 --- a/drivers/net/ethernet/ibm/emac/core.h +++ b/drivers/net/ethernet/ibm/emac/core.h @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/core.h + * drivers/net/ethernet/ibm/emac/core.h * * Driver for PowerPC 4xx on-chip ethernet controller. * diff --git a/drivers/net/ethernet/ibm/emac/debug.c b/drivers/net/ethernet/ibm/emac/debug.c index 8c6c1e2a8750..b16b4828b64d 100644 --- a/drivers/net/ethernet/ibm/emac/debug.c +++ b/drivers/net/ethernet/ibm/emac/debug.c @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/debug.c + * drivers/net/ethernet/ibm/emac/debug.c * * Driver for PowerPC 4xx on-chip ethernet controller, debug print routines. * diff --git a/drivers/net/ethernet/ibm/emac/debug.h b/drivers/net/ethernet/ibm/emac/debug.h index 90477fe69d0c..59a92d5870b5 100644 --- a/drivers/net/ethernet/ibm/emac/debug.h +++ b/drivers/net/ethernet/ibm/emac/debug.h @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/debug.h + * drivers/net/ethernet/ibm/emac/debug.h * * Driver for PowerPC 4xx on-chip ethernet controller, debug print routines. * diff --git a/drivers/net/ethernet/ibm/emac/emac.h b/drivers/net/ethernet/ibm/emac/emac.h index 1568278d759a..b44bd243fb58 100644 --- a/drivers/net/ethernet/ibm/emac/emac.h +++ b/drivers/net/ethernet/ibm/emac/emac.h @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/emac.h + * drivers/net/ethernet/ibm/emac/emac.h * * Register definitions for PowerPC 4xx on-chip ethernet contoller * diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c index f3c50b97ec61..479e43e2f1ef 100644 --- a/drivers/net/ethernet/ibm/emac/mal.c +++ b/drivers/net/ethernet/ibm/emac/mal.c @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/mal.c + * drivers/net/ethernet/ibm/emac/mal.c * * Memory Access Layer (MAL) support * diff --git a/drivers/net/ethernet/ibm/emac/mal.h b/drivers/net/ethernet/ibm/emac/mal.h index d06f985bda32..e431a32e3d69 100644 --- a/drivers/net/ethernet/ibm/emac/mal.h +++ b/drivers/net/ethernet/ibm/emac/mal.h @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/mal.h + * drivers/net/ethernet/ibm/emac/mal.h * * Memory Access Layer (MAL) support * diff --git a/drivers/net/ethernet/ibm/emac/phy.c b/drivers/net/ethernet/ibm/emac/phy.c index ab4e5969fe65..d3b9d103353e 100644 --- a/drivers/net/ethernet/ibm/emac/phy.c +++ b/drivers/net/ethernet/ibm/emac/phy.c @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/phy.c + * drivers/net/ethernet/ibm/emac/phy.c * * Driver for PowerPC 4xx on-chip ethernet controller, PHY support. * Borrowed from sungem_phy.c, though I only kept the generic MII diff --git a/drivers/net/ethernet/ibm/emac/phy.h b/drivers/net/ethernet/ibm/emac/phy.h index 5d2bf4cbe50b..d7e41ec37467 100644 --- a/drivers/net/ethernet/ibm/emac/phy.h +++ b/drivers/net/ethernet/ibm/emac/phy.h @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/phy.h + * drivers/net/ethernet/ibm/emac/phy.h * * Driver for PowerPC 4xx on-chip ethernet controller, PHY support * diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c index 4fa53f3def64..d3123282e18e 100644 --- a/drivers/net/ethernet/ibm/emac/rgmii.c +++ b/drivers/net/ethernet/ibm/emac/rgmii.c @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/rgmii.c + * drivers/net/ethernet/ibm/emac/rgmii.c * * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support. * @@ -237,11 +237,8 @@ static int __devinit rgmii_probe(struct platform_device *ofdev) rc = -ENOMEM; dev = kzalloc(sizeof(struct rgmii_instance), GFP_KERNEL); - if (dev == NULL) { - printk(KERN_ERR "%s: could not allocate RGMII device!\n", - np->full_name); + if (dev == NULL) goto err_gone; - } mutex_init(&dev->lock); dev->ofdev = ofdev; diff --git a/drivers/net/ethernet/ibm/emac/rgmii.h b/drivers/net/ethernet/ibm/emac/rgmii.h index 9296b6c5f920..668bceeff4a2 100644 --- a/drivers/net/ethernet/ibm/emac/rgmii.h +++ b/drivers/net/ethernet/ibm/emac/rgmii.h @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/rgmii.h + * drivers/net/ethernet/ibm/emac/rgmii.h * * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support. * diff --git a/drivers/net/ethernet/ibm/emac/tah.c b/drivers/net/ethernet/ibm/emac/tah.c index 5f51bf7c9dc5..872912ef518d 100644 --- a/drivers/net/ethernet/ibm/emac/tah.c +++ b/drivers/net/ethernet/ibm/emac/tah.c @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/tah.c + * drivers/net/ethernet/ibm/emac/tah.c * * Driver for PowerPC 4xx on-chip ethernet controller, TAH support. * @@ -96,11 +96,8 @@ static int __devinit tah_probe(struct platform_device *ofdev) rc = -ENOMEM; dev = kzalloc(sizeof(struct tah_instance), GFP_KERNEL); - if (dev == NULL) { - printk(KERN_ERR "%s: could not allocate TAH device!\n", - np->full_name); + if (dev == NULL) goto err_gone; - } mutex_init(&dev->lock); dev->ofdev = ofdev; diff --git a/drivers/net/ethernet/ibm/emac/tah.h b/drivers/net/ethernet/ibm/emac/tah.h index 3437ab4964c7..350b7096a041 100644 --- a/drivers/net/ethernet/ibm/emac/tah.h +++ b/drivers/net/ethernet/ibm/emac/tah.h @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/tah.h + * drivers/net/ethernet/ibm/emac/tah.h * * Driver for PowerPC 4xx on-chip ethernet controller, TAH support. * diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c index 97449e786d61..415e9b4d5408 100644 --- a/drivers/net/ethernet/ibm/emac/zmii.c +++ b/drivers/net/ethernet/ibm/emac/zmii.c @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/zmii.c + * drivers/net/ethernet/ibm/emac/zmii.c * * Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support. * @@ -240,11 +240,8 @@ static int __devinit zmii_probe(struct platform_device *ofdev) rc = -ENOMEM; dev = kzalloc(sizeof(struct zmii_instance), GFP_KERNEL); - if (dev == NULL) { - printk(KERN_ERR "%s: could not allocate ZMII device!\n", - np->full_name); + if (dev == NULL) goto err_gone; - } mutex_init(&dev->lock); dev->ofdev = ofdev; diff --git a/drivers/net/ethernet/ibm/emac/zmii.h b/drivers/net/ethernet/ibm/emac/zmii.h index ceaed823a83c..455bfb085493 100644 --- a/drivers/net/ethernet/ibm/emac/zmii.h +++ b/drivers/net/ethernet/ibm/emac/zmii.h @@ -1,5 +1,5 @@ /* - * drivers/net/ibm_newemac/zmii.h + * drivers/net/ethernet/ibm/emac/zmii.h * * Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support. * diff --git a/drivers/net/ethernet/ibm/iseries_veth.c b/drivers/net/ethernet/ibm/iseries_veth.c index acc31af6594a..1cafa6562a06 100644 --- a/drivers/net/ethernet/ibm/iseries_veth.c +++ b/drivers/net/ethernet/ibm/iseries_veth.c @@ -1032,10 +1032,8 @@ static struct net_device *veth_probe_one(int vlan, } dev = alloc_etherdev(sizeof (struct veth_port)); - if (! dev) { - veth_error("Unable to allocate net_device structure!\n"); + if (!dev) return NULL; - } port = netdev_priv(dev); diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c index 075451d0207d..1b563bb959c2 100644 --- a/drivers/net/ethernet/icplus/ipg.c +++ b/drivers/net/ethernet/icplus/ipg.c @@ -744,9 +744,6 @@ static int ipg_get_rxbuff(struct net_device *dev, int entry) return -ENOMEM; } - /* Associate the receive buffer with the IPG NIC. */ - skb->dev = dev; - /* Save the address of the sk_buff structure. */ sp->rx_buff[entry] = skb; @@ -2233,7 +2230,6 @@ static int __devinit ipg_probe(struct pci_dev *pdev, */ dev = alloc_etherdev(sizeof(struct ipg_nic_private)); if (!dev) { - pr_err("%s: alloc_etherdev failed\n", pci_name(pdev)); rc = -ENOMEM; goto err_disable_0; } diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 9436397e5725..485ab8cdac48 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -2751,11 +2751,8 @@ static int __devinit e100_probe(struct pci_dev *pdev, struct nic *nic; int err; - if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { - if (((1 << debug) - 1) & NETIF_MSG_PROBE) - pr_err("Etherdev alloc failed, aborting\n"); + if (!(netdev = alloc_etherdev(sizeof(struct nic)))) return -ENOMEM; - } netdev->netdev_ops = &e100_netdev_ops; SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h index 1e1596990b5c..2b6cd02bfba0 100644 --- a/drivers/net/ethernet/intel/e1000/e1000.h +++ b/drivers/net/ethernet/intel/e1000/e1000.h @@ -254,6 +254,7 @@ struct e1000_adapter { atomic_t tx_fifo_stall; bool pcix_82544; bool detect_tx_hung; + bool dump_buffers; /* RX */ bool (*clean_rx)(struct e1000_adapter *adapter, diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.h b/drivers/net/ethernet/intel/e1000/e1000_hw.h index f6c4d7e2560c..11578c8978db 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_hw.h +++ b/drivers/net/ethernet/intel/e1000/e1000_hw.h @@ -895,6 +895,11 @@ struct e1000_ffvt_entry { #define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ #define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ +#define E1000_RDFH 0x02410 /* RX Data FIFO Head - RW */ +#define E1000_RDFT 0x02418 /* RX Data FIFO Tail - RW */ +#define E1000_RDFHS 0x02420 /* RX Data FIFO Head Saved - RW */ +#define E1000_RDFTS 0x02428 /* RX Data FIFO Tail Saved - RW */ +#define E1000_RDFPC 0x02430 /* RX Data FIFO Packet Count - RW */ #define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */ #define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */ #define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */ @@ -1074,6 +1079,11 @@ struct e1000_ffvt_entry { #define E1000_82542_IMC E1000_IMC #define E1000_82542_RCTL E1000_RCTL #define E1000_82542_RDTR 0x00108 +#define E1000_82542_RDFH E1000_RDFH +#define E1000_82542_RDFT E1000_RDFT +#define E1000_82542_RDFHS E1000_RDFHS +#define E1000_82542_RDFTS E1000_RDFTS +#define E1000_82542_RDFPC E1000_RDFPC #define E1000_82542_RDBAL 0x00110 #define E1000_82542_RDBAH 0x00114 #define E1000_82542_RDLEN 0x00118 diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index d94d64b5d695..e72dc8175955 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -730,10 +730,8 @@ static void e1000_dump_eeprom(struct e1000_adapter *adapter) eeprom.offset = 0; data = kmalloc(eeprom.len, GFP_KERNEL); - if (!data) { - pr_err("Unable to allocate memory to dump EEPROM data\n"); + if (!data) return; - } ops->get_eeprom(netdev, &eeprom, data); @@ -3241,6 +3239,228 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, return NETDEV_TX_OK; } +#define NUM_REGS 38 /* 1 based count */ +static void e1000_regdump(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 regs[NUM_REGS]; + u32 *regs_buff = regs; + int i = 0; + + char *reg_name[] = { + "CTRL", "STATUS", + "RCTL", "RDLEN", "RDH", "RDT", "RDTR", + "TCTL", "TDBAL", "TDBAH", "TDLEN", "TDH", "TDT", + "TIDV", "TXDCTL", "TADV", "TARC0", + "TDBAL1", "TDBAH1", "TDLEN1", "TDH1", "TDT1", + "TXDCTL1", "TARC1", + "CTRL_EXT", "ERT", "RDBAL", "RDBAH", + "TDFH", "TDFT", "TDFHS", "TDFTS", "TDFPC", + "RDFH", "RDFT", "RDFHS", "RDFTS", "RDFPC" + }; + + regs_buff[0] = er32(CTRL); + regs_buff[1] = er32(STATUS); + + regs_buff[2] = er32(RCTL); + regs_buff[3] = er32(RDLEN); + regs_buff[4] = er32(RDH); + regs_buff[5] = er32(RDT); + regs_buff[6] = er32(RDTR); + + regs_buff[7] = er32(TCTL); + regs_buff[8] = er32(TDBAL); + regs_buff[9] = er32(TDBAH); + regs_buff[10] = er32(TDLEN); + regs_buff[11] = er32(TDH); + regs_buff[12] = er32(TDT); + regs_buff[13] = er32(TIDV); + regs_buff[14] = er32(TXDCTL); + regs_buff[15] = er32(TADV); + regs_buff[16] = er32(TARC0); + + regs_buff[17] = er32(TDBAL1); + regs_buff[18] = er32(TDBAH1); + regs_buff[19] = er32(TDLEN1); + regs_buff[20] = er32(TDH1); + regs_buff[21] = er32(TDT1); + regs_buff[22] = er32(TXDCTL1); + regs_buff[23] = er32(TARC1); + regs_buff[24] = er32(CTRL_EXT); + regs_buff[25] = er32(ERT); + regs_buff[26] = er32(RDBAL0); + regs_buff[27] = er32(RDBAH0); + regs_buff[28] = er32(TDFH); + regs_buff[29] = er32(TDFT); + regs_buff[30] = er32(TDFHS); + regs_buff[31] = er32(TDFTS); + regs_buff[32] = er32(TDFPC); + regs_buff[33] = er32(RDFH); + regs_buff[34] = er32(RDFT); + regs_buff[35] = er32(RDFHS); + regs_buff[36] = er32(RDFTS); + regs_buff[37] = er32(RDFPC); + + pr_info("Register dump\n"); + for (i = 0; i < NUM_REGS; i++) { + printk(KERN_INFO "%-15s %08x\n", + reg_name[i], regs_buff[i]); + } +} + +/* + * e1000_dump: Print registers, tx ring and rx ring + */ +static void e1000_dump(struct e1000_adapter *adapter) +{ + /* this code doesn't handle multiple rings */ + struct e1000_tx_ring *tx_ring = adapter->tx_ring; + struct e1000_rx_ring *rx_ring = adapter->rx_ring; + int i; + + if (!netif_msg_hw(adapter)) + return; + + /* Print Registers */ + e1000_regdump(adapter); + + /* + * transmit dump + */ + pr_info("TX Desc ring0 dump\n"); + + /* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended) + * + * Legacy Transmit Descriptor + * +--------------------------------------------------------------+ + * 0 | Buffer Address [63:0] (Reserved on Write Back) | + * +--------------------------------------------------------------+ + * 8 | Special | CSS | Status | CMD | CSO | Length | + * +--------------------------------------------------------------+ + * 63 48 47 36 35 32 31 24 23 16 15 0 + * + * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload + * 63 48 47 40 39 32 31 16 15 8 7 0 + * +----------------------------------------------------------------+ + * 0 | TUCSE | TUCS0 | TUCSS | IPCSE | IPCS0 | IPCSS | + * +----------------------------------------------------------------+ + * 8 | MSS | HDRLEN | RSV | STA | TUCMD | DTYP | PAYLEN | + * +----------------------------------------------------------------+ + * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 + * + * Extended Data Descriptor (DTYP=0x1) + * +----------------------------------------------------------------+ + * 0 | Buffer Address [63:0] | + * +----------------------------------------------------------------+ + * 8 | VLAN tag | POPTS | Rsvd | Status | Command | DTYP | DTALEN | + * +----------------------------------------------------------------+ + * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 + */ + printk(KERN_INFO "Tc[desc] [Ce CoCsIpceCoS] [MssHlRSCm0Plen] [bi->dma ]" + " leng ntw timestmp bi->skb\n"); + printk(KERN_INFO "Td[desc] [address 63:0 ] [VlaPoRSCm1Dlen] [bi->dma ]" + " leng ntw timestmp bi->skb\n"); + + if (!netif_msg_tx_done(adapter)) + goto rx_ring_summary; + + for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { + struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i); + struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i]; + struct my_u { u64 a; u64 b; }; + struct my_u *u = (struct my_u *)tx_desc; + printk(KERN_INFO "T%c[0x%03X] %016llX %016llX %016llX %04X %3X " + "%016llX %p", + ((le64_to_cpu(u->b) & (1<<20)) ? 'd' : 'c'), i, + le64_to_cpu(u->a), le64_to_cpu(u->b), + (u64)buffer_info->dma, buffer_info->length, + buffer_info->next_to_watch, (u64)buffer_info->time_stamp, + buffer_info->skb); + if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean) + printk(KERN_CONT" NTC/U\n"); + else if (i == tx_ring->next_to_use) + printk(KERN_CONT " NTU\n"); + else if (i == tx_ring->next_to_clean) + printk(KERN_CONT " NTC\n"); + else + printk(KERN_CONT "\n"); + + + if (netif_msg_pktdata(adapter) && buffer_info->dma != 0) + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, + 16, 1, phys_to_virt(buffer_info->dma), + buffer_info->length, true); + } + +rx_ring_summary: + /* + * receive dump + */ + pr_info("\nRX Desc ring dump\n"); + + /* Legacy Receive Descriptor Format + * + * +-----------------------------------------------------+ + * | Buffer Address [63:0] | + * +-----------------------------------------------------+ + * | VLAN Tag | Errors | Status 0 | Packet csum | Length | + * +-----------------------------------------------------+ + * 63 48 47 40 39 32 31 16 15 0 + */ + printk(KERN_INFO "R[desc] [address 63:0 ] [vl er S cks ln] " + "[bi->dma ] [bi->skb]\n"); + + if (!netif_msg_rx_status(adapter)) + goto exit; + + for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) { + struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i); + struct e1000_buffer *buffer_info = &rx_ring->buffer_info[i]; + struct my_u { u64 a; u64 b; }; + struct my_u *u = (struct my_u *)rx_desc; + printk(KERN_INFO "R[0x%03X] %016llX %016llX %016llX %p", + i, le64_to_cpu(u->a), le64_to_cpu(u->b), + (u64)buffer_info->dma, buffer_info->skb); + if (i == rx_ring->next_to_use) + printk(KERN_CONT " NTU\n"); + else if (i == rx_ring->next_to_clean) + printk(KERN_CONT " NTC\n"); + else + printk(KERN_CONT "\n"); + + if (netif_msg_pktdata(adapter)) + print_hex_dump(KERN_INFO, "", + DUMP_PREFIX_ADDRESS, 16, 1, + phys_to_virt(buffer_info->dma), + buffer_info->length, true); + + } /* for */ + + /* dump the descriptor caches */ + /* rx */ + printk(KERN_INFO "e1000: Rx descriptor cache in 64bit format\n"); + for (i = 0x6000; i <= 0x63FF ; i += 0x10) { + printk(KERN_INFO "R%04X: %08X|%08X %08X|%08X\n", + i, + readl(adapter->hw.hw_addr + i+4), + readl(adapter->hw.hw_addr + i), + readl(adapter->hw.hw_addr + i+12), + readl(adapter->hw.hw_addr + i+8)); + } + /* tx */ + printk(KERN_INFO "e1000: Tx descriptor cache in 64bit format\n"); + for (i = 0x7000; i <= 0x73FF ; i += 0x10) { + printk(KERN_INFO "T%04X: %08X|%08X %08X|%08X\n", + i, + readl(adapter->hw.hw_addr + i+4), + readl(adapter->hw.hw_addr + i), + readl(adapter->hw.hw_addr + i+12), + readl(adapter->hw.hw_addr + i+8)); + } +exit: + return; +} + /** * e1000_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure @@ -3262,6 +3482,7 @@ static void e1000_reset_task(struct work_struct *work) if (test_bit(__E1000_DOWN, &adapter->flags)) return; + e_err(drv, "Reset adapter\n"); e1000_reinit_safe(adapter); } @@ -3679,6 +3900,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, eop, jiffies, eop_desc->upper.fields.status); + e1000_dump(adapter); netif_stop_queue(netdev); } } diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c index e1159e54334a..cfb361e5f498 100644 --- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c +++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2011 Intel Corporation. + Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -201,19 +201,23 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) * e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs. * @hw: pointer to the HW structure **/ -static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter) +static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw) { - struct e1000_hw *hw = &adapter->hw; struct e1000_mac_info *mac = &hw->mac; - struct e1000_mac_operations *func = &mac->ops; - /* Set media type */ - switch (adapter->pdev->device) { + /* Set media type and media-dependent function pointers */ + switch (hw->adapter->pdev->device) { case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: hw->phy.media_type = e1000_media_type_internal_serdes; + mac->ops.check_for_link = e1000e_check_for_serdes_link; + mac->ops.setup_physical_interface = + e1000e_setup_fiber_serdes_link; break; default: hw->phy.media_type = e1000_media_type_copper; + mac->ops.check_for_link = e1000e_check_for_copper_link; + mac->ops.setup_physical_interface = + e1000_setup_copper_link_80003es2lan; break; } @@ -230,25 +234,6 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter) /* Adaptive IFS not supported */ mac->adaptive_ifs = false; - /* check for link */ - switch (hw->phy.media_type) { - case e1000_media_type_copper: - func->setup_physical_interface = e1000_setup_copper_link_80003es2lan; - func->check_for_link = e1000e_check_for_copper_link; - break; - case e1000_media_type_fiber: - func->setup_physical_interface = e1000e_setup_fiber_serdes_link; - func->check_for_link = e1000e_check_for_fiber_link; - break; - case e1000_media_type_internal_serdes: - func->setup_physical_interface = e1000e_setup_fiber_serdes_link; - func->check_for_link = e1000e_check_for_serdes_link; - break; - default: - return -E1000_ERR_CONFIG; - break; - } - /* set lan id for port to determine which phy lock to use */ hw->mac.ops.set_lan_id(hw); @@ -260,7 +245,7 @@ static s32 e1000_get_variants_80003es2lan(struct e1000_adapter *adapter) struct e1000_hw *hw = &adapter->hw; s32 rc; - rc = e1000_init_mac_params_80003es2lan(adapter); + rc = e1000_init_mac_params_80003es2lan(hw); if (rc) return rc; @@ -667,8 +652,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) udelay(1); if (hw->phy.autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link " - "on GG82563 phy.\n"); + e_dbg("Waiting for forced speed/duplex link on GG82563 phy.\n"); ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); @@ -1502,8 +1486,7 @@ const struct e1000_info e1000_es2_info = { | FLAG_RX_NEEDS_RESTART /* errata */ | FLAG_TARC_SET_BIT_ZERO /* errata */ | FLAG_APME_CHECK_PORT_B - | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ - | FLAG_TIPG_MEDIUM_FOR_80003ESLAN, + | FLAG_DISABLE_FC_PAUSE_TIME, /* errata */ .flags2 = FLAG2_DMA_BURST, .pba = 38, .max_hw_frame_size = DEFAULT_JUMBO, diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index a3e65fd26e09..795c3d640615 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2011 Intel Corporation. + Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -235,30 +235,42 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) * e1000_init_mac_params_82571 - Init MAC func ptrs. * @hw: pointer to the HW structure **/ -static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) +static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) { - struct e1000_hw *hw = &adapter->hw; struct e1000_mac_info *mac = &hw->mac; - struct e1000_mac_operations *func = &mac->ops; u32 swsm = 0; u32 swsm2 = 0; bool force_clear_smbi = false; - /* Set media type */ - switch (adapter->pdev->device) { + /* Set media type and media-dependent function pointers */ + switch (hw->adapter->pdev->device) { case E1000_DEV_ID_82571EB_FIBER: case E1000_DEV_ID_82572EI_FIBER: case E1000_DEV_ID_82571EB_QUAD_FIBER: hw->phy.media_type = e1000_media_type_fiber; + mac->ops.setup_physical_interface = + e1000_setup_fiber_serdes_link_82571; + mac->ops.check_for_link = e1000e_check_for_fiber_link; + mac->ops.get_link_up_info = + e1000e_get_speed_and_duplex_fiber_serdes; break; case E1000_DEV_ID_82571EB_SERDES: - case E1000_DEV_ID_82572EI_SERDES: case E1000_DEV_ID_82571EB_SERDES_DUAL: case E1000_DEV_ID_82571EB_SERDES_QUAD: + case E1000_DEV_ID_82572EI_SERDES: hw->phy.media_type = e1000_media_type_internal_serdes; + mac->ops.setup_physical_interface = + e1000_setup_fiber_serdes_link_82571; + mac->ops.check_for_link = e1000_check_for_serdes_link_82571; + mac->ops.get_link_up_info = + e1000e_get_speed_and_duplex_fiber_serdes; break; default: hw->phy.media_type = e1000_media_type_copper; + mac->ops.setup_physical_interface = + e1000_setup_copper_link_82571; + mac->ops.check_for_link = e1000e_check_for_copper_link; + mac->ops.get_link_up_info = e1000e_get_speed_and_duplex_copper; break; } @@ -269,38 +281,13 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) /* Adaptive IFS supported */ mac->adaptive_ifs = true; - /* check for link */ - switch (hw->phy.media_type) { - case e1000_media_type_copper: - func->setup_physical_interface = e1000_setup_copper_link_82571; - func->check_for_link = e1000e_check_for_copper_link; - func->get_link_up_info = e1000e_get_speed_and_duplex_copper; - break; - case e1000_media_type_fiber: - func->setup_physical_interface = - e1000_setup_fiber_serdes_link_82571; - func->check_for_link = e1000e_check_for_fiber_link; - func->get_link_up_info = - e1000e_get_speed_and_duplex_fiber_serdes; - break; - case e1000_media_type_internal_serdes: - func->setup_physical_interface = - e1000_setup_fiber_serdes_link_82571; - func->check_for_link = e1000_check_for_serdes_link_82571; - func->get_link_up_info = - e1000e_get_speed_and_duplex_fiber_serdes; - break; - default: - return -E1000_ERR_CONFIG; - break; - } - + /* MAC-specific function pointers */ switch (hw->mac.type) { case e1000_82573: - func->set_lan_id = e1000_set_lan_id_single_port; - func->check_mng_mode = e1000e_check_mng_mode_generic; - func->led_on = e1000e_led_on_generic; - func->blink_led = e1000e_blink_led_generic; + mac->ops.set_lan_id = e1000_set_lan_id_single_port; + mac->ops.check_mng_mode = e1000e_check_mng_mode_generic; + mac->ops.led_on = e1000e_led_on_generic; + mac->ops.blink_led = e1000e_blink_led_generic; /* FWSM register */ mac->has_fwsm = true; @@ -314,14 +301,14 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) break; case e1000_82574: case e1000_82583: - func->set_lan_id = e1000_set_lan_id_single_port; - func->check_mng_mode = e1000_check_mng_mode_82574; - func->led_on = e1000_led_on_82574; + mac->ops.set_lan_id = e1000_set_lan_id_single_port; + mac->ops.check_mng_mode = e1000_check_mng_mode_82574; + mac->ops.led_on = e1000_led_on_82574; break; default: - func->check_mng_mode = e1000e_check_mng_mode_generic; - func->led_on = e1000e_led_on_generic; - func->blink_led = e1000e_blink_led_generic; + mac->ops.check_mng_mode = e1000e_check_mng_mode_generic; + mac->ops.led_on = e1000e_led_on_generic; + mac->ops.blink_led = e1000e_blink_led_generic; /* FWSM register */ mac->has_fwsm = true; @@ -342,11 +329,11 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) if (!(swsm2 & E1000_SWSM2_LOCK)) { /* Only do this for the first interface on this card */ - ew32(SWSM2, - swsm2 | E1000_SWSM2_LOCK); + ew32(SWSM2, swsm2 | E1000_SWSM2_LOCK); force_clear_smbi = true; - } else + } else { force_clear_smbi = false; + } break; default: force_clear_smbi = true; @@ -383,7 +370,7 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter) int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1; s32 rc; - rc = e1000_init_mac_params_82571(adapter); + rc = e1000_init_mac_params_82571(hw); if (rc) return rc; @@ -1227,6 +1214,10 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) case e1000_82572: reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26); break; + case e1000_82574: + case e1000_82583: + reg |= (1 << 26); + break; default: break; } @@ -1873,7 +1864,7 @@ static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw) struct e1000_phy_info *phy = &hw->phy; struct e1000_mac_info *mac = &hw->mac; - if (!(phy->ops.check_reset_block)) + if (!phy->ops.check_reset_block) return; /* If the management interface is not enabled, then power down */ diff --git a/drivers/net/ethernet/intel/e1000e/Makefile b/drivers/net/ethernet/intel/e1000e/Makefile index 948c05db5d68..591b71324505 100644 --- a/drivers/net/ethernet/intel/e1000e/Makefile +++ b/drivers/net/ethernet/intel/e1000e/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel PRO/1000 Linux driver -# Copyright(c) 1999 - 2011 Intel Corporation. +# Copyright(c) 1999 - 2012 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, @@ -33,5 +33,6 @@ obj-$(CONFIG_E1000E) += e1000e.o e1000e-objs := 82571.o ich8lan.o 80003es2lan.o \ - lib.o phy.o param.o ethtool.o netdev.o + mac.o manage.o nvm.o phy.o \ + param.o ethtool.o netdev.o diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h index c516a7440bec..1af30b967a4f 100644 --- a/drivers/net/ethernet/intel/e1000e/defines.h +++ b/drivers/net/ethernet/intel/e1000e/defines.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2011 Intel Corporation. + Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -126,6 +126,13 @@ E1000_RXDEXT_STATERR_CXE | \ E1000_RXDEXT_STATERR_RXE) +#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000 +#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 +#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000 +#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 +#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000 +#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 + #define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000 /* Management Control */ @@ -326,6 +333,7 @@ /* Receive Checksum Control */ #define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ #define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ +#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ /* Header split receive */ #define E1000_RFCTL_NFSW_DIS 0x00000040 diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index f478a22ed577..45e5ae8a9fb7 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2011 Intel Corporation. + Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -234,6 +234,7 @@ struct e1000_buffer { }; struct e1000_ring { + struct e1000_adapter *adapter; /* back pointer to adapter */ void *desc; /* pointer to ring memory */ dma_addr_t dma; /* phys address of ring */ unsigned int size; /* length of ring in bytes */ @@ -242,8 +243,8 @@ struct e1000_ring { u16 next_to_use; u16 next_to_clean; - u16 head; - u16 tail; + void __iomem *head; + void __iomem *tail; /* array of buffer information structs */ struct e1000_buffer *buffer_info; @@ -251,7 +252,7 @@ struct e1000_ring { char name[IFNAMSIZ + 5]; u32 ims_val; u32 itr_val; - u16 itr_register; + void __iomem *itr_register; int set_itr; struct sk_buff *rx_skb_top; @@ -334,11 +335,10 @@ struct e1000_adapter { /* * Rx */ - bool (*clean_rx) (struct e1000_adapter *adapter, - int *work_done, int work_to_do) - ____cacheline_aligned_in_smp; - void (*alloc_rx_buf) (struct e1000_adapter *adapter, - int cleaned_count, gfp_t gfp); + bool (*clean_rx) (struct e1000_ring *ring, int *work_done, + int work_to_do) ____cacheline_aligned_in_smp; + void (*alloc_rx_buf) (struct e1000_ring *ring, int cleaned_count, + gfp_t gfp); struct e1000_ring *rx_ring; u32 rx_int_delay; @@ -398,6 +398,9 @@ struct e1000_adapter { bool idle_check; int phy_hang_count; + + u16 tx_ring_count; + u16 rx_ring_count; }; struct e1000_info { @@ -417,7 +420,7 @@ struct e1000_info { #define FLAG_HAS_FLASH (1 << 1) #define FLAG_HAS_HW_VLAN_FILTER (1 << 2) #define FLAG_HAS_WOL (1 << 3) -#define FLAG_HAS_ERT (1 << 4) +/* reserved bit4 */ #define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) #define FLAG_HAS_SWSM_ON_LOAD (1 << 6) #define FLAG_HAS_JUMBO_FRAMES (1 << 7) @@ -427,7 +430,7 @@ struct e1000_info { #define FLAG_HAS_SMART_POWER_DOWN (1 << 11) #define FLAG_IS_QUAD_PORT_A (1 << 12) #define FLAG_IS_QUAD_PORT (1 << 13) -#define FLAG_TIPG_MEDIUM_FOR_80003ESLAN (1 << 14) +/* reserved bit14 */ #define FLAG_APME_IN_WUC (1 << 15) #define FLAG_APME_IN_CTRL3 (1 << 16) #define FLAG_APME_CHECK_PORT_B (1 << 17) @@ -492,10 +495,10 @@ extern void e1000e_down(struct e1000_adapter *adapter); extern void e1000e_reinit_locked(struct e1000_adapter *adapter); extern void e1000e_reset(struct e1000_adapter *adapter); extern void e1000e_power_up_phy(struct e1000_adapter *adapter); -extern int e1000e_setup_rx_resources(struct e1000_adapter *adapter); -extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter); -extern void e1000e_free_rx_resources(struct e1000_adapter *adapter); -extern void e1000e_free_tx_resources(struct e1000_adapter *adapter); +extern int e1000e_setup_rx_resources(struct e1000_ring *ring); +extern int e1000e_setup_tx_resources(struct e1000_ring *ring); +extern void e1000e_free_rx_resources(struct e1000_ring *ring); +extern void e1000e_free_tx_resources(struct e1000_ring *ring); extern struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats); diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index fb2c28e799a2..b1f5d7491b57 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2011 Intel Corporation. + Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -34,6 +34,7 @@ #include <linux/pci.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/vmalloc.h> #include "e1000.h" @@ -536,7 +537,7 @@ static int e1000_set_eeprom(struct net_device *netdev, ret_val = e1000_read_nvm(hw, first_word, 1, &eeprom_buff[0]); ptr++; } - if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) + if (((eeprom->offset + eeprom->len) & 1) && (!ret_val)) /* need read/modify/write of last changed EEPROM word */ /* only the first byte of the word is being modified */ ret_val = e1000_read_nvm(hw, last_word, 1, @@ -552,7 +553,7 @@ static int e1000_set_eeprom(struct net_device *netdev, memcpy(ptr, bytes, eeprom->len); for (i = 0; i < last_word - first_word + 1; i++) - eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); + cpu_to_le16s(&eeprom_buff[i]); ret_val = e1000_write_nvm(hw, first_word, last_word - first_word + 1, eeprom_buff); @@ -605,94 +606,112 @@ static void e1000_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_ring *tx_ring = adapter->tx_ring; - struct e1000_ring *rx_ring = adapter->rx_ring; ring->rx_max_pending = E1000_MAX_RXD; ring->tx_max_pending = E1000_MAX_TXD; - ring->rx_pending = rx_ring->count; - ring->tx_pending = tx_ring->count; + ring->rx_pending = adapter->rx_ring_count; + ring->tx_pending = adapter->tx_ring_count; } static int e1000_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_ring *tx_ring, *tx_old; - struct e1000_ring *rx_ring, *rx_old; - int err; + struct e1000_ring *temp_tx = NULL, *temp_rx = NULL; + int err = 0, size = sizeof(struct e1000_ring); + bool set_tx = false, set_rx = false; + u16 new_rx_count, new_tx_count; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) return -EINVAL; - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - usleep_range(1000, 2000); + new_rx_count = clamp_t(u32, ring->rx_pending, E1000_MIN_RXD, + E1000_MAX_RXD); + new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE); - if (netif_running(adapter->netdev)) - e1000e_down(adapter); + new_tx_count = clamp_t(u32, ring->tx_pending, E1000_MIN_TXD, + E1000_MAX_TXD); + new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE); - tx_old = adapter->tx_ring; - rx_old = adapter->rx_ring; + if ((new_tx_count == adapter->tx_ring_count) && + (new_rx_count == adapter->rx_ring_count)) + /* nothing to do */ + return 0; - err = -ENOMEM; - tx_ring = kmemdup(tx_old, sizeof(struct e1000_ring), GFP_KERNEL); - if (!tx_ring) - goto err_alloc_tx; + while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) + usleep_range(1000, 2000); - rx_ring = kmemdup(rx_old, sizeof(struct e1000_ring), GFP_KERNEL); - if (!rx_ring) - goto err_alloc_rx; + if (!netif_running(adapter->netdev)) { + /* Set counts now and allocate resources during open() */ + adapter->tx_ring->count = new_tx_count; + adapter->rx_ring->count = new_rx_count; + adapter->tx_ring_count = new_tx_count; + adapter->rx_ring_count = new_rx_count; + goto clear_reset; + } - adapter->tx_ring = tx_ring; - adapter->rx_ring = rx_ring; + set_tx = (new_tx_count != adapter->tx_ring_count); + set_rx = (new_rx_count != adapter->rx_ring_count); - rx_ring->count = max(ring->rx_pending, (u32)E1000_MIN_RXD); - rx_ring->count = min(rx_ring->count, (u32)(E1000_MAX_RXD)); - rx_ring->count = ALIGN(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE); + /* Allocate temporary storage for ring updates */ + if (set_tx) { + temp_tx = vmalloc(size); + if (!temp_tx) { + err = -ENOMEM; + goto free_temp; + } + } + if (set_rx) { + temp_rx = vmalloc(size); + if (!temp_rx) { + err = -ENOMEM; + goto free_temp; + } + } - tx_ring->count = max(ring->tx_pending, (u32)E1000_MIN_TXD); - tx_ring->count = min(tx_ring->count, (u32)(E1000_MAX_TXD)); - tx_ring->count = ALIGN(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE); + e1000e_down(adapter); - if (netif_running(adapter->netdev)) { - /* Try to get new resources before deleting old */ - err = e1000e_setup_rx_resources(adapter); + /* + * We can't just free everything and then setup again, because the + * ISRs in MSI-X mode get passed pointers to the Tx and Rx ring + * structs. First, attempt to allocate new resources... + */ + if (set_tx) { + memcpy(temp_tx, adapter->tx_ring, size); + temp_tx->count = new_tx_count; + err = e1000e_setup_tx_resources(temp_tx); if (err) - goto err_setup_rx; - err = e1000e_setup_tx_resources(adapter); + goto err_setup; + } + if (set_rx) { + memcpy(temp_rx, adapter->rx_ring, size); + temp_rx->count = new_rx_count; + err = e1000e_setup_rx_resources(temp_rx); if (err) - goto err_setup_tx; + goto err_setup_rx; + } - /* - * restore the old in order to free it, - * then add in the new - */ - adapter->rx_ring = rx_old; - adapter->tx_ring = tx_old; - e1000e_free_rx_resources(adapter); - e1000e_free_tx_resources(adapter); - kfree(tx_old); - kfree(rx_old); - adapter->rx_ring = rx_ring; - adapter->tx_ring = tx_ring; - err = e1000e_up(adapter); - if (err) - goto err_setup; + /* ...then free the old resources and copy back any new ring data */ + if (set_tx) { + e1000e_free_tx_resources(adapter->tx_ring); + memcpy(adapter->tx_ring, temp_tx, size); + adapter->tx_ring_count = new_tx_count; + } + if (set_rx) { + e1000e_free_rx_resources(adapter->rx_ring); + memcpy(adapter->rx_ring, temp_rx, size); + adapter->rx_ring_count = new_rx_count; } - clear_bit(__E1000_RESETTING, &adapter->state); - return 0; -err_setup_tx: - e1000e_free_rx_resources(adapter); err_setup_rx: - adapter->rx_ring = rx_old; - adapter->tx_ring = tx_old; - kfree(rx_ring); -err_alloc_rx: - kfree(tx_ring); -err_alloc_tx: - e1000e_up(adapter); + if (err && set_tx) + e1000e_free_tx_resources(temp_tx); err_setup: + e1000e_up(adapter); +free_temp: + vfree(temp_tx); + vfree(temp_rx); +clear_reset: clear_bit(__E1000_RESETTING, &adapter->state); return err; } @@ -1069,7 +1088,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) tx_ring->buffer_info = kcalloc(tx_ring->count, sizeof(struct e1000_buffer), GFP_KERNEL); - if (!(tx_ring->buffer_info)) { + if (!tx_ring->buffer_info) { ret_val = 1; goto err_nomem; } @@ -1131,7 +1150,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) rx_ring->buffer_info = kcalloc(rx_ring->count, sizeof(struct e1000_buffer), GFP_KERNEL); - if (!(rx_ring->buffer_info)) { + if (!rx_ring->buffer_info) { ret_val = 5; goto err_nomem; } @@ -1837,11 +1856,11 @@ static int e1000_set_phys_id(struct net_device *netdev, break; case ETHTOOL_ID_ON: - adapter->hw.mac.ops.led_on(&adapter->hw); + hw->mac.ops.led_on(hw); break; case ETHTOOL_ID_OFF: - adapter->hw.mac.ops.led_off(&adapter->hw); + hw->mac.ops.led_off(hw); break; } return 0; @@ -1955,6 +1974,53 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset, } } +static int e1000_get_rxnfc(struct net_device *netdev, + struct ethtool_rxnfc *info, u32 *rule_locs) +{ + info->data = 0; + + switch (info->cmd) { + case ETHTOOL_GRXFH: { + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 mrqc = er32(MRQC); + + if (!(mrqc & E1000_MRQC_RSS_FIELD_MASK)) + return 0; + + switch (info->flow_type) { + case TCP_V4_FLOW: + if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_TCP) + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + /* fall through */ + case UDP_V4_FLOW: + case SCTP_V4_FLOW: + case AH_ESP_V4_FLOW: + case IPV4_FLOW: + if (mrqc & E1000_MRQC_RSS_FIELD_IPV4) + info->data |= RXH_IP_SRC | RXH_IP_DST; + break; + case TCP_V6_FLOW: + if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP) + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + /* fall through */ + case UDP_V6_FLOW: + case SCTP_V6_FLOW: + case AH_ESP_V6_FLOW: + case IPV6_FLOW: + if (mrqc & E1000_MRQC_RSS_FIELD_IPV6) + info->data |= RXH_IP_SRC | RXH_IP_DST; + break; + default: + break; + } + return 0; + } + default: + return -EOPNOTSUPP; + } +} + static const struct ethtool_ops e1000_ethtool_ops = { .get_settings = e1000_get_settings, .set_settings = e1000_set_settings, @@ -1981,6 +2047,7 @@ static const struct ethtool_ops e1000_ethtool_ops = { .get_sset_count = e1000e_get_sset_count, .get_coalesce = e1000_get_coalesce, .set_coalesce = e1000_set_coalesce, + .get_rxnfc = e1000_get_rxnfc, }; void e1000e_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h index 29670397079b..197059bb9abf 100644 --- a/drivers/net/ethernet/intel/e1000e/hw.h +++ b/drivers/net/ethernet/intel/e1000e/hw.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2011 Intel Corporation. + Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -204,6 +204,7 @@ enum e1e_registers { E1000_WUC = 0x05800, /* Wakeup Control - RW */ E1000_WUFC = 0x05808, /* Wakeup Filter Control - RW */ E1000_WUS = 0x05810, /* Wakeup Status - RO */ + E1000_MRQC = 0x05818, /* Multiple Receive Control - RW */ E1000_MANC = 0x05820, /* Management Control - RW */ E1000_FFLT = 0x05F00, /* Flexible Filter Length Table - RW Array */ E1000_HOST_IF = 0x08800, /* Host Interface */ @@ -219,6 +220,10 @@ enum e1e_registers { E1000_SWSM = 0x05B50, /* SW Semaphore */ E1000_FWSM = 0x05B54, /* FW Semaphore */ E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ + E1000_RETA_BASE = 0x05C00, /* Redirection Table - RW */ +#define E1000_RETA(_n) (E1000_RETA_BASE + ((_n) * 4)) + E1000_RSSRK_BASE = 0x05C80, /* RSS Random Key - RW */ +#define E1000_RSSRK(_n) (E1000_RSSRK_BASE + ((_n) * 4)) E1000_FFLT_DBG = 0x05F04, /* Debug Register */ E1000_PCH_RAICC_BASE = 0x05F50, /* Receive Address Initial CRC */ #define E1000_PCH_RAICC(_n) (E1000_PCH_RAICC_BASE + ((_n) * 4)) @@ -964,8 +969,8 @@ struct e1000_dev_spec_ich8lan { struct e1000_hw { struct e1000_adapter *adapter; - u8 __iomem *hw_addr; - u8 __iomem *flash_address; + void __iomem *hw_addr; + void __iomem *flash_address; struct e1000_mac_info mac; struct e1000_fc_info fc; diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index e2a80a283fd3..112d55f76b79 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2011 Intel Corporation. + Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -145,6 +145,8 @@ #define I82579_EMI_ADDR 0x10 #define I82579_EMI_DATA 0x11 #define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */ +#define I82579_MSE_THRESHOLD 0x084F /* Mean Square Error Threshold */ +#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */ /* Strapping Option Register - RO */ #define E1000_STRAP 0x0000C @@ -278,8 +280,8 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) #define er16flash(reg) __er16flash(hw, (reg)) #define er32flash(reg) __er32flash(hw, (reg)) -#define ew16flash(reg,val) __ew16flash(hw, (reg), (val)) -#define ew32flash(reg,val) __ew32flash(hw, (reg), (val)) +#define ew16flash(reg, val) __ew16flash(hw, (reg), (val)) +#define ew32flash(reg, val) __ew32flash(hw, (reg), (val)) static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw) { @@ -304,7 +306,6 @@ static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw) static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - u32 fwsm; s32 ret_val = 0; phy->addr = 1; @@ -323,14 +324,14 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - /* - * The MAC-PHY interconnect may still be in SMBus mode - * after Sx->S0. If the manageability engine (ME) is - * disabled, then toggle the LANPHYPC Value bit to force - * the interconnect to PCIe mode. - */ - fwsm = er32(FWSM); - if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && !e1000_check_reset_block(hw)) { + if (!e1000_check_reset_block(hw)) { + u32 fwsm = er32(FWSM); + + /* + * The MAC-PHY interconnect may still be in SMBus mode after + * Sx->S0. If resetting the PHY is not blocked, toggle the + * LANPHYPC Value bit to force the interconnect to PCIe mode. + */ e1000_toggle_lanphypc_value_ich8lan(hw); msleep(50); @@ -338,25 +339,26 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) * Gate automatic PHY configuration by hardware on * non-managed 82579 */ - if (hw->mac.type == e1000_pch2lan) + if ((hw->mac.type == e1000_pch2lan) && + !(fwsm & E1000_ICH_FWSM_FW_VALID)) e1000_gate_hw_phy_config_ich8lan(hw, true); - } - /* - * Reset the PHY before any access to it. Doing so, ensures that - * the PHY is in a known good state before we read/write PHY registers. - * The generic reset is sufficient here, because we haven't determined - * the PHY type yet. - */ - ret_val = e1000e_phy_hw_reset_generic(hw); - if (ret_val) - goto out; + /* + * Reset the PHY before any access to it. Doing so, ensures + * that the PHY is in a known good state before we read/write + * PHY registers. The generic reset is sufficient here, + * because we haven't determined the PHY type yet. + */ + ret_val = e1000e_phy_hw_reset_generic(hw); + if (ret_val) + goto out; - /* Ungate automatic PHY configuration on non-managed 82579 */ - if ((hw->mac.type == e1000_pch2lan) && - !(fwsm & E1000_ICH_FWSM_FW_VALID)) { - usleep_range(10000, 20000); - e1000_gate_hw_phy_config_ich8lan(hw, false); + /* Ungate automatic PHY configuration on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(fwsm & E1000_ICH_FWSM_FW_VALID)) { + usleep_range(10000, 20000); + e1000_gate_hw_phy_config_ich8lan(hw, false); + } } phy->id = e1000_phy_unknown; @@ -551,9 +553,8 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) * Initialize family-specific MAC parameters and function * pointers. **/ -static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) +static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) { - struct e1000_hw *hw = &adapter->hw; struct e1000_mac_info *mac = &hw->mac; /* Set media type function pointer */ @@ -773,7 +774,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) struct e1000_hw *hw = &adapter->hw; s32 rc; - rc = e1000_init_mac_params_ich8lan(adapter); + rc = e1000_init_mac_params_ich8lan(hw); if (rc) return rc; @@ -900,8 +901,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) } if (!timeout) { - e_dbg("Failed to acquire the semaphore, FW or HW has it: " - "FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n", + e_dbg("Failed to acquire the semaphore, FW or HW has it: FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n", er32(FWSM), extcnf_ctrl); extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; ew32(EXTCNF_CTRL, extcnf_ctrl); @@ -1669,6 +1669,26 @@ static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw) /* Set MDIO slow mode before any other MDIO access */ ret_val = e1000_set_mdio_slow_mode_hv(hw); + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR, + I82579_MSE_THRESHOLD); + if (ret_val) + goto release; + /* set MSE higher to enable link to stay up when noise is high */ + ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, 0x0034); + if (ret_val) + goto release; + ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR, + I82579_MSE_LINK_DOWN); + if (ret_val) + goto release; + /* drop link after 5 times MSE threshold was reached */ + ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, 0x0005); +release: + hw->phy.ops.release(hw); + out: return ret_val; } @@ -1741,7 +1761,6 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate) extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG; ew32(EXTCNF_CTRL, extcnf_ctrl); - return; } /** @@ -1899,7 +1918,9 @@ static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active) else oem_reg &= ~HV_OEM_BITS_LPLU; - oem_reg |= HV_OEM_BITS_RESTART_AN; + if (!e1000_check_reset_block(hw)) + oem_reg |= HV_OEM_BITS_RESTART_AN; + ret_val = e1e_wphy(hw, HV_OEM_BITS, oem_reg); out: @@ -2108,8 +2129,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) return 0; } - e_dbg("Unable to determine valid NVM bank via EEC - " - "reading flash signature\n"); + e_dbg("Unable to determine valid NVM bank via EEC - reading flash signature\n"); /* fall-thru */ default: /* set bank to 0 in case flash read fails */ @@ -2221,8 +2241,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) /* Check if the flash descriptor is valid */ if (hsfsts.hsf_status.fldesvalid == 0) { - e_dbg("Flash descriptor invalid. " - "SW Sequencing must be used.\n"); + e_dbg("Flash descriptor invalid. SW Sequencing must be used.\n"); return -E1000_ERR_NVM; } @@ -2258,14 +2277,14 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) * cycle has a chance to end before giving up. */ for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { - hsfsts.regval = __er16flash(hw, ICH_FLASH_HSFSTS); + hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcinprog == 0) { ret_val = 0; break; } udelay(1); } - if (ret_val == 0) { + if (!ret_val) { /* * Successful in waiting for previous cycle to timeout, * now set the Flash Cycle Done. @@ -2383,7 +2402,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, udelay(1); /* Steps */ ret_val = e1000_flash_cycle_init_ich8lan(hw); - if (ret_val != 0) + if (ret_val) break; hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); @@ -2403,7 +2422,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, * read in (shift in) the Flash Data0, the order is * least significant byte first msb to lsb */ - if (ret_val == 0) { + if (!ret_val) { flash_data = er32flash(ICH_FLASH_FDATA0); if (size == 1) *data = (u8)(flash_data & 0x000000FF); @@ -2422,8 +2441,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, /* Repeat for some time before giving up. */ continue; } else if (hsfsts.hsf_status.flcdone == 0) { - e_dbg("Timeout error - flash cycle " - "did not complete.\n"); + e_dbg("Timeout error - flash cycle did not complete.\n"); break; } } @@ -2774,8 +2792,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, /* Repeat for some time before giving up. */ continue; if (hsfsts.hsf_status.flcdone == 0) { - e_dbg("Timeout error - flash cycle " - "did not complete."); + e_dbg("Timeout error - flash cycle did not complete.\n"); break; } } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); @@ -2917,7 +2934,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) ret_val = e1000_flash_cycle_ich8lan(hw, ICH_FLASH_ERASE_COMMAND_TIMEOUT); - if (ret_val == 0) + if (!ret_val) break; /* @@ -3676,9 +3693,10 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) * * During S0 to Sx transition, it is possible the link remains at gig * instead of negotiating to a lower speed. Before going to Sx, set - * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation - * to a lower speed. For PCH and newer parts, the OEM bits PHY register - * (LED, GbE disable and LPLU configurations) also needs to be written. + * 'Gig Disable' to force link speed negotiation to a lower speed based on + * the LPLU setting in the NVM or custom setting. For PCH and newer parts, + * the OEM bits PHY register (LED, GbE disable and LPLU configurations) also + * needs to be written. **/ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) { @@ -3686,7 +3704,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) s32 ret_val; phy_ctrl = er32(PHY_CTRL); - phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE; + phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE; ew32(PHY_CTRL, phy_ctrl); if (hw->mac.type == e1000_ich8lan) @@ -3714,47 +3732,40 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) **/ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) { - u32 fwsm; + u16 phy_id1, phy_id2; + s32 ret_val; - if (hw->mac.type != e1000_pch2lan) + if ((hw->mac.type != e1000_pch2lan) || e1000_check_reset_block(hw)) return; - fwsm = er32(FWSM); - if (!(fwsm & E1000_ICH_FWSM_FW_VALID) || !e1000_check_reset_block(hw)) { - u16 phy_id1, phy_id2; - s32 ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) { - e_dbg("Failed to acquire PHY semaphore in resume\n"); - return; - } + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) { + e_dbg("Failed to acquire PHY semaphore in resume\n"); + return; + } - /* Test access to the PHY registers by reading the ID regs */ - ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1); - if (ret_val) - goto release; - ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2); - if (ret_val) - goto release; + /* Test access to the PHY registers by reading the ID regs */ + ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1); + if (ret_val) + goto release; + ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2); + if (ret_val) + goto release; - if (hw->phy.id == ((u32)(phy_id1 << 16) | - (u32)(phy_id2 & PHY_REVISION_MASK))) - goto release; + if (hw->phy.id == ((u32)(phy_id1 << 16) | + (u32)(phy_id2 & PHY_REVISION_MASK))) + goto release; - e1000_toggle_lanphypc_value_ich8lan(hw); + e1000_toggle_lanphypc_value_ich8lan(hw); - hw->phy.ops.release(hw); - msleep(50); - e1000_phy_hw_reset(hw); - msleep(50); - return; - } + hw->phy.ops.release(hw); + msleep(50); + e1000_phy_hw_reset(hw); + msleep(50); + return; release: hw->phy.ops.release(hw); - - return; } /** @@ -4088,10 +4099,9 @@ const struct e1000_info e1000_ich9_info = { | FLAG_HAS_WOL | FLAG_HAS_CTRLEXT_ON_LOAD | FLAG_HAS_AMT - | FLAG_HAS_ERT | FLAG_HAS_FLASH | FLAG_APME_IN_WUC, - .pba = 10, + .pba = 18, .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_ich8lan, .mac_ops = &ich8_mac_ops, @@ -4106,10 +4116,9 @@ const struct e1000_info e1000_ich10_info = { | FLAG_HAS_WOL | FLAG_HAS_CTRLEXT_ON_LOAD | FLAG_HAS_AMT - | FLAG_HAS_ERT | FLAG_HAS_FLASH | FLAG_APME_IN_WUC, - .pba = 10, + .pba = 18, .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_ich8lan, .mac_ops = &ich8_mac_ops, diff --git a/drivers/net/ethernet/intel/e1000e/lib.c b/drivers/net/ethernet/intel/e1000e/mac.c index 0893ab107adf..83f93684dc2f 100644 --- a/drivers/net/ethernet/intel/e1000e/lib.c +++ b/drivers/net/ethernet/intel/e1000e/mac.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2011 Intel Corporation. + Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -28,19 +28,6 @@ #include "e1000.h" -enum e1000_mng_mode { - e1000_mng_mode_none = 0, - e1000_mng_mode_asf, - e1000_mng_mode_pt, - e1000_mng_mode_ipmi, - e1000_mng_mode_host_if_only -}; - -#define E1000_FACTPS_MNGCG 0x20000000 - -/* Intel(R) Active Management Technology signature */ -#define E1000_IAMT_SIGNATURE 0x544D4149 - /** * e1000e_get_bus_info_pcie - Get PCIe bus information * @hw: pointer to the HW structure @@ -151,7 +138,7 @@ void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count) { u32 i; - u8 mac_addr[ETH_ALEN] = {0}; + u8 mac_addr[ETH_ALEN] = { 0 }; /* Setup the receive address */ e_dbg("Programming MAC Address into RAR[0]\n"); @@ -159,7 +146,7 @@ void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count) e1000e_rar_set(hw, hw->mac.addr, 0); /* Zero out the other (rar_entry_count - 1) receive addresses */ - e_dbg("Clearing RAR[1-%u]\n", rar_count-1); + e_dbg("Clearing RAR[1-%u]\n", rar_count - 1); for (i = 1; i < rar_count; i++) e1000e_rar_set(hw, mac_addr, i); } @@ -187,15 +174,12 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) if (ret_val) goto out; - /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */ - if (!((nvm_data & NVM_COMPAT_LOM) || - (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) || - (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) || - (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES))) + /* not supported on 82573 */ + if (hw->mac.type == e1000_82573) goto out; ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, - &nvm_alt_mac_addr_offset); + &nvm_alt_mac_addr_offset); if (ret_val) { e_dbg("NVM Read Error\n"); goto out; @@ -254,11 +238,10 @@ void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) * HW expects these in little endian so we reverse the byte order * from network order (big endian) to little endian */ - rar_low = ((u32) addr[0] | - ((u32) addr[1] << 8) | - ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); + rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | + ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); - rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); + rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); /* If MAC address zero, no need to set the AV bit */ if (rar_low || rar_high) @@ -318,7 +301,7 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) * values resulting from each mc_filter_type... * [0] [1] [2] [3] [4] [5] * 01 AA 00 12 34 56 - * LSB MSB + * LSB MSB * * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 @@ -341,7 +324,7 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) } hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | - (((u16) mc_addr[5]) << bit_shift))); + (((u16)mc_addr[5]) << bit_shift))); return hash_value; } @@ -365,7 +348,7 @@ void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); /* update mta_shadow from mc_addr_list */ - for (i = 0; (u32) i < mc_addr_count; i++) { + for (i = 0; (u32)i < mc_addr_count; i++) { hash_value = e1000_hash_mc_addr(hw, mc_addr_list); hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); @@ -461,7 +444,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) return ret_val; if (!link) - return ret_val; /* No link detected */ + return ret_val; /* No link detected */ mac->get_link_status = false; @@ -528,10 +511,10 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) * was just plugged in. The autoneg_failed flag does this. */ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) && - (!(rxcw & E1000_RXCW_C))) { - if (mac->autoneg_failed == 0) { - mac->autoneg_failed = 1; + if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) && + !(rxcw & E1000_RXCW_C)) { + if (!mac->autoneg_failed) { + mac->autoneg_failed = true; return 0; } e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); @@ -594,9 +577,9 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) * time to complete. */ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { - if (mac->autoneg_failed == 0) { - mac->autoneg_failed = 1; + if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) { + if (!mac->autoneg_failed) { + mac->autoneg_failed = true; return 0; } e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); @@ -656,12 +639,10 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) if (rxcw & E1000_RXCW_SYNCH) { if (!(rxcw & E1000_RXCW_IV)) { mac->serdes_has_link = true; - e_dbg("SERDES: Link up - autoneg " - "completed successfully.\n"); + e_dbg("SERDES: Link up - autoneg completed successfully.\n"); } else { mac->serdes_has_link = false; - e_dbg("SERDES: Link down - invalid" - "codewords detected in autoneg.\n"); + e_dbg("SERDES: Link down - invalid codewords detected in autoneg.\n"); } } else { mac->serdes_has_link = false; @@ -706,8 +687,7 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw) if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0) hw->fc.requested_mode = e1000_fc_none; - else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == - NVM_WORD0F_ASM_DIR) + else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == NVM_WORD0F_ASM_DIR) hw->fc.requested_mode = e1000_fc_tx_pause; else hw->fc.requested_mode = e1000_fc_full; @@ -753,8 +733,7 @@ s32 e1000e_setup_link(struct e1000_hw *hw) */ hw->fc.current_mode = hw->fc.requested_mode; - e_dbg("After fix-ups FlowControl is now = %x\n", - hw->fc.current_mode); + e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); /* Call the necessary media_type subroutine to configure the link. */ ret_val = mac->ops.setup_physical_interface(hw); @@ -876,7 +855,7 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) } if (i == FIBER_LINK_UP_LIMIT) { e_dbg("Never got a valid link from auto-neg!!!\n"); - mac->autoneg_failed = 1; + mac->autoneg_failed = true; /* * AutoNeg failed to achieve a link, so we'll call * mac->check_for_link. This routine will force the @@ -888,9 +867,9 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) e_dbg("Error while checking for link\n"); return ret_val; } - mac->autoneg_failed = 0; + mac->autoneg_failed = false; } else { - mac->autoneg_failed = 0; + mac->autoneg_failed = false; e_dbg("Valid Link Found\n"); } @@ -1121,8 +1100,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) return ret_val; if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { - e_dbg("Copper PHY and Auto Neg " - "has not completed.\n"); + e_dbg("Copper PHY and Auto Neg has not completed.\n"); return ret_val; } @@ -1186,11 +1164,10 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) */ if (hw->fc.requested_mode == e1000_fc_full) { hw->fc.current_mode = e1000_fc_full; - e_dbg("Flow Control = FULL.\r\n"); + e_dbg("Flow Control = FULL.\n"); } else { hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = " - "Rx PAUSE frames only.\r\n"); + e_dbg("Flow Control = Rx PAUSE frames only.\n"); } } /* @@ -1202,11 +1179,11 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) * 0 | 1 | 1 | 1 | e1000_fc_tx_pause */ else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { + (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && + (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && + (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc.current_mode = e1000_fc_tx_pause; - e_dbg("Flow Control = Tx PAUSE frames only.\r\n"); + e_dbg("Flow Control = Tx PAUSE frames only.\n"); } /* * For transmitting PAUSE frames ONLY. @@ -1221,14 +1198,14 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = Rx PAUSE frames only.\r\n"); + e_dbg("Flow Control = Rx PAUSE frames only.\n"); } else { /* * Per the IEEE spec, at this point flow control * should be disabled. */ hw->fc.current_mode = e1000_fc_none; - e_dbg("Flow Control = NONE.\r\n"); + e_dbg("Flow Control = NONE.\n"); } /* @@ -1268,7 +1245,8 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) * Read the status register for the current speed/duplex and store the current * speed and duplex for copper connections. **/ -s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex) +s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, + u16 *duplex) { u32 status; @@ -1301,7 +1279,8 @@ s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *dup * Sets the speed and duplex to gigabit full duplex (the only possible option) * for fiber/serdes links. **/ -s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex) +s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, + u16 *duplex) { *speed = SPEED_1000; *duplex = FULL_DUPLEX; @@ -1504,11 +1483,10 @@ s32 e1000e_setup_led_generic(struct e1000_hw *hw) ledctl = er32(LEDCTL); hw->mac.ledctl_default = ledctl; /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | - E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); + ledctl &= ~(E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_LED0_BLINK | + E1000_LEDCTL_LED0_MODE_MASK); ledctl |= (E1000_LEDCTL_MODE_LED_OFF << - E1000_LEDCTL_LED0_MODE_SHIFT); + E1000_LEDCTL_LED0_MODE_SHIFT); ew32(LEDCTL, ledctl); } else if (hw->phy.media_type == e1000_media_type_copper) { ew32(LEDCTL, hw->mac.ledctl_mode1); @@ -1544,7 +1522,7 @@ s32 e1000e_blink_led_generic(struct e1000_hw *hw) if (hw->phy.media_type == e1000_media_type_fiber) { /* always blink LED0 for PCI-E fiber */ ledctl_blink = E1000_LEDCTL_LED0_BLINK | - (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); + (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); } else { /* * set the blink bit for each LED that's "on" (0x0E) @@ -1657,8 +1635,7 @@ s32 e1000e_disable_pcie_master(struct e1000_hw *hw) ew32(CTRL, ctrl); while (timeout) { - if (!(er32(STATUS) & - E1000_STATUS_GIO_MASTER_ENABLE)) + if (!(er32(STATUS) & E1000_STATUS_GIO_MASTER_ENABLE)) break; udelay(100); timeout--; @@ -1684,7 +1661,7 @@ void e1000e_reset_adaptive(struct e1000_hw *hw) if (!mac->adaptive_ifs) { e_dbg("Not in Adaptive IFS mode!\n"); - goto out; + return; } mac->current_ifs_val = 0; @@ -1695,8 +1672,6 @@ void e1000e_reset_adaptive(struct e1000_hw *hw) mac->in_ifs_mode = false; ew32(AIT, 0); -out: - return; } /** @@ -1712,7 +1687,7 @@ void e1000e_update_adaptive(struct e1000_hw *hw) if (!mac->adaptive_ifs) { e_dbg("Not in Adaptive IFS mode!\n"); - goto out; + return; } if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { @@ -1723,7 +1698,7 @@ void e1000e_update_adaptive(struct e1000_hw *hw) mac->current_ifs_val = mac->ifs_min_val; else mac->current_ifs_val += - mac->ifs_step_size; + mac->ifs_step_size; ew32(AIT, mac->current_ifs_val); } } @@ -1735,959 +1710,4 @@ void e1000e_update_adaptive(struct e1000_hw *hw) ew32(AIT, 0); } } -out: - return; -} - -/** - * e1000_raise_eec_clk - Raise EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Enable/Raise the EEPROM clock bit. - **/ -static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd | E1000_EECD_SK; - ew32(EECD, *eecd); - e1e_flush(); - udelay(hw->nvm.delay_usec); -} - -/** - * e1000_lower_eec_clk - Lower EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Clear/Lower the EEPROM clock bit. - **/ -static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd & ~E1000_EECD_SK; - ew32(EECD, *eecd); - e1e_flush(); - udelay(hw->nvm.delay_usec); -} - -/** - * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM - * @hw: pointer to the HW structure - * @data: data to send to the EEPROM - * @count: number of bits to shift out - * - * We need to shift 'count' bits out to the EEPROM. So, the value in the - * "data" parameter will be shifted out to the EEPROM one bit at a time. - * In order to do this, "data" must be broken down into bits. - **/ -static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u32 mask; - - mask = 0x01 << (count - 1); - if (nvm->type == e1000_nvm_eeprom_spi) - eecd |= E1000_EECD_DO; - - do { - eecd &= ~E1000_EECD_DI; - - if (data & mask) - eecd |= E1000_EECD_DI; - - ew32(EECD, eecd); - e1e_flush(); - - udelay(nvm->delay_usec); - - e1000_raise_eec_clk(hw, &eecd); - e1000_lower_eec_clk(hw, &eecd); - - mask >>= 1; - } while (mask); - - eecd &= ~E1000_EECD_DI; - ew32(EECD, eecd); -} - -/** - * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM - * @hw: pointer to the HW structure - * @count: number of bits to shift in - * - * In order to read a register from the EEPROM, we need to shift 'count' bits - * in from the EEPROM. Bits are "shifted in" by raising the clock input to - * the EEPROM (setting the SK bit), and then reading the value of the data out - * "DO" bit. During this "shifting in" process the data in "DI" bit should - * always be clear. - **/ -static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) -{ - u32 eecd; - u32 i; - u16 data; - - eecd = er32(EECD); - - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); - data = 0; - - for (i = 0; i < count; i++) { - data <<= 1; - e1000_raise_eec_clk(hw, &eecd); - - eecd = er32(EECD); - - eecd &= ~E1000_EECD_DI; - if (eecd & E1000_EECD_DO) - data |= 1; - - e1000_lower_eec_clk(hw, &eecd); - } - - return data; -} - -/** - * e1000e_poll_eerd_eewr_done - Poll for EEPROM read/write completion - * @hw: pointer to the HW structure - * @ee_reg: EEPROM flag for polling - * - * Polls the EEPROM status bit for either read or write completion based - * upon the value of 'ee_reg'. - **/ -s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) -{ - u32 attempts = 100000; - u32 i, reg = 0; - - for (i = 0; i < attempts; i++) { - if (ee_reg == E1000_NVM_POLL_READ) - reg = er32(EERD); - else - reg = er32(EEWR); - - if (reg & E1000_NVM_RW_REG_DONE) - return 0; - - udelay(5); - } - - return -E1000_ERR_NVM; -} - -/** - * e1000e_acquire_nvm - Generic request for access to EEPROM - * @hw: pointer to the HW structure - * - * Set the EEPROM access request bit and wait for EEPROM access grant bit. - * Return successful if access grant bit set, else clear the request for - * EEPROM access and return -E1000_ERR_NVM (-1). - **/ -s32 e1000e_acquire_nvm(struct e1000_hw *hw) -{ - u32 eecd = er32(EECD); - s32 timeout = E1000_NVM_GRANT_ATTEMPTS; - - ew32(EECD, eecd | E1000_EECD_REQ); - eecd = er32(EECD); - - while (timeout) { - if (eecd & E1000_EECD_GNT) - break; - udelay(5); - eecd = er32(EECD); - timeout--; - } - - if (!timeout) { - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); - e_dbg("Could not acquire NVM grant\n"); - return -E1000_ERR_NVM; - } - - return 0; -} - -/** - * e1000_standby_nvm - Return EEPROM to standby state - * @hw: pointer to the HW structure - * - * Return the EEPROM to a standby state. - **/ -static void e1000_standby_nvm(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - - if (nvm->type == e1000_nvm_eeprom_spi) { - /* Toggle CS to flush commands */ - eecd |= E1000_EECD_CS; - ew32(EECD, eecd); - e1e_flush(); - udelay(nvm->delay_usec); - eecd &= ~E1000_EECD_CS; - ew32(EECD, eecd); - e1e_flush(); - udelay(nvm->delay_usec); - } -} - -/** - * e1000_stop_nvm - Terminate EEPROM command - * @hw: pointer to the HW structure - * - * Terminates the current command by inverting the EEPROM's chip select pin. - **/ -static void e1000_stop_nvm(struct e1000_hw *hw) -{ - u32 eecd; - - eecd = er32(EECD); - if (hw->nvm.type == e1000_nvm_eeprom_spi) { - /* Pull CS high */ - eecd |= E1000_EECD_CS; - e1000_lower_eec_clk(hw, &eecd); - } -} - -/** - * e1000e_release_nvm - Release exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * Stop any current commands to the EEPROM and clear the EEPROM request bit. - **/ -void e1000e_release_nvm(struct e1000_hw *hw) -{ - u32 eecd; - - e1000_stop_nvm(hw); - - eecd = er32(EECD); - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); -} - -/** - * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write - * @hw: pointer to the HW structure - * - * Setups the EEPROM for reading and writing. - **/ -static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u8 spi_stat_reg; - - if (nvm->type == e1000_nvm_eeprom_spi) { - u16 timeout = NVM_MAX_RETRY_SPI; - - /* Clear SK and CS */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - ew32(EECD, eecd); - e1e_flush(); - udelay(1); - - /* - * Read "Status Register" repeatedly until the LSB is cleared. - * The EEPROM will signal that the command has been completed - * by clearing bit 0 of the internal status register. If it's - * not cleared within 'timeout', then error out. - */ - while (timeout) { - e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, - hw->nvm.opcode_bits); - spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); - if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) - break; - - udelay(5); - e1000_standby_nvm(hw); - timeout--; - } - - if (!timeout) { - e_dbg("SPI NVM Status error\n"); - return -E1000_ERR_NVM; - } - } - - return 0; -} - -/** - * e1000e_read_nvm_eerd - Reads EEPROM using EERD register - * @hw: pointer to the HW structure - * @offset: offset of word in the EEPROM to read - * @words: number of words to read - * @data: word read from the EEPROM - * - * Reads a 16 bit word from the EEPROM using the EERD register. - **/ -s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i, eerd = 0; - s32 ret_val = 0; - - /* - * A check for invalid values: offset too large, too many words, - * too many words for the offset, and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - return -E1000_ERR_NVM; - } - - for (i = 0; i < words; i++) { - eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + - E1000_NVM_RW_REG_START; - - ew32(EERD, eerd); - ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); - if (ret_val) - break; - - data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA); - } - - return ret_val; -} - -/** - * e1000e_write_nvm_spi - Write to EEPROM using SPI - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * Writes data to EEPROM at offset using SPI interface. - * - * If e1000e_update_nvm_checksum is not called after this function , the - * EEPROM will most likely contain an invalid checksum. - **/ -s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val; - u16 widx = 0; - - /* - * A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - return -E1000_ERR_NVM; - } - - ret_val = nvm->ops.acquire(hw); - if (ret_val) - return ret_val; - - while (widx < words) { - u8 write_opcode = NVM_WRITE_OPCODE_SPI; - - ret_val = e1000_ready_nvm_eeprom(hw); - if (ret_val) { - nvm->ops.release(hw); - return ret_val; - } - - e1000_standby_nvm(hw); - - /* Send the WRITE ENABLE command (8 bit opcode) */ - e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, - nvm->opcode_bits); - - e1000_standby_nvm(hw); - - /* - * Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((nvm->address_bits == 8) && (offset >= 128)) - write_opcode |= NVM_A8_OPCODE_SPI; - - /* Send the Write command (8-bit opcode + addr) */ - e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); - e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), - nvm->address_bits); - - /* Loop to allow for up to whole page write of eeprom */ - while (widx < words) { - u16 word_out = data[widx]; - word_out = (word_out >> 8) | (word_out << 8); - e1000_shift_out_eec_bits(hw, word_out, 16); - widx++; - - if ((((offset + widx) * 2) % nvm->page_size) == 0) { - e1000_standby_nvm(hw); - break; - } - } - } - - usleep_range(10000, 20000); - nvm->ops.release(hw); - return 0; -} - -/** - * e1000_read_pba_string_generic - Read device part number - * @hw: pointer to the HW structure - * @pba_num: pointer to device part number - * @pba_num_size: size of part number buffer - * - * Reads the product board assembly (PBA) number from the EEPROM and stores - * the value in pba_num. - **/ -s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, - u32 pba_num_size) -{ - s32 ret_val; - u16 nvm_data; - u16 pba_ptr; - u16 offset; - u16 length; - - if (pba_num == NULL) { - e_dbg("PBA string buffer was null\n"); - ret_val = E1000_ERR_INVALID_ARGUMENT; - goto out; - } - - ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - - ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - - /* - * if nvm_data is not ptr guard the PBA must be in legacy format which - * means pba_ptr is actually our second data word for the PBA number - * and we can decode it into an ascii string - */ - if (nvm_data != NVM_PBA_PTR_GUARD) { - e_dbg("NVM PBA number is not stored as string\n"); - - /* we will need 11 characters to store the PBA */ - if (pba_num_size < 11) { - e_dbg("PBA string buffer too small\n"); - return E1000_ERR_NO_SPACE; - } - - /* extract hex string from data and pba_ptr */ - pba_num[0] = (nvm_data >> 12) & 0xF; - pba_num[1] = (nvm_data >> 8) & 0xF; - pba_num[2] = (nvm_data >> 4) & 0xF; - pba_num[3] = nvm_data & 0xF; - pba_num[4] = (pba_ptr >> 12) & 0xF; - pba_num[5] = (pba_ptr >> 8) & 0xF; - pba_num[6] = '-'; - pba_num[7] = 0; - pba_num[8] = (pba_ptr >> 4) & 0xF; - pba_num[9] = pba_ptr & 0xF; - - /* put a null character on the end of our string */ - pba_num[10] = '\0'; - - /* switch all the data but the '-' to hex char */ - for (offset = 0; offset < 10; offset++) { - if (pba_num[offset] < 0xA) - pba_num[offset] += '0'; - else if (pba_num[offset] < 0x10) - pba_num[offset] += 'A' - 0xA; - } - - goto out; - } - - ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - - if (length == 0xFFFF || length == 0) { - e_dbg("NVM PBA number section invalid length\n"); - ret_val = E1000_ERR_NVM_PBA_SECTION; - goto out; - } - /* check if pba_num buffer is big enough */ - if (pba_num_size < (((u32)length * 2) - 1)) { - e_dbg("PBA string buffer too small\n"); - ret_val = E1000_ERR_NO_SPACE; - goto out; - } - - /* trim pba length from start of string */ - pba_ptr++; - length--; - - for (offset = 0; offset < length; offset++) { - ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - goto out; - } - pba_num[offset * 2] = (u8)(nvm_data >> 8); - pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF); - } - pba_num[offset * 2] = '\0'; - -out: - return ret_val; -} - -/** - * e1000_read_mac_addr_generic - Read device MAC address - * @hw: pointer to the HW structure - * - * Reads the device MAC address from the EEPROM and stores the value. - * Since devices with two ports use the same EEPROM, we increment the - * last bit in the MAC address for the second port. - **/ -s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) -{ - u32 rar_high; - u32 rar_low; - u16 i; - - rar_high = er32(RAH(0)); - rar_low = er32(RAL(0)); - - for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); - - for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); - - for (i = 0; i < ETH_ALEN; i++) - hw->mac.addr[i] = hw->mac.perm_addr[i]; - - return 0; -} - -/** - * e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Calculates the EEPROM checksum by reading/adding each word of the EEPROM - * and then verifies that the sum of the EEPROM is equal to 0xBABA. - **/ -s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val; - u16 checksum = 0; - u16 i, nvm_data; - - for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - checksum += nvm_data; - } - - if (checksum != (u16) NVM_SUM) { - e_dbg("NVM Checksum Invalid\n"); - return -E1000_ERR_NVM; - } - - return 0; -} - -/** - * e1000e_update_nvm_checksum_generic - Update EEPROM checksum - * @hw: pointer to the HW structure - * - * Updates the EEPROM checksum by reading/adding each word of the EEPROM - * up to the checksum. Then calculates the EEPROM checksum and writes the - * value to the EEPROM. - **/ -s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val; - u16 checksum = 0; - u16 i, nvm_data; - - for (i = 0; i < NVM_CHECKSUM_REG; i++) { - ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error while updating checksum.\n"); - return ret_val; - } - checksum += nvm_data; - } - checksum = (u16) NVM_SUM - checksum; - ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum); - if (ret_val) - e_dbg("NVM Write Error while updating checksum.\n"); - - return ret_val; -} - -/** - * e1000e_reload_nvm - Reloads EEPROM - * @hw: pointer to the HW structure - * - * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the - * extended control register. - **/ -void e1000e_reload_nvm(struct e1000_hw *hw) -{ - u32 ctrl_ext; - - udelay(10); - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); -} - -/** - * e1000_calculate_checksum - Calculate checksum for buffer - * @buffer: pointer to EEPROM - * @length: size of EEPROM to calculate a checksum for - * - * Calculates the checksum for some buffer on a specified length. The - * checksum calculated is returned. - **/ -static u8 e1000_calculate_checksum(u8 *buffer, u32 length) -{ - u32 i; - u8 sum = 0; - - if (!buffer) - return 0; - - for (i = 0; i < length; i++) - sum += buffer[i]; - - return (u8) (0 - sum); -} - -/** - * e1000_mng_enable_host_if - Checks host interface is enabled - * @hw: pointer to the HW structure - * - * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND - * - * This function checks whether the HOST IF is enabled for command operation - * and also checks whether the previous command is completed. It busy waits - * in case of previous command is not completed. - **/ -static s32 e1000_mng_enable_host_if(struct e1000_hw *hw) -{ - u32 hicr; - u8 i; - - if (!(hw->mac.arc_subsystem_valid)) { - e_dbg("ARC subsystem not valid.\n"); - return -E1000_ERR_HOST_INTERFACE_COMMAND; - } - - /* Check that the host interface is enabled. */ - hicr = er32(HICR); - if ((hicr & E1000_HICR_EN) == 0) { - e_dbg("E1000_HOST_EN bit disabled.\n"); - return -E1000_ERR_HOST_INTERFACE_COMMAND; - } - /* check the previous command is completed */ - for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { - hicr = er32(HICR); - if (!(hicr & E1000_HICR_C)) - break; - mdelay(1); - } - - if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { - e_dbg("Previous command timeout failed .\n"); - return -E1000_ERR_HOST_INTERFACE_COMMAND; - } - - return 0; -} - -/** - * e1000e_check_mng_mode_generic - check management mode - * @hw: pointer to the HW structure - * - * Reads the firmware semaphore register and returns true (>0) if - * manageability is enabled, else false (0). - **/ -bool e1000e_check_mng_mode_generic(struct e1000_hw *hw) -{ - u32 fwsm = er32(FWSM); - - return (fwsm & E1000_FWSM_MODE_MASK) == - (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); -} - -/** - * e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx - * @hw: pointer to the HW structure - * - * Enables packet filtering on transmit packets if manageability is enabled - * and host interface is enabled. - **/ -bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw) -{ - struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; - u32 *buffer = (u32 *)&hw->mng_cookie; - u32 offset; - s32 ret_val, hdr_csum, csum; - u8 i, len; - - hw->mac.tx_pkt_filtering = true; - - /* No manageability, no filtering */ - if (!e1000e_check_mng_mode(hw)) { - hw->mac.tx_pkt_filtering = false; - goto out; - } - - /* - * If we can't read from the host interface for whatever - * reason, disable filtering. - */ - ret_val = e1000_mng_enable_host_if(hw); - if (ret_val) { - hw->mac.tx_pkt_filtering = false; - goto out; - } - - /* Read in the header. Length and offset are in dwords. */ - len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; - offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; - for (i = 0; i < len; i++) - *(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset + i); - hdr_csum = hdr->checksum; - hdr->checksum = 0; - csum = e1000_calculate_checksum((u8 *)hdr, - E1000_MNG_DHCP_COOKIE_LENGTH); - /* - * If either the checksums or signature don't match, then - * the cookie area isn't considered valid, in which case we - * take the safe route of assuming Tx filtering is enabled. - */ - if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) { - hw->mac.tx_pkt_filtering = true; - goto out; - } - - /* Cookie area is valid, make the final check for filtering. */ - if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) { - hw->mac.tx_pkt_filtering = false; - goto out; - } - -out: - return hw->mac.tx_pkt_filtering; -} - -/** - * e1000_mng_write_cmd_header - Writes manageability command header - * @hw: pointer to the HW structure - * @hdr: pointer to the host interface command header - * - * Writes the command header after does the checksum calculation. - **/ -static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr) -{ - u16 i, length = sizeof(struct e1000_host_mng_command_header); - - /* Write the whole command header structure with new checksum. */ - - hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); - - length >>= 2; - /* Write the relevant command block into the ram area. */ - for (i = 0; i < length; i++) { - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i, - *((u32 *) hdr + i)); - e1e_flush(); - } - - return 0; -} - -/** - * e1000_mng_host_if_write - Write to the manageability host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface buffer - * @length: size of the buffer - * @offset: location in the buffer to write to - * @sum: sum of the data (not checksum) - * - * This function writes the buffer content at the offset given on the host if. - * It also does alignment considerations to do the writes in most efficient - * way. Also fills up the sum of the buffer in *buffer parameter. - **/ -static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, - u16 length, u16 offset, u8 *sum) -{ - u8 *tmp; - u8 *bufptr = buffer; - u32 data = 0; - u16 remaining, i, j, prev_bytes; - - /* sum = only sum of the data and it is not checksum */ - - if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) - return -E1000_ERR_PARAM; - - tmp = (u8 *)&data; - prev_bytes = offset & 0x3; - offset >>= 2; - - if (prev_bytes) { - data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset); - for (j = prev_bytes; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data); - length -= j - prev_bytes; - offset++; - } - - remaining = length & 0x3; - length -= remaining; - - /* Calculate length in DWORDs */ - length >>= 2; - - /* - * The device driver writes the relevant command block into the - * ram area. - */ - for (i = 0; i < length; i++) { - for (j = 0; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); - } - if (remaining) { - for (j = 0; j < sizeof(u32); j++) { - if (j < remaining) - *(tmp + j) = *bufptr++; - else - *(tmp + j) = 0; - - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); - } - - return 0; -} - -/** - * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface - * @length: size of the buffer - * - * Writes the DHCP information to the host interface. - **/ -s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length) -{ - struct e1000_host_mng_command_header hdr; - s32 ret_val; - u32 hicr; - - hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; - hdr.command_length = length; - hdr.reserved1 = 0; - hdr.reserved2 = 0; - hdr.checksum = 0; - - /* Enable the host interface */ - ret_val = e1000_mng_enable_host_if(hw); - if (ret_val) - return ret_val; - - /* Populate the host interface with the contents of "buffer". */ - ret_val = e1000_mng_host_if_write(hw, buffer, length, - sizeof(hdr), &(hdr.checksum)); - if (ret_val) - return ret_val; - - /* Write the manageability command header */ - ret_val = e1000_mng_write_cmd_header(hw, &hdr); - if (ret_val) - return ret_val; - - /* Tell the ARC a new command is pending. */ - hicr = er32(HICR); - ew32(HICR, hicr | E1000_HICR_C); - - return 0; -} - -/** - * e1000e_enable_mng_pass_thru - Check if management passthrough is needed - * @hw: pointer to the HW structure - * - * Verifies the hardware needs to leave interface enabled so that frames can - * be directed to and from the management interface. - **/ -bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw) -{ - u32 manc; - u32 fwsm, factps; - bool ret_val = false; - - manc = er32(MANC); - - if (!(manc & E1000_MANC_RCV_TCO_EN)) - goto out; - - if (hw->mac.has_fwsm) { - fwsm = er32(FWSM); - factps = er32(FACTPS); - - if (!(factps & E1000_FACTPS_MNGCG) && - ((fwsm & E1000_FWSM_MODE_MASK) == - (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { - ret_val = true; - goto out; - } - } else if ((hw->mac.type == e1000_82574) || - (hw->mac.type == e1000_82583)) { - u16 data; - - factps = er32(FACTPS); - e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); - - if (!(factps & E1000_FACTPS_MNGCG) && - ((data & E1000_NVM_INIT_CTRL2_MNGM) == - (e1000_mng_mode_pt << 13))) { - ret_val = true; - goto out; - } - } else if ((manc & E1000_MANC_SMBUS_EN) && - !(manc & E1000_MANC_ASF_EN)) { - ret_val = true; - goto out; - } - -out: - return ret_val; } diff --git a/drivers/net/ethernet/intel/e1000e/manage.c b/drivers/net/ethernet/intel/e1000e/manage.c new file mode 100644 index 000000000000..c54caf6e5801 --- /dev/null +++ b/drivers/net/ethernet/intel/e1000e/manage.c @@ -0,0 +1,377 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2012 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS <linux.nics@intel.com> + e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include "e1000.h" + +enum e1000_mng_mode { + e1000_mng_mode_none = 0, + e1000_mng_mode_asf, + e1000_mng_mode_pt, + e1000_mng_mode_ipmi, + e1000_mng_mode_host_if_only +}; + +#define E1000_FACTPS_MNGCG 0x20000000 + +/* Intel(R) Active Management Technology signature */ +#define E1000_IAMT_SIGNATURE 0x544D4149 + +/** + * e1000_calculate_checksum - Calculate checksum for buffer + * @buffer: pointer to EEPROM + * @length: size of EEPROM to calculate a checksum for + * + * Calculates the checksum for some buffer on a specified length. The + * checksum calculated is returned. + **/ +static u8 e1000_calculate_checksum(u8 *buffer, u32 length) +{ + u32 i; + u8 sum = 0; + + if (!buffer) + return 0; + + for (i = 0; i < length; i++) + sum += buffer[i]; + + return (u8)(0 - sum); +} + +/** + * e1000_mng_enable_host_if - Checks host interface is enabled + * @hw: pointer to the HW structure + * + * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND + * + * This function checks whether the HOST IF is enabled for command operation + * and also checks whether the previous command is completed. It busy waits + * in case of previous command is not completed. + **/ +static s32 e1000_mng_enable_host_if(struct e1000_hw *hw) +{ + u32 hicr; + u8 i; + + if (!hw->mac.arc_subsystem_valid) { + e_dbg("ARC subsystem not valid.\n"); + return -E1000_ERR_HOST_INTERFACE_COMMAND; + } + + /* Check that the host interface is enabled. */ + hicr = er32(HICR); + if ((hicr & E1000_HICR_EN) == 0) { + e_dbg("E1000_HOST_EN bit disabled.\n"); + return -E1000_ERR_HOST_INTERFACE_COMMAND; + } + /* check the previous command is completed */ + for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { + hicr = er32(HICR); + if (!(hicr & E1000_HICR_C)) + break; + mdelay(1); + } + + if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { + e_dbg("Previous command timeout failed .\n"); + return -E1000_ERR_HOST_INTERFACE_COMMAND; + } + + return 0; +} + +/** + * e1000e_check_mng_mode_generic - check management mode + * @hw: pointer to the HW structure + * + * Reads the firmware semaphore register and returns true (>0) if + * manageability is enabled, else false (0). + **/ +bool e1000e_check_mng_mode_generic(struct e1000_hw *hw) +{ + u32 fwsm = er32(FWSM); + + return (fwsm & E1000_FWSM_MODE_MASK) == + (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); +} + +/** + * e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx + * @hw: pointer to the HW structure + * + * Enables packet filtering on transmit packets if manageability is enabled + * and host interface is enabled. + **/ +bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw) +{ + struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; + u32 *buffer = (u32 *)&hw->mng_cookie; + u32 offset; + s32 ret_val, hdr_csum, csum; + u8 i, len; + + hw->mac.tx_pkt_filtering = true; + + /* No manageability, no filtering */ + if (!e1000e_check_mng_mode(hw)) { + hw->mac.tx_pkt_filtering = false; + goto out; + } + + /* + * If we can't read from the host interface for whatever + * reason, disable filtering. + */ + ret_val = e1000_mng_enable_host_if(hw); + if (ret_val) { + hw->mac.tx_pkt_filtering = false; + goto out; + } + + /* Read in the header. Length and offset are in dwords. */ + len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; + offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; + for (i = 0; i < len; i++) + *(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, + offset + i); + hdr_csum = hdr->checksum; + hdr->checksum = 0; + csum = e1000_calculate_checksum((u8 *)hdr, + E1000_MNG_DHCP_COOKIE_LENGTH); + /* + * If either the checksums or signature don't match, then + * the cookie area isn't considered valid, in which case we + * take the safe route of assuming Tx filtering is enabled. + */ + if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) { + hw->mac.tx_pkt_filtering = true; + goto out; + } + + /* Cookie area is valid, make the final check for filtering. */ + if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) { + hw->mac.tx_pkt_filtering = false; + goto out; + } + +out: + return hw->mac.tx_pkt_filtering; +} + +/** + * e1000_mng_write_cmd_header - Writes manageability command header + * @hw: pointer to the HW structure + * @hdr: pointer to the host interface command header + * + * Writes the command header after does the checksum calculation. + **/ +static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, + struct e1000_host_mng_command_header *hdr) +{ + u16 i, length = sizeof(struct e1000_host_mng_command_header); + + /* Write the whole command header structure with new checksum. */ + + hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); + + length >>= 2; + /* Write the relevant command block into the ram area. */ + for (i = 0; i < length; i++) { + E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i, *((u32 *)hdr + i)); + e1e_flush(); + } + + return 0; +} + +/** + * e1000_mng_host_if_write - Write to the manageability host interface + * @hw: pointer to the HW structure + * @buffer: pointer to the host interface buffer + * @length: size of the buffer + * @offset: location in the buffer to write to + * @sum: sum of the data (not checksum) + * + * This function writes the buffer content at the offset given on the host if. + * It also does alignment considerations to do the writes in most efficient + * way. Also fills up the sum of the buffer in *buffer parameter. + **/ +static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, + u16 length, u16 offset, u8 *sum) +{ + u8 *tmp; + u8 *bufptr = buffer; + u32 data = 0; + u16 remaining, i, j, prev_bytes; + + /* sum = only sum of the data and it is not checksum */ + + if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) + return -E1000_ERR_PARAM; + + tmp = (u8 *)&data; + prev_bytes = offset & 0x3; + offset >>= 2; + + if (prev_bytes) { + data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset); + for (j = prev_bytes; j < sizeof(u32); j++) { + *(tmp + j) = *bufptr++; + *sum += *(tmp + j); + } + E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data); + length -= j - prev_bytes; + offset++; + } + + remaining = length & 0x3; + length -= remaining; + + /* Calculate length in DWORDs */ + length >>= 2; + + /* + * The device driver writes the relevant command block into the + * ram area. + */ + for (i = 0; i < length; i++) { + for (j = 0; j < sizeof(u32); j++) { + *(tmp + j) = *bufptr++; + *sum += *(tmp + j); + } + + E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); + } + if (remaining) { + for (j = 0; j < sizeof(u32); j++) { + if (j < remaining) + *(tmp + j) = *bufptr++; + else + *(tmp + j) = 0; + + *sum += *(tmp + j); + } + E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); + } + + return 0; +} + +/** + * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface + * @hw: pointer to the HW structure + * @buffer: pointer to the host interface + * @length: size of the buffer + * + * Writes the DHCP information to the host interface. + **/ +s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length) +{ + struct e1000_host_mng_command_header hdr; + s32 ret_val; + u32 hicr; + + hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; + hdr.command_length = length; + hdr.reserved1 = 0; + hdr.reserved2 = 0; + hdr.checksum = 0; + + /* Enable the host interface */ + ret_val = e1000_mng_enable_host_if(hw); + if (ret_val) + return ret_val; + + /* Populate the host interface with the contents of "buffer". */ + ret_val = e1000_mng_host_if_write(hw, buffer, length, + sizeof(hdr), &(hdr.checksum)); + if (ret_val) + return ret_val; + + /* Write the manageability command header */ + ret_val = e1000_mng_write_cmd_header(hw, &hdr); + if (ret_val) + return ret_val; + + /* Tell the ARC a new command is pending. */ + hicr = er32(HICR); + ew32(HICR, hicr | E1000_HICR_C); + + return 0; +} + +/** + * e1000e_enable_mng_pass_thru - Check if management passthrough is needed + * @hw: pointer to the HW structure + * + * Verifies the hardware needs to leave interface enabled so that frames can + * be directed to and from the management interface. + **/ +bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw) +{ + u32 manc; + u32 fwsm, factps; + bool ret_val = false; + + manc = er32(MANC); + + if (!(manc & E1000_MANC_RCV_TCO_EN)) + goto out; + + if (hw->mac.has_fwsm) { + fwsm = er32(FWSM); + factps = er32(FACTPS); + + if (!(factps & E1000_FACTPS_MNGCG) && + ((fwsm & E1000_FWSM_MODE_MASK) == + (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { + ret_val = true; + goto out; + } + } else if ((hw->mac.type == e1000_82574) || + (hw->mac.type == e1000_82583)) { + u16 data; + + factps = er32(FACTPS); + e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); + + if (!(factps & E1000_FACTPS_MNGCG) && + ((data & E1000_NVM_INIT_CTRL2_MNGM) == + (e1000_mng_mode_pt << 13))) { + ret_val = true; + goto out; + } + } else if ((manc & E1000_MANC_SMBUS_EN) && + !(manc & E1000_MANC_ASF_EN)) { + ret_val = true; + goto out; + } + +out: + return ret_val; +} diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 3911401ed65d..f868fb822a30 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2011 Intel Corporation. + Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -56,7 +56,7 @@ #define DRV_EXTRAVERSION "-k" -#define DRV_VERSION "1.5.1" DRV_EXTRAVERSION +#define DRV_VERSION "1.9.5" DRV_EXTRAVERSION char e1000e_driver_name[] = "e1000e"; const char e1000e_driver_version[] = DRV_VERSION; @@ -137,7 +137,7 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = { {E1000_TDFPC, "TDFPC"}, /* List Terminator */ - {} + {0, NULL} }; /* @@ -183,18 +183,18 @@ static void e1000e_dump(struct e1000_adapter *adapter) struct e1000_ring *tx_ring = adapter->tx_ring; struct e1000_tx_desc *tx_desc; struct my_u0 { - u64 a; - u64 b; + __le64 a; + __le64 b; } *u0; struct e1000_buffer *buffer_info; struct e1000_ring *rx_ring = adapter->rx_ring; union e1000_rx_desc_packet_split *rx_desc_ps; union e1000_rx_desc_extended *rx_desc; struct my_u1 { - u64 a; - u64 b; - u64 c; - u64 d; + __le64 a; + __le64 b; + __le64 c; + __le64 d; } *u1; u32 staterr; int i = 0; @@ -221,7 +221,7 @@ static void e1000e_dump(struct e1000_adapter *adapter) /* Print Tx Ring Summary */ if (!netdev || !netif_running(netdev)) - goto exit; + return; dev_info(&adapter->pdev->dev, "Tx Ring Summary\n"); pr_info("Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n"); @@ -308,7 +308,7 @@ rx_ring_summary: /* Print Rx Ring */ if (!netif_msg_rx_status(adapter)) - goto exit; + return; dev_info(&adapter->pdev->dev, "Rx Ring Dump\n"); switch (adapter->rx_ps_pages) { @@ -449,9 +449,6 @@ rx_ring_summary: } } } - -exit: - return; } /** @@ -487,22 +484,27 @@ static void e1000_receive_skb(struct e1000_adapter *adapter, /** * e1000_rx_checksum - Receive Checksum Offload - * @adapter: board private structure - * @status_err: receive descriptor status and error fields - * @csum: receive descriptor csum field - * @sk_buff: socket buffer with received data + * @adapter: board private structure + * @status_err: receive descriptor status and error fields + * @csum: receive descriptor csum field + * @sk_buff: socket buffer with received data **/ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, - u32 csum, struct sk_buff *skb) + __le16 csum, struct sk_buff *skb) { u16 status = (u16)status_err; u8 errors = (u8)(status_err >> 24); skb_checksum_none_assert(skb); + /* Rx checksum disabled */ + if (!(adapter->netdev->features & NETIF_F_RXCSUM)) + return; + /* Ignore Checksum bit is set */ if (status & E1000_RXD_STAT_IXSM) return; + /* TCP/UDP checksum error bit is set */ if (errors & E1000_RXD_ERR_TCPE) { /* let the stack verify checksum errors */ @@ -524,7 +526,7 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, * Hardware complements the payload checksum, so we undo it * and then put the value in host order for further stack use. */ - __sum16 sum = (__force __sum16)htons(csum); + __sum16 sum = (__force __sum16)swab16((__force u16)csum); skb->csum = csum_unfold(~sum); skb->ip_summed = CHECKSUM_COMPLETE; } @@ -545,7 +547,7 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, * which has bit 24 set while ME is accessing Host CSR registers, wait * if it is set and try again a number of times. **/ -static inline s32 e1000e_update_tail_wa(struct e1000_hw *hw, u8 __iomem * tail, +static inline s32 e1000e_update_tail_wa(struct e1000_hw *hw, void __iomem *tail, unsigned int i) { unsigned int j = 0; @@ -562,12 +564,12 @@ static inline s32 e1000e_update_tail_wa(struct e1000_hw *hw, u8 __iomem * tail, return 0; } -static void e1000e_update_rdt_wa(struct e1000_adapter *adapter, unsigned int i) +static void e1000e_update_rdt_wa(struct e1000_ring *rx_ring, unsigned int i) { - u8 __iomem *tail = (adapter->hw.hw_addr + adapter->rx_ring->tail); + struct e1000_adapter *adapter = rx_ring->adapter; struct e1000_hw *hw = &adapter->hw; - if (e1000e_update_tail_wa(hw, tail, i)) { + if (e1000e_update_tail_wa(hw, rx_ring->tail, i)) { u32 rctl = er32(RCTL); ew32(RCTL, rctl & ~E1000_RCTL_EN); e_err("ME firmware caused invalid RDT - resetting\n"); @@ -575,12 +577,12 @@ static void e1000e_update_rdt_wa(struct e1000_adapter *adapter, unsigned int i) } } -static void e1000e_update_tdt_wa(struct e1000_adapter *adapter, unsigned int i) +static void e1000e_update_tdt_wa(struct e1000_ring *tx_ring, unsigned int i) { - u8 __iomem *tail = (adapter->hw.hw_addr + adapter->tx_ring->tail); + struct e1000_adapter *adapter = tx_ring->adapter; struct e1000_hw *hw = &adapter->hw; - if (e1000e_update_tail_wa(hw, tail, i)) { + if (e1000e_update_tail_wa(hw, tx_ring->tail, i)) { u32 tctl = er32(TCTL); ew32(TCTL, tctl & ~E1000_TCTL_EN); e_err("ME firmware caused invalid TDT - resetting\n"); @@ -590,14 +592,14 @@ static void e1000e_update_tdt_wa(struct e1000_adapter *adapter, unsigned int i) /** * e1000_alloc_rx_buffers - Replace used receive buffers - * @adapter: address of board private structure + * @rx_ring: Rx descriptor ring **/ -static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, +static void e1000_alloc_rx_buffers(struct e1000_ring *rx_ring, int cleaned_count, gfp_t gfp) { + struct e1000_adapter *adapter = rx_ring->adapter; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; - struct e1000_ring *rx_ring = adapter->rx_ring; union e1000_rx_desc_extended *rx_desc; struct e1000_buffer *buffer_info; struct sk_buff *skb; @@ -644,9 +646,9 @@ map_skb: */ wmb(); if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_rdt_wa(adapter, i); + e1000e_update_rdt_wa(rx_ring, i); else - writel(i, adapter->hw.hw_addr + rx_ring->tail); + writel(i, rx_ring->tail); } i++; if (i == rx_ring->count) @@ -659,15 +661,15 @@ map_skb: /** * e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split - * @adapter: address of board private structure + * @rx_ring: Rx descriptor ring **/ -static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, +static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring, int cleaned_count, gfp_t gfp) { + struct e1000_adapter *adapter = rx_ring->adapter; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; union e1000_rx_desc_packet_split *rx_desc; - struct e1000_ring *rx_ring = adapter->rx_ring; struct e1000_buffer *buffer_info; struct e1000_ps_page *ps_page; struct sk_buff *skb; @@ -747,10 +749,9 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, */ wmb(); if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_rdt_wa(adapter, i << 1); + e1000e_update_rdt_wa(rx_ring, i << 1); else - writel(i << 1, - adapter->hw.hw_addr + rx_ring->tail); + writel(i << 1, rx_ring->tail); } i++; @@ -765,17 +766,17 @@ no_buffers: /** * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers - * @adapter: address of board private structure + * @rx_ring: Rx descriptor ring * @cleaned_count: number of buffers to allocate this pass **/ -static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, +static void e1000_alloc_jumbo_rx_buffers(struct e1000_ring *rx_ring, int cleaned_count, gfp_t gfp) { + struct e1000_adapter *adapter = rx_ring->adapter; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; union e1000_rx_desc_extended *rx_desc; - struct e1000_ring *rx_ring = adapter->rx_ring; struct e1000_buffer *buffer_info; struct sk_buff *skb; unsigned int i; @@ -834,26 +835,33 @@ check_page: * such as IA-64). */ wmb(); if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_rdt_wa(adapter, i); + e1000e_update_rdt_wa(rx_ring, i); else - writel(i, adapter->hw.hw_addr + rx_ring->tail); + writel(i, rx_ring->tail); } } +static inline void e1000_rx_hash(struct net_device *netdev, __le32 rss, + struct sk_buff *skb) +{ + if (netdev->features & NETIF_F_RXHASH) + skb->rxhash = le32_to_cpu(rss); +} + /** - * e1000_clean_rx_irq - Send received data up the network stack; legacy - * @adapter: board private structure + * e1000_clean_rx_irq - Send received data up the network stack + * @rx_ring: Rx descriptor ring * * the return value indicates whether actual cleaning was done, there * is no guarantee that everything was cleaned **/ -static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, - int *work_done, int work_to_do) +static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done, + int work_to_do) { + struct e1000_adapter *adapter = rx_ring->adapter; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; struct e1000_hw *hw = &adapter->hw; - struct e1000_ring *rx_ring = adapter->rx_ring; union e1000_rx_desc_extended *rx_desc, *next_rxd; struct e1000_buffer *buffer_info, *next_buffer; u32 length, staterr; @@ -957,8 +965,9 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, /* Receive Checksum Offload */ e1000_rx_checksum(adapter, staterr, - le16_to_cpu(rx_desc->wb.lower.hi_dword. - csum_ip.csum), skb); + rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); + + e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); e1000_receive_skb(adapter, netdev, skb, staterr, rx_desc->wb.upper.vlan); @@ -968,7 +977,7 @@ next_desc: /* return some buffers to hardware, one at a time is too slow */ if (cleaned_count >= E1000_RX_BUFFER_WRITE) { - adapter->alloc_rx_buf(adapter, cleaned_count, + adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); cleaned_count = 0; } @@ -983,16 +992,18 @@ next_desc: cleaned_count = e1000_desc_unused(rx_ring); if (cleaned_count) - adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC); + adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); adapter->total_rx_bytes += total_rx_bytes; adapter->total_rx_packets += total_rx_packets; return cleaned; } -static void e1000_put_txbuf(struct e1000_adapter *adapter, - struct e1000_buffer *buffer_info) +static void e1000_put_txbuf(struct e1000_ring *tx_ring, + struct e1000_buffer *buffer_info) { + struct e1000_adapter *adapter = tx_ring->adapter; + if (buffer_info->dma) { if (buffer_info->mapped_as_page) dma_unmap_page(&adapter->pdev->dev, buffer_info->dma, @@ -1063,8 +1074,8 @@ static void e1000_print_hw_hang(struct work_struct *work) "PHY 1000BASE-T Status <%x>\n" "PHY Extended Status <%x>\n" "PCI Status <%x>\n", - readl(adapter->hw.hw_addr + tx_ring->head), - readl(adapter->hw.hw_addr + tx_ring->tail), + readl(tx_ring->head), + readl(tx_ring->tail), tx_ring->next_to_use, tx_ring->next_to_clean, tx_ring->buffer_info[eop].time_stamp, @@ -1080,16 +1091,16 @@ static void e1000_print_hw_hang(struct work_struct *work) /** * e1000_clean_tx_irq - Reclaim resources after transmit completes - * @adapter: board private structure + * @tx_ring: Tx descriptor ring * * the return value indicates whether actual cleaning was done, there * is no guarantee that everything was cleaned **/ -static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) +static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring) { + struct e1000_adapter *adapter = tx_ring->adapter; struct net_device *netdev = adapter->netdev; struct e1000_hw *hw = &adapter->hw; - struct e1000_ring *tx_ring = adapter->tx_ring; struct e1000_tx_desc *tx_desc, *eop_desc; struct e1000_buffer *buffer_info; unsigned int i, eop; @@ -1119,7 +1130,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) } } - e1000_put_txbuf(adapter, buffer_info); + e1000_put_txbuf(tx_ring, buffer_info); tx_desc->upper.data = 0; i++; @@ -1173,19 +1184,19 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) /** * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split - * @adapter: board private structure + * @rx_ring: Rx descriptor ring * * the return value indicates whether actual cleaning was done, there * is no guarantee that everything was cleaned **/ -static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, - int *work_done, int work_to_do) +static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done, + int work_to_do) { + struct e1000_adapter *adapter = rx_ring->adapter; struct e1000_hw *hw = &adapter->hw; union e1000_rx_desc_packet_split *rx_desc, *next_rxd; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; - struct e1000_ring *rx_ring = adapter->rx_ring; struct e1000_buffer *buffer_info, *next_buffer; struct e1000_ps_page *ps_page; struct sk_buff *skb; @@ -1253,43 +1264,49 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, skb_put(skb, length); { - /* - * this looks ugly, but it seems compiler issues make it - * more efficient than reusing j - */ - int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); - - /* - * page alloc/put takes too long and effects small packet - * throughput, so unsplit small packets and save the alloc/put - * only valid in softirq (napi) context to call kmap_* - */ - if (l1 && (l1 <= copybreak) && - ((length + l1) <= adapter->rx_ps_bsize0)) { - u8 *vaddr; - - ps_page = &buffer_info->ps_pages[0]; + /* + * this looks ugly, but it seems compiler issues make + * it more efficient than reusing j + */ + int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); /* - * there is no documentation about how to call - * kmap_atomic, so we can't hold the mapping - * very long + * page alloc/put takes too long and effects small + * packet throughput, so unsplit small packets and + * save the alloc/put only valid in softirq (napi) + * context to call kmap_* */ - dma_sync_single_for_cpu(&pdev->dev, ps_page->dma, - PAGE_SIZE, DMA_FROM_DEVICE); - vaddr = kmap_atomic(ps_page->page, KM_SKB_DATA_SOFTIRQ); - memcpy(skb_tail_pointer(skb), vaddr, l1); - kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); - dma_sync_single_for_device(&pdev->dev, ps_page->dma, - PAGE_SIZE, DMA_FROM_DEVICE); - - /* remove the CRC */ - if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) - l1 -= 4; - - skb_put(skb, l1); - goto copydone; - } /* if */ + if (l1 && (l1 <= copybreak) && + ((length + l1) <= adapter->rx_ps_bsize0)) { + u8 *vaddr; + + ps_page = &buffer_info->ps_pages[0]; + + /* + * there is no documentation about how to call + * kmap_atomic, so we can't hold the mapping + * very long + */ + dma_sync_single_for_cpu(&pdev->dev, + ps_page->dma, + PAGE_SIZE, + DMA_FROM_DEVICE); + vaddr = kmap_atomic(ps_page->page, + KM_SKB_DATA_SOFTIRQ); + memcpy(skb_tail_pointer(skb), vaddr, l1); + kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); + dma_sync_single_for_device(&pdev->dev, + ps_page->dma, + PAGE_SIZE, + DMA_FROM_DEVICE); + + /* remove the CRC */ + if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) + l1 -= 4; + + skb_put(skb, l1); + goto copydone; + } /* if */ } for (j = 0; j < PS_PAGE_BUFFERS; j++) { @@ -1318,8 +1335,10 @@ copydone: total_rx_bytes += skb->len; total_rx_packets++; - e1000_rx_checksum(adapter, staterr, le16_to_cpu( - rx_desc->wb.lower.hi_dword.csum_ip.csum), skb); + e1000_rx_checksum(adapter, staterr, + rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); + + e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); if (rx_desc->wb.upper.header_status & cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)) @@ -1334,7 +1353,7 @@ next_desc: /* return some buffers to hardware, one at a time is too slow */ if (cleaned_count >= E1000_RX_BUFFER_WRITE) { - adapter->alloc_rx_buf(adapter, cleaned_count, + adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); cleaned_count = 0; } @@ -1349,7 +1368,7 @@ next_desc: cleaned_count = e1000_desc_unused(rx_ring); if (cleaned_count) - adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC); + adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); adapter->total_rx_bytes += total_rx_bytes; adapter->total_rx_packets += total_rx_packets; @@ -1375,13 +1394,12 @@ static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb, * the return value indicates whether actual cleaning was done, there * is no guarantee that everything was cleaned **/ - -static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, - int *work_done, int work_to_do) +static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done, + int work_to_do) { + struct e1000_adapter *adapter = rx_ring->adapter; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; - struct e1000_ring *rx_ring = adapter->rx_ring; union e1000_rx_desc_extended *rx_desc, *next_rxd; struct e1000_buffer *buffer_info, *next_buffer; u32 length, staterr; @@ -1491,8 +1509,9 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, /* Receive Checksum Offload XXX recompute due to CRC strip? */ e1000_rx_checksum(adapter, staterr, - le16_to_cpu(rx_desc->wb.lower.hi_dword. - csum_ip.csum), skb); + rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); + + e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; @@ -1513,7 +1532,7 @@ next_desc: /* return some buffers to hardware, one at a time is too slow */ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { - adapter->alloc_rx_buf(adapter, cleaned_count, + adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); cleaned_count = 0; } @@ -1528,7 +1547,7 @@ next_desc: cleaned_count = e1000_desc_unused(rx_ring); if (cleaned_count) - adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC); + adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); adapter->total_rx_bytes += total_rx_bytes; adapter->total_rx_packets += total_rx_packets; @@ -1537,11 +1556,11 @@ next_desc: /** * e1000_clean_rx_ring - Free Rx Buffers per Queue - * @adapter: board private structure + * @rx_ring: Rx descriptor ring **/ -static void e1000_clean_rx_ring(struct e1000_adapter *adapter) +static void e1000_clean_rx_ring(struct e1000_ring *rx_ring) { - struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_adapter *adapter = rx_ring->adapter; struct e1000_buffer *buffer_info; struct e1000_ps_page *ps_page; struct pci_dev *pdev = adapter->pdev; @@ -1601,8 +1620,8 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) rx_ring->next_to_use = 0; adapter->flags2 &= ~FLAG2_IS_DISCARDING; - writel(0, adapter->hw.hw_addr + rx_ring->head); - writel(0, adapter->hw.hw_addr + rx_ring->tail); + writel(0, rx_ring->head); + writel(0, rx_ring->tail); } static void e1000e_downshift_workaround(struct work_struct *work) @@ -1633,7 +1652,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data) */ if (icr & E1000_ICR_LSC) { - hw->mac.get_link_status = 1; + hw->mac.get_link_status = true; /* * ICH8 workaround-- Call gig speed drop workaround on cable * disconnect (LSC) before accessing any PHY registers @@ -1699,7 +1718,7 @@ static irqreturn_t e1000_intr(int irq, void *data) */ if (icr & E1000_ICR_LSC) { - hw->mac.get_link_status = 1; + hw->mac.get_link_status = true; /* * ICH8 workaround-- Call gig speed drop workaround on cable * disconnect (LSC) before accessing any PHY registers @@ -1756,7 +1775,7 @@ static irqreturn_t e1000_msix_other(int irq, void *data) if (icr & E1000_ICR_OTHER) { if (!(icr & E1000_ICR_LSC)) goto no_link_interrupt; - hw->mac.get_link_status = 1; + hw->mac.get_link_status = true; /* guard against interrupt when we're going down */ if (!test_bit(__E1000_DOWN, &adapter->state)) mod_timer(&adapter->watchdog_timer, jiffies + 1); @@ -1781,7 +1800,7 @@ static irqreturn_t e1000_intr_msix_tx(int irq, void *data) adapter->total_tx_bytes = 0; adapter->total_tx_packets = 0; - if (!e1000_clean_tx_irq(adapter)) + if (!e1000_clean_tx_irq(tx_ring)) /* Ring was not completely cleaned, so fire another interrupt */ ew32(ICS, tx_ring->ims_val); @@ -1792,14 +1811,15 @@ static irqreturn_t e1000_intr_msix_rx(int irq, void *data) { struct net_device *netdev = data; struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_ring *rx_ring = adapter->rx_ring; /* Write the ITR value calculated at the end of the * previous interrupt. */ - if (adapter->rx_ring->set_itr) { - writel(1000000000 / (adapter->rx_ring->itr_val * 256), - adapter->hw.hw_addr + adapter->rx_ring->itr_register); - adapter->rx_ring->set_itr = 0; + if (rx_ring->set_itr) { + writel(1000000000 / (rx_ring->itr_val * 256), + rx_ring->itr_register); + rx_ring->set_itr = 0; } if (napi_schedule_prep(&adapter->napi)) { @@ -1839,9 +1859,9 @@ static void e1000_configure_msix(struct e1000_adapter *adapter) adapter->eiac_mask |= rx_ring->ims_val; if (rx_ring->itr_val) writel(1000000000 / (rx_ring->itr_val * 256), - hw->hw_addr + rx_ring->itr_register); + rx_ring->itr_register); else - writel(1, hw->hw_addr + rx_ring->itr_register); + writel(1, rx_ring->itr_register); ivar = E1000_IVAR_INT_ALLOC_VALID | vector; /* Configure Tx vector */ @@ -1849,9 +1869,9 @@ static void e1000_configure_msix(struct e1000_adapter *adapter) vector++; if (tx_ring->itr_val) writel(1000000000 / (tx_ring->itr_val * 256), - hw->hw_addr + tx_ring->itr_register); + tx_ring->itr_register); else - writel(1, hw->hw_addr + tx_ring->itr_register); + writel(1, tx_ring->itr_register); adapter->eiac_mask |= tx_ring->ims_val; ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 8); @@ -1966,7 +1986,8 @@ static int e1000_request_msix(struct e1000_adapter *adapter) netdev); if (err) goto out; - adapter->rx_ring->itr_register = E1000_EITR_82574(vector); + adapter->rx_ring->itr_register = adapter->hw.hw_addr + + E1000_EITR_82574(vector); adapter->rx_ring->itr_val = adapter->itr; vector++; @@ -1981,7 +2002,8 @@ static int e1000_request_msix(struct e1000_adapter *adapter) netdev); if (err) goto out; - adapter->tx_ring->itr_register = E1000_EITR_82574(vector); + adapter->tx_ring->itr_register = adapter->hw.hw_addr + + E1000_EITR_82574(vector); adapter->tx_ring->itr_val = adapter->itr; vector++; @@ -2162,13 +2184,13 @@ static int e1000_alloc_ring_dma(struct e1000_adapter *adapter, /** * e1000e_setup_tx_resources - allocate Tx resources (Descriptors) - * @adapter: board private structure + * @tx_ring: Tx descriptor ring * * Return 0 on success, negative on failure **/ -int e1000e_setup_tx_resources(struct e1000_adapter *adapter) +int e1000e_setup_tx_resources(struct e1000_ring *tx_ring) { - struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_adapter *adapter = tx_ring->adapter; int err = -ENOMEM, size; size = sizeof(struct e1000_buffer) * tx_ring->count; @@ -2196,13 +2218,13 @@ err: /** * e1000e_setup_rx_resources - allocate Rx resources (Descriptors) - * @adapter: board private structure + * @rx_ring: Rx descriptor ring * * Returns 0 on success, negative on failure **/ -int e1000e_setup_rx_resources(struct e1000_adapter *adapter) +int e1000e_setup_rx_resources(struct e1000_ring *rx_ring) { - struct e1000_ring *rx_ring = adapter->rx_ring; + struct e1000_adapter *adapter = rx_ring->adapter; struct e1000_buffer *buffer_info; int i, size, desc_len, err = -ENOMEM; @@ -2249,18 +2271,18 @@ err: /** * e1000_clean_tx_ring - Free Tx Buffers - * @adapter: board private structure + * @tx_ring: Tx descriptor ring **/ -static void e1000_clean_tx_ring(struct e1000_adapter *adapter) +static void e1000_clean_tx_ring(struct e1000_ring *tx_ring) { - struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_adapter *adapter = tx_ring->adapter; struct e1000_buffer *buffer_info; unsigned long size; unsigned int i; for (i = 0; i < tx_ring->count; i++) { buffer_info = &tx_ring->buffer_info[i]; - e1000_put_txbuf(adapter, buffer_info); + e1000_put_txbuf(tx_ring, buffer_info); } netdev_reset_queue(adapter->netdev); @@ -2272,22 +2294,22 @@ static void e1000_clean_tx_ring(struct e1000_adapter *adapter) tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; - writel(0, adapter->hw.hw_addr + tx_ring->head); - writel(0, adapter->hw.hw_addr + tx_ring->tail); + writel(0, tx_ring->head); + writel(0, tx_ring->tail); } /** * e1000e_free_tx_resources - Free Tx Resources per Queue - * @adapter: board private structure + * @tx_ring: Tx descriptor ring * * Free all transmit software resources **/ -void e1000e_free_tx_resources(struct e1000_adapter *adapter) +void e1000e_free_tx_resources(struct e1000_ring *tx_ring) { + struct e1000_adapter *adapter = tx_ring->adapter; struct pci_dev *pdev = adapter->pdev; - struct e1000_ring *tx_ring = adapter->tx_ring; - e1000_clean_tx_ring(adapter); + e1000_clean_tx_ring(tx_ring); vfree(tx_ring->buffer_info); tx_ring->buffer_info = NULL; @@ -2299,18 +2321,17 @@ void e1000e_free_tx_resources(struct e1000_adapter *adapter) /** * e1000e_free_rx_resources - Free Rx Resources - * @adapter: board private structure + * @rx_ring: Rx descriptor ring * * Free all receive software resources **/ - -void e1000e_free_rx_resources(struct e1000_adapter *adapter) +void e1000e_free_rx_resources(struct e1000_ring *rx_ring) { + struct e1000_adapter *adapter = rx_ring->adapter; struct pci_dev *pdev = adapter->pdev; - struct e1000_ring *rx_ring = adapter->rx_ring; int i; - e1000_clean_rx_ring(adapter); + e1000_clean_rx_ring(rx_ring); for (i = 0; i < rx_ring->count; i++) kfree(rx_ring->buffer_info[i].ps_pages); @@ -2464,13 +2485,19 @@ set_itr_now: **/ static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter) { - adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); + int size = sizeof(struct e1000_ring); + + adapter->tx_ring = kzalloc(size, GFP_KERNEL); if (!adapter->tx_ring) goto err; + adapter->tx_ring->count = adapter->tx_ring_count; + adapter->tx_ring->adapter = adapter; - adapter->rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL); + adapter->rx_ring = kzalloc(size, GFP_KERNEL); if (!adapter->rx_ring) goto err; + adapter->rx_ring->count = adapter->rx_ring_count; + adapter->rx_ring->adapter = adapter; return 0; err: @@ -2498,10 +2525,10 @@ static int e1000_clean(struct napi_struct *napi, int budget) !(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val)) goto clean_rx; - tx_cleaned = e1000_clean_tx_irq(adapter); + tx_cleaned = e1000_clean_tx_irq(adapter->tx_ring); clean_rx: - adapter->clean_rx(adapter, &work_done, budget); + adapter->clean_rx(adapter->rx_ring, &work_done, budget); if (!tx_cleaned) work_done = budget; @@ -2746,8 +2773,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) struct e1000_hw *hw = &adapter->hw; struct e1000_ring *tx_ring = adapter->tx_ring; u64 tdba; - u32 tdlen, tctl, tipg, tarc; - u32 ipgr1, ipgr2; + u32 tdlen, tarc; /* Setup the HW Tx Head and Tail descriptor pointers */ tdba = tx_ring->dma; @@ -2757,20 +2783,8 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) ew32(TDLEN, tdlen); ew32(TDH, 0); ew32(TDT, 0); - tx_ring->head = E1000_TDH; - tx_ring->tail = E1000_TDT; - - /* Set the default values for the Tx Inter Packet Gap timer */ - tipg = DEFAULT_82543_TIPG_IPGT_COPPER; /* 8 */ - ipgr1 = DEFAULT_82543_TIPG_IPGR1; /* 8 */ - ipgr2 = DEFAULT_82543_TIPG_IPGR2; /* 6 */ - - if (adapter->flags & FLAG_TIPG_MEDIUM_FOR_80003ESLAN) - ipgr2 = DEFAULT_80003ES2LAN_TIPG_IPGR2; /* 7 */ - - tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT; - tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT; - ew32(TIPG, tipg); + tx_ring->head = adapter->hw.hw_addr + E1000_TDH; + tx_ring->tail = adapter->hw.hw_addr + E1000_TDT; /* Set the Tx Interrupt Delay register */ ew32(TIDV, adapter->tx_int_delay); @@ -2793,15 +2807,9 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) */ txdctl |= E1000_TXDCTL_DMA_BURST_ENABLE; ew32(TXDCTL(0), txdctl); - /* erratum work around: set txdctl the same for both queues */ - ew32(TXDCTL(1), txdctl); } - - /* Program the Transmit Control Register */ - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_CT; - tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | - (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); + /* erratum work around: set txdctl the same for both queues */ + ew32(TXDCTL(1), er32(TXDCTL(0))); if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) { tarc = er32(TARC(0)); @@ -2834,8 +2842,6 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) /* enable Report Status bit */ adapter->txd_cmd |= E1000_TXD_CMD_RS; - ew32(TCTL, tctl); - e1000e_config_collision_dist(hw); } @@ -2944,8 +2950,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) * per packet. */ pages = PAGE_USE_COUNT(adapter->netdev->mtu); - if (!(adapter->flags & FLAG_HAS_ERT) && (pages <= 3) && - (PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE)) + if ((pages <= 3) && (PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE)) adapter->rx_ps_pages = pages; else adapter->rx_ps_pages = 0; @@ -3072,8 +3077,8 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) ew32(RDLEN, rdlen); ew32(RDH, 0); ew32(RDT, 0); - rx_ring->head = E1000_RDH; - rx_ring->tail = E1000_RDT; + rx_ring->head = adapter->hw.hw_addr + E1000_RDH; + rx_ring->tail = adapter->hw.hw_addr + E1000_RDT; /* Enable Receive Checksum Offload for TCP and UDP */ rxcsum = er32(RXCSUM); @@ -3092,23 +3097,14 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) } ew32(RXCSUM, rxcsum); - /* - * Enable early receives on supported devices, only takes effect when - * packet size is equal or larger than the specified value (in 8 byte - * units), e.g. using jumbo frames when setting to E1000_ERT_2048 - */ - if ((adapter->flags & FLAG_HAS_ERT) || - (adapter->hw.mac.type == e1000_pch2lan)) { + if (adapter->hw.mac.type == e1000_pch2lan) { + /* + * With jumbo frames, excessive C-state transition + * latencies result in dropped transactions. + */ if (adapter->netdev->mtu > ETH_DATA_LEN) { u32 rxdctl = er32(RXDCTL(0)); ew32(RXDCTL(0), rxdctl | 0x3); - if (adapter->flags & FLAG_HAS_ERT) - ew32(ERT, E1000_ERT_2048 | (1 << 13)); - /* - * With jumbo frames and early-receive enabled, - * excessive C-state transition latencies result in - * dropped transactions. - */ pm_qos_update_request(&adapter->netdev->pm_qos_req, 55); } else { pm_qos_update_request(&adapter->netdev->pm_qos_req, @@ -3268,22 +3264,62 @@ static void e1000e_set_rx_mode(struct net_device *netdev) e1000e_vlan_strip_disable(adapter); } +static void e1000e_setup_rss_hash(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 mrqc, rxcsum; + int i; + static const u32 rsskey[10] = { + 0xda565a6d, 0xc20e5b25, 0x3d256741, 0xb08fa343, 0xcb2bcad0, + 0xb4307bae, 0xa32dcb77, 0x0cf23080, 0x3bb7426a, 0xfa01acbe + }; + + /* Fill out hash function seed */ + for (i = 0; i < 10; i++) + ew32(RSSRK(i), rsskey[i]); + + /* Direct all traffic to queue 0 */ + for (i = 0; i < 32; i++) + ew32(RETA(i), 0); + + /* + * Disable raw packet checksumming so that RSS hash is placed in + * descriptor on writeback. + */ + rxcsum = er32(RXCSUM); + rxcsum |= E1000_RXCSUM_PCSD; + + ew32(RXCSUM, rxcsum); + + mrqc = (E1000_MRQC_RSS_FIELD_IPV4 | + E1000_MRQC_RSS_FIELD_IPV4_TCP | + E1000_MRQC_RSS_FIELD_IPV6 | + E1000_MRQC_RSS_FIELD_IPV6_TCP | + E1000_MRQC_RSS_FIELD_IPV6_TCP_EX); + + ew32(MRQC, mrqc); +} + /** * e1000_configure - configure the hardware for Rx and Tx * @adapter: private board structure **/ static void e1000_configure(struct e1000_adapter *adapter) { + struct e1000_ring *rx_ring = adapter->rx_ring; + e1000e_set_rx_mode(adapter->netdev); e1000_restore_vlan(adapter); e1000_init_manageability_pt(adapter); e1000_configure_tx(adapter); + + if (adapter->netdev->features & NETIF_F_RXHASH) + e1000e_setup_rss_hash(adapter); e1000_setup_rctl(adapter); e1000_configure_rx(adapter); - adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring), - GFP_KERNEL); + adapter->alloc_rx_buf(rx_ring, e1000_desc_unused(rx_ring), GFP_KERNEL); } /** @@ -3379,9 +3415,7 @@ void e1000e_reset(struct e1000_adapter *adapter) * if short on Rx space, Rx wins and must trump Tx * adjustment or use Early Receive if available */ - if ((pba < min_rx_space) && - (!(adapter->flags & FLAG_HAS_ERT))) - /* ERT enabled in e1000_configure_rx */ + if (pba < min_rx_space) pba = min_rx_space; } @@ -3395,8 +3429,6 @@ void e1000e_reset(struct e1000_adapter *adapter) * (or the size used for early receive) above it in the Rx FIFO. * Set it to the lower of: * - 90% of the Rx FIFO size, and - * - the full Rx FIFO size minus the early receive size (for parts - * with ERT support assuming ERT set to E1000_ERT_2048), or * - the full Rx FIFO size minus one full frame */ if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME) @@ -3407,14 +3439,19 @@ void e1000e_reset(struct e1000_adapter *adapter) fc->current_mode = fc->requested_mode; switch (hw->mac.type) { + case e1000_ich9lan: + case e1000_ich10lan: + if (adapter->netdev->mtu > ETH_DATA_LEN) { + pba = 14; + ew32(PBA, pba); + fc->high_water = 0x2800; + fc->low_water = fc->high_water - 8; + break; + } + /* fall-through */ default: - if ((adapter->flags & FLAG_HAS_ERT) && - (adapter->netdev->mtu > ETH_DATA_LEN)) - hwm = min(((pba << 10) * 9 / 10), - ((pba << 10) - (E1000_ERT_2048 << 3))); - else - hwm = min(((pba << 10) * 9 / 10), - ((pba << 10) - adapter->max_frame_size)); + hwm = min(((pba << 10) * 9 / 10), + ((pba << 10) - adapter->max_frame_size)); fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ fc->low_water = fc->high_water - 8; @@ -3447,11 +3484,10 @@ void e1000e_reset(struct e1000_adapter *adapter) /* * Disable Adaptive Interrupt Moderation if 2 full packets cannot - * fit in receive buffer and early-receive not supported. + * fit in receive buffer. */ if (adapter->itr_setting & 0x3) { - if (((adapter->max_frame_size * 2) > (pba << 10)) && - !(adapter->flags & FLAG_HAS_ERT)) { + if ((adapter->max_frame_size * 2) > (pba << 10)) { if (!(adapter->flags2 & FLAG2_DISABLE_AIM)) { dev_info(&adapter->pdev->dev, "Interrupt Throttle Rate turned off\n"); @@ -3593,8 +3629,8 @@ void e1000e_down(struct e1000_adapter *adapter) spin_unlock(&adapter->stats64_lock); e1000e_flush_descriptors(adapter); - e1000_clean_tx_ring(adapter); - e1000_clean_rx_ring(adapter); + e1000_clean_tx_ring(adapter->tx_ring); + e1000_clean_rx_ring(adapter->rx_ring); adapter->link_speed = 0; adapter->link_duplex = 0; @@ -3634,6 +3670,8 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) adapter->rx_ps_bsize0 = 128; adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; + adapter->tx_ring_count = E1000_DEFAULT_TXD; + adapter->rx_ring_count = E1000_DEFAULT_RXD; spin_lock_init(&adapter->stats64_lock); @@ -3721,8 +3759,9 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) if (adapter->flags & FLAG_MSI_TEST_FAILED) { adapter->int_mode = E1000E_INT_MODE_LEGACY; e_info("MSI interrupt test failed, using legacy interrupt.\n"); - } else + } else { e_dbg("MSI interrupt test succeeded!\n"); + } free_irq(adapter->pdev->irq, netdev); pci_disable_msi(adapter->pdev); @@ -3792,12 +3831,12 @@ static int e1000_open(struct net_device *netdev) netif_carrier_off(netdev); /* allocate transmit descriptors */ - err = e1000e_setup_tx_resources(adapter); + err = e1000e_setup_tx_resources(adapter->tx_ring); if (err) goto err_setup_tx; /* allocate receive descriptors */ - err = e1000e_setup_rx_resources(adapter); + err = e1000e_setup_rx_resources(adapter->rx_ring); if (err) goto err_setup_rx; @@ -3817,9 +3856,8 @@ static int e1000_open(struct net_device *netdev) E1000_MNG_DHCP_COOKIE_STATUS_VLAN)) e1000_update_mng_vlan(adapter); - /* DMA latency requirement to workaround early-receive/jumbo issue */ - if ((adapter->flags & FLAG_HAS_ERT) || - (adapter->hw.mac.type == e1000_pch2lan)) + /* DMA latency requirement to workaround jumbo issue */ + if (adapter->hw.mac.type == e1000_pch2lan) pm_qos_add_request(&adapter->netdev->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); @@ -3873,9 +3911,9 @@ static int e1000_open(struct net_device *netdev) err_req_irq: e1000e_release_hw_control(adapter); e1000_power_down_phy(adapter); - e1000e_free_rx_resources(adapter); + e1000e_free_rx_resources(adapter->rx_ring); err_setup_rx: - e1000e_free_tx_resources(adapter); + e1000e_free_tx_resources(adapter->tx_ring); err_setup_tx: e1000e_reset(adapter); pm_runtime_put_sync(&pdev->dev); @@ -3911,8 +3949,8 @@ static int e1000_close(struct net_device *netdev) } e1000_power_down_phy(adapter); - e1000e_free_tx_resources(adapter); - e1000e_free_rx_resources(adapter); + e1000e_free_tx_resources(adapter->tx_ring); + e1000e_free_rx_resources(adapter->rx_ring); /* * kill manageability vlan ID if supported, but not if a vlan with @@ -3930,8 +3968,7 @@ static int e1000_close(struct net_device *netdev) !test_bit(__E1000_TESTING, &adapter->state)) e1000e_release_hw_control(adapter); - if ((adapter->flags & FLAG_HAS_ERT) || - (adapter->hw.mac.type == e1000_pch2lan)) + if (adapter->hw.mac.type == e1000_pch2lan) pm_qos_remove_request(&adapter->netdev->pm_qos_req); pm_runtime_put_sync(&pdev->dev); @@ -4569,10 +4606,8 @@ link_up: #define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 #define E1000_TX_FLAGS_VLAN_SHIFT 16 -static int e1000_tso(struct e1000_adapter *adapter, - struct sk_buff *skb) +static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb) { - struct e1000_ring *tx_ring = adapter->tx_ring; struct e1000_context_desc *context_desc; struct e1000_buffer *buffer_info; unsigned int i; @@ -4641,9 +4676,9 @@ static int e1000_tso(struct e1000_adapter *adapter, return 1; } -static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) +static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb) { - struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_adapter *adapter = tx_ring->adapter; struct e1000_context_desc *context_desc; struct e1000_buffer *buffer_info; unsigned int i; @@ -4704,12 +4739,11 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) #define E1000_MAX_PER_TXD 8192 #define E1000_MAX_TXD_PWR 12 -static int e1000_tx_map(struct e1000_adapter *adapter, - struct sk_buff *skb, unsigned int first, - unsigned int max_per_txd, unsigned int nr_frags, - unsigned int mss) +static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb, + unsigned int first, unsigned int max_per_txd, + unsigned int nr_frags, unsigned int mss) { - struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_adapter *adapter = tx_ring->adapter; struct pci_dev *pdev = adapter->pdev; struct e1000_buffer *buffer_info; unsigned int len = skb_headlen(skb); @@ -4795,16 +4829,15 @@ dma_error: i += tx_ring->count; i--; buffer_info = &tx_ring->buffer_info[i]; - e1000_put_txbuf(adapter, buffer_info); + e1000_put_txbuf(tx_ring, buffer_info); } return 0; } -static void e1000_tx_queue(struct e1000_adapter *adapter, - int tx_flags, int count) +static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count) { - struct e1000_ring *tx_ring = adapter->tx_ring; + struct e1000_adapter *adapter = tx_ring->adapter; struct e1000_tx_desc *tx_desc = NULL; struct e1000_buffer *buffer_info; u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; @@ -4857,9 +4890,9 @@ static void e1000_tx_queue(struct e1000_adapter *adapter, tx_ring->next_to_use = i; if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_tdt_wa(adapter, i); + e1000e_update_tdt_wa(tx_ring, i); else - writel(i, adapter->hw.hw_addr + tx_ring->tail); + writel(i, tx_ring->tail); /* * we need this if more than one processor can write to our tail @@ -4907,11 +4940,11 @@ static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter, return 0; } -static int __e1000_maybe_stop_tx(struct net_device *netdev, int size) +static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = tx_ring->adapter; - netif_stop_queue(netdev); + netif_stop_queue(adapter->netdev); /* * Herbert's original patch had: * smp_mb__after_netif_stop_queue(); @@ -4923,25 +4956,23 @@ static int __e1000_maybe_stop_tx(struct net_device *netdev, int size) * We need to check again in a case another CPU has just * made room available. */ - if (e1000_desc_unused(adapter->tx_ring) < size) + if (e1000_desc_unused(tx_ring) < size) return -EBUSY; /* A reprieve! */ - netif_start_queue(netdev); + netif_start_queue(adapter->netdev); ++adapter->restart_queue; return 0; } -static int e1000_maybe_stop_tx(struct net_device *netdev, int size) +static int e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) { - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (e1000_desc_unused(adapter->tx_ring) >= size) + if (e1000_desc_unused(tx_ring) >= size) return 0; - return __e1000_maybe_stop_tx(netdev, size); + return __e1000_maybe_stop_tx(tx_ring, size); } -#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) +#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1) static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { @@ -4995,7 +5026,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, if (skb->data_len && (hdr_len == len)) { unsigned int pull_size; - pull_size = min((unsigned int)4, skb->data_len); + pull_size = min_t(unsigned int, 4, skb->data_len); if (!__pskb_pull_tail(skb, pull_size)) { e_err("__pskb_pull_tail failed.\n"); dev_kfree_skb_any(skb); @@ -5024,7 +5055,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, * need: count + 2 desc gap to keep tail from touching * head, otherwise try next time */ - if (e1000_maybe_stop_tx(netdev, count + 2)) + if (e1000_maybe_stop_tx(tx_ring, count + 2)) return NETDEV_TX_BUSY; if (vlan_tx_tag_present(skb)) { @@ -5034,7 +5065,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, first = tx_ring->next_to_use; - tso = e1000_tso(adapter, skb); + tso = e1000_tso(tx_ring, skb); if (tso < 0) { dev_kfree_skb_any(skb); return NETDEV_TX_OK; @@ -5042,7 +5073,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, if (tso) tx_flags |= E1000_TX_FLAGS_TSO; - else if (e1000_tx_csum(adapter, skb)) + else if (e1000_tx_csum(tx_ring, skb)) tx_flags |= E1000_TX_FLAGS_CSUM; /* @@ -5054,12 +5085,12 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, tx_flags |= E1000_TX_FLAGS_IPV4; /* if count is 0 then mapping error has occurred */ - count = e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss); + count = e1000_tx_map(tx_ring, skb, first, max_per_txd, nr_frags, mss); if (count) { netdev_sent_queue(netdev, skb->len); - e1000_tx_queue(adapter, tx_flags, count); + e1000_tx_queue(tx_ring, tx_flags, count); /* Make sure there is space in the ring for the next send. */ - e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2); + e1000_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 2); } else { dev_kfree_skb_any(skb); @@ -5165,10 +5196,22 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; /* Jumbo frame support */ - if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) && - !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { - e_err("Jumbo Frames not supported.\n"); - return -EINVAL; + if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) { + if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { + e_err("Jumbo Frames not supported.\n"); + return -EINVAL; + } + + /* + * IP payload checksum (enabled with jumbos/packet-split when + * Rx checksum is enabled) and generation of RSS hash is + * mutually exclusive in the hardware. + */ + if ((netdev->features & NETIF_F_RXCSUM) && + (netdev->features & NETIF_F_RXHASH)) { + e_err("Jumbo frames cannot be enabled when both receive checksum offload and receive hashing are enabled. Disable one of the receive offload features before enabling jumbos.\n"); + return -EINVAL; + } } /* Supported frame sizes */ @@ -5908,7 +5951,7 @@ static void e1000_print_device_info(struct e1000_adapter *adapter) ret_val = e1000_read_pba_string_generic(hw, pba_str, E1000_PBANUM_LENGTH); if (ret_val) - strncpy((char *)pba_str, "Unknown", sizeof(pba_str) - 1); + strlcpy((char *)pba_str, "Unknown", sizeof(pba_str)); e_info("MAC: %d, PHY: %d, PBA No: %s\n", hw->mac.type, hw->phy.type, pba_str); } @@ -5923,7 +5966,8 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter) return; ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf); - if (!ret_val && (!(le16_to_cpu(buf) & (1 << 0)))) { + le16_to_cpus(&buf); + if (!ret_val && (!(buf & (1 << 0)))) { /* Deep Smart Power Down (DSPD) */ dev_warn(&adapter->pdev->dev, "Warning: detected DSPD enabled in EEPROM\n"); @@ -5931,7 +5975,7 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter) } static int e1000_set_features(struct net_device *netdev, - netdev_features_t features) + netdev_features_t features) { struct e1000_adapter *adapter = netdev_priv(netdev); netdev_features_t changed = features ^ netdev->features; @@ -5940,9 +5984,22 @@ static int e1000_set_features(struct net_device *netdev, adapter->flags |= FLAG_TSO_FORCE; if (!(changed & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX | - NETIF_F_RXCSUM))) + NETIF_F_RXCSUM | NETIF_F_RXHASH))) return 0; + /* + * IP payload checksum (enabled with jumbos/packet-split when Rx + * checksum is enabled) and generation of RSS hash is mutually + * exclusive in the hardware. + */ + if (adapter->rx_ps_pages && + (features & NETIF_F_RXCSUM) && (features & NETIF_F_RXHASH)) { + e_err("Enabling both receive checksum offload and receive hashing is not possible with jumbo frames. Disable jumbos or enable only one of the receive offload features.\n"); + return -EINVAL; + } + + netdev->features = features; + if (netif_running(netdev)) e1000e_reinit_locked(adapter); else @@ -6087,7 +6144,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, e1000e_set_ethtool_ops(netdev); netdev->watchdog_timeo = 5 * HZ; netif_napi_add(netdev, &adapter->napi, e1000_clean, 64); - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name)); netdev->mem_start = mmio_start; netdev->mem_end = mmio_start + mmio_len; @@ -6133,6 +6190,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, NETIF_F_HW_VLAN_TX | NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_RXHASH | NETIF_F_RXCSUM | NETIF_F_HW_CSUM); @@ -6268,7 +6326,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (!(adapter->flags & FLAG_HAS_AMT)) e1000e_get_hw_control(adapter); - strncpy(netdev->name, "eth%d", sizeof(netdev->name) - 1); + strlcpy(netdev->name, "eth%d", sizeof(netdev->name)); err = register_netdev(netdev); if (err) goto err_register; @@ -6449,7 +6507,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_LM), board_pch2lan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_V), board_pch2lan }, - { } /* terminate list */ + { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); @@ -6468,7 +6526,9 @@ static struct pci_driver e1000_driver = { .probe = e1000_probe, .remove = __devexit_p(e1000_remove), #ifdef CONFIG_PM - .driver.pm = &e1000_pm_ops, + .driver = { + .pm = &e1000_pm_ops, + }, #endif .shutdown = e1000_shutdown, .err_handler = &e1000_err_handler @@ -6485,7 +6545,7 @@ static int __init e1000_init_module(void) int ret; pr_info("Intel(R) PRO/1000 Network Driver - %s\n", e1000e_driver_version); - pr_info("Copyright(c) 1999 - 2011 Intel Corporation.\n"); + pr_info("Copyright(c) 1999 - 2012 Intel Corporation.\n"); ret = pci_register_driver(&e1000_driver); return ret; diff --git a/drivers/net/ethernet/intel/e1000e/nvm.c b/drivers/net/ethernet/intel/e1000e/nvm.c new file mode 100644 index 000000000000..f6fb7a768ba5 --- /dev/null +++ b/drivers/net/ethernet/intel/e1000e/nvm.c @@ -0,0 +1,647 @@ +/******************************************************************************* + + Intel PRO/1000 Linux driver + Copyright(c) 1999 - 2012 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + Linux NICS <linux.nics@intel.com> + e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include "e1000.h" + +/** + * e1000_raise_eec_clk - Raise EEPROM clock + * @hw: pointer to the HW structure + * @eecd: pointer to the EEPROM + * + * Enable/Raise the EEPROM clock bit. + **/ +static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) +{ + *eecd = *eecd | E1000_EECD_SK; + ew32(EECD, *eecd); + e1e_flush(); + udelay(hw->nvm.delay_usec); +} + +/** + * e1000_lower_eec_clk - Lower EEPROM clock + * @hw: pointer to the HW structure + * @eecd: pointer to the EEPROM + * + * Clear/Lower the EEPROM clock bit. + **/ +static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) +{ + *eecd = *eecd & ~E1000_EECD_SK; + ew32(EECD, *eecd); + e1e_flush(); + udelay(hw->nvm.delay_usec); +} + +/** + * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM + * @hw: pointer to the HW structure + * @data: data to send to the EEPROM + * @count: number of bits to shift out + * + * We need to shift 'count' bits out to the EEPROM. So, the value in the + * "data" parameter will be shifted out to the EEPROM one bit at a time. + * In order to do this, "data" must be broken down into bits. + **/ +static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 eecd = er32(EECD); + u32 mask; + + mask = 0x01 << (count - 1); + if (nvm->type == e1000_nvm_eeprom_spi) + eecd |= E1000_EECD_DO; + + do { + eecd &= ~E1000_EECD_DI; + + if (data & mask) + eecd |= E1000_EECD_DI; + + ew32(EECD, eecd); + e1e_flush(); + + udelay(nvm->delay_usec); + + e1000_raise_eec_clk(hw, &eecd); + e1000_lower_eec_clk(hw, &eecd); + + mask >>= 1; + } while (mask); + + eecd &= ~E1000_EECD_DI; + ew32(EECD, eecd); +} + +/** + * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM + * @hw: pointer to the HW structure + * @count: number of bits to shift in + * + * In order to read a register from the EEPROM, we need to shift 'count' bits + * in from the EEPROM. Bits are "shifted in" by raising the clock input to + * the EEPROM (setting the SK bit), and then reading the value of the data out + * "DO" bit. During this "shifting in" process the data in "DI" bit should + * always be clear. + **/ +static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) +{ + u32 eecd; + u32 i; + u16 data; + + eecd = er32(EECD); + + eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); + data = 0; + + for (i = 0; i < count; i++) { + data <<= 1; + e1000_raise_eec_clk(hw, &eecd); + + eecd = er32(EECD); + + eecd &= ~E1000_EECD_DI; + if (eecd & E1000_EECD_DO) + data |= 1; + + e1000_lower_eec_clk(hw, &eecd); + } + + return data; +} + +/** + * e1000e_poll_eerd_eewr_done - Poll for EEPROM read/write completion + * @hw: pointer to the HW structure + * @ee_reg: EEPROM flag for polling + * + * Polls the EEPROM status bit for either read or write completion based + * upon the value of 'ee_reg'. + **/ +s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) +{ + u32 attempts = 100000; + u32 i, reg = 0; + + for (i = 0; i < attempts; i++) { + if (ee_reg == E1000_NVM_POLL_READ) + reg = er32(EERD); + else + reg = er32(EEWR); + + if (reg & E1000_NVM_RW_REG_DONE) + return 0; + + udelay(5); + } + + return -E1000_ERR_NVM; +} + +/** + * e1000e_acquire_nvm - Generic request for access to EEPROM + * @hw: pointer to the HW structure + * + * Set the EEPROM access request bit and wait for EEPROM access grant bit. + * Return successful if access grant bit set, else clear the request for + * EEPROM access and return -E1000_ERR_NVM (-1). + **/ +s32 e1000e_acquire_nvm(struct e1000_hw *hw) +{ + u32 eecd = er32(EECD); + s32 timeout = E1000_NVM_GRANT_ATTEMPTS; + + ew32(EECD, eecd | E1000_EECD_REQ); + eecd = er32(EECD); + + while (timeout) { + if (eecd & E1000_EECD_GNT) + break; + udelay(5); + eecd = er32(EECD); + timeout--; + } + + if (!timeout) { + eecd &= ~E1000_EECD_REQ; + ew32(EECD, eecd); + e_dbg("Could not acquire NVM grant\n"); + return -E1000_ERR_NVM; + } + + return 0; +} + +/** + * e1000_standby_nvm - Return EEPROM to standby state + * @hw: pointer to the HW structure + * + * Return the EEPROM to a standby state. + **/ +static void e1000_standby_nvm(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 eecd = er32(EECD); + + if (nvm->type == e1000_nvm_eeprom_spi) { + /* Toggle CS to flush commands */ + eecd |= E1000_EECD_CS; + ew32(EECD, eecd); + e1e_flush(); + udelay(nvm->delay_usec); + eecd &= ~E1000_EECD_CS; + ew32(EECD, eecd); + e1e_flush(); + udelay(nvm->delay_usec); + } +} + +/** + * e1000_stop_nvm - Terminate EEPROM command + * @hw: pointer to the HW structure + * + * Terminates the current command by inverting the EEPROM's chip select pin. + **/ +static void e1000_stop_nvm(struct e1000_hw *hw) +{ + u32 eecd; + + eecd = er32(EECD); + if (hw->nvm.type == e1000_nvm_eeprom_spi) { + /* Pull CS high */ + eecd |= E1000_EECD_CS; + e1000_lower_eec_clk(hw, &eecd); + } +} + +/** + * e1000e_release_nvm - Release exclusive access to EEPROM + * @hw: pointer to the HW structure + * + * Stop any current commands to the EEPROM and clear the EEPROM request bit. + **/ +void e1000e_release_nvm(struct e1000_hw *hw) +{ + u32 eecd; + + e1000_stop_nvm(hw); + + eecd = er32(EECD); + eecd &= ~E1000_EECD_REQ; + ew32(EECD, eecd); +} + +/** + * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write + * @hw: pointer to the HW structure + * + * Setups the EEPROM for reading and writing. + **/ +static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 eecd = er32(EECD); + u8 spi_stat_reg; + + if (nvm->type == e1000_nvm_eeprom_spi) { + u16 timeout = NVM_MAX_RETRY_SPI; + + /* Clear SK and CS */ + eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); + ew32(EECD, eecd); + e1e_flush(); + udelay(1); + + /* + * Read "Status Register" repeatedly until the LSB is cleared. + * The EEPROM will signal that the command has been completed + * by clearing bit 0 of the internal status register. If it's + * not cleared within 'timeout', then error out. + */ + while (timeout) { + e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, + hw->nvm.opcode_bits); + spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); + if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) + break; + + udelay(5); + e1000_standby_nvm(hw); + timeout--; + } + + if (!timeout) { + e_dbg("SPI NVM Status error\n"); + return -E1000_ERR_NVM; + } + } + + return 0; +} + +/** + * e1000e_read_nvm_eerd - Reads EEPROM using EERD register + * @hw: pointer to the HW structure + * @offset: offset of word in the EEPROM to read + * @words: number of words to read + * @data: word read from the EEPROM + * + * Reads a 16 bit word from the EEPROM using the EERD register. + **/ +s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + u32 i, eerd = 0; + s32 ret_val = 0; + + /* + * A check for invalid values: offset too large, too many words, + * too many words for the offset, and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || + (words == 0)) { + e_dbg("nvm parameter(s) out of bounds\n"); + return -E1000_ERR_NVM; + } + + for (i = 0; i < words; i++) { + eerd = ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) + + E1000_NVM_RW_REG_START; + + ew32(EERD, eerd); + ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); + if (ret_val) + break; + + data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA); + } + + return ret_val; +} + +/** + * e1000e_write_nvm_spi - Write to EEPROM using SPI + * @hw: pointer to the HW structure + * @offset: offset within the EEPROM to be written to + * @words: number of words to write + * @data: 16 bit word(s) to be written to the EEPROM + * + * Writes data to EEPROM at offset using SPI interface. + * + * If e1000e_update_nvm_checksum is not called after this function , the + * EEPROM will most likely contain an invalid checksum. + **/ +s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + s32 ret_val; + u16 widx = 0; + + /* + * A check for invalid values: offset too large, too many words, + * and not enough words. + */ + if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || + (words == 0)) { + e_dbg("nvm parameter(s) out of bounds\n"); + return -E1000_ERR_NVM; + } + + ret_val = nvm->ops.acquire(hw); + if (ret_val) + return ret_val; + + while (widx < words) { + u8 write_opcode = NVM_WRITE_OPCODE_SPI; + + ret_val = e1000_ready_nvm_eeprom(hw); + if (ret_val) { + nvm->ops.release(hw); + return ret_val; + } + + e1000_standby_nvm(hw); + + /* Send the WRITE ENABLE command (8 bit opcode) */ + e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, + nvm->opcode_bits); + + e1000_standby_nvm(hw); + + /* + * Some SPI eeproms use the 8th address bit embedded in the + * opcode + */ + if ((nvm->address_bits == 8) && (offset >= 128)) + write_opcode |= NVM_A8_OPCODE_SPI; + + /* Send the Write command (8-bit opcode + addr) */ + e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); + e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), + nvm->address_bits); + + /* Loop to allow for up to whole page write of eeprom */ + while (widx < words) { + u16 word_out = data[widx]; + word_out = (word_out >> 8) | (word_out << 8); + e1000_shift_out_eec_bits(hw, word_out, 16); + widx++; + + if ((((offset + widx) * 2) % nvm->page_size) == 0) { + e1000_standby_nvm(hw); + break; + } + } + } + + usleep_range(10000, 20000); + nvm->ops.release(hw); + return 0; +} + +/** + * e1000_read_pba_string_generic - Read device part number + * @hw: pointer to the HW structure + * @pba_num: pointer to device part number + * @pba_num_size: size of part number buffer + * + * Reads the product board assembly (PBA) number from the EEPROM and stores + * the value in pba_num. + **/ +s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, + u32 pba_num_size) +{ + s32 ret_val; + u16 nvm_data; + u16 pba_ptr; + u16 offset; + u16 length; + + if (pba_num == NULL) { + e_dbg("PBA string buffer was null\n"); + ret_val = E1000_ERR_INVALID_ARGUMENT; + goto out; + } + + ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); + if (ret_val) { + e_dbg("NVM Read Error\n"); + goto out; + } + + ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); + if (ret_val) { + e_dbg("NVM Read Error\n"); + goto out; + } + + /* + * if nvm_data is not ptr guard the PBA must be in legacy format which + * means pba_ptr is actually our second data word for the PBA number + * and we can decode it into an ascii string + */ + if (nvm_data != NVM_PBA_PTR_GUARD) { + e_dbg("NVM PBA number is not stored as string\n"); + + /* we will need 11 characters to store the PBA */ + if (pba_num_size < 11) { + e_dbg("PBA string buffer too small\n"); + return E1000_ERR_NO_SPACE; + } + + /* extract hex string from data and pba_ptr */ + pba_num[0] = (nvm_data >> 12) & 0xF; + pba_num[1] = (nvm_data >> 8) & 0xF; + pba_num[2] = (nvm_data >> 4) & 0xF; + pba_num[3] = nvm_data & 0xF; + pba_num[4] = (pba_ptr >> 12) & 0xF; + pba_num[5] = (pba_ptr >> 8) & 0xF; + pba_num[6] = '-'; + pba_num[7] = 0; + pba_num[8] = (pba_ptr >> 4) & 0xF; + pba_num[9] = pba_ptr & 0xF; + + /* put a null character on the end of our string */ + pba_num[10] = '\0'; + + /* switch all the data but the '-' to hex char */ + for (offset = 0; offset < 10; offset++) { + if (pba_num[offset] < 0xA) + pba_num[offset] += '0'; + else if (pba_num[offset] < 0x10) + pba_num[offset] += 'A' - 0xA; + } + + goto out; + } + + ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length); + if (ret_val) { + e_dbg("NVM Read Error\n"); + goto out; + } + + if (length == 0xFFFF || length == 0) { + e_dbg("NVM PBA number section invalid length\n"); + ret_val = E1000_ERR_NVM_PBA_SECTION; + goto out; + } + /* check if pba_num buffer is big enough */ + if (pba_num_size < (((u32)length * 2) - 1)) { + e_dbg("PBA string buffer too small\n"); + ret_val = E1000_ERR_NO_SPACE; + goto out; + } + + /* trim pba length from start of string */ + pba_ptr++; + length--; + + for (offset = 0; offset < length; offset++) { + ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data); + if (ret_val) { + e_dbg("NVM Read Error\n"); + goto out; + } + pba_num[offset * 2] = (u8)(nvm_data >> 8); + pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF); + } + pba_num[offset * 2] = '\0'; + +out: + return ret_val; +} + +/** + * e1000_read_mac_addr_generic - Read device MAC address + * @hw: pointer to the HW structure + * + * Reads the device MAC address from the EEPROM and stores the value. + * Since devices with two ports use the same EEPROM, we increment the + * last bit in the MAC address for the second port. + **/ +s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) +{ + u32 rar_high; + u32 rar_low; + u16 i; + + rar_high = er32(RAH(0)); + rar_low = er32(RAL(0)); + + for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) + hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8)); + + for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) + hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8)); + + for (i = 0; i < ETH_ALEN; i++) + hw->mac.addr[i] = hw->mac.perm_addr[i]; + + return 0; +} + +/** + * e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum + * @hw: pointer to the HW structure + * + * Calculates the EEPROM checksum by reading/adding each word of the EEPROM + * and then verifies that the sum of the EEPROM is equal to 0xBABA. + **/ +s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw) +{ + s32 ret_val; + u16 checksum = 0; + u16 i, nvm_data; + + for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { + ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); + if (ret_val) { + e_dbg("NVM Read Error\n"); + return ret_val; + } + checksum += nvm_data; + } + + if (checksum != (u16)NVM_SUM) { + e_dbg("NVM Checksum Invalid\n"); + return -E1000_ERR_NVM; + } + + return 0; +} + +/** + * e1000e_update_nvm_checksum_generic - Update EEPROM checksum + * @hw: pointer to the HW structure + * + * Updates the EEPROM checksum by reading/adding each word of the EEPROM + * up to the checksum. Then calculates the EEPROM checksum and writes the + * value to the EEPROM. + **/ +s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw) +{ + s32 ret_val; + u16 checksum = 0; + u16 i, nvm_data; + + for (i = 0; i < NVM_CHECKSUM_REG; i++) { + ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); + if (ret_val) { + e_dbg("NVM Read Error while updating checksum.\n"); + return ret_val; + } + checksum += nvm_data; + } + checksum = (u16)NVM_SUM - checksum; + ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum); + if (ret_val) + e_dbg("NVM Write Error while updating checksum.\n"); + + return ret_val; +} + +/** + * e1000e_reload_nvm - Reloads EEPROM + * @hw: pointer to the HW structure + * + * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the + * extended control register. + **/ +void e1000e_reload_nvm(struct e1000_hw *hw) +{ + u32 ctrl_ext; + + udelay(10); + ctrl_ext = er32(CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; + ew32(CTRL_EXT, ctrl_ext); + e1e_flush(); +} diff --git a/drivers/net/ethernet/intel/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c index 20e93b08e7f3..9c6a56d804a4 100644 --- a/drivers/net/ethernet/intel/e1000e/param.c +++ b/drivers/net/ethernet/intel/e1000e/param.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2011 Intel Corporation. + Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -113,11 +113,20 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); #define MAX_ITR 100000 #define MIN_ITR 100 -/* IntMode (Interrupt Mode) +/* + * IntMode (Interrupt Mode) + * + * Valid Range: varies depending on kernel configuration & hardware support + * + * legacy=0, MSI=1, MSI-X=2 * - * Valid Range: 0 - 2 + * When MSI/MSI-X support is enabled in kernel- + * Default Value: 2 (MSI-X) when supported by hardware, 1 (MSI) otherwise + * When MSI/MSI-X support is not enabled in kernel- + * Default Value: 0 (legacy) * - * Default Value: 2 (MSI-X) + * When a mode is specified that is not allowed/supported, it will be + * demoted to the most advanced interrupt mode available. */ E1000_PARAM(IntMode, "Interrupt Mode"); #define MAX_INTMODE 2 @@ -388,12 +397,33 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) static struct e1000_option opt = { .type = range_option, .name = "Interrupt Mode", - .err = "defaulting to 2 (MSI-X)", - .def = E1000E_INT_MODE_MSIX, - .arg = { .r = { .min = MIN_INTMODE, - .max = MAX_INTMODE } } +#ifndef CONFIG_PCI_MSI + .err = "defaulting to 0 (legacy)", + .def = E1000E_INT_MODE_LEGACY, + .arg = { .r = { .min = 0, + .max = 0 } } +#endif }; +#ifdef CONFIG_PCI_MSI + if (adapter->flags & FLAG_HAS_MSIX) { + opt.err = kstrdup("defaulting to 2 (MSI-X)", + GFP_KERNEL); + opt.def = E1000E_INT_MODE_MSIX; + opt.arg.r.max = E1000E_INT_MODE_MSIX; + } else { + opt.err = kstrdup("defaulting to 1 (MSI)", GFP_KERNEL); + opt.def = E1000E_INT_MODE_MSI; + opt.arg.r.max = E1000E_INT_MODE_MSI; + } + + if (!opt.err) { + dev_err(&adapter->pdev->dev, + "Failed to allocate memory\n"); + return; + } +#endif + if (num_IntMode > bd) { unsigned int int_mode = IntMode[bd]; e1000_validate_option(&int_mode, &opt, adapter); @@ -401,6 +431,10 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) } else { adapter->int_mode = opt.def; } + +#ifdef CONFIG_PCI_MSI + kfree(opt.err); +#endif } { /* Smart Power Down */ static const struct e1000_option opt = { diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c index 8666476cb9be..6f44c3fb80b6 100644 --- a/drivers/net/ethernet/intel/e1000e/phy.c +++ b/drivers/net/ethernet/intel/e1000e/phy.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2011 Intel Corporation. + Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -132,7 +132,7 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw) u16 phy_id; u16 retry_count = 0; - if (!(phy->ops.read_reg)) + if (!phy->ops.read_reg) goto out; while (retry_count < 2) { @@ -382,7 +382,7 @@ static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, s32 ret_val = 0; if (!locked) { - if (!(hw->phy.ops.acquire)) + if (!hw->phy.ops.acquire) goto out; ret_val = hw->phy.ops.acquire(hw); @@ -453,7 +453,7 @@ static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, s32 ret_val = 0; if (!locked) { - if (!(hw->phy.ops.acquire)) + if (!hw->phy.ops.acquire) goto out; ret_val = hw->phy.ops.acquire(hw); @@ -526,7 +526,7 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, s32 ret_val = 0; if (!locked) { - if (!(hw->phy.ops.acquire)) + if (!hw->phy.ops.acquire) goto out; ret_val = hw->phy.ops.acquire(hw); @@ -599,7 +599,7 @@ static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, s32 ret_val = 0; if (!locked) { - if (!(hw->phy.ops.acquire)) + if (!hw->phy.ops.acquire) goto out; ret_val = hw->phy.ops.acquire(hw); @@ -1136,13 +1136,12 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) if (phy->autoneg_wait_to_complete) { ret_val = e1000_wait_autoneg(hw); if (ret_val) { - e_dbg("Error while waiting for " - "autoneg to complete\n"); + e_dbg("Error while waiting for autoneg to complete\n"); return ret_val; } } - hw->mac.get_link_status = 1; + hw->mac.get_link_status = true; return ret_val; } diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 94be6c32fa7d..fda824735e18 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -173,7 +173,9 @@ static int igb_check_vf_assignment(struct igb_adapter *adapter); #endif #ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int igb_suspend(struct device *); +#endif static int igb_resume(struct device *); #ifdef CONFIG_PM_RUNTIME static int igb_runtime_suspend(struct device *dev); @@ -6710,6 +6712,7 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, } #ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int igb_suspend(struct device *dev) { int retval; @@ -6729,6 +6732,7 @@ static int igb_suspend(struct device *dev) return 0; } +#endif /* CONFIG_PM_SLEEP */ static int igb_resume(struct device *dev) { diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c index db7dce2351c2..8ce67064b9c5 100644 --- a/drivers/net/ethernet/intel/igbvf/ethtool.c +++ b/drivers/net/ethernet/intel/igbvf/ethtool.c @@ -343,10 +343,10 @@ static int igbvf_get_coalesce(struct net_device *netdev, { struct igbvf_adapter *adapter = netdev_priv(netdev); - if (adapter->itr_setting <= 3) - ec->rx_coalesce_usecs = adapter->itr_setting; + if (adapter->requested_itr <= 3) + ec->rx_coalesce_usecs = adapter->requested_itr; else - ec->rx_coalesce_usecs = adapter->itr_setting >> 2; + ec->rx_coalesce_usecs = adapter->current_itr >> 2; return 0; } @@ -365,15 +365,16 @@ static int igbvf_set_coalesce(struct net_device *netdev, /* convert to rate of irq's per second */ if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) { - adapter->itr = IGBVF_START_ITR; - adapter->itr_setting = ec->rx_coalesce_usecs; + adapter->current_itr = IGBVF_START_ITR; + adapter->requested_itr = ec->rx_coalesce_usecs; } else { - adapter->itr = ec->rx_coalesce_usecs << 2; - adapter->itr_setting = adapter->itr; + adapter->current_itr = ec->rx_coalesce_usecs << 2; + adapter->requested_itr = 1000000000 / + (adapter->current_itr * 256); } - writel(adapter->itr, - hw->hw_addr + adapter->rx_ring[0].itr_register); + writel(adapter->current_itr, + hw->hw_addr + adapter->rx_ring->itr_register); return 0; } diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h index 2c6d87e4d3d9..a895e2f7b34d 100644 --- a/drivers/net/ethernet/intel/igbvf/igbvf.h +++ b/drivers/net/ethernet/intel/igbvf/igbvf.h @@ -43,7 +43,18 @@ struct igbvf_info; struct igbvf_adapter; /* Interrupt defines */ -#define IGBVF_START_ITR 648 /* ~6000 ints/sec */ +#define IGBVF_START_ITR 488 /* ~8000 ints/sec */ +#define IGBVF_4K_ITR 980 +#define IGBVF_20K_ITR 196 +#define IGBVF_70K_ITR 56 + +enum latency_range { + lowest_latency = 0, + low_latency = 1, + bulk_latency = 2, + latency_invalid = 255 +}; + /* Interrupt modes, as used by the IntMode parameter */ #define IGBVF_INT_MODE_LEGACY 0 @@ -155,6 +166,7 @@ struct igbvf_ring { char name[IFNAMSIZ + 5]; u32 eims_value; u32 itr_val; + enum latency_range itr_range; u16 itr_register; int set_itr; @@ -187,10 +199,8 @@ struct igbvf_adapter { unsigned long state; /* Interrupt Throttle Rate */ - u32 itr; - u32 itr_setting; - u16 tx_itr; - u16 rx_itr; + u32 requested_itr; /* ints/sec or adaptive */ + u32 current_itr; /* Actual ITR register value, not ints/sec */ /* * Tx @@ -299,13 +309,6 @@ enum igbvf_state_t { __IGBVF_DOWN }; -enum latency_range { - lowest_latency = 0, - low_latency = 1, - bulk_latency = 2, - latency_invalid = 255 -}; - extern char igbvf_driver_name[]; extern const char igbvf_driver_version[]; diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 4e9141cfe81d..446297ff0104 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -632,14 +632,13 @@ void igbvf_free_rx_resources(struct igbvf_ring *rx_ring) * traffic pattern. Constants in this function were computed * based on theoretical maximum wire speed and thresholds were set based * on testing data as well as attempting to minimize response time - * while increasing bulk throughput. This functionality is controlled - * by the InterruptThrottleRate module parameter. + * while increasing bulk throughput. **/ -static unsigned int igbvf_update_itr(struct igbvf_adapter *adapter, - u16 itr_setting, int packets, - int bytes) +static enum latency_range igbvf_update_itr(struct igbvf_adapter *adapter, + enum latency_range itr_setting, + int packets, int bytes) { - unsigned int retval = itr_setting; + enum latency_range retval = itr_setting; if (packets == 0) goto update_itr_done; @@ -675,65 +674,87 @@ static unsigned int igbvf_update_itr(struct igbvf_adapter *adapter, retval = low_latency; } break; + default: + break; } update_itr_done: return retval; } -static void igbvf_set_itr(struct igbvf_adapter *adapter) +static int igbvf_range_to_itr(enum latency_range current_range) { - struct e1000_hw *hw = &adapter->hw; - u16 current_itr; - u32 new_itr = adapter->itr; - - adapter->tx_itr = igbvf_update_itr(adapter, adapter->tx_itr, - adapter->total_tx_packets, - adapter->total_tx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) - adapter->tx_itr = low_latency; - - adapter->rx_itr = igbvf_update_itr(adapter, adapter->rx_itr, - adapter->total_rx_packets, - adapter->total_rx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) - adapter->rx_itr = low_latency; + int new_itr; - current_itr = max(adapter->rx_itr, adapter->tx_itr); - - switch (current_itr) { + switch (current_range) { /* counts and packets in update_itr are dependent on these numbers */ case lowest_latency: - new_itr = 70000; + new_itr = IGBVF_70K_ITR; break; case low_latency: - new_itr = 20000; /* aka hwitr = ~200 */ + new_itr = IGBVF_20K_ITR; break; case bulk_latency: - new_itr = 4000; + new_itr = IGBVF_4K_ITR; break; default: + new_itr = IGBVF_START_ITR; break; } + return new_itr; +} + +static void igbvf_set_itr(struct igbvf_adapter *adapter) +{ + u32 new_itr; + + adapter->tx_ring->itr_range = + igbvf_update_itr(adapter, + adapter->tx_ring->itr_val, + adapter->total_tx_packets, + adapter->total_tx_bytes); + + /* conservative mode (itr 3) eliminates the lowest_latency setting */ + if (adapter->requested_itr == 3 && + adapter->tx_ring->itr_range == lowest_latency) + adapter->tx_ring->itr_range = low_latency; - if (new_itr != adapter->itr) { + new_itr = igbvf_range_to_itr(adapter->tx_ring->itr_range); + + + if (new_itr != adapter->tx_ring->itr_val) { + u32 current_itr = adapter->tx_ring->itr_val; /* * this attempts to bias the interrupt rate towards Bulk * by adding intermediate steps when interrupt rate is * increasing */ - new_itr = new_itr > adapter->itr ? - min(adapter->itr + (new_itr >> 2), new_itr) : - new_itr; - adapter->itr = new_itr; - adapter->rx_ring->itr_val = 1952; - - if (adapter->msix_entries) - adapter->rx_ring->set_itr = 1; - else - ew32(ITR, 1952); + new_itr = new_itr > current_itr ? + min(current_itr + (new_itr >> 2), new_itr) : + new_itr; + adapter->tx_ring->itr_val = new_itr; + + adapter->tx_ring->set_itr = 1; + } + + adapter->rx_ring->itr_range = + igbvf_update_itr(adapter, adapter->rx_ring->itr_val, + adapter->total_rx_packets, + adapter->total_rx_bytes); + if (adapter->requested_itr == 3 && + adapter->rx_ring->itr_range == lowest_latency) + adapter->rx_ring->itr_range = low_latency; + + new_itr = igbvf_range_to_itr(adapter->rx_ring->itr_range); + + if (new_itr != adapter->rx_ring->itr_val) { + u32 current_itr = adapter->rx_ring->itr_val; + new_itr = new_itr > current_itr ? + min(current_itr + (new_itr >> 2), new_itr) : + new_itr; + adapter->rx_ring->itr_val = new_itr; + + adapter->rx_ring->set_itr = 1; } } @@ -835,6 +856,11 @@ static irqreturn_t igbvf_intr_msix_tx(int irq, void *data) struct e1000_hw *hw = &adapter->hw; struct igbvf_ring *tx_ring = adapter->tx_ring; + if (tx_ring->set_itr) { + writel(tx_ring->itr_val, + adapter->hw.hw_addr + tx_ring->itr_register); + adapter->tx_ring->set_itr = 0; + } adapter->total_tx_bytes = 0; adapter->total_tx_packets = 0; @@ -937,19 +963,10 @@ static void igbvf_configure_msix(struct igbvf_adapter *adapter) igbvf_assign_vector(adapter, IGBVF_NO_QUEUE, 0, vector++); adapter->eims_enable_mask |= tx_ring->eims_value; - if (tx_ring->itr_val) - writel(tx_ring->itr_val, - hw->hw_addr + tx_ring->itr_register); - else - writel(1952, hw->hw_addr + tx_ring->itr_register); - + writel(tx_ring->itr_val, hw->hw_addr + tx_ring->itr_register); igbvf_assign_vector(adapter, 0, IGBVF_NO_QUEUE, vector++); adapter->eims_enable_mask |= rx_ring->eims_value; - if (rx_ring->itr_val) - writel(rx_ring->itr_val, - hw->hw_addr + rx_ring->itr_register); - else - writel(1952, hw->hw_addr + rx_ring->itr_register); + writel(rx_ring->itr_val, hw->hw_addr + rx_ring->itr_register); /* set vector for other causes, i.e. link changes */ @@ -1027,7 +1044,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter) goto out; adapter->tx_ring->itr_register = E1000_EITR(vector); - adapter->tx_ring->itr_val = 1952; + adapter->tx_ring->itr_val = adapter->current_itr; vector++; err = request_irq(adapter->msix_entries[vector].vector, @@ -1037,7 +1054,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter) goto out; adapter->rx_ring->itr_register = E1000_EITR(vector); - adapter->rx_ring->itr_val = 1952; + adapter->rx_ring->itr_val = adapter->current_itr; vector++; err = request_irq(adapter->msix_entries[vector].vector, @@ -1151,7 +1168,7 @@ static int igbvf_poll(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete(napi); - if (adapter->itr_setting & 3) + if (adapter->requested_itr & 3) igbvf_set_itr(adapter); if (!test_bit(__IGBVF_DOWN, &adapter->state)) @@ -1521,8 +1538,8 @@ static int __devinit igbvf_sw_init(struct igbvf_adapter *adapter) adapter->tx_abs_int_delay = 32; adapter->rx_int_delay = 0; adapter->rx_abs_int_delay = 8; - adapter->itr_setting = 3; - adapter->itr = 20000; + adapter->requested_itr = 3; + adapter->current_itr = IGBVF_START_ITR; /* Set various function pointers */ adapter->ei->init_ops(&adapter->hw); diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c index 9bd5faf64a85..002478801a1b 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -1136,10 +1136,8 @@ ixgb_set_multi(struct net_device *netdev) u8 *mta = kmalloc(IXGB_MAX_NUM_MULTICAST_ADDRESSES * ETH_ALEN, GFP_ATOMIC); u8 *addr; - if (!mta) { - pr_err("allocation of multicast memory failed\n"); + if (!mta) goto alloc_failed; - } IXGB_WRITE_REG(hw, RCTL, rctl); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 3dc6cef58107..6441acc34c23 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -131,6 +131,11 @@ MODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate per physical function"); #endif /* CONFIG_PCI_IOV */ +static unsigned int allow_unsupported_sfp; +module_param(allow_unsupported_sfp, uint, 0); +MODULE_PARM_DESC(allow_unsupported_sfp, + "Allow unsupported and untested SFP+ modules on 82599-based adapters"); + MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver"); MODULE_LICENSE("GPL"); @@ -7493,6 +7498,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, e_crit(probe, "Fan has stopped, replace the adapter\n"); } + if (allow_unsupported_sfp) + hw->allow_unsupported_sfp = allow_unsupported_sfp; + /* reset_hw fills in the perm_addr as well */ hw->phy.reset_if_overtemp = true; err = hw->mac.ops.reset_hw(hw); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index b91773551a38..bf9f82f4b1ae 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -834,6 +834,7 @@ out: **/ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) { + struct ixgbe_adapter *adapter = hw->back; s32 status = IXGBE_ERR_PHY_ADDR_INVALID; u32 vendor_oui = 0; enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; @@ -1068,9 +1069,16 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) if (hw->phy.type == ixgbe_phy_sfp_intel) { status = 0; } else { - hw_dbg(hw, "SFP+ module not supported\n"); - hw->phy.type = ixgbe_phy_sfp_unsupported; - status = IXGBE_ERR_SFP_NOT_SUPPORTED; + if (hw->allow_unsupported_sfp) { + e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules."); + status = 0; + } else { + hw_dbg(hw, + "SFP+ module not supported\n"); + hw->phy.type = + ixgbe_phy_sfp_unsupported; + status = IXGBE_ERR_SFP_NOT_SUPPORTED; + } } } else { status = 0; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 9b95bef60970..4c060292395f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -2892,6 +2892,7 @@ struct ixgbe_hw { u8 revision_id; bool adapter_stopped; bool force_full_reset; + bool allow_unsupported_sfp; }; struct ixgbe_info { diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index e51d552410ae..58c04b69ce70 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -2521,12 +2521,8 @@ int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter, size = sizeof(struct ixgbevf_rx_buffer) * rx_ring->count; rx_ring->rx_buffer_info = vzalloc(size); - if (!rx_ring->rx_buffer_info) { - hw_dbg(&adapter->hw, - "Unable to vmalloc buffer memory for " - "the receive descriptor ring\n"); + if (!rx_ring->rx_buffer_info) goto alloc_failed; - } /* Round up to nearest 4K */ rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc); diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index 27d651a80f3f..1b86d0b45f3c 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -2999,7 +2999,6 @@ jme_init_one(struct pci_dev *pdev, */ netdev = alloc_etherdev(sizeof(*jme)); if (!netdev) { - pr_err("Cannot allocate netdev structure\n"); rc = -ENOMEM; goto err_out_release_regions; } diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 6ad094f176f8..f30db1c46600 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -1108,10 +1108,9 @@ static int korina_probe(struct platform_device *pdev) int rc; dev = alloc_etherdev(sizeof(struct korina_private)); - if (!dev) { - printk(KERN_ERR DRV_NAME ": alloc_etherdev failed\n"); + if (!dev) return -ENOMEM; - } + SET_NETDEV_DEV(dev, &pdev->dev); lp = netdev_priv(dev); @@ -1150,7 +1149,6 @@ static int korina_probe(struct platform_device *pdev) lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL); if (!lp->td_ring) { - printk(KERN_ERR DRV_NAME ": cannot allocate descriptors\n"); rc = -ENXIO; goto probe_err_td_ring; } diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 85e2c6cd9708..3369b7db777d 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -114,7 +114,7 @@ struct ltq_etop_priv { static int ltq_etop_alloc_skb(struct ltq_etop_chan *ch) { - ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN); + ch->skb[ch->dma.desc] = netdev_alloc_skb(ch->netdev, MAX_DMA_DATA_LEN); if (!ch->skb[ch->dma.desc]) return -ENOMEM; ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL, @@ -731,6 +731,10 @@ ltq_etop_probe(struct platform_device *pdev) } dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4); + if (!dev) { + err = -ENOMEM; + goto err_out; + } strcpy(dev->name, "eth%d"); dev->netdev_ops = <q_eth_netdev_ops; dev->ethtool_ops = <q_etop_ethtool_ops; diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 9edecfa1f0f4..f702d0dc18c7 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -667,7 +667,7 @@ static int rxq_refill(struct rx_queue *rxq, int budget) skb = __skb_dequeue(&mp->rx_recycle); if (skb == NULL) - skb = dev_alloc_skb(mp->skb_size); + skb = netdev_alloc_skb(mp->dev, mp->skb_size); if (skb == NULL) { mp->oom = 1; diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 953ba5851f7b..75df2091bd2e 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -350,7 +350,7 @@ static void rxq_refill(struct net_device *dev) while (pep->rx_desc_count < pep->rx_ring_size) { int size; - skb = dev_alloc_skb(pep->skb_size); + skb = netdev_alloc_skb(dev, pep->skb_size); if (!skb) break; if (SKB_DMA_REALIGN) @@ -1017,10 +1017,9 @@ static int rxq_init(struct net_device *dev) /* Allocate RX skb rings */ pep->rx_skb = kmalloc(sizeof(*pep->rx_skb) * pep->rx_ring_size, GFP_KERNEL); - if (!pep->rx_skb) { - printk(KERN_ERR "%s: Cannot alloc RX skb ring\n", dev->name); + if (!pep->rx_skb) return -ENOMEM; - } + /* Allocate RX ring */ pep->rx_desc_count = 0; size = pep->rx_ring_size * sizeof(struct rx_desc); @@ -1081,10 +1080,9 @@ static int txq_init(struct net_device *dev) pep->tx_skb = kmalloc(sizeof(*pep->tx_skb) * pep->tx_ring_size, GFP_KERNEL); - if (!pep->tx_skb) { - printk(KERN_ERR "%s: Cannot alloc TX skb ring\n", dev->name); + if (!pep->tx_skb) return -ENOMEM; - } + /* Allocate TX ring */ pep->tx_desc_count = 0; size = pep->tx_ring_size * sizeof(struct tx_desc); diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 33947ac595c0..5a30bf823099 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -3807,10 +3807,8 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, struct skge_port *skge; struct net_device *dev = alloc_etherdev(sizeof(*skge)); - if (!dev) { - dev_err(&hw->pdev->dev, "etherdev alloc failed\n"); + if (!dev) return NULL; - } SET_NETDEV_DEV(dev, &hw->pdev->dev); dev->netdev_ops = &skge_netdev_ops; diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 760c2b17dfd3..82c2c86a1951 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -4700,10 +4700,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, struct sky2_port *sky2; struct net_device *dev = alloc_etherdev(sizeof(*sky2)); - if (!dev) { - dev_err(&hw->pdev->dev, "etherdev alloc failed\n"); + if (!dev) return NULL; - } SET_NETDEV_DEV(dev, &hw->pdev->dev); dev->irq = hw->pdev->irq; diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index eaf09d4f02d0..48d5c48d7ce8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -1314,7 +1314,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, down(&priv->cmd.slave_sem); if (mlx4_master_process_vhcr(dev, slave, NULL)) { mlx4_err(dev, "Failed processing vhcr for slave:%d," - " reseting slave.\n", slave); + " resetting slave.\n", slave); up(&priv->cmd.slave_sem); goto reset_slave; } diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 149e60da0a32..9fe4f94c6da7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -1048,10 +1048,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv), prof->tx_ring_num, prof->rx_ring_num); - if (dev == NULL) { - mlx4_err(mdev, "Net device allocation failed\n"); + if (dev == NULL) return -ENOMEM; - } SET_NETDEV_DEV(dev, &mdev->dev->pdev->dev); dev->dev_id = port - 1; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index d4ad8c226b51..d703ef2c9c91 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -285,10 +285,9 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv, tmp = size * roundup_pow_of_two(MLX4_EN_MAX_RX_FRAGS * sizeof(struct skb_frag_struct)); ring->rx_info = vmalloc(tmp); - if (!ring->rx_info) { - en_err(priv, "Failed allocating rx_info ring\n"); + if (!ring->rx_info) return -ENOMEM; - } + en_dbg(DRV, priv, "Allocated rx_info ring at addr:%p size:%d\n", ring->rx_info, tmp); @@ -468,12 +467,11 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, int used_frags; dma_addr_t dma; - skb = dev_alloc_skb(SMALL_PACKET_SIZE + NET_IP_ALIGN); + skb = netdev_alloc_skb(priv->dev, SMALL_PACKET_SIZE + NET_IP_ALIGN); if (!skb) { en_dbg(RX_ERR, priv, "Failed allocating skb\n"); return NULL; } - skb->dev = priv->dev; skb_reserve(skb, NET_IP_ALIGN); skb->len = length; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 9ef9038d0629..ff3250586584 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -71,16 +71,14 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, tmp = size * sizeof(struct mlx4_en_tx_info); ring->tx_info = vmalloc(tmp); - if (!ring->tx_info) { - en_err(priv, "Failed allocating tx_info ring\n"); + if (!ring->tx_info) return -ENOMEM; - } + en_dbg(DRV, priv, "Allocated tx_info ring at addr:%p size:%d\n", ring->tx_info, tmp); ring->bounce_buf = kmalloc(MAX_DESC_SIZE, GFP_KERNEL); if (!ring->bounce_buf) { - en_err(priv, "Failed allocating bounce buffer\n"); err = -ENOMEM; goto err_tx; } diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c index ab81c0dc96e2..dccae1d1743a 100644 --- a/drivers/net/ethernet/micrel/ks8695net.c +++ b/drivers/net/ethernet/micrel/ks8695net.c @@ -278,7 +278,8 @@ ks8695_refill_rxbuffers(struct ks8695_priv *ksp) for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) { if (!ksp->rx_buffers[buff_n].skb) { - struct sk_buff *skb = dev_alloc_skb(MAX_RXBUF_SIZE); + struct sk_buff *skb = + netdev_alloc_skb(ksp->ndev, MAX_RXBUF_SIZE); dma_addr_t mapping; ksp->rx_buffers[buff_n].skb = skb; @@ -299,7 +300,6 @@ ks8695_refill_rxbuffers(struct ks8695_priv *ksp) break; } ksp->rx_buffers[buff_n].dma_ptr = mapping; - skb->dev = ksp->ndev; ksp->rx_buffers[buff_n].length = MAX_RXBUF_SIZE; /* Record this into the DMA ring */ @@ -1362,10 +1362,8 @@ ks8695_probe(struct platform_device *pdev) /* Initialise a net_device */ ndev = alloc_etherdev(sizeof(struct ks8695_priv)); - if (!ndev) { - dev_err(&pdev->dev, "could not allocate device.\n"); + if (!ndev) return -ENOMEM; - } SET_NETDEV_DEV(ndev, &pdev->dev); diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 6b35e7da9a9c..4b551feae4c5 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -1,4 +1,4 @@ -/* drivers/net/ks8851.c +/* drivers/net/ethernet/micrel/ks8851.c * * Copyright 2009 Simtec Electronics * http://www.simtec.co.uk/ @@ -1419,10 +1419,8 @@ static int __devinit ks8851_probe(struct spi_device *spi) int ret; ndev = alloc_etherdev(sizeof(struct ks8851_net)); - if (!ndev) { - dev_err(&spi->dev, "failed to alloc ethernet device\n"); + if (!ndev) return -ENOMEM; - } spi->bits_per_word = 8; diff --git a/drivers/net/ethernet/micrel/ks8851.h b/drivers/net/ethernet/micrel/ks8851.h index b0fae86aacad..852256ef1f22 100644 --- a/drivers/net/ethernet/micrel/ks8851.h +++ b/drivers/net/ethernet/micrel/ks8851.h @@ -1,4 +1,4 @@ -/* drivers/net/ks8851.h +/* drivers/net/ethernet/micrel/ks8851.h * * Copyright 2009 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index e58e78e5c930..61a2f61a31f6 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c @@ -1,5 +1,5 @@ /** - * drivers/net/ks8851_mll.c + * drivers/net/ethernet/micrel/ks8851_mll.c * Copyright (c) 2009 Micrel Inc. * * This program is free software; you can redistribute it and/or modify @@ -796,7 +796,7 @@ static void ks_rcv(struct ks_net *ks, struct net_device *netdev) frame_hdr = ks->frame_head_info; while (ks->frame_cnt--) { - skb = dev_alloc_skb(frame_hdr->len + 16); + skb = netdev_alloc_skb(netdev, frame_hdr->len + 16); if (likely(skb && (frame_hdr->sts & RXFSHR_RXFV) && (frame_hdr->len < RX_BUF_SIZE) && frame_hdr->len)) { skb_reserve(skb, 2); @@ -1501,10 +1501,8 @@ static int ks_hw_init(struct ks_net *ks) ks->mcast_lst_size = 0; ks->frame_head_info = kmalloc(MHEADER_SIZE, GFP_KERNEL); - if (!ks->frame_head_info) { - pr_err("Error: Fail to allocate frame memory\n"); + if (!ks->frame_head_info) return false; - } ks_set_mac(ks, KS_DEFAULT_MAC_ADDRESS); return true; diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index e52cd310ae76..ef723b185d85 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -1,5 +1,5 @@ /** - * drivers/net/ksx884x.c - Micrel KSZ8841/2 PCI Ethernet driver + * drivers/net/ethernet/micrel/ksx884x.c - Micrel KSZ8841/2 PCI Ethernet driver * * Copyright (c) 2009-2010 Micrel, Inc. * Tristram Ha <Tristram.Ha@micrel.com> @@ -4863,7 +4863,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev) memset(&skb->data[skb->len], 0, 50 - skb->len); skb->len = 50; } else { - skb = dev_alloc_skb(50); + skb = netdev_alloc_skb(dev, 50); if (!skb) return NETDEV_TX_BUSY; memcpy(skb->data, org_skb->data, org_skb->len); @@ -4885,7 +4885,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev) (ETH_P_IPV6 == htons(skb->protocol)))) { struct sk_buff *org_skb = skb; - skb = dev_alloc_skb(org_skb->len); + skb = netdev_alloc_skb(dev, org_skb->len); if (!skb) { rc = NETDEV_TX_BUSY; goto unlock; @@ -5019,7 +5019,7 @@ static inline int rx_proc(struct net_device *dev, struct ksz_hw* hw, do { /* skb->data != skb->head */ - skb = dev_alloc_skb(packet_len + 2); + skb = netdev_alloc_skb(dev, packet_len + 2); if (!skb) { dev->stats.rx_dropped++; return -ENOMEM; diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c index 50055e0282ed..1d6b7ce3e1ee 100644 --- a/drivers/net/ethernet/microchip/enc28j60.c +++ b/drivers/net/ethernet/microchip/enc28j60.c @@ -954,14 +954,13 @@ static void enc28j60_hw_rx(struct net_device *ndev) if (len > MAX_FRAMELEN) ndev->stats.rx_over_errors++; } else { - skb = dev_alloc_skb(len + NET_IP_ALIGN); + skb = netdev_alloc_skb(ndev, len + NET_IP_ALIGN); if (!skb) { if (netif_msg_rx_err(priv)) dev_err(&ndev->dev, "out of memory for Rx'd frame\n"); ndev->stats.rx_dropped++; } else { - skb->dev = ndev; skb_reserve(skb, NET_IP_ALIGN); /* copy the packet from the receive buffer */ enc28j60_mem_read(priv, @@ -1553,9 +1552,6 @@ static int __devinit enc28j60_probe(struct spi_device *spi) dev = alloc_etherdev(sizeof(struct enc28j60_net)); if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&spi->dev, DRV_NAME - ": unable to alloc new ethernet\n"); ret = -ENOMEM; goto error_alloc; } diff --git a/drivers/net/ethernet/mipsnet.c b/drivers/net/ethernet/mipsnet.c index d05b0c9e1e9c..dbc666a3d523 100644 --- a/drivers/net/ethernet/mipsnet.c +++ b/drivers/net/ethernet/mipsnet.c @@ -152,7 +152,7 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t len) if (!len) return len; - skb = dev_alloc_skb(len + NET_IP_ALIGN); + skb = netdev_alloc_skb(dev, len + NET_IP_ALIGN); if (!skb) { dev->stats.rx_dropped++; return -ENOMEM; diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 20b72ecb020a..27273ae1a6e6 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -3910,10 +3910,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) static int board_number; netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES); - if (netdev == NULL) { - dev_err(dev, "Could not allocate ethernet device\n"); + if (netdev == NULL) return -ENOMEM; - } SET_NETDEV_DEV(netdev, &pdev->dev); diff --git a/drivers/net/ethernet/natsemi/ibmlana.c b/drivers/net/ethernet/natsemi/ibmlana.c index 999407f7ebdf..3f94ddbf4dc0 100644 --- a/drivers/net/ethernet/natsemi/ibmlana.c +++ b/drivers/net/ethernet/natsemi/ibmlana.c @@ -589,7 +589,7 @@ static void irqrx_handler(struct net_device *dev) /* fetch buffer */ - skb = dev_alloc_skb(rda.length + 2); + skb = netdev_alloc_skb(dev, rda.length + 2); if (skb == NULL) dev->stats.rx_dropped++; else { diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c index ac7b16b6e7af..d38e48d4f430 100644 --- a/drivers/net/ethernet/natsemi/natsemi.c +++ b/drivers/net/ethernet/natsemi/natsemi.c @@ -1934,11 +1934,10 @@ static void refill_rx(struct net_device *dev) int entry = np->dirty_rx % RX_RING_SIZE; if (np->rx_skbuff[entry] == NULL) { unsigned int buflen = np->rx_buf_sz+NATSEMI_PADDING; - skb = dev_alloc_skb(buflen); + skb = netdev_alloc_skb(dev, buflen); np->rx_skbuff[entry] = skb; if (skb == NULL) break; /* Better luck next round. */ - skb->dev = dev; /* Mark as being used by this device. */ np->rx_dma[entry] = pci_map_single(np->pci_dev, skb->data, buflen, PCI_DMA_FROMDEVICE); np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]); @@ -2344,7 +2343,7 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do) /* Check if the packet is long enough to accept * without copying to a minimally-sized skbuff. */ if (pkt_len < rx_copybreak && - (skb = dev_alloc_skb(pkt_len + RX_OFFSET)) != NULL) { + (skb = netdev_alloc_skb(dev, pkt_len + RX_OFFSET)) != NULL) { /* 16 byte align the IP header */ skb_reserve(skb, RX_OFFSET); pci_dma_sync_single_for_cpu(np->pci_dev, diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index 26e25d7f5829..46795e403467 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -51,7 +51,7 @@ static int sonic_open(struct net_device *dev) printk("sonic_open: initializing sonic driver.\n"); for (i = 0; i < SONIC_NUM_RRS; i++) { - struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2); + struct sk_buff *skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2); if (skb == NULL) { while(i > 0) { /* free any that were allocated successfully */ i--; @@ -422,7 +422,7 @@ static void sonic_rx(struct net_device *dev) status = sonic_rda_get(dev, entry, SONIC_RD_STATUS); if (status & SONIC_RCR_PRX) { /* Malloc up new buffer. */ - new_skb = dev_alloc_skb(SONIC_RBSIZE + 2); + new_skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2); if (new_skb == NULL) { printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index 97f63e12d86e..44a6065794c3 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -2524,7 +2524,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, struct ring_info *ring, size = ring->mtu + ALIGN_SIZE + BUF0_LEN + 4; /* allocate skb */ - skb = dev_alloc_skb(size); + skb = netdev_alloc_skb(nic->dev, size); if (!skb) { DBG_PRINT(INFO_DBG, "%s: Could not allocate skb\n", ring->dev->name); @@ -6820,7 +6820,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, */ rxdp1->Buffer0_ptr = *temp0; } else { - *skb = dev_alloc_skb(size); + *skb = netdev_alloc_skb(dev, size); if (!(*skb)) { DBG_PRINT(INFO_DBG, "%s: Out of memory to allocate %s\n", @@ -6849,7 +6849,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, rxdp3->Buffer0_ptr = *temp0; rxdp3->Buffer1_ptr = *temp1; } else { - *skb = dev_alloc_skb(size); + *skb = netdev_alloc_skb(dev, size); if (!(*skb)) { DBG_PRINT(INFO_DBG, "%s: Out of memory to allocate %s\n", @@ -7760,7 +7760,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) else dev = alloc_etherdev(sizeof(struct s2io_nic)); if (dev == NULL) { - DBG_PRINT(ERR_DBG, "Device allocation failed\n"); pci_disable_device(pdev); pci_release_regions(pdev); return -ENODEV; diff --git a/drivers/net/ethernet/netx-eth.c b/drivers/net/ethernet/netx-eth.c index 8d288af16fc9..9d11ab7521bc 100644 --- a/drivers/net/ethernet/netx-eth.c +++ b/drivers/net/ethernet/netx-eth.c @@ -1,5 +1,5 @@ /* - * drivers/net/netx-eth.c + * drivers/net/ethernet/netx-eth.c * * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix * @@ -150,7 +150,7 @@ static void netx_eth_receive(struct net_device *ndev) seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT; len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT; - skb = dev_alloc_skb(len); + skb = netdev_alloc_skb(ndev, len); if (unlikely(skb == NULL)) { printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", ndev->name); @@ -383,7 +383,6 @@ static int netx_eth_drv_probe(struct platform_device *pdev) ndev = alloc_etherdev(sizeof (struct netx_eth_priv)); if (!ndev) { - printk("%s: could not allocate device.\n", CARDNAME); ret = -ENOMEM; goto exit; } diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c index b75a0497d58d..6893a65ae55f 100644 --- a/drivers/net/ethernet/nuvoton/w90p910_ether.c +++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c @@ -735,7 +735,7 @@ static void netdev_rx(struct net_device *dev) if (status & RXDS_RXGD) { data = ether->rdesc->recv_buf[ether->cur_rx]; - skb = dev_alloc_skb(length+2); + skb = netdev_alloc_skb(dev, length + 2); if (!skb) { dev_err(&pdev->dev, "get skb buffer error\n"); ether->stats.rx_dropped++; diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 4c4e7f458383..5eeb92f87380 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -1815,7 +1815,7 @@ static int nv_alloc_rx(struct net_device *dev) less_rx = np->last_rx.orig; while (np->put_rx.orig != less_rx) { - struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD); + struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz + NV_RX_ALLOC_PAD); if (skb) { np->put_rx_ctx->skb = skb; np->put_rx_ctx->dma = pci_map_single(np->pci_dev, @@ -1850,7 +1850,7 @@ static int nv_alloc_rx_optimized(struct net_device *dev) less_rx = np->last_rx.ex; while (np->put_rx.ex != less_rx) { - struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD); + struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz + NV_RX_ALLOC_PAD); if (skb) { np->put_rx_ctx->skb = skb; np->put_rx_ctx->dma = pci_map_single(np->pci_dev, @@ -4993,9 +4993,9 @@ static int nv_loopback_test(struct net_device *dev) /* setup packet for tx */ pkt_len = ETH_DATA_LEN; - tx_skb = dev_alloc_skb(pkt_len); + tx_skb = netdev_alloc_skb(dev, pkt_len); if (!tx_skb) { - netdev_err(dev, "dev_alloc_skb() failed during loopback test\n"); + netdev_err(dev, "netdev_alloc_skb() failed during loopback test\n"); ret = 0; goto out; } diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 3ead111111e1..bdbec7e04a4c 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -1587,10 +1587,8 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter, size = (int)sizeof(struct pch_gbe_buffer) * tx_ring->count; tx_ring->buffer_info = vzalloc(size); - if (!tx_ring->buffer_info) { - pr_err("Unable to allocate memory for the buffer information\n"); + if (!tx_ring->buffer_info) return -ENOMEM; - } tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc); @@ -1636,10 +1634,9 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter, size = (int)sizeof(struct pch_gbe_buffer) * rx_ring->count; rx_ring->buffer_info = vzalloc(size); - if (!rx_ring->buffer_info) { - pr_err("Unable to allocate memory for the receive descriptor ring\n"); + if (!rx_ring->buffer_info) return -ENOMEM; - } + rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc); rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, &rx_ring->dma, GFP_KERNEL); @@ -2422,8 +2419,6 @@ static int pch_gbe_probe(struct pci_dev *pdev, netdev = alloc_etherdev((int)sizeof(struct pch_gbe_adapter)); if (!netdev) { ret = -ENOMEM; - dev_err(&pdev->dev, - "ERR: Can't allocate and set up an Ethernet device\n"); goto err_release_pci; } SET_NETDEV_DEV(netdev, &pdev->dev); diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c index 3458df3780b8..0d29f5f4b8e4 100644 --- a/drivers/net/ethernet/packetengines/hamachi.c +++ b/drivers/net/ethernet/packetengines/hamachi.c @@ -1188,11 +1188,10 @@ static void hamachi_init_ring(struct net_device *dev) } /* Fill in the Rx buffers. Handle allocation failure gracefully. */ for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz + 2); + struct sk_buff *skb = netdev_alloc_skb(dev, hmp->rx_buf_sz + 2); hmp->rx_skbuff[i] = skb; if (skb == NULL) break; - skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* 16 byte align the IP header. */ hmp->rx_ring[i].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE)); @@ -1488,7 +1487,7 @@ static int hamachi_rx(struct net_device *dev) /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < rx_copybreak && - (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) { #ifdef RX_CHECKSUM printk(KERN_ERR "%s: rx_copybreak non-zero " "not good with RX_CHECKSUM\n", dev->name); @@ -1591,12 +1590,11 @@ static int hamachi_rx(struct net_device *dev) entry = hmp->dirty_rx % RX_RING_SIZE; desc = &(hmp->rx_ring[entry]); if (hmp->rx_skbuff[entry] == NULL) { - struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz + 2); + struct sk_buff *skb = netdev_alloc_skb(dev, hmp->rx_buf_sz + 2); hmp->rx_skbuff[entry] = skb; if (skb == NULL) break; /* Better luck next round. */ - skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ desc->addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE)); diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c index db44e9af03c3..7757b80ef924 100644 --- a/drivers/net/ethernet/packetengines/yellowfin.c +++ b/drivers/net/ethernet/packetengines/yellowfin.c @@ -397,10 +397,9 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev, if (i) return i; dev = alloc_etherdev(sizeof(*np)); - if (!dev) { - pr_err("cannot allocate ethernet device\n"); + if (!dev) return -ENOMEM; - } + SET_NETDEV_DEV(dev, &pdev->dev); np = netdev_priv(dev); @@ -744,11 +743,10 @@ static int yellowfin_init_ring(struct net_device *dev) } for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz + 2); + struct sk_buff *skb = netdev_alloc_skb(dev, yp->rx_buf_sz + 2); yp->rx_skbuff[i] = skb; if (skb == NULL) break; - skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* 16 byte align the IP header. */ yp->rx_ring[i].addr = cpu_to_le32(pci_map_single(yp->pci_dev, skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE)); @@ -1134,7 +1132,7 @@ static int yellowfin_rx(struct net_device *dev) PCI_DMA_FROMDEVICE); yp->rx_skbuff[entry] = NULL; } else { - skb = dev_alloc_skb(pkt_len + 2); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) break; skb_reserve(skb, 2); /* 16 byte align the IP header */ @@ -1157,11 +1155,10 @@ static int yellowfin_rx(struct net_device *dev) for (; yp->cur_rx - yp->dirty_rx > 0; yp->dirty_rx++) { entry = yp->dirty_rx % RX_RING_SIZE; if (yp->rx_skbuff[entry] == NULL) { - struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz + 2); + struct sk_buff *skb = netdev_alloc_skb(dev, yp->rx_buf_sz + 2); if (skb == NULL) break; /* Better luck next round. */ yp->rx_skbuff[entry] = skb; - skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ yp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(yp->pci_dev, skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE)); diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index 49b549ff2c78..667498ea4603 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -643,7 +643,7 @@ static void pasemi_mac_replenish_rx_ring(const struct net_device *dev, /* Entry in use? */ WARN_ON(*buff); - skb = dev_alloc_skb(mac->bufsz); + skb = netdev_alloc_skb(dev, mac->bufsz); skb_reserve(skb, LOCAL_SKB_ALIGN); if (unlikely(!skb)) @@ -1740,8 +1740,6 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev = alloc_etherdev(sizeof(struct pasemi_mac)); if (dev == NULL) { - dev_err(&pdev->dev, - "pasemi_mac: Could not allocate ethernet device.\n"); err = -ENOMEM; goto out_disable_device; } diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h index a876dffd7101..2eeac32f7fdd 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h @@ -53,8 +53,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 77 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.77" +#define _NETXEN_NIC_LINUX_SUBVERSION 78 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.78" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) #define _major(v) (((v) >> 24) & 0xff) @@ -686,6 +686,18 @@ struct netxen_recv_context { dma_addr_t phys_addr; }; +struct _cdrp_cmd { + u32 cmd; + u32 arg1; + u32 arg2; + u32 arg3; +}; + +struct netxen_cmd_args { + struct _cdrp_cmd req; + struct _cdrp_cmd rsp; +}; + /* New HW context creation */ #define NX_OS_CRB_RETRY_COUNT 4000 @@ -1142,6 +1154,7 @@ typedef struct { #define NETXEN_NIC_LRO_DISABLED 0x00 #define NETXEN_NIC_BRIDGE_ENABLED 0X10 #define NETXEN_NIC_DIAG_ENABLED 0x20 +#define NETXEN_FW_RESET_OWNER 0x40 #define NETXEN_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED)) @@ -1159,6 +1172,419 @@ typedef struct { #define __NX_DEV_UP 1 #define __NX_RESETTING 2 +/* Mini Coredump FW supported version */ +#define NX_MD_SUPPORT_MAJOR 4 +#define NX_MD_SUPPORT_MINOR 0 +#define NX_MD_SUPPORT_SUBVERSION 579 + +#define LSW(x) ((uint16_t)(x)) +#define LSD(x) ((uint32_t)((uint64_t)(x))) +#define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16)) + +/* Mini Coredump mask level */ +#define NX_DUMP_MASK_MIN 0x03 +#define NX_DUMP_MASK_DEF 0x1f +#define NX_DUMP_MASK_MAX 0xff + +/* Mini Coredump CDRP commands */ +#define NX_CDRP_CMD_TEMP_SIZE 0x0000002f +#define NX_CDRP_CMD_GET_TEMP_HDR 0x00000030 + + +#define NX_DUMP_STATE_ARRAY_LEN 16 +#define NX_DUMP_CAP_SIZE_ARRAY_LEN 8 + +/* Mini Coredump sysfs entries flags*/ +#define NX_FORCE_FW_DUMP_KEY 0xdeadfeed +#define NX_ENABLE_FW_DUMP 0xaddfeed +#define NX_DISABLE_FW_DUMP 0xbadfeed +#define NX_FORCE_FW_RESET 0xdeaddead + + +/* Flash read/write address */ +#define NX_FW_DUMP_REG1 0x00130060 +#define NX_FW_DUMP_REG2 0x001e0000 +#define NX_FLASH_SEM2_LK 0x0013C010 +#define NX_FLASH_SEM2_ULK 0x0013C014 +#define NX_FLASH_LOCK_ID 0x001B2100 +#define FLASH_ROM_WINDOW 0x42110030 +#define FLASH_ROM_DATA 0x42150000 + +/* Mini Coredump register read/write routine */ +#define NX_RD_DUMP_REG(addr, bar0, data) do { \ + writel((addr & 0xFFFF0000), (void __iomem *) (bar0 + \ + NX_FW_DUMP_REG1)); \ + readl((void __iomem *) (bar0 + NX_FW_DUMP_REG1)); \ + *data = readl((void __iomem *) (bar0 + NX_FW_DUMP_REG2 + \ + LSW(addr))); \ +} while (0) + +#define NX_WR_DUMP_REG(addr, bar0, data) do { \ + writel((addr & 0xFFFF0000), (void __iomem *) (bar0 + \ + NX_FW_DUMP_REG1)); \ + readl((void __iomem *) (bar0 + NX_FW_DUMP_REG1)); \ + writel(data, (void __iomem *) (bar0 + NX_FW_DUMP_REG2 + LSW(addr)));\ + readl((void __iomem *) (bar0 + NX_FW_DUMP_REG2 + LSW(addr))); \ +} while (0) + + +/* +Entry Type Defines +*/ + +#define RDNOP 0 +#define RDCRB 1 +#define RDMUX 2 +#define QUEUE 3 +#define BOARD 4 +#define RDSRE 5 +#define RDOCM 6 +#define PREGS 7 +#define L1DTG 8 +#define L1ITG 9 +#define CACHE 10 + +#define L1DAT 11 +#define L1INS 12 +#define RDSTK 13 +#define RDCON 14 + +#define L2DTG 21 +#define L2ITG 22 +#define L2DAT 23 +#define L2INS 24 +#define RDOC3 25 + +#define MEMBK 32 + +#define RDROM 71 +#define RDMEM 72 +#define RDMN 73 + +#define INFOR 81 +#define CNTRL 98 + +#define TLHDR 99 +#define RDEND 255 + +#define PRIMQ 103 +#define SQG2Q 104 +#define SQG3Q 105 + +/* +* Opcodes for Control Entries. +* These Flags are bit fields. +*/ +#define NX_DUMP_WCRB 0x01 +#define NX_DUMP_RWCRB 0x02 +#define NX_DUMP_ANDCRB 0x04 +#define NX_DUMP_ORCRB 0x08 +#define NX_DUMP_POLLCRB 0x10 +#define NX_DUMP_RD_SAVE 0x20 +#define NX_DUMP_WRT_SAVED 0x40 +#define NX_DUMP_MOD_SAVE_ST 0x80 + +/* Driver Flags */ +#define NX_DUMP_SKIP 0x80 /* driver skipped this entry */ +#define NX_DUMP_SIZE_ERR 0x40 /*entry size vs capture size mismatch*/ + +#define NX_PCI_READ_32(ADDR) readl((ADDR)) +#define NX_PCI_WRITE_32(DATA, ADDR) writel(DATA, (ADDR)) + + + +struct netxen_minidump { + u32 pos; /* position in the dump buffer */ + u8 fw_supports_md; /* FW supports Mini cordump */ + u8 has_valid_dump; /* indicates valid dump */ + u8 md_capture_mask; /* driver capture mask */ + u8 md_enabled; /* Turn Mini Coredump on/off */ + u32 md_dump_size; /* Total FW Mini Coredump size */ + u32 md_capture_size; /* FW dump capture size */ + u32 md_template_size; /* FW template size */ + u32 md_template_ver; /* FW template version */ + u64 md_timestamp; /* FW Mini dump timestamp */ + void *md_template; /* FW template will be stored */ + void *md_capture_buff; /* FW dump will be stored */ +}; + + + +struct netxen_minidump_template_hdr { + u32 entry_type; + u32 first_entry_offset; + u32 size_of_template; + u32 capture_mask; + u32 num_of_entries; + u32 version; + u32 driver_timestamp; + u32 checksum; + u32 driver_capture_mask; + u32 driver_info_word2; + u32 driver_info_word3; + u32 driver_info_word4; + u32 saved_state_array[NX_DUMP_STATE_ARRAY_LEN]; + u32 capture_size_array[NX_DUMP_CAP_SIZE_ARRAY_LEN]; + u32 rsvd[0]; +}; + +/* Common Entry Header: Common to All Entry Types */ +/* + * Driver Code is for driver to write some info about the entry. + * Currently not used. + */ + +struct netxen_common_entry_hdr { + u32 entry_type; + u32 entry_size; + u32 entry_capture_size; + union { + struct { + u8 entry_capture_mask; + u8 entry_code; + u8 driver_code; + u8 driver_flags; + }; + u32 entry_ctrl_word; + }; +}; + + +/* Generic Entry Including Header */ +struct netxen_minidump_entry { + struct netxen_common_entry_hdr hdr; + u32 entry_data00; + u32 entry_data01; + u32 entry_data02; + u32 entry_data03; + u32 entry_data04; + u32 entry_data05; + u32 entry_data06; + u32 entry_data07; +}; + +/* Read ROM Header */ +struct netxen_minidump_entry_rdrom { + struct netxen_common_entry_hdr h; + union { + struct { + u32 select_addr_reg; + }; + u32 rsvd_0; + }; + union { + struct { + u8 addr_stride; + u8 addr_cnt; + u16 data_size; + }; + u32 rsvd_1; + }; + union { + struct { + u32 op_count; + }; + u32 rsvd_2; + }; + union { + struct { + u32 read_addr_reg; + }; + u32 rsvd_3; + }; + union { + struct { + u32 write_mask; + }; + u32 rsvd_4; + }; + union { + struct { + u32 read_mask; + }; + u32 rsvd_5; + }; + u32 read_addr; + u32 read_data_size; +}; + + +/* Read CRB and Control Entry Header */ +struct netxen_minidump_entry_crb { + struct netxen_common_entry_hdr h; + u32 addr; + union { + struct { + u8 addr_stride; + u8 state_index_a; + u16 poll_timeout; + }; + u32 addr_cntrl; + }; + u32 data_size; + u32 op_count; + union { + struct { + u8 opcode; + u8 state_index_v; + u8 shl; + u8 shr; + }; + u32 control_value; + }; + u32 value_1; + u32 value_2; + u32 value_3; +}; + +/* Read Memory and MN Header */ +struct netxen_minidump_entry_rdmem { + struct netxen_common_entry_hdr h; + union { + struct { + u32 select_addr_reg; + }; + u32 rsvd_0; + }; + union { + struct { + u8 addr_stride; + u8 addr_cnt; + u16 data_size; + }; + u32 rsvd_1; + }; + union { + struct { + u32 op_count; + }; + u32 rsvd_2; + }; + union { + struct { + u32 read_addr_reg; + }; + u32 rsvd_3; + }; + union { + struct { + u32 cntrl_addr_reg; + }; + u32 rsvd_4; + }; + union { + struct { + u8 wr_byte0; + u8 wr_byte1; + u8 poll_mask; + u8 poll_cnt; + }; + u32 rsvd_5; + }; + u32 read_addr; + u32 read_data_size; +}; + +/* Read Cache L1 and L2 Header */ +struct netxen_minidump_entry_cache { + struct netxen_common_entry_hdr h; + u32 tag_reg_addr; + union { + struct { + u16 tag_value_stride; + u16 init_tag_value; + }; + u32 select_addr_cntrl; + }; + u32 data_size; + u32 op_count; + u32 control_addr; + union { + struct { + u16 write_value; + u8 poll_mask; + u8 poll_wait; + }; + u32 control_value; + }; + u32 read_addr; + union { + struct { + u8 read_addr_stride; + u8 read_addr_cnt; + u16 rsvd_1; + }; + u32 read_addr_cntrl; + }; +}; + +/* Read OCM Header */ +struct netxen_minidump_entry_rdocm { + struct netxen_common_entry_hdr h; + u32 rsvd_0; + union { + struct { + u32 rsvd_1; + }; + u32 select_addr_cntrl; + }; + u32 data_size; + u32 op_count; + u32 rsvd_2; + u32 rsvd_3; + u32 read_addr; + union { + struct { + u32 read_addr_stride; + }; + u32 read_addr_cntrl; + }; +}; + +/* Read MUX Header */ +struct netxen_minidump_entry_mux { + struct netxen_common_entry_hdr h; + u32 select_addr; + union { + struct { + u32 rsvd_0; + }; + u32 select_addr_cntrl; + }; + u32 data_size; + u32 op_count; + u32 select_value; + u32 select_value_stride; + u32 read_addr; + u32 rsvd_1; +}; + +/* Read Queue Header */ +struct netxen_minidump_entry_queue { + struct netxen_common_entry_hdr h; + u32 select_addr; + union { + struct { + u16 queue_id_stride; + u16 rsvd_0; + }; + u32 select_addr_cntrl; + }; + u32 data_size; + u32 op_count; + u32 rsvd_1; + u32 rsvd_2; + u32 read_addr; + union { + struct { + u8 read_addr_stride; + u8 read_addr_cnt; + u16 rsvd_3; + }; + u32 read_addr_cntrl; + }; +}; + struct netxen_dummy_dma { void *addr; dma_addr_t phys_addr; @@ -1263,6 +1689,8 @@ struct netxen_adapter { __le32 file_prd_off; /*File fw product offset*/ u32 fw_version; const struct firmware *fw; + struct netxen_minidump mdump; /* mdump ptr */ + int fw_mdump_rdy; /* for mdump ready */ }; int nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val); @@ -1365,13 +1793,16 @@ int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable); int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable); int netxen_send_lro_cleanup(struct netxen_adapter *adapter); - +int netxen_setup_minidump(struct netxen_adapter *adapter); +void netxen_dump_fw(struct netxen_adapter *adapter); void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, struct nx_host_tx_ring *tx_ring); /* Functions from netxen_nic_main.c */ int netxen_nic_reset_context(struct netxen_adapter *); +int nx_dev_request_reset(struct netxen_adapter *adapter); + /* * NetXen Board information */ diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c index a925392abd6f..f3c0057a802b 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c @@ -48,28 +48,27 @@ netxen_poll_rsp(struct netxen_adapter *adapter) } static u32 -netxen_issue_cmd(struct netxen_adapter *adapter, - u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd) +netxen_issue_cmd(struct netxen_adapter *adapter, struct netxen_cmd_args *cmd) { u32 rsp; u32 signature = 0; u32 rcode = NX_RCODE_SUCCESS; - signature = NX_CDRP_SIGNATURE_MAKE(pci_fn, version); - + signature = NX_CDRP_SIGNATURE_MAKE(adapter->ahw.pci_func, + NXHAL_VERSION); /* Acquire semaphore before accessing CRB */ if (netxen_api_lock(adapter)) return NX_RCODE_TIMEOUT; NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature); - NXWR32(adapter, NX_ARG1_CRB_OFFSET, arg1); + NXWR32(adapter, NX_ARG1_CRB_OFFSET, cmd->req.arg1); - NXWR32(adapter, NX_ARG2_CRB_OFFSET, arg2); + NXWR32(adapter, NX_ARG2_CRB_OFFSET, cmd->req.arg2); - NXWR32(adapter, NX_ARG3_CRB_OFFSET, arg3); + NXWR32(adapter, NX_ARG3_CRB_OFFSET, cmd->req.arg3); - NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd)); + NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd->req.cmd)); rsp = netxen_poll_rsp(adapter); @@ -83,28 +82,179 @@ netxen_issue_cmd(struct netxen_adapter *adapter, printk(KERN_ERR "%s: failed card response code:0x%x\n", netxen_nic_driver_name, rcode); + } else if (rsp == NX_CDRP_RSP_OK) { + cmd->rsp.cmd = NX_RCODE_SUCCESS; + if (cmd->rsp.arg2) + cmd->rsp.arg2 = NXRD32(adapter, NX_ARG2_CRB_OFFSET); + if (cmd->rsp.arg3) + cmd->rsp.arg3 = NXRD32(adapter, NX_ARG3_CRB_OFFSET); } + if (cmd->rsp.arg1) + cmd->rsp.arg1 = NXRD32(adapter, NX_ARG1_CRB_OFFSET); /* Release semaphore */ netxen_api_unlock(adapter); return rcode; } +static int +netxen_get_minidump_template_size(struct netxen_adapter *adapter) +{ + struct netxen_cmd_args cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.req.cmd = NX_CDRP_CMD_TEMP_SIZE; + memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); + netxen_issue_cmd(adapter, &cmd); + if (cmd.rsp.cmd != NX_RCODE_SUCCESS) { + dev_info(&adapter->pdev->dev, + "Can't get template size %d\n", cmd.rsp.cmd); + return -EIO; + } + adapter->mdump.md_template_size = cmd.rsp.arg2; + adapter->mdump.md_template_ver = cmd.rsp.arg3; + return 0; +} + +static int +netxen_get_minidump_template(struct netxen_adapter *adapter) +{ + dma_addr_t md_template_addr; + void *addr; + u32 size; + struct netxen_cmd_args cmd; + size = adapter->mdump.md_template_size; + + if (size == 0) { + dev_err(&adapter->pdev->dev, "Can not capture Minidump " + "template. Invalid template size.\n"); + return NX_RCODE_INVALID_ARGS; + } + + addr = pci_alloc_consistent(adapter->pdev, size, &md_template_addr); + + if (!addr) { + dev_err(&adapter->pdev->dev, "Unable to allocate dmable memory for template.\n"); + return -ENOMEM; + } + + memset(addr, 0, size); + memset(&cmd, 0, sizeof(cmd)); + memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); + cmd.req.cmd = NX_CDRP_CMD_GET_TEMP_HDR; + cmd.req.arg1 = LSD(md_template_addr); + cmd.req.arg2 = MSD(md_template_addr); + cmd.req.arg3 |= size; + netxen_issue_cmd(adapter, &cmd); + + if ((cmd.rsp.cmd == NX_RCODE_SUCCESS) && (size == cmd.rsp.arg2)) { + memcpy(adapter->mdump.md_template, addr, size); + } else { + dev_err(&adapter->pdev->dev, "Failed to get minidump template, " + "err_code : %d, requested_size : %d, actual_size : %d\n ", + cmd.rsp.cmd, size, cmd.rsp.arg2); + } + pci_free_consistent(adapter->pdev, size, addr, md_template_addr); + return 0; +} + +static u32 +netxen_check_template_checksum(struct netxen_adapter *adapter) +{ + u64 sum = 0 ; + u32 *buff = adapter->mdump.md_template; + int count = adapter->mdump.md_template_size/sizeof(uint32_t) ; + + while (count-- > 0) + sum += *buff++ ; + while (sum >> 32) + sum = (sum & 0xFFFFFFFF) + (sum >> 32) ; + + return ~sum; +} + +int +netxen_setup_minidump(struct netxen_adapter *adapter) +{ + int err = 0, i; + u32 *template, *tmp_buf; + struct netxen_minidump_template_hdr *hdr; + err = netxen_get_minidump_template_size(adapter); + if (err) { + adapter->mdump.fw_supports_md = 0; + if ((err == NX_RCODE_CMD_INVALID) || + (err == NX_RCODE_CMD_NOT_IMPL)) { + dev_info(&adapter->pdev->dev, + "Flashed firmware version does not support minidump, " + "minimum version required is [ %u.%u.%u ].\n ", + NX_MD_SUPPORT_MAJOR, NX_MD_SUPPORT_MINOR, + NX_MD_SUPPORT_SUBVERSION); + } + return err; + } + + if (!adapter->mdump.md_template_size) { + dev_err(&adapter->pdev->dev, "Error : Invalid template size " + ",should be non-zero.\n"); + return -EIO; + } + adapter->mdump.md_template = + kmalloc(adapter->mdump.md_template_size, GFP_KERNEL); + + if (!adapter->mdump.md_template) { + dev_err(&adapter->pdev->dev, "Unable to allocate memory " + "for minidump template.\n"); + return -ENOMEM; + } + + err = netxen_get_minidump_template(adapter); + if (err) { + if (err == NX_RCODE_CMD_NOT_IMPL) + adapter->mdump.fw_supports_md = 0; + goto free_template; + } + + if (netxen_check_template_checksum(adapter)) { + dev_err(&adapter->pdev->dev, "Minidump template checksum Error\n"); + err = -EIO; + goto free_template; + } + + adapter->mdump.md_capture_mask = NX_DUMP_MASK_DEF; + tmp_buf = (u32 *) adapter->mdump.md_template; + template = (u32 *) adapter->mdump.md_template; + for (i = 0; i < adapter->mdump.md_template_size/sizeof(u32); i++) + *template++ = __le32_to_cpu(*tmp_buf++); + hdr = (struct netxen_minidump_template_hdr *) + adapter->mdump.md_template; + adapter->mdump.md_capture_buff = NULL; + adapter->mdump.fw_supports_md = 1; + adapter->mdump.md_enabled = 1; + + return err; + +free_template: + kfree(adapter->mdump.md_template); + adapter->mdump.md_template = NULL; + return err; +} + + int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) { u32 rcode = NX_RCODE_SUCCESS; struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + struct netxen_cmd_args cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.req.cmd = NX_CDRP_CMD_SET_MTU; + cmd.req.arg1 = recv_ctx->context_id; + cmd.req.arg2 = mtu; + cmd.req.arg3 = 0; if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE) - rcode = netxen_issue_cmd(adapter, - adapter->ahw.pci_func, - NXHAL_VERSION, - recv_ctx->context_id, - mtu, - 0, - NX_CDRP_CMD_SET_MTU); + netxen_issue_cmd(adapter, &cmd); if (rcode != NX_RCODE_SUCCESS) return -EIO; @@ -116,15 +266,14 @@ int nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter, u32 speed, u32 duplex, u32 autoneg) { - - return netxen_issue_cmd(adapter, - adapter->ahw.pci_func, - NXHAL_VERSION, - speed, - duplex, - autoneg, - NX_CDRP_CMD_CONFIG_GBE_PORT); - + struct netxen_cmd_args cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.req.cmd = NX_CDRP_CMD_CONFIG_GBE_PORT; + cmd.req.arg1 = speed; + cmd.req.arg2 = duplex; + cmd.req.arg3 = autoneg; + return netxen_issue_cmd(adapter, &cmd); } static int @@ -139,6 +288,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) nx_cardrsp_sds_ring_t *prsp_sds; struct nx_host_rds_ring *rds_ring; struct nx_host_sds_ring *sds_ring; + struct netxen_cmd_args cmd; dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; u64 phys_addr; @@ -218,13 +368,12 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) } phys_addr = hostrq_phys_addr; - err = netxen_issue_cmd(adapter, - adapter->ahw.pci_func, - NXHAL_VERSION, - (u32)(phys_addr >> 32), - (u32)(phys_addr & 0xffffffff), - rq_size, - NX_CDRP_CMD_CREATE_RX_CTX); + memset(&cmd, 0, sizeof(cmd)); + cmd.req.arg1 = (u32)(phys_addr >> 32); + cmd.req.arg2 = (u32)(phys_addr & 0xffffffff); + cmd.req.arg3 = rq_size; + cmd.req.cmd = NX_CDRP_CMD_CREATE_RX_CTX; + err = netxen_issue_cmd(adapter, &cmd); if (err) { printk(KERN_WARNING "Failed to create rx ctx in firmware%d\n", err); @@ -273,15 +422,15 @@ static void nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + struct netxen_cmd_args cmd; - if (netxen_issue_cmd(adapter, - adapter->ahw.pci_func, - NXHAL_VERSION, - recv_ctx->context_id, - NX_DESTROY_CTX_RESET, - 0, - NX_CDRP_CMD_DESTROY_RX_CTX)) { + memset(&cmd, 0, sizeof(cmd)); + cmd.req.arg1 = recv_ctx->context_id; + cmd.req.arg2 = NX_DESTROY_CTX_RESET; + cmd.req.arg3 = 0; + cmd.req.cmd = NX_CDRP_CMD_DESTROY_RX_CTX; + if (netxen_issue_cmd(adapter, &cmd)) { printk(KERN_WARNING "%s: Failed to destroy rx ctx in firmware\n", netxen_nic_driver_name); @@ -302,6 +451,7 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) dma_addr_t rq_phys_addr, rsp_phys_addr; struct nx_host_tx_ring *tx_ring = adapter->tx_ring; struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + struct netxen_cmd_args cmd; rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t); rq_addr = pci_alloc_consistent(adapter->pdev, @@ -345,13 +495,12 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); phys_addr = rq_phys_addr; - err = netxen_issue_cmd(adapter, - adapter->ahw.pci_func, - NXHAL_VERSION, - (u32)(phys_addr >> 32), - ((u32)phys_addr & 0xffffffff), - rq_size, - NX_CDRP_CMD_CREATE_TX_CTX); + memset(&cmd, 0, sizeof(cmd)); + cmd.req.arg1 = (u32)(phys_addr >> 32); + cmd.req.arg2 = ((u32)phys_addr & 0xffffffff); + cmd.req.arg3 = rq_size; + cmd.req.cmd = NX_CDRP_CMD_CREATE_TX_CTX; + err = netxen_issue_cmd(adapter, &cmd); if (err == NX_RCODE_SUCCESS) { temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); @@ -380,14 +529,14 @@ out_free_rq: static void nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter) { - if (netxen_issue_cmd(adapter, - adapter->ahw.pci_func, - NXHAL_VERSION, - adapter->tx_context_id, - NX_DESTROY_CTX_RESET, - 0, - NX_CDRP_CMD_DESTROY_TX_CTX)) { - + struct netxen_cmd_args cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.req.arg1 = adapter->tx_context_id; + cmd.req.arg2 = NX_DESTROY_CTX_RESET; + cmd.req.arg3 = 0; + cmd.req.cmd = NX_CDRP_CMD_DESTROY_TX_CTX; + if (netxen_issue_cmd(adapter, &cmd)) { printk(KERN_WARNING "%s: Failed to destroy tx ctx in firmware\n", netxen_nic_driver_name); @@ -398,34 +547,37 @@ int nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val) { u32 rcode; - - rcode = netxen_issue_cmd(adapter, - adapter->ahw.pci_func, - NXHAL_VERSION, - reg, - 0, - 0, - NX_CDRP_CMD_READ_PHY); - + struct netxen_cmd_args cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.req.arg1 = reg; + cmd.req.arg2 = 0; + cmd.req.arg3 = 0; + cmd.req.cmd = NX_CDRP_CMD_READ_PHY; + cmd.rsp.arg1 = 1; + rcode = netxen_issue_cmd(adapter, &cmd); if (rcode != NX_RCODE_SUCCESS) return -EIO; - return NXRD32(adapter, NX_ARG1_CRB_OFFSET); + if (val == NULL) + return -EIO; + + *val = cmd.rsp.arg1; + return 0; } int nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val) { u32 rcode; - - rcode = netxen_issue_cmd(adapter, - adapter->ahw.pci_func, - NXHAL_VERSION, - reg, - val, - 0, - NX_CDRP_CMD_WRITE_PHY); - + struct netxen_cmd_args cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.req.arg1 = reg; + cmd.req.arg2 = val; + cmd.req.arg3 = 0; + cmd.req.cmd = NX_CDRP_CMD_WRITE_PHY; + rcode = netxen_issue_cmd(adapter, &cmd); if (rcode != NX_RCODE_SUCCESS) return -EIO; diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c index 8a371985319f..8c39299331a2 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c @@ -248,6 +248,11 @@ skip: } } + if (!netif_running(dev) || !adapter->ahw.linkup) { + ecmd->duplex = DUPLEX_UNKNOWN; + ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); + } + return 0; } @@ -812,6 +817,107 @@ static int netxen_get_intr_coalesce(struct net_device *netdev, return 0; } +static int +netxen_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) +{ + struct netxen_adapter *adapter = netdev_priv(netdev); + struct netxen_minidump *mdump = &adapter->mdump; + if (adapter->fw_mdump_rdy) + dump->len = mdump->md_dump_size; + else + dump->len = 0; + dump->flag = mdump->md_capture_mask; + dump->version = adapter->fw_version; + return 0; +} + +static int +netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val) +{ + int ret = 0; + struct netxen_adapter *adapter = netdev_priv(netdev); + struct netxen_minidump *mdump = &adapter->mdump; + + switch (val->flag) { + case NX_FORCE_FW_DUMP_KEY: + if (!mdump->md_enabled) + mdump->md_enabled = 1; + if (adapter->fw_mdump_rdy) { + netdev_info(netdev, "Previous dump not cleared, not forcing dump\n"); + return ret; + } + netdev_info(netdev, "Forcing a fw dump\n"); + nx_dev_request_reset(adapter); + break; + case NX_DISABLE_FW_DUMP: + if (mdump->md_enabled) { + netdev_info(netdev, "Disabling FW Dump\n"); + mdump->md_enabled = 0; + } + break; + case NX_ENABLE_FW_DUMP: + if (!mdump->md_enabled) { + netdev_info(netdev, "Enabling FW dump\n"); + mdump->md_enabled = 1; + } + break; + case NX_FORCE_FW_RESET: + netdev_info(netdev, "Forcing FW reset\n"); + nx_dev_request_reset(adapter); + adapter->flags &= ~NETXEN_FW_RESET_OWNER; + break; + default: + if (val->flag <= NX_DUMP_MASK_MAX && + val->flag >= NX_DUMP_MASK_MIN) { + mdump->md_capture_mask = val->flag & 0xff; + netdev_info(netdev, "Driver mask changed to: 0x%x\n", + mdump->md_capture_mask); + break; + } + netdev_info(netdev, + "Invalid dump level: 0x%x\n", val->flag); + return -EINVAL; + } + + return ret; +} + +static int +netxen_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, + void *buffer) +{ + int i, copy_sz; + u32 *hdr_ptr, *data; + struct netxen_adapter *adapter = netdev_priv(netdev); + struct netxen_minidump *mdump = &adapter->mdump; + + + if (!adapter->fw_mdump_rdy) { + netdev_info(netdev, "Dump not available\n"); + return -EINVAL; + } + /* Copy template header first */ + copy_sz = mdump->md_template_size; + hdr_ptr = (u32 *) mdump->md_template; + data = buffer; + for (i = 0; i < copy_sz/sizeof(u32); i++) + *data++ = cpu_to_le32(*hdr_ptr++); + + /* Copy captured dump data */ + memcpy(buffer + copy_sz, + mdump->md_capture_buff + mdump->md_template_size, + mdump->md_capture_size); + dump->len = copy_sz + mdump->md_capture_size; + dump->flag = mdump->md_capture_mask; + + /* Free dump area once data has been captured */ + vfree(mdump->md_capture_buff); + mdump->md_capture_buff = NULL; + adapter->fw_mdump_rdy = 0; + netdev_info(netdev, "extracted the fw dump Successfully\n"); + return 0; +} + const struct ethtool_ops netxen_nic_ethtool_ops = { .get_settings = netxen_nic_get_settings, .set_settings = netxen_nic_set_settings, @@ -833,4 +939,7 @@ const struct ethtool_ops netxen_nic_ethtool_ops = { .get_sset_count = netxen_get_sset_count, .get_coalesce = netxen_get_intr_coalesce, .set_coalesce = netxen_set_intr_coalesce, + .get_dump_flag = netxen_get_dump_flag, + .get_dump_data = netxen_get_dump_data, + .set_dump = netxen_set_dump, }; diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h index dc1967c1f312..b1a897cd9a8d 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h @@ -969,6 +969,7 @@ enum { #define NX_RCODE_FATAL_ERROR 0x80000000 #define NX_FWERROR_PEGNUM(code) ((code) & 0xff) #define NX_FWERROR_CODE(code) ((code >> 8) & 0xfffff) +#define NX_FWERROR_PEGSTAT1(code) ((code >> 8) & 0x1fffff) #define FW_POLL_DELAY (2 * HZ) #define FW_FAIL_THRESH 3 diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c index 3f89e57cae50..6f37470750f3 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c @@ -46,7 +46,6 @@ static void netxen_nic_io_write_128M(struct netxen_adapter *adapter, void __iomem *addr, u32 data); static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, void __iomem *addr); - #ifndef readq static inline u64 readq(void __iomem *addr) { @@ -1974,3 +1973,631 @@ netxen_nic_wol_supported(struct netxen_adapter *adapter) return 0; } + +static u32 netxen_md_cntrl(struct netxen_adapter *adapter, + struct netxen_minidump_template_hdr *template_hdr, + struct netxen_minidump_entry_crb *crtEntry) +{ + int loop_cnt, i, rv = 0, timeout_flag; + u32 op_count, stride; + u32 opcode, read_value, addr; + unsigned long timeout, timeout_jiffies; + addr = crtEntry->addr; + op_count = crtEntry->op_count; + stride = crtEntry->addr_stride; + + for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) { + for (i = 0; i < sizeof(crtEntry->opcode) * 8; i++) { + opcode = (crtEntry->opcode & (0x1 << i)); + if (opcode) { + switch (opcode) { + case NX_DUMP_WCRB: + NX_WR_DUMP_REG(addr, + adapter->ahw.pci_base0, + crtEntry->value_1); + break; + case NX_DUMP_RWCRB: + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + NX_WR_DUMP_REG(addr, + adapter->ahw.pci_base0, + read_value); + break; + case NX_DUMP_ANDCRB: + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + read_value &= crtEntry->value_2; + NX_WR_DUMP_REG(addr, + adapter->ahw.pci_base0, + read_value); + break; + case NX_DUMP_ORCRB: + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + read_value |= crtEntry->value_3; + NX_WR_DUMP_REG(addr, + adapter->ahw.pci_base0, + read_value); + break; + case NX_DUMP_POLLCRB: + timeout = crtEntry->poll_timeout; + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + timeout_jiffies = + msecs_to_jiffies(timeout) + jiffies; + for (timeout_flag = 0; + !timeout_flag + && ((read_value & crtEntry->value_2) + != crtEntry->value_1);) { + if (time_after(jiffies, + timeout_jiffies)) + timeout_flag = 1; + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + } + + if (timeout_flag) { + dev_err(&adapter->pdev->dev, "%s : " + "Timeout in poll_crb control operation.\n" + , __func__); + return -1; + } + break; + case NX_DUMP_RD_SAVE: + /* Decide which address to use */ + if (crtEntry->state_index_a) + addr = + template_hdr->saved_state_array + [crtEntry->state_index_a]; + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + template_hdr->saved_state_array + [crtEntry->state_index_v] + = read_value; + break; + case NX_DUMP_WRT_SAVED: + /* Decide which value to use */ + if (crtEntry->state_index_v) + read_value = + template_hdr->saved_state_array + [crtEntry->state_index_v]; + else + read_value = crtEntry->value_1; + + /* Decide which address to use */ + if (crtEntry->state_index_a) + addr = + template_hdr->saved_state_array + [crtEntry->state_index_a]; + + NX_WR_DUMP_REG(addr, + adapter->ahw.pci_base0, + read_value); + break; + case NX_DUMP_MOD_SAVE_ST: + read_value = + template_hdr->saved_state_array + [crtEntry->state_index_v]; + read_value <<= crtEntry->shl; + read_value >>= crtEntry->shr; + if (crtEntry->value_2) + read_value &= + crtEntry->value_2; + read_value |= crtEntry->value_3; + read_value += crtEntry->value_1; + /* Write value back to state area.*/ + template_hdr->saved_state_array + [crtEntry->state_index_v] + = read_value; + break; + default: + rv = 1; + break; + } + } + } + addr = addr + stride; + } + return rv; +} + +/* Read memory or MN */ +static u32 +netxen_md_rdmem(struct netxen_adapter *adapter, + struct netxen_minidump_entry_rdmem + *memEntry, u64 *data_buff) +{ + u64 addr, value = 0; + int i = 0, loop_cnt; + + addr = (u64)memEntry->read_addr; + loop_cnt = memEntry->read_data_size; /* This is size in bytes */ + loop_cnt /= sizeof(value); + + for (i = 0; i < loop_cnt; i++) { + if (netxen_nic_pci_mem_read_2M(adapter, addr, &value)) + goto out; + *data_buff++ = value; + addr += sizeof(value); + } +out: + return i * sizeof(value); +} + +/* Read CRB operation */ +static u32 netxen_md_rd_crb(struct netxen_adapter *adapter, + struct netxen_minidump_entry_crb + *crbEntry, u32 *data_buff) +{ + int loop_cnt; + u32 op_count, addr, stride, value; + + addr = crbEntry->addr; + op_count = crbEntry->op_count; + stride = crbEntry->addr_stride; + + for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) { + NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0, &value); + *data_buff++ = addr; + *data_buff++ = value; + addr = addr + stride; + } + return loop_cnt * (2 * sizeof(u32)); +} + +/* Read ROM */ +static u32 +netxen_md_rdrom(struct netxen_adapter *adapter, + struct netxen_minidump_entry_rdrom + *romEntry, u32 *data_buff) +{ + int i, count = 0; + u32 size, lck_val; + u32 val; + u32 fl_addr, waddr, raddr; + fl_addr = romEntry->read_addr; + size = romEntry->read_data_size/4; +lock_try: + lck_val = readl((void __iomem *)(adapter->ahw.pci_base0 + + NX_FLASH_SEM2_LK)); + if (!lck_val && count < MAX_CTL_CHECK) { + msleep(20); + count++; + goto lock_try; + } + writel(adapter->ahw.pci_func, (void __iomem *)(adapter->ahw.pci_base0 + + NX_FLASH_LOCK_ID)); + for (i = 0; i < size; i++) { + waddr = fl_addr & 0xFFFF0000; + NX_WR_DUMP_REG(FLASH_ROM_WINDOW, adapter->ahw.pci_base0, waddr); + raddr = FLASH_ROM_DATA + (fl_addr & 0x0000FFFF); + NX_RD_DUMP_REG(raddr, adapter->ahw.pci_base0, &val); + *data_buff++ = cpu_to_le32(val); + fl_addr += sizeof(val); + } + readl((void __iomem *)(adapter->ahw.pci_base0 + NX_FLASH_SEM2_ULK)); + return romEntry->read_data_size; +} + +/* Handle L2 Cache */ +static u32 +netxen_md_L2Cache(struct netxen_adapter *adapter, + struct netxen_minidump_entry_cache + *cacheEntry, u32 *data_buff) +{ + int loop_cnt, i, k, timeout_flag = 0; + u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr; + u32 tag_value, read_cnt; + u8 cntl_value_w, cntl_value_r; + unsigned long timeout, timeout_jiffies; + + loop_cnt = cacheEntry->op_count; + read_addr = cacheEntry->read_addr; + cntrl_addr = cacheEntry->control_addr; + cntl_value_w = (u32) cacheEntry->write_value; + tag_reg_addr = cacheEntry->tag_reg_addr; + tag_value = cacheEntry->init_tag_value; + read_cnt = cacheEntry->read_addr_cnt; + + for (i = 0; i < loop_cnt; i++) { + NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value); + if (cntl_value_w) + NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0, + (u32)cntl_value_w); + if (cacheEntry->poll_mask) { + timeout = cacheEntry->poll_wait; + NX_RD_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0, + &cntl_value_r); + timeout_jiffies = msecs_to_jiffies(timeout) + jiffies; + for (timeout_flag = 0; !timeout_flag && + ((cntl_value_r & cacheEntry->poll_mask) != 0);) { + if (time_after(jiffies, timeout_jiffies)) + timeout_flag = 1; + NX_RD_DUMP_REG(cntrl_addr, + adapter->ahw.pci_base0, + &cntl_value_r); + } + if (timeout_flag) { + dev_err(&adapter->pdev->dev, + "Timeout in processing L2 Tag poll.\n"); + return -1; + } + } + addr = read_addr; + for (k = 0; k < read_cnt; k++) { + NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0, + &read_value); + *data_buff++ = read_value; + addr += cacheEntry->read_addr_stride; + } + tag_value += cacheEntry->tag_value_stride; + } + return read_cnt * loop_cnt * sizeof(read_value); +} + + +/* Handle L1 Cache */ +static u32 netxen_md_L1Cache(struct netxen_adapter *adapter, + struct netxen_minidump_entry_cache + *cacheEntry, u32 *data_buff) +{ + int i, k, loop_cnt; + u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr; + u32 tag_value, read_cnt; + u8 cntl_value_w; + + loop_cnt = cacheEntry->op_count; + read_addr = cacheEntry->read_addr; + cntrl_addr = cacheEntry->control_addr; + cntl_value_w = (u32) cacheEntry->write_value; + tag_reg_addr = cacheEntry->tag_reg_addr; + tag_value = cacheEntry->init_tag_value; + read_cnt = cacheEntry->read_addr_cnt; + + for (i = 0; i < loop_cnt; i++) { + NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value); + NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0, + (u32) cntl_value_w); + addr = read_addr; + for (k = 0; k < read_cnt; k++) { + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + *data_buff++ = read_value; + addr += cacheEntry->read_addr_stride; + } + tag_value += cacheEntry->tag_value_stride; + } + return read_cnt * loop_cnt * sizeof(read_value); +} + +/* Reading OCM memory */ +static u32 +netxen_md_rdocm(struct netxen_adapter *adapter, + struct netxen_minidump_entry_rdocm + *ocmEntry, u32 *data_buff) +{ + int i, loop_cnt; + u32 value; + void __iomem *addr; + addr = (ocmEntry->read_addr + adapter->ahw.pci_base0); + loop_cnt = ocmEntry->op_count; + + for (i = 0; i < loop_cnt; i++) { + value = readl(addr); + *data_buff++ = value; + addr += ocmEntry->read_addr_stride; + } + return i * sizeof(u32); +} + +/* Read MUX data */ +static u32 +netxen_md_rdmux(struct netxen_adapter *adapter, struct netxen_minidump_entry_mux + *muxEntry, u32 *data_buff) +{ + int loop_cnt = 0; + u32 read_addr, read_value, select_addr, sel_value; + + read_addr = muxEntry->read_addr; + sel_value = muxEntry->select_value; + select_addr = muxEntry->select_addr; + + for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) { + NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, sel_value); + NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0, &read_value); + *data_buff++ = sel_value; + *data_buff++ = read_value; + sel_value += muxEntry->select_value_stride; + } + return loop_cnt * (2 * sizeof(u32)); +} + +/* Handling Queue State Reads */ +static u32 +netxen_md_rdqueue(struct netxen_adapter *adapter, + struct netxen_minidump_entry_queue + *queueEntry, u32 *data_buff) +{ + int loop_cnt, k; + u32 queue_id, read_addr, read_value, read_stride, select_addr, read_cnt; + + read_cnt = queueEntry->read_addr_cnt; + read_stride = queueEntry->read_addr_stride; + select_addr = queueEntry->select_addr; + + for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count; + loop_cnt++) { + NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, queue_id); + read_addr = queueEntry->read_addr; + for (k = 0; k < read_cnt; k--) { + NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0, + &read_value); + *data_buff++ = read_value; + read_addr += read_stride; + } + queue_id += queueEntry->queue_id_stride; + } + return loop_cnt * (read_cnt * sizeof(read_value)); +} + + +/* +* We catch an error where driver does not read +* as much data as we expect from the entry. +*/ + +static int netxen_md_entry_err_chk(struct netxen_adapter *adapter, + struct netxen_minidump_entry *entry, int esize) +{ + if (esize < 0) { + entry->hdr.driver_flags |= NX_DUMP_SKIP; + return esize; + } + if (esize != entry->hdr.entry_capture_size) { + entry->hdr.entry_capture_size = esize; + entry->hdr.driver_flags |= NX_DUMP_SIZE_ERR; + dev_info(&adapter->pdev->dev, + "Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n", + entry->hdr.entry_type, entry->hdr.entry_capture_mask, + esize, entry->hdr.entry_capture_size); + dev_info(&adapter->pdev->dev, "Aborting further dump capture\n"); + } + return 0; +} + +static int netxen_parse_md_template(struct netxen_adapter *adapter) +{ + int num_of_entries, buff_level, e_cnt, esize; + int end_cnt = 0, rv = 0, sane_start = 0, sane_end = 0; + char *dbuff; + void *template_buff = adapter->mdump.md_template; + char *dump_buff = adapter->mdump.md_capture_buff; + int capture_mask = adapter->mdump.md_capture_mask; + struct netxen_minidump_template_hdr *template_hdr; + struct netxen_minidump_entry *entry; + + if ((capture_mask & 0x3) != 0x3) { + dev_err(&adapter->pdev->dev, "Capture mask %02x below minimum needed " + "for valid firmware dump\n", capture_mask); + return -EINVAL; + } + template_hdr = (struct netxen_minidump_template_hdr *) template_buff; + num_of_entries = template_hdr->num_of_entries; + entry = (struct netxen_minidump_entry *) ((char *) template_buff + + template_hdr->first_entry_offset); + memcpy(dump_buff, template_buff, adapter->mdump.md_template_size); + dump_buff = dump_buff + adapter->mdump.md_template_size; + + if (template_hdr->entry_type == TLHDR) + sane_start = 1; + + for (e_cnt = 0, buff_level = 0; e_cnt < num_of_entries; e_cnt++) { + if (!(entry->hdr.entry_capture_mask & capture_mask)) { + entry->hdr.driver_flags |= NX_DUMP_SKIP; + entry = (struct netxen_minidump_entry *) + ((char *) entry + entry->hdr.entry_size); + continue; + } + switch (entry->hdr.entry_type) { + case RDNOP: + entry->hdr.driver_flags |= NX_DUMP_SKIP; + break; + case RDEND: + entry->hdr.driver_flags |= NX_DUMP_SKIP; + if (!sane_end) + end_cnt = e_cnt; + sane_end += 1; + break; + case CNTRL: + rv = netxen_md_cntrl(adapter, + template_hdr, (void *)entry); + if (rv) + entry->hdr.driver_flags |= NX_DUMP_SKIP; + break; + case RDCRB: + dbuff = dump_buff + buff_level; + esize = netxen_md_rd_crb(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case RDMN: + case RDMEM: + dbuff = dump_buff + buff_level; + esize = netxen_md_rdmem(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case BOARD: + case RDROM: + dbuff = dump_buff + buff_level; + esize = netxen_md_rdrom(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case L2ITG: + case L2DTG: + case L2DAT: + case L2INS: + dbuff = dump_buff + buff_level; + esize = netxen_md_L2Cache(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case L1DAT: + case L1INS: + dbuff = dump_buff + buff_level; + esize = netxen_md_L1Cache(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case RDOCM: + dbuff = dump_buff + buff_level; + esize = netxen_md_rdocm(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case RDMUX: + dbuff = dump_buff + buff_level; + esize = netxen_md_rdmux(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case QUEUE: + dbuff = dump_buff + buff_level; + esize = netxen_md_rdqueue(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + default: + entry->hdr.driver_flags |= NX_DUMP_SKIP; + break; + } + /* Next entry in the template */ + entry = (struct netxen_minidump_entry *) + ((char *) entry + entry->hdr.entry_size); + } + if (!sane_start || sane_end > 1) { + dev_err(&adapter->pdev->dev, + "Firmware minidump template configuration error.\n"); + } + return 0; +} + +static int +netxen_collect_minidump(struct netxen_adapter *adapter) +{ + int ret = 0; + struct netxen_minidump_template_hdr *hdr; + struct timespec val; + hdr = (struct netxen_minidump_template_hdr *) + adapter->mdump.md_template; + hdr->driver_capture_mask = adapter->mdump.md_capture_mask; + jiffies_to_timespec(jiffies, &val); + hdr->driver_timestamp = (u32) val.tv_sec; + hdr->driver_info_word2 = adapter->fw_version; + hdr->driver_info_word3 = NXRD32(adapter, CRB_DRIVER_VERSION); + ret = netxen_parse_md_template(adapter); + if (ret) + return ret; + + return ret; +} + + +void +netxen_dump_fw(struct netxen_adapter *adapter) +{ + struct netxen_minidump_template_hdr *hdr; + int i, k, data_size = 0; + u32 capture_mask; + hdr = (struct netxen_minidump_template_hdr *) + adapter->mdump.md_template; + capture_mask = adapter->mdump.md_capture_mask; + + for (i = 0x2, k = 1; (i & NX_DUMP_MASK_MAX); i <<= 1, k++) { + if (i & capture_mask) + data_size += hdr->capture_size_array[k]; + } + if (!data_size) { + dev_err(&adapter->pdev->dev, + "Invalid cap sizes for capture_mask=0x%x\n", + adapter->mdump.md_capture_mask); + return; + } + adapter->mdump.md_capture_size = data_size; + adapter->mdump.md_dump_size = adapter->mdump.md_template_size + + adapter->mdump.md_capture_size; + if (!adapter->mdump.md_capture_buff) { + adapter->mdump.md_capture_buff = + vmalloc(adapter->mdump.md_dump_size); + if (!adapter->mdump.md_capture_buff) { + dev_info(&adapter->pdev->dev, + "Unable to allocate memory for minidump " + "capture_buffer(%d bytes).\n", + adapter->mdump.md_dump_size); + return; + } + memset(adapter->mdump.md_capture_buff, 0, + adapter->mdump.md_dump_size); + if (netxen_collect_minidump(adapter)) { + adapter->mdump.has_valid_dump = 0; + adapter->mdump.md_dump_size = 0; + vfree(adapter->mdump.md_capture_buff); + adapter->mdump.md_capture_buff = NULL; + dev_err(&adapter->pdev->dev, + "Error in collecting firmware minidump.\n"); + } else { + adapter->mdump.md_timestamp = jiffies; + adapter->mdump.has_valid_dump = 1; + adapter->fw_mdump_rdy = 1; + dev_info(&adapter->pdev->dev, "%s Successfully " + "collected fw dump.\n", adapter->netdev->name); + } + + } else { + dev_info(&adapter->pdev->dev, + "Cannot overwrite previously collected " + "firmware minidump.\n"); + adapter->fw_mdump_rdy = 1; + return; + } +} diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index a8259cc19a63..718b27440351 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -280,13 +280,10 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) } rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring)); - if (rds_ring->rx_buf_arr == NULL) { - printk(KERN_ERR "%s: Failed to allocate " - "rx buffer ring %d\n", - netdev->name, ring); + if (rds_ring->rx_buf_arr == NULL) /* free whatever was already allocated */ goto err_out; - } + INIT_LIST_HEAD(&rds_ring->free_list); /* * Now go through all of them, set reference handles @@ -449,7 +446,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter) /* resetall */ netxen_rom_lock(adapter); - NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff); + NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xfeffffff); netxen_rom_unlock(adapter); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { @@ -480,11 +477,8 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter) } buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL); - if (buf == NULL) { - printk("%s: netxen_pinit_from_rom: Unable to calloc memory.\n", - netxen_nic_driver_name); + if (buf == NULL) return -ENOMEM; - } for (i = 0; i < n; i++) { if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 || @@ -1353,7 +1347,6 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) do { val = NXRD32(adapter, CRB_CMDPEG_STATE); - switch (val) { case PHAN_INITIALIZE_COMPLETE: case PHAN_INITIALIZE_ACK: @@ -1494,7 +1487,7 @@ netxen_alloc_rx_skb(struct netxen_adapter *adapter, dma_addr_t dma; struct pci_dev *pdev = adapter->pdev; - buffer->skb = dev_alloc_skb(rds_ring->skb_size); + buffer->skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size); if (!buffer->skb) return 1; diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 7dd9a4b107e6..8dc4a134dece 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -82,7 +82,6 @@ static void netxen_create_sysfs_entries(struct netxen_adapter *adapter); static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter); static void netxen_create_diag_entries(struct netxen_adapter *adapter); static void netxen_remove_diag_entries(struct netxen_adapter *adapter); - static int nx_dev_request_aer(struct netxen_adapter *adapter); static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter); static int netxen_can_start_firmware(struct netxen_adapter *adapter); @@ -802,10 +801,10 @@ err_out: static void netxen_check_options(struct netxen_adapter *adapter) { - u32 fw_major, fw_minor, fw_build; + u32 fw_major, fw_minor, fw_build, prev_fw_version; char brd_name[NETXEN_MAX_SHORT_NAME]; char serial_num[32]; - int i, offset, val; + int i, offset, val, err; int *ptr32; struct pci_dev *pdev = adapter->pdev; @@ -826,9 +825,22 @@ netxen_check_options(struct netxen_adapter *adapter) fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); - + prev_fw_version = adapter->fw_version; adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); + /* Get FW Mini Coredump template and store it */ + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + if (adapter->mdump.md_template == NULL || + adapter->fw_version > prev_fw_version) { + kfree(adapter->mdump.md_template); + adapter->mdump.md_template = NULL; + err = netxen_setup_minidump(adapter); + if (err) + dev_err(&adapter->pdev->dev, + "Failed to setup minidump rcode = %d\n", err); + } + } + if (adapter->portnum == 0) { get_brd_name_by_type(adapter->ahw.board_type, brd_name); @@ -909,7 +921,12 @@ netxen_start_firmware(struct netxen_adapter *adapter) if (err) return err; - if (!netxen_can_start_firmware(adapter)) + err = netxen_can_start_firmware(adapter); + + if (err < 0) + return err; + + if (!err) goto wait_init; first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); @@ -1403,7 +1420,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev = alloc_etherdev(sizeof(struct netxen_adapter)); if(!netdev) { - dev_err(&pdev->dev, "failed to allocate net_device\n"); err = -ENOMEM; goto err_out_free_res; } @@ -1529,6 +1545,18 @@ err_out_disable_pdev: return err; } +static +void netxen_cleanup_minidump(struct netxen_adapter *adapter) +{ + kfree(adapter->mdump.md_template); + adapter->mdump.md_template = NULL; + + if (adapter->mdump.md_capture_buff) { + vfree(adapter->mdump.md_capture_buff); + adapter->mdump.md_capture_buff = NULL; + } +} + static void __devexit netxen_nic_remove(struct pci_dev *pdev) { struct netxen_adapter *adapter; @@ -1564,8 +1592,10 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_release_firmware(adapter); - if (NX_IS_REVISION_P3(pdev->revision)) + if (NX_IS_REVISION_P3(pdev->revision)) { + netxen_cleanup_minidump(adapter); pci_disable_pcie_error_reporting(pdev); + } pci_release_regions(pdev); pci_disable_device(pdev); @@ -2317,7 +2347,7 @@ nx_incr_dev_ref_cnt(struct netxen_adapter *adapter) static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) { - int count; + int count, state; if (netxen_api_lock(adapter)) return -EIO; @@ -2325,8 +2355,9 @@ nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) WARN_ON(count == 0); NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count); + state = NXRD32(adapter, NX_CRB_DEV_STATE); - if (count == 0) + if (count == 0 && state != NX_DEV_FAILED) NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD); netxen_api_unlock(adapter); @@ -2355,7 +2386,7 @@ nx_dev_request_aer(struct netxen_adapter *adapter) return ret; } -static int +int nx_dev_request_reset(struct netxen_adapter *adapter) { u32 state; @@ -2366,10 +2397,11 @@ nx_dev_request_reset(struct netxen_adapter *adapter) state = NXRD32(adapter, NX_CRB_DEV_STATE); - if (state == NX_DEV_NEED_RESET) + if (state == NX_DEV_NEED_RESET || state == NX_DEV_FAILED) ret = 0; else if (state != NX_DEV_INITALIZING && state != NX_DEV_NEED_AER) { NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); + adapter->flags |= NETXEN_FW_RESET_OWNER; ret = 0; } @@ -2384,8 +2416,10 @@ netxen_can_start_firmware(struct netxen_adapter *adapter) int count; int can_start = 0; - if (netxen_api_lock(adapter)) - return 0; + if (netxen_api_lock(adapter)) { + nx_incr_dev_ref_cnt(adapter); + return -1; + } count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); @@ -2457,8 +2491,31 @@ netxen_fwinit_work(struct work_struct *work) struct netxen_adapter *adapter = container_of(work, struct netxen_adapter, fw_work.work); int dev_state; - + int count; dev_state = NXRD32(adapter, NX_CRB_DEV_STATE); + if (adapter->flags & NETXEN_FW_RESET_OWNER) { + count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); + WARN_ON(count == 0); + if (count == 1) { + if (adapter->mdump.md_enabled) { + rtnl_lock(); + netxen_dump_fw(adapter); + rtnl_unlock(); + } + adapter->flags &= ~NETXEN_FW_RESET_OWNER; + if (netxen_api_lock(adapter)) { + clear_bit(__NX_RESETTING, &adapter->state); + NXWR32(adapter, NX_CRB_DEV_STATE, + NX_DEV_FAILED); + return; + } + count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); + NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count); + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD); + dev_state = NX_DEV_COLD; + netxen_api_unlock(adapter); + } + } switch (dev_state) { case NX_DEV_COLD: @@ -2471,11 +2528,9 @@ netxen_fwinit_work(struct work_struct *work) case NX_DEV_NEED_RESET: case NX_DEV_INITALIZING: - if (++adapter->fw_wait_cnt < FW_POLL_THRESH) { netxen_schedule_work(adapter, netxen_fwinit_work, 2 * FW_POLL_DELAY); return; - } case NX_DEV_FAILED: default: @@ -2483,6 +2538,15 @@ netxen_fwinit_work(struct work_struct *work) break; } + if (netxen_api_lock(adapter)) { + clear_bit(__NX_RESETTING, &adapter->state); + return; + } + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_FAILED); + netxen_api_unlock(adapter); + dev_err(&adapter->pdev->dev, "%s: Device initialization Failed\n", + adapter->netdev->name); + clear_bit(__NX_RESETTING, &adapter->state); } @@ -2492,7 +2556,7 @@ netxen_detach_work(struct work_struct *work) struct netxen_adapter *adapter = container_of(work, struct netxen_adapter, fw_work.work); struct net_device *netdev = adapter->netdev; - int ref_cnt, delay; + int ref_cnt = 0, delay; u32 status; netif_device_detach(netdev); @@ -2511,7 +2575,8 @@ netxen_detach_work(struct work_struct *work) if (adapter->temp == NX_TEMP_PANIC) goto err_ret; - ref_cnt = nx_decr_dev_ref_cnt(adapter); + if (!(adapter->flags & NETXEN_FW_RESET_OWNER)) + ref_cnt = nx_decr_dev_ref_cnt(adapter); if (ref_cnt == -EIO) goto err_ret; @@ -2531,6 +2596,7 @@ static int netxen_check_health(struct netxen_adapter *adapter) { u32 state, heartbit; + u32 peg_status; struct net_device *netdev = adapter->netdev; state = NXRD32(adapter, NX_CRB_DEV_STATE); @@ -2551,7 +2617,7 @@ netxen_check_health(struct netxen_adapter *adapter) * Send request to destroy context in case of tx timeout only * and doesn't required in case of Fw hang */ - if (state == NX_DEV_NEED_RESET) { + if (state == NX_DEV_NEED_RESET || state == NX_DEV_FAILED) { adapter->need_fw_reset = 1; if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) goto detach; @@ -2577,8 +2643,24 @@ netxen_check_health(struct netxen_adapter *adapter) clear_bit(__NX_FW_ATTACHED, &adapter->state); - dev_info(&netdev->dev, "firmware hang detected\n"); - + dev_err(&netdev->dev, "firmware hang detected\n"); + peg_status = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1); + dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n" + "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n" + "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n" + "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n" + "PEG_NET_4_PC: 0x%x\n", + peg_status, + NXRD32(adapter, NETXEN_PEG_HALT_STATUS2), + NXRD32(adapter, NETXEN_CRB_PEG_NET_0 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_1 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_2 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_3 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_4 + 0x3c)); + if (NX_FWERROR_PEGSTAT1(peg_status) == 0x67) + dev_err(&adapter->pdev->dev, + "Firmware aborted with error code 0x00006700. " + "Device is being reset.\n"); detach: if ((auto_fw_reset == AUTO_FW_RESET_ENABLED) && !test_and_set_bit(__NX_RESETTING, &adapter->state)) @@ -2848,13 +2930,12 @@ static struct bin_attribute bin_attr_mem = { static void netxen_create_sysfs_entries(struct netxen_adapter *adapter) { - struct net_device *netdev = adapter->netdev; - struct device *dev = &netdev->dev; + struct device *dev = &adapter->pdev->dev; if (adapter->capabilities & NX_FW_CAPABILITY_BDG) { /* bridged_mode control */ if (device_create_file(dev, &dev_attr_bridged_mode)) { - dev_warn(&netdev->dev, + dev_warn(dev, "failed to create bridged_mode sysfs entry\n"); } } @@ -2863,8 +2944,7 @@ netxen_create_sysfs_entries(struct netxen_adapter *adapter) static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter) { - struct net_device *netdev = adapter->netdev; - struct device *dev = &netdev->dev; + struct device *dev = &adapter->pdev->dev; if (adapter->capabilities & NX_FW_CAPABILITY_BDG) device_remove_file(dev, &dev_attr_bridged_mode); diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index 7931531c3a40..d49f6dac51fd 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -3805,7 +3805,6 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, ndev = alloc_etherdev(sizeof(struct ql3_adapter)); if (!ndev) { - pr_err("%s could not alloc etherdev\n", pci_name(pdev)); err = -ENOMEM; goto err_out_free_regions; } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 60976fc4ccc6..2b5af22419a5 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -37,7 +37,7 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 0 #define _QLCNIC_LINUX_SUBVERSION 25 -#define QLCNIC_LINUX_VERSIONID "5.0.25" +#define QLCNIC_LINUX_VERSIONID "5.0.26" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index cc228cf3d84b..89ddf7f7d7df 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -155,7 +155,6 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct qlcnic_adapter *adapter = netdev_priv(dev); int check_sfp_module = 0; - u16 pcifn = adapter->ahw->pci_func; /* read which mode */ if (adapter->ahw->port_type == QLCNIC_GBE) { @@ -194,10 +193,8 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) goto skip; } - val = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn)); - ethtool_cmd_speed_set(ecmd, P3P_LINK_SPEED_MHZ * - P3P_LINK_SPEED_VAL(pcifn, val)); - ecmd->duplex = DUPLEX_FULL; + ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); + ecmd->duplex = DUPLEX_UNKNOWN; ecmd->autoneg = AUTONEG_DISABLE; } else return -EIO; @@ -722,7 +719,7 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) int i, loop, cnt = 0; for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) { - skb = dev_alloc_skb(QLCNIC_ILB_PKT_SIZE); + skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE); qlcnic_create_loopback_buff(skb->data, adapter->mac_addr); skb_put(skb, QLCNIC_ILB_PKT_SIZE); @@ -1155,7 +1152,6 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, if (!fw_dump->clr) { netdev_info(netdev, "Dump not available\n"); - qlcnic_api_unlock(adapter); return -EINVAL; } /* Copy template header first */ @@ -1174,7 +1170,7 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, vfree(fw_dump->data); fw_dump->data = NULL; fw_dump->clr = 0; - + netdev_info(netdev, "extracted the FW dump Successfully\n"); return 0; } @@ -1192,7 +1188,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) return ret; } if (fw_dump->clr) { - dev_info(&adapter->pdev->dev, + netdev_info(netdev, "Previous dump not cleared, not forcing dump\n"); return ret; } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c index 38669583840c..d32cf0ddf1b9 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c @@ -1369,7 +1369,13 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter, adapter->module_type = module; adapter->link_autoneg = autoneg; - adapter->link_speed = link_speed; + + if (link_status) { + adapter->link_speed = link_speed; + } else { + adapter->link_speed = SPEED_UNKNOWN; + adapter->link_duplex = DUPLEX_UNKNOWN; + } } static void @@ -1434,7 +1440,7 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, dma_addr_t dma; struct pci_dev *pdev = adapter->pdev; - skb = dev_alloc_skb(rds_ring->skb_size); + skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size); if (!skb) { adapter->stats.skb_alloc_failure++; return -ENOMEM; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 69b8e4ef14d9..dba95311a462 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -1576,7 +1576,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev = alloc_etherdev(sizeof(struct qlcnic_adapter)); if (!netdev) { - dev_err(&pdev->dev, "failed to allocate net_device\n"); err = -ENOMEM; goto err_out_free_res; } @@ -3000,8 +2999,18 @@ qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter) void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) { - u32 state; - + u32 state, xg_val = 0, gb_val = 0; + + qlcnic_xg_set_xg0_mask(xg_val); + qlcnic_xg_set_xg1_mask(xg_val); + QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, xg_val); + qlcnic_gb_set_gb0_mask(gb_val); + qlcnic_gb_set_gb1_mask(gb_val); + qlcnic_gb_set_gb2_mask(gb_val); + qlcnic_gb_set_gb3_mask(gb_val); + QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, gb_val); + dev_info(&adapter->pdev->dev, "Pause control frames disabled" + " on all ports\n"); adapter->need_fw_reset = 1; if (qlcnic_api_lock(adapter)) return; @@ -3150,7 +3159,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter) QLCRD32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c), QLCRD32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c)); peg_status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1); - if (LSW(MSB(peg_status)) == 0x67) + if (QLCNIC_FWERROR_CODE(peg_status) == 0x67) dev_err(&adapter->pdev->dev, "Firmware aborted with error code 0x00006700. " "Device is being reset.\n"); diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h index b8478aab050e..5a639df33f18 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge.h +++ b/drivers/net/ethernet/qlogic/qlge/qlge.h @@ -18,7 +18,7 @@ */ #define DRV_NAME "qlge" #define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver " -#define DRV_VERSION "v1.00.00.29.00.00-01" +#define DRV_VERSION "v1.00.00.30.00.00-01" #define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */ diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c index fca804f36d61..58185b604b72 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c @@ -1824,10 +1824,8 @@ void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id) pr_err("%s: Enter\n", __func__); ptr = kmalloc(size, GFP_ATOMIC); - if (ptr == NULL) { - pr_err("%s: Couldn't allocate a buffer\n", __func__); + if (ptr == NULL) return; - } if (ql_write_cfg(qdev, ptr, size, bit, q_id)) { pr_err("%s: Failed to upload control block!\n", __func__); diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index b54898737284..49343ec21c82 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -375,13 +375,6 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, u32 lower = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | (addr[5]); - - netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, - "Adding %s address %pM at index %d in the CAM.\n", - type == MAC_ADDR_TYPE_MULTI_MAC ? - "MULTICAST" : "UNICAST", - addr, index); - status = ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, MAC_ADDR_MW, 0); @@ -430,12 +423,6 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, * addressing. It's either MAC_ADDR_E on or off. * That's bit-27 we're talking about. */ - netif_info(qdev, ifup, qdev->ndev, - "%s VLAN ID %d %s the CAM.\n", - enable_bit ? "Adding" : "Removing", - index, - enable_bit ? "to" : "from"); - status = ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, MAC_ADDR_MW, 0); @@ -535,28 +522,6 @@ static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask, int status = -EINVAL; /* Return error if no mask match. */ u32 value = 0; - netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, - "%s %s mask %s the routing reg.\n", - enable ? "Adding" : "Removing", - index == RT_IDX_ALL_ERR_SLOT ? "MAC ERROR/ALL ERROR" : - index == RT_IDX_IP_CSUM_ERR_SLOT ? "IP CSUM ERROR" : - index == RT_IDX_TCP_UDP_CSUM_ERR_SLOT ? "TCP/UDP CSUM ERROR" : - index == RT_IDX_BCAST_SLOT ? "BROADCAST" : - index == RT_IDX_MCAST_MATCH_SLOT ? "MULTICAST MATCH" : - index == RT_IDX_ALLMULTI_SLOT ? "ALL MULTICAST MATCH" : - index == RT_IDX_UNUSED6_SLOT ? "UNUSED6" : - index == RT_IDX_UNUSED7_SLOT ? "UNUSED7" : - index == RT_IDX_RSS_MATCH_SLOT ? "RSS ALL/IPV4 MATCH" : - index == RT_IDX_RSS_IPV6_SLOT ? "RSS IPV6" : - index == RT_IDX_RSS_TCP4_SLOT ? "RSS TCP4" : - index == RT_IDX_RSS_TCP6_SLOT ? "RSS TCP6" : - index == RT_IDX_CAM_HIT_SLOT ? "CAM HIT" : - index == RT_IDX_UNUSED013 ? "UNUSED13" : - index == RT_IDX_UNUSED014 ? "UNUSED14" : - index == RT_IDX_PROMISCUOUS_SLOT ? "PROMISCUOUS" : - "(Bad index != RT_IDX)", - enable ? "to" : "from"); - switch (mask) { case RT_IDX_CAM_HIT: { @@ -1178,14 +1143,16 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) int i; while (rx_ring->lbq_free_cnt > 32) { - for (i = 0; i < 16; i++) { + for (i = (rx_ring->lbq_clean_idx % 16); i < 16; i++) { netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "lbq: try cleaning clean_idx = %d.\n", clean_idx); lbq_desc = &rx_ring->lbq[clean_idx]; if (ql_get_next_chunk(qdev, rx_ring, lbq_desc)) { + rx_ring->lbq_clean_idx = clean_idx; netif_err(qdev, ifup, qdev->ndev, - "Could not get a page chunk.\n"); + "Could not get a page chunk, i=%d, clean_idx =%d .\n", + i, clean_idx); return; } @@ -1230,7 +1197,7 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) int i; while (rx_ring->sbq_free_cnt > 16) { - for (i = 0; i < 16; i++) { + for (i = (rx_ring->sbq_clean_idx % 16); i < 16; i++) { sbq_desc = &rx_ring->sbq[clean_idx]; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "sbq: try cleaning clean_idx = %d.\n", @@ -1576,13 +1543,14 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { /* Unfragmented ipv4 UDP frame. */ - struct iphdr *iph = (struct iphdr *) skb->data; + struct iphdr *iph = + (struct iphdr *) ((u8 *)addr + ETH_HLEN); if (!(iph->frag_off & cpu_to_be16(IP_MF|IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, - "TCP checksum done!\n"); + "UDP checksum done!\n"); } } } @@ -1690,7 +1658,7 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, skb->ip_summed = CHECKSUM_UNNECESSARY; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, - "TCP checksum done!\n"); + "UDP checksum done!\n"); } } } @@ -2312,13 +2280,9 @@ static void qlge_vlan_mode(struct net_device *ndev, netdev_features_t features) struct ql_adapter *qdev = netdev_priv(ndev); if (features & NETIF_F_HW_VLAN_RX) { - netif_printk(qdev, ifup, KERN_DEBUG, ndev, - "Turning on VLAN in NIC_RCV_CFG.\n"); ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK | NIC_RCV_CFG_VLAN_MATCH_AND_NON); } else { - netif_printk(qdev, ifup, KERN_DEBUG, ndev, - "Turning off VLAN in NIC_RCV_CFG.\n"); ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK); } } @@ -3183,8 +3147,6 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, "Invalid rx_ring->type = %d.\n", rx_ring->type); } - netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, - "Initializing rx work queue.\n"); err = ql_write_cfg(qdev, cqicb, sizeof(struct cqicb), CFG_LCQ, rx_ring->cq_id); if (err) { @@ -3237,8 +3199,6 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring) netif_err(qdev, ifup, qdev->ndev, "Failed to load tx_ring.\n"); return err; } - netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, - "Successfully loaded WQICB.\n"); return err; } @@ -3488,12 +3448,8 @@ static void ql_free_irq(struct ql_adapter *qdev) if (test_bit(QL_MSIX_ENABLED, &qdev->flags)) { free_irq(qdev->msi_x_entry[i].vector, &qdev->rx_ring[i]); - netif_printk(qdev, ifdown, KERN_DEBUG, qdev->ndev, - "freeing msix interrupt %d.\n", i); } else { free_irq(qdev->pdev->irq, &qdev->rx_ring[0]); - netif_printk(qdev, ifdown, KERN_DEBUG, qdev->ndev, - "freeing msi interrupt %d.\n", i); } } } @@ -3522,17 +3478,6 @@ static int ql_request_irq(struct ql_adapter *qdev) "Failed request for MSIX interrupt %d.\n", i); goto err_irq; - } else { - netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, - "Hooked intr %d, queue type %s, with name %s.\n", - i, - qdev->rx_ring[i].type == DEFAULT_Q ? - "DEFAULT_Q" : - qdev->rx_ring[i].type == TX_Q ? - "TX_Q" : - qdev->rx_ring[i].type == RX_Q ? - "RX_Q" : "", - intr_context->name); } } else { netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, @@ -3602,15 +3547,11 @@ static int ql_start_rss(struct ql_adapter *qdev) memcpy((void *)&ricb->ipv6_hash_key[0], init_hash_seed, 40); memcpy((void *)&ricb->ipv4_hash_key[0], init_hash_seed, 16); - netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, "Initializing RSS.\n"); - status = ql_write_cfg(qdev, ricb, sizeof(*ricb), CFG_LR, 0); if (status) { netif_err(qdev, ifup, qdev->ndev, "Failed to load RICB.\n"); return status; } - netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, - "Successfully loaded RICB.\n"); return status; } @@ -3817,11 +3758,8 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) } /* Start NAPI for the RSS queues. */ - for (i = 0; i < qdev->rss_ring_count; i++) { - netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, - "Enabling NAPI for rx_ring[%d].\n", i); + for (i = 0; i < qdev->rss_ring_count; i++) napi_enable(&qdev->rx_ring[i].napi); - } return status; } @@ -4121,10 +4059,6 @@ static int ql_configure_rings(struct ql_adapter *qdev) rx_ring->lbq_size = rx_ring->lbq_len * sizeof(__le64); rx_ring->lbq_buf_size = (u16)lbq_buf_len; - netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, - "lbq_buf_size %d, order = %d\n", - rx_ring->lbq_buf_size, - qdev->lbq_buf_order); rx_ring->sbq_len = NUM_SMALL_BUFFERS; rx_ring->sbq_size = rx_ring->sbq_len * sizeof(__le64); diff --git a/drivers/net/ethernet/racal/ni5010.c b/drivers/net/ethernet/racal/ni5010.c index 072810da9a37..807982220050 100644 --- a/drivers/net/ethernet/racal/ni5010.c +++ b/drivers/net/ethernet/racal/ni5010.c @@ -552,7 +552,7 @@ static void ni5010_rx(struct net_device *dev) } /* Malloc up new buffer. */ - skb = dev_alloc_skb(i_pkt_size + 3); + skb = netdev_alloc_skb(dev, i_pkt_size + 3); if (skb == NULL) { printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); dev->stats.rx_dropped++; diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c index cb0eca807852..76cab284876b 100644 --- a/drivers/net/ethernet/rdc/r6040.c +++ b/drivers/net/ethernet/rdc/r6040.c @@ -1107,7 +1107,6 @@ static int __devinit r6040_init_one(struct pci_dev *pdev, dev = alloc_etherdev(sizeof(struct r6040_private)); if (!dev) { - dev_err(&pdev->dev, "Failed to allocate etherdev\n"); err = -ENOMEM; goto err_out; } diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c index a8779bedb3d9..1c3feb0116b5 100644 --- a/drivers/net/ethernet/realtek/8139too.c +++ b/drivers/net/ethernet/realtek/8139too.c @@ -754,10 +754,9 @@ static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) /* dev and priv zeroed in alloc_etherdev */ dev = alloc_etherdev (sizeof (*tp)); - if (dev == NULL) { - dev_err(&pdev->dev, "Unable to alloc new net device\n"); + if (dev == NULL) return ERR_PTR(-ENOMEM); - } + SET_NETDEV_DEV(dev, &pdev->dev); tp = netdev_priv(dev); diff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig index 0578859a3c73..5821966f9f28 100644 --- a/drivers/net/ethernet/realtek/Kconfig +++ b/drivers/net/ethernet/realtek/Kconfig @@ -24,11 +24,11 @@ config ATP select CRC32 ---help--- This is a network (Ethernet) device which attaches to your parallel - port. Read <file:drivers/net/atp.c> as well as the Ethernet-HOWTO, - available from <http://www.tldp.org/docs.html#howto>, if you - want to use this. If you intend to use this driver, you should have - said N to the "Parallel printer support", because the two drivers - don't like each other. + port. Read <file:drivers/net/ethernet/realtek/atp.c> as well as the + Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>, + if you want to use this. If you intend to use this driver, you + should have said N to the "Parallel printer support", because the two + drivers don't like each other. To compile this driver as a module, choose M here: the module will be called atp. diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c index e3f57fdbf0ea..46c1932048cb 100644 --- a/drivers/net/ethernet/realtek/atp.c +++ b/drivers/net/ethernet/realtek/atp.c @@ -783,7 +783,7 @@ static void net_rx(struct net_device *dev) int pkt_len = (rx_head.rx_count & 0x7ff) - 4; struct sk_buff *skb; - skb = dev_alloc_skb(pkt_len + 2); + skb = netdev_alloc_skb(dev, pkt_len + 2); if (skb == NULL) { printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name); diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 7a0c800b50ad..5eb6858ed0a7 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -667,12 +667,19 @@ struct rtl8169_counters { __le16 tx_underun; }; +enum rtl_flag { + RTL_FLAG_TASK_ENABLED, + RTL_FLAG_TASK_SLOW_PENDING, + RTL_FLAG_TASK_RESET_PENDING, + RTL_FLAG_TASK_PHY_PENDING, + RTL_FLAG_MAX +}; + struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; struct net_device *dev; struct napi_struct napi; - spinlock_t lock; u32 msg_enable; u16 txd_version; u16 mac_version; @@ -688,9 +695,8 @@ struct rtl8169_private { struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ struct timer_list timer; u16 cp_cmd; - u16 intr_event; - u16 napi_event; - u16 intr_mask; + + u16 event_slow; struct mdio_ops { void (*write)(void __iomem *, int, int); @@ -714,7 +720,13 @@ struct rtl8169_private { unsigned int (*phy_reset_pending)(struct rtl8169_private *tp); unsigned int (*link_ok)(void __iomem *); int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - struct delayed_work task; + + struct { + DECLARE_BITMAP(flags, RTL_FLAG_MAX); + struct mutex mutex; + struct work_struct work; + } wk; + unsigned features; struct mii_if_info mii; @@ -764,13 +776,20 @@ static int rtl8169_close(struct net_device *dev); static void rtl_set_rx_mode(struct net_device *dev); static void rtl8169_tx_timeout(struct net_device *dev); static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); -static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8169_down(struct net_device *dev); static void rtl8169_rx_clear(struct rtl8169_private *tp); static int rtl8169_poll(struct napi_struct *napi, int budget); +static void rtl_lock_work(struct rtl8169_private *tp) +{ + mutex_lock(&tp->wk.mutex); +} + +static void rtl_unlock_work(struct rtl8169_private *tp) +{ + mutex_unlock(&tp->wk.mutex); +} + static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) { int cap = pci_pcie_cap(pdev); @@ -1180,12 +1199,51 @@ static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) return value; } +static u16 rtl_get_events(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + + return RTL_R16(IntrStatus); +} + +static void rtl_ack_events(struct rtl8169_private *tp, u16 bits) +{ + void __iomem *ioaddr = tp->mmio_addr; + + RTL_W16(IntrStatus, bits); + mmiowb(); +} + +static void rtl_irq_disable(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + + RTL_W16(IntrMask, 0); + mmiowb(); +} + +static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits) +{ + void __iomem *ioaddr = tp->mmio_addr; + + RTL_W16(IntrMask, bits); +} + +#define RTL_EVENT_NAPI_RX (RxOK | RxErr) +#define RTL_EVENT_NAPI_TX (TxOK | TxErr) +#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX) + +static void rtl_irq_enable_all(struct rtl8169_private *tp) +{ + rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow); +} + static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; - RTL_W16(IntrMask, 0x0000); - RTL_W16(IntrStatus, tp->intr_event); + rtl_irq_disable(tp); + rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow); RTL_R8(ChipCmd); } @@ -1276,9 +1334,6 @@ static void __rtl8169_check_link_status(struct net_device *dev, struct rtl8169_private *tp, void __iomem *ioaddr, bool pm) { - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); if (tp->link_ok(ioaddr)) { rtl_link_chg_patch(tp); /* This is to cancel a scheduled suspend if there's one. */ @@ -1293,7 +1348,6 @@ static void __rtl8169_check_link_status(struct net_device *dev, if (pm) pm_schedule_suspend(&tp->pci_dev->dev, 5000); } - spin_unlock_irqrestore(&tp->lock, flags); } static void rtl8169_check_link_status(struct net_device *dev, @@ -1336,12 +1390,12 @@ static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct rtl8169_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); + rtl_lock_work(tp); wol->supported = WAKE_ANY; wol->wolopts = __rtl8169_get_wol(tp); - spin_unlock_irq(&tp->lock); + rtl_unlock_work(tp); } static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) @@ -1378,14 +1432,15 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct rtl8169_private *tp = netdev_priv(dev); - spin_lock_irq(&tp->lock); + rtl_lock_work(tp); if (wol->wolopts) tp->features |= RTL_FEATURE_WOL; else tp->features &= ~RTL_FEATURE_WOL; __rtl8169_set_wol(tp, wol->wolopts); - spin_unlock_irq(&tp->lock); + + rtl_unlock_work(tp); device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); @@ -1540,15 +1595,14 @@ out: static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; int ret; del_timer_sync(&tp->timer); - spin_lock_irqsave(&tp->lock, flags); + rtl_lock_work(tp); ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd), cmd->duplex, cmd->advertising); - spin_unlock_irqrestore(&tp->lock, flags); + rtl_unlock_work(tp); return ret; } @@ -1568,14 +1622,12 @@ static netdev_features_t rtl8169_fix_features(struct net_device *dev, return features; } -static int rtl8169_set_features(struct net_device *dev, - netdev_features_t features) +static void __rtl8169_set_features(struct net_device *dev, + netdev_features_t features) { struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - spin_lock_irqsave(&tp->lock, flags); + void __iomem *ioaddr = tp->mmio_addr; if (features & NETIF_F_RXCSUM) tp->cp_cmd |= RxChkSum; @@ -1589,12 +1641,21 @@ static int rtl8169_set_features(struct net_device *dev, RTL_W16(CPlusCmd, tp->cp_cmd); RTL_R16(CPlusCmd); +} + +static int rtl8169_set_features(struct net_device *dev, + netdev_features_t features) +{ + struct rtl8169_private *tp = netdev_priv(dev); - spin_unlock_irqrestore(&tp->lock, flags); + rtl_lock_work(tp); + __rtl8169_set_features(dev, features); + rtl_unlock_work(tp); return 0; } + static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, struct sk_buff *skb) { @@ -1643,14 +1704,12 @@ static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; int rc; - spin_lock_irqsave(&tp->lock, flags); - + rtl_lock_work(tp); rc = tp->get_settings(dev, cmd); + rtl_unlock_work(tp); - spin_unlock_irqrestore(&tp->lock, flags); return rc; } @@ -1658,14 +1717,13 @@ static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) { struct rtl8169_private *tp = netdev_priv(dev); - unsigned long flags; if (regs->len > R8169_REGS_SIZE) regs->len = R8169_REGS_SIZE; - spin_lock_irqsave(&tp->lock, flags); + rtl_lock_work(tp); memcpy_fromio(p, tp->mmio_addr, regs->len); - spin_unlock_irqrestore(&tp->lock, flags); + rtl_unlock_work(tp); } static u32 rtl8169_get_msglevel(struct net_device *dev) @@ -3182,18 +3240,14 @@ static void rtl_hw_phy_config(struct net_device *dev) } } -static void rtl8169_phy_timer(unsigned long __opaque) +static void rtl_phy_work(struct rtl8169_private *tp) { - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; void __iomem *ioaddr = tp->mmio_addr; unsigned long timeout = RTL8169_PHY_TIMEOUT; assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - spin_lock_irq(&tp->lock); - if (tp->phy_reset_pending(tp)) { /* * A busy loop could burn quite a few cycles on nowadays CPU. @@ -3204,32 +3258,36 @@ static void rtl8169_phy_timer(unsigned long __opaque) } if (tp->link_ok(ioaddr)) - goto out_unlock; + return; - netif_warn(tp, link, dev, "PHY reset until link up\n"); + netif_warn(tp, link, tp->dev, "PHY reset until link up\n"); tp->phy_reset_enable(tp); out_mod_timer: mod_timer(timer, jiffies + timeout); -out_unlock: - spin_unlock_irq(&tp->lock); +} + +static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag) +{ + if (!test_and_set_bit(flag, tp->wk.flags)) + schedule_work(&tp->wk.work); +} + +static void rtl8169_phy_timer(unsigned long __opaque) +{ + struct net_device *dev = (struct net_device *)__opaque; + struct rtl8169_private *tp = netdev_priv(dev); + + rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING); } #ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ static void rtl8169_netpoll(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); - enable_irq(pdev->irq); + rtl8169_interrupt(tp->pci_dev->irq, dev); } #endif @@ -3310,7 +3368,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); high = addr[4] | (addr[5] << 8); - spin_lock_irq(&tp->lock); + rtl_lock_work(tp); RTL_W8(Cfg9346, Cfg9346_Unlock); @@ -3334,7 +3392,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) RTL_W8(Cfg9346, Cfg9346_Lock); - spin_unlock_irq(&tp->lock); + rtl_unlock_work(tp); } static int rtl_set_mac_address(struct net_device *dev, void *p) @@ -3388,8 +3446,7 @@ static const struct rtl_cfg_info { void (*hw_start)(struct net_device *); unsigned int region; unsigned int align; - u16 intr_event; - u16 napi_event; + u16 event_slow; unsigned features; u8 default_ver; } rtl_cfg_infos [] = { @@ -3397,9 +3454,7 @@ static const struct rtl_cfg_info { .hw_start = rtl_hw_start_8169, .region = 1, .align = 0, - .intr_event = SYSErr | LinkChg | RxOverflow | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, + .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver, .features = RTL_FEATURE_GMII, .default_ver = RTL_GIGA_MAC_VER_01, }, @@ -3407,9 +3462,7 @@ static const struct rtl_cfg_info { .hw_start = rtl_hw_start_8168, .region = 2, .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | - TxErr | TxOK | RxOK | RxErr, - .napi_event = TxErr | TxOK | RxOK | RxOverflow, + .event_slow = SYSErr | LinkChg | RxOverflow, .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, .default_ver = RTL_GIGA_MAC_VER_11, }, @@ -3417,9 +3470,8 @@ static const struct rtl_cfg_info { .hw_start = rtl_hw_start_8101, .region = 2, .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | - RxFIFOOver | TxErr | TxOK | RxOK | RxErr, - .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, + .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver | + PCSTimeout, .features = RTL_FEATURE_MSI, .default_ver = RTL_GIGA_MAC_VER_13, } @@ -3824,23 +3876,21 @@ static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp) static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; RTL_W8(MaxTxPacketSize, 0x3f); RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); RTL_W8(Config4, RTL_R8(Config4) | 0x01); - pci_write_config_byte(pdev, 0x79, 0x20); + rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT); } static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; RTL_W8(MaxTxPacketSize, 0x0c); RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); RTL_W8(Config4, RTL_R8(Config4) & ~0x01); - pci_write_config_byte(pdev, 0x79, 0x50); + rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); } static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp) @@ -3958,8 +4008,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev = alloc_etherdev(sizeof (*tp)); if (!dev) { - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); rc = -ENOMEM; goto out; } @@ -4048,11 +4096,11 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl_init_rxcfg(tp); - RTL_W16(IntrMask, 0x0000); + rtl_irq_disable(tp); rtl_hw_reset(tp); - RTL_W16(IntrStatus, 0xffff); + rtl_ack_events(tp, 0xffff); pci_set_master(pdev); @@ -4098,7 +4146,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->do_ioctl = rtl_xmii_ioctl; } - spin_lock_init(&tp->lock); + mutex_init(&tp->wk.mutex); /* Get MAC address */ for (i = 0; i < ETH_ALEN; i++) @@ -4126,10 +4174,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* 8110SCd requires hardware Rx VLAN - disallow toggling */ dev->hw_features &= ~NETIF_F_HW_VLAN_RX; - tp->intr_mask = 0xffff; tp->hw_start = cfg->hw_start; - tp->intr_event = cfg->intr_event; - tp->napi_event = cfg->napi_event; + tp->event_slow = cfg->event_slow; tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ? ~(RxBOVF | RxFOVF) : ~0; @@ -4196,7 +4242,7 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) rtl8168_driver_stop(tp); } - cancel_delayed_work_sync(&tp->task); + cancel_work_sync(&tp->wk.work); unregister_netdev(dev); @@ -4257,6 +4303,8 @@ static void rtl_request_firmware(struct rtl8169_private *tp) rtl_request_uncached_firmware(tp); } +static void rtl_task(struct work_struct *); + static int rtl8169_open(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -4284,7 +4332,7 @@ static int rtl8169_open(struct net_device *dev) if (retval < 0) goto err_free_rx_1; - INIT_DELAYED_WORK(&tp->task, NULL); + INIT_WORK(&tp->wk.work, rtl_task); smp_mb(); @@ -4296,16 +4344,24 @@ static int rtl8169_open(struct net_device *dev) if (retval < 0) goto err_release_fw_2; + rtl_lock_work(tp); + + set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); + napi_enable(&tp->napi); rtl8169_init_phy(dev, tp); - rtl8169_set_features(dev, dev->features); + __rtl8169_set_features(dev, dev->features); rtl_pll_power_up(tp); rtl_hw_start(dev); + netif_start_queue(dev); + + rtl_unlock_work(tp); + tp->saved_wolopts = 0; pm_runtime_put_noidle(&pdev->dev); @@ -4379,7 +4435,7 @@ static void rtl_hw_start(struct net_device *dev) tp->hw_start(dev); - netif_start_queue(dev); + rtl_irq_enable_all(tp); } static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, @@ -4506,9 +4562,6 @@ static void rtl_hw_start_8169(struct net_device *dev) /* no early-rx interrupts */ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - /* Enable all known interrupts by setting the interrupt mask. */ - RTL_W16(IntrMask, tp->intr_event); } static void rtl_csi_access_enable(void __iomem *ioaddr, u32 bits) @@ -4888,8 +4941,8 @@ static void rtl_hw_start_8168(struct net_device *dev) /* Work around for RxFIFO overflow. */ if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->intr_event |= RxFIFOOver | PCSTimeout; - tp->intr_event &= ~RxOverflow; + tp->event_slow |= RxFIFOOver | PCSTimeout; + tp->event_slow &= ~RxOverflow; } rtl_set_rx_tx_desc_registers(tp, ioaddr); @@ -4977,8 +5030,6 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_W8(Cfg9346, Cfg9346_Lock); RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); - - RTL_W16(IntrMask, tp->intr_event); } #define R810X_CPCMD_QUIRK_MASK (\ @@ -5077,10 +5128,8 @@ static void rtl_hw_start_8101(struct net_device *dev) void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; - if (tp->mac_version >= RTL_GIGA_MAC_VER_30) { - tp->intr_event &= ~RxFIFOOver; - tp->napi_event &= ~RxFIFOOver; - } + if (tp->mac_version >= RTL_GIGA_MAC_VER_30) + tp->event_slow &= ~RxFIFOOver; if (tp->mac_version == RTL_GIGA_MAC_VER_13 || tp->mac_version == RTL_GIGA_MAC_VER_16) { @@ -5136,8 +5185,6 @@ static void rtl_hw_start_8101(struct net_device *dev) rtl_set_rx_mode(dev); RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); - - RTL_W16(IntrMask, tp->intr_event); } static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) @@ -5330,92 +5377,34 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp) tp->cur_tx = tp->dirty_tx = 0; } -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - PREPARE_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8169_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ - napi_disable(&tp->napi); - - rtl8169_irq_mask_and_ack(tp); - - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -} - -static void rtl8169_reinit_task(struct work_struct *work) +static void rtl_reset_work(struct rtl8169_private *tp) { - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; - int ret; - - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; - - rtl8169_wait_for_quiescence(dev); - rtl8169_close(dev); - - ret = rtl8169_open(dev); - if (unlikely(ret < 0)) { - if (net_ratelimit()) - netif_err(tp, drv, dev, - "reinit failure (status = %d). Rescheduling\n", - ret); - rtl8169_schedule_work(dev, rtl8169_reinit_task); - } - -out_unlock: - rtnl_unlock(); -} - -static void rtl8169_reset_task(struct work_struct *work) -{ - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); struct net_device *dev = tp->dev; int i; - rtnl_lock(); - - if (!netif_running(dev)) - goto out_unlock; + napi_disable(&tp->napi); + netif_stop_queue(dev); + synchronize_sched(); rtl8169_hw_reset(tp); - rtl8169_wait_for_quiescence(dev); - for (i = 0; i < NUM_RX_DESC; i++) rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz); rtl8169_tx_clear(tp); rtl8169_init_ring_indexes(tp); + napi_enable(&tp->napi); rtl_hw_start(dev); netif_wake_queue(dev); rtl8169_check_link_status(dev, tp, tp->mmio_addr); - -out_unlock: - rtnl_unlock(); } static void rtl8169_tx_timeout(struct net_device *dev) { - rtl8169_schedule_work(dev, rtl8169_reset_task); + struct rtl8169_private *tp = netdev_priv(dev); + + rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); } static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, @@ -5552,9 +5541,22 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, RTL_W8(TxPoll, NPQ); + mmiowb(); + if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { + /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must + * not miss a ring update when it notices a stopped queue. + */ + smp_wmb(); netif_stop_queue(dev); - smp_rmb(); + /* Sync with rtl_tx: + * - publish queue status and cur_tx ring index (write barrier) + * - refresh dirty_tx ring index (read barrier). + * May the current thread have a pessimistic view of the ring + * status and forget to wake up queue, a racing rtl_tx thread + * can't. + */ + smp_mb(); if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) netif_wake_queue(dev); } @@ -5618,12 +5620,10 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) rtl8169_hw_reset(tp); - rtl8169_schedule_work(dev, rtl8169_reinit_task); + rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); } -static void rtl8169_tx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) +static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) { unsigned int dirty_tx, tx_left; @@ -5655,7 +5655,14 @@ static void rtl8169_tx_interrupt(struct net_device *dev, if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; - smp_wmb(); + /* Sync with rtl8169_start_xmit: + * - publish dirty_tx ring index (write barrier) + * - refresh cur_tx ring index and queue status (read barrier) + * May the current thread miss the stopped queue condition, + * a racing xmit thread can only have a right view of the + * ring status. + */ + smp_mb(); if (netif_queue_stopped(dev) && (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { netif_wake_queue(dev); @@ -5666,9 +5673,11 @@ static void rtl8169_tx_interrupt(struct net_device *dev, * of start_xmit activity is detected (if it is not detected, * it is slow enough). -- FR */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) + if (tp->cur_tx != dirty_tx) { + void __iomem *ioaddr = tp->mmio_addr; + RTL_W8(TxPoll, NPQ); + } } } @@ -5707,9 +5716,7 @@ static struct sk_buff *rtl8169_try_rx_copy(void *data, return skb; } -static int rtl8169_rx_interrupt(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) +static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget) { unsigned int cur_rx, rx_left; unsigned int count; @@ -5737,7 +5744,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, if (status & RxCRC) dev->stats.rx_crc_errors++; if (status & RxFOVF) { - rtl8169_schedule_work(dev, rtl8169_reset_task); + rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); dev->stats.rx_fifo_errors++; } rtl8169_mark_to_asic(desc, rx_buf_sz); @@ -5798,101 +5805,120 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) { struct net_device *dev = dev_instance; struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; int handled = 0; - int status; + u16 status; - /* loop handling interrupts until we have no new ones or - * we hit a invalid/hotplug case. - */ - status = RTL_R16(IntrStatus); - while (status && status != 0xffff) { - status &= tp->intr_event; - if (!status) - break; + status = rtl_get_events(tp); + if (status && status != 0xffff) { + status &= RTL_EVENT_NAPI | tp->event_slow; + if (status) { + handled = 1; - handled = 1; + rtl_irq_disable(tp); + napi_schedule(&tp->napi); + } + } + return IRQ_RETVAL(handled); +} - /* Handle all of the error cases first. These will reset - * the chip, so just exit the loop. - */ - if (unlikely(!netif_running(dev))) { - rtl8169_hw_reset(tp); +/* + * Workqueue context. + */ +static void rtl_slow_event_work(struct rtl8169_private *tp) +{ + struct net_device *dev = tp->dev; + u16 status; + + status = rtl_get_events(tp) & tp->event_slow; + rtl_ack_events(tp, status); + + if (unlikely(status & RxFIFOOver)) { + switch (tp->mac_version) { + /* Work around for rx fifo overflow */ + case RTL_GIGA_MAC_VER_11: + netif_stop_queue(dev); + /* XXX - Hack alert. See rtl_task(). */ + set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags); + default: break; } + } - if (unlikely(status & RxFIFOOver)) { - switch (tp->mac_version) { - /* Work around for rx fifo overflow */ - case RTL_GIGA_MAC_VER_11: - netif_stop_queue(dev); - rtl8169_tx_timeout(dev); - goto done; - default: - break; - } - } + if (unlikely(status & SYSErr)) + rtl8169_pcierr_interrupt(dev); - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - break; - } + if (status & LinkChg) + __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true); - if (status & LinkChg) - __rtl8169_check_link_status(dev, tp, ioaddr, true); + napi_disable(&tp->napi); + rtl_irq_disable(tp); - /* We need to see the lastest version of tp->intr_mask to - * avoid ignoring an MSI interrupt and having to wait for - * another event which may never come. - */ - smp_rmb(); - if (status & tp->intr_mask & tp->napi_event) { - RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); - tp->intr_mask = ~tp->napi_event; - - if (likely(napi_schedule_prep(&tp->napi))) - __napi_schedule(&tp->napi); - else - netif_info(tp, intr, dev, - "interrupt %04x in poll\n", status); - } + napi_enable(&tp->napi); + napi_schedule(&tp->napi); +} - /* We only get a new MSI interrupt when all active irq - * sources on the chip have been acknowledged. So, ack - * everything we've seen and check if new sources have become - * active to avoid blocking all interrupts from the chip. - */ - RTL_W16(IntrStatus, - (status & RxFIFOOver) ? (status | RxOverflow) : status); - status = RTL_R16(IntrStatus); +static void rtl_task(struct work_struct *work) +{ + static const struct { + int bitnr; + void (*action)(struct rtl8169_private *); + } rtl_work[] = { + /* XXX - keep rtl_slow_event_work() as first element. */ + { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work }, + { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work }, + { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work } + }; + struct rtl8169_private *tp = + container_of(work, struct rtl8169_private, wk.work); + struct net_device *dev = tp->dev; + int i; + + rtl_lock_work(tp); + + if (!netif_running(dev) || + !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags)) + goto out_unlock; + + for (i = 0; i < ARRAY_SIZE(rtl_work); i++) { + bool pending; + + pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags); + if (pending) + rtl_work[i].action(tp); } -done: - return IRQ_RETVAL(handled); + +out_unlock: + rtl_unlock_work(tp); } static int rtl8169_poll(struct napi_struct *napi, int budget) { struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); struct net_device *dev = tp->dev; - void __iomem *ioaddr = tp->mmio_addr; - int work_done; + u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow; + int work_done= 0; + u16 status; + + status = rtl_get_events(tp); + rtl_ack_events(tp, status & ~tp->event_slow); - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); - rtl8169_tx_interrupt(dev, tp, ioaddr); + if (status & RTL_EVENT_NAPI_RX) + work_done = rtl_rx(dev, tp, (u32) budget); + + if (status & RTL_EVENT_NAPI_TX) + rtl_tx(dev, tp); + + if (status & tp->event_slow) { + enable_mask &= ~tp->event_slow; + + rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING); + } if (work_done < budget) { napi_complete(napi); - /* We need for force the visibility of tp->intr_mask - * for other CPUs, as we can loose an MSI interrupt - * and potentially wait for a retransmit timeout if we don't. - * The posted write to IntrMask is safe, as it will - * eventually make it to the chip and we won't loose anything - * until it does. - */ - tp->intr_mask = 0xffff; - wmb(); - RTL_W16(IntrMask, tp->intr_event); + rtl_irq_enable(tp, enable_mask); + mmiowb(); } return work_done; @@ -5916,26 +5942,19 @@ static void rtl8169_down(struct net_device *dev) del_timer_sync(&tp->timer); - netif_stop_queue(dev); - napi_disable(&tp->napi); - - spin_lock_irq(&tp->lock); + netif_stop_queue(dev); rtl8169_hw_reset(tp); /* * At this point device interrupts can not be enabled in any function, - * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task, - * rtl8169_reinit_task) and napi is disabled (rtl8169_poll). + * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task) + * and napi is disabled (rtl8169_poll). */ rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irq(&tp->lock); - - synchronize_irq(dev->irq); - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); /* FIXME: should this be synchronize_irq()? */ + synchronize_sched(); rtl8169_tx_clear(tp); @@ -5954,7 +5973,11 @@ static int rtl8169_close(struct net_device *dev) /* Update counters before going down */ rtl8169_update_counters(dev); + rtl_lock_work(tp); + clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); + rtl8169_down(dev); + rtl_unlock_work(tp); free_irq(dev->irq, dev); @@ -5974,7 +5997,6 @@ static void rtl_set_rx_mode(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; u32 mc_filter[2]; /* Multicast hash filter */ int rx_mode; u32 tmp = 0; @@ -6003,8 +6025,6 @@ static void rtl_set_rx_mode(struct net_device *dev) } } - spin_lock_irqsave(&tp->lock, flags); - tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode; if (tp->mac_version > RTL_GIGA_MAC_VER_06) { @@ -6018,8 +6038,6 @@ static void rtl_set_rx_mode(struct net_device *dev) RTL_W32(MAR0 + 0, mc_filter[0]); RTL_W32(RxConfig, tmp); - - spin_unlock_irqrestore(&tp->lock, flags); } /** @@ -6032,13 +6050,9 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - if (netif_running(dev)) { - spin_lock_irqsave(&tp->lock, flags); + if (netif_running(dev)) rtl8169_rx_missed(dev, ioaddr); - spin_unlock_irqrestore(&tp->lock, flags); - } return &dev->stats; } @@ -6050,10 +6064,15 @@ static void rtl8169_net_suspend(struct net_device *dev) if (!netif_running(dev)) return; - rtl_pll_power_down(tp); - netif_device_detach(dev); netif_stop_queue(dev); + + rtl_lock_work(tp); + napi_disable(&tp->napi); + clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); + rtl_unlock_work(tp); + + rtl_pll_power_down(tp); } #ifdef CONFIG_PM @@ -6076,7 +6095,9 @@ static void __rtl8169_resume(struct net_device *dev) rtl_pll_power_up(tp); - rtl8169_schedule_work(dev, rtl8169_reset_task); + set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); + + rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); } static int rtl8169_resume(struct device *device) @@ -6102,10 +6123,10 @@ static int rtl8169_runtime_suspend(struct device *device) if (!tp->TxDescArray) return 0; - spin_lock_irq(&tp->lock); + rtl_lock_work(tp); tp->saved_wolopts = __rtl8169_get_wol(tp); __rtl8169_set_wol(tp, WAKE_ANY); - spin_unlock_irq(&tp->lock); + rtl_unlock_work(tp); rtl8169_net_suspend(dev); @@ -6121,10 +6142,10 @@ static int rtl8169_runtime_resume(struct device *device) if (!tp->TxDescArray) return 0; - spin_lock_irq(&tp->lock); + rtl_lock_work(tp); __rtl8169_set_wol(tp, tp->saved_wolopts); tp->saved_wolopts = 0; - spin_unlock_irq(&tp->lock); + rtl_unlock_work(tp); rtl8169_init_phy(dev, tp); @@ -6192,12 +6213,8 @@ static void rtl_shutdown(struct pci_dev *pdev) /* Restore original MAC address */ rtl_rar_set(tp, dev->perm_addr); - spin_lock_irq(&tp->lock); - rtl8169_hw_reset(tp); - spin_unlock_irq(&tp->lock); - if (system_state == SYSTEM_POWER_OFF) { if (__rtl8169_get_wol(tp) & WAKE_ANY) { rtl_wol_suspend_quirk(tp); diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 87b650131774..cfad09107054 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -654,13 +654,12 @@ static void sh_eth_ring_format(struct net_device *ndev) for (i = 0; i < RX_RING_SIZE; i++) { /* skb */ mdp->rx_skbuff[i] = NULL; - skb = dev_alloc_skb(mdp->rx_buf_sz); + skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz); mdp->rx_skbuff[i] = skb; if (skb == NULL) break; - dma_map_single(&ndev->dev, skb->tail, mdp->rx_buf_sz, + dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz, DMA_FROM_DEVICE); - skb->dev = ndev; /* Mark as being used by this device. */ sh_eth_set_receive_align(skb); /* RX descriptor */ @@ -883,8 +882,8 @@ static int sh_eth_txfree(struct net_device *ndev) if (entry >= TX_RING_SIZE - 1) txdesc->status |= cpu_to_edmac(mdp, TD_TDLE); - mdp->stats.tx_packets++; - mdp->stats.tx_bytes += txdesc->buffer_length; + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += txdesc->buffer_length; } return freeNum; } @@ -910,23 +909,23 @@ static int sh_eth_rx(struct net_device *ndev) break; if (!(desc_status & RDFEND)) - mdp->stats.rx_length_errors++; + ndev->stats.rx_length_errors++; if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 | RD_RFS5 | RD_RFS6 | RD_RFS10)) { - mdp->stats.rx_errors++; + ndev->stats.rx_errors++; if (desc_status & RD_RFS1) - mdp->stats.rx_crc_errors++; + ndev->stats.rx_crc_errors++; if (desc_status & RD_RFS2) - mdp->stats.rx_frame_errors++; + ndev->stats.rx_frame_errors++; if (desc_status & RD_RFS3) - mdp->stats.rx_length_errors++; + ndev->stats.rx_length_errors++; if (desc_status & RD_RFS4) - mdp->stats.rx_length_errors++; + ndev->stats.rx_length_errors++; if (desc_status & RD_RFS6) - mdp->stats.rx_missed_errors++; + ndev->stats.rx_missed_errors++; if (desc_status & RD_RFS10) - mdp->stats.rx_over_errors++; + ndev->stats.rx_over_errors++; } else { if (!mdp->cd->hw_swap) sh_eth_soft_swap( @@ -939,8 +938,8 @@ static int sh_eth_rx(struct net_device *ndev) skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, ndev); netif_rx(skb); - mdp->stats.rx_packets++; - mdp->stats.rx_bytes += pkt_len; + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += pkt_len; } rxdesc->status |= cpu_to_edmac(mdp, RD_RACT); entry = (++mdp->cur_rx) % RX_RING_SIZE; @@ -955,13 +954,12 @@ static int sh_eth_rx(struct net_device *ndev) rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); if (mdp->rx_skbuff[entry] == NULL) { - skb = dev_alloc_skb(mdp->rx_buf_sz); + skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz); mdp->rx_skbuff[entry] = skb; if (skb == NULL) break; /* Better luck next round. */ - dma_map_single(&ndev->dev, skb->tail, mdp->rx_buf_sz, + dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz, DMA_FROM_DEVICE); - skb->dev = ndev; sh_eth_set_receive_align(skb); skb_checksum_none_assert(skb); @@ -1009,7 +1007,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) felic_stat = sh_eth_read(ndev, ECSR); sh_eth_write(ndev, felic_stat, ECSR); /* clear int */ if (felic_stat & ECSR_ICD) - mdp->stats.tx_carrier_errors++; + ndev->stats.tx_carrier_errors++; if (felic_stat & ECSR_LCHNG) { /* Link Changed */ if (mdp->cd->no_psr || mdp->no_ether_link) { @@ -1042,7 +1040,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) if (intr_status & EESR_TWB) { /* Write buck end. unused write back interrupt */ if (intr_status & EESR_TABT) /* Transmit Abort int */ - mdp->stats.tx_aborted_errors++; + ndev->stats.tx_aborted_errors++; if (netif_msg_tx_err(mdp)) dev_err(&ndev->dev, "Transmit Abort\n"); } @@ -1051,7 +1049,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) /* Receive Abort int */ if (intr_status & EESR_RFRMER) { /* Receive Frame Overflow int */ - mdp->stats.rx_frame_errors++; + ndev->stats.rx_frame_errors++; if (netif_msg_rx_err(mdp)) dev_err(&ndev->dev, "Receive Abort\n"); } @@ -1059,21 +1057,21 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) if (intr_status & EESR_TDE) { /* Transmit Descriptor Empty int */ - mdp->stats.tx_fifo_errors++; + ndev->stats.tx_fifo_errors++; if (netif_msg_tx_err(mdp)) dev_err(&ndev->dev, "Transmit Descriptor Empty\n"); } if (intr_status & EESR_TFE) { /* FIFO under flow */ - mdp->stats.tx_fifo_errors++; + ndev->stats.tx_fifo_errors++; if (netif_msg_tx_err(mdp)) dev_err(&ndev->dev, "Transmit FIFO Under flow\n"); } if (intr_status & EESR_RDE) { /* Receive Descriptor Empty int */ - mdp->stats.rx_over_errors++; + ndev->stats.rx_over_errors++; if (sh_eth_read(ndev, EDRRR) ^ EDRRR_R) sh_eth_write(ndev, EDRRR_R, EDRRR); @@ -1083,14 +1081,14 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) if (intr_status & EESR_RFE) { /* Receive FIFO Overflow int */ - mdp->stats.rx_fifo_errors++; + ndev->stats.rx_fifo_errors++; if (netif_msg_rx_err(mdp)) dev_err(&ndev->dev, "Receive FIFO Overflow\n"); } if (!mdp->cd->no_ade && (intr_status & EESR_ADE)) { /* Address Error */ - mdp->stats.tx_fifo_errors++; + ndev->stats.tx_fifo_errors++; if (netif_msg_tx_err(mdp)) dev_err(&ndev->dev, "Address Error\n"); } @@ -1447,7 +1445,7 @@ static void sh_eth_tx_timeout(struct net_device *ndev) " resetting...\n", ndev->name, (int)sh_eth_read(ndev, EESR)); /* tx_errors count up */ - mdp->stats.tx_errors++; + ndev->stats.tx_errors++; /* timer off */ del_timer_sync(&mdp->timer); @@ -1569,27 +1567,27 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev) pm_runtime_get_sync(&mdp->pdev->dev); - mdp->stats.tx_dropped += sh_eth_read(ndev, TROCR); + ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR); sh_eth_write(ndev, 0, TROCR); /* (write clear) */ - mdp->stats.collisions += sh_eth_read(ndev, CDCR); + ndev->stats.collisions += sh_eth_read(ndev, CDCR); sh_eth_write(ndev, 0, CDCR); /* (write clear) */ - mdp->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR); + ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR); sh_eth_write(ndev, 0, LCCR); /* (write clear) */ if (sh_eth_is_gether(mdp)) { - mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR); + ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR); sh_eth_write(ndev, 0, CERCR); /* (write clear) */ - mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR); + ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR); sh_eth_write(ndev, 0, CEECR); /* (write clear) */ } else { - mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR); + ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR); sh_eth_write(ndev, 0, CNDCR); /* (write clear) */ } pm_runtime_put_sync(&mdp->pdev->dev); - return &mdp->stats; + return &ndev->stats; } -/* ioctl to device funciotn*/ +/* ioctl to device function */ static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) { @@ -1794,7 +1792,6 @@ static int sh_eth_drv_probe(struct platform_device *pdev) ndev = alloc_etherdev(sizeof(struct sh_eth_private)); if (!ndev) { - dev_err(&pdev->dev, "Could not allocate device.\n"); ret = -ENOMEM; goto out; } diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index cdbd844662a7..cb07add8638f 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -759,7 +759,6 @@ struct sh_eth_private { struct sh_eth_txdesc *tx_ring; struct sk_buff **rx_skbuff; struct sk_buff **tx_skbuff; - struct net_device_stats stats; struct timer_list timer; spinlock_t lock; u32 cur_rx, dirty_rx; /* Producer/consumer ring indices */ diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c index 22e9c0181ce8..1895605abb35 100644 --- a/drivers/net/ethernet/s6gmac.c +++ b/drivers/net/ethernet/s6gmac.c @@ -370,12 +370,13 @@ struct s6gmac { } link; }; -static void s6gmac_rx_fillfifo(struct s6gmac *pd) +static void s6gmac_rx_fillfifo(struct net_device *dev) { + struct s6gmac *pd = netdev_priv(dev); struct sk_buff *skb; while ((((u8)(pd->rx_skb_i - pd->rx_skb_o)) < S6_NUM_RX_SKB) && (!s6dmac_fifo_full(pd->rx_dma, pd->rx_chan)) && - (skb = dev_alloc_skb(S6_MAX_FRLEN + 2))) { + (skb = netdev_alloc_skb(dev, S6_MAX_FRLEN + 2))) { pd->rx_skb[(pd->rx_skb_i++) % S6_NUM_RX_SKB] = skb; s6dmac_put_fifo_cache(pd->rx_dma, pd->rx_chan, pd->io, (u32)skb->data, S6_MAX_FRLEN); @@ -514,7 +515,7 @@ static irqreturn_t s6gmac_interrupt(int irq, void *dev_id) spin_lock(&pd->lock); if (s6dmac_termcnt_irq(pd->rx_dma, pd->rx_chan)) s6gmac_rx_interrupt(dev); - s6gmac_rx_fillfifo(pd); + s6gmac_rx_fillfifo(dev); if (s6dmac_termcnt_irq(pd->tx_dma, pd->tx_chan)) s6gmac_tx_interrupt(dev); s6gmac_stats_interrupt(pd, 0); @@ -894,7 +895,7 @@ static int s6gmac_open(struct net_device *dev) s6gmac_init_device(dev); s6gmac_init_stats(dev); s6gmac_init_dmac(dev); - s6gmac_rx_fillfifo(pd); + s6gmac_rx_fillfifo(dev); s6dmac_enable_chan(pd->rx_dma, pd->rx_chan, 2, 1, 0, 1, 0, 0, 0, 7, -1, 2, 0, 1); s6dmac_enable_chan(pd->tx_dma, pd->tx_chan, @@ -960,11 +961,11 @@ static int __devinit s6gmac_probe(struct platform_device *pdev) int res; unsigned long i; struct mii_bus *mb; + dev = alloc_etherdev(sizeof(*pd)); - if (!dev) { - printk(KERN_ERR DRV_PRMT "etherdev alloc failed, aborting.\n"); + if (!dev) return -ENOMEM; - } + dev->open = s6gmac_open; dev->stop = s6gmac_stop; dev->hard_start_xmit = s6gmac_tx; diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c index 893c880dadf0..7b819bd8c416 100644 --- a/drivers/net/ethernet/seeq/ether3.c +++ b/drivers/net/ethernet/seeq/ether3.c @@ -643,7 +643,7 @@ if (next_ptr < RX_START || next_ptr >= RX_END) { if (next_ptr <= this_ptr) length += RX_END - RX_START; - skb = dev_alloc_skb(length + 2); + skb = netdev_alloc_skb(dev, length + 2); if (skb) { unsigned char *buf; diff --git a/drivers/net/ethernet/seeq/seeq8005.c b/drivers/net/ethernet/seeq/seeq8005.c index 60561451789b..798990774446 100644 --- a/drivers/net/ethernet/seeq/seeq8005.c +++ b/drivers/net/ethernet/seeq/seeq8005.c @@ -548,7 +548,7 @@ static void seeq8005_rx(struct net_device *dev) struct sk_buff *skb; unsigned char *buf; - skb = dev_alloc_skb(pkt_len); + skb = netdev_alloc_skb(dev, pkt_len); if (skb == NULL) { printk("%s: Memory squeeze, dropping packet.\n", dev->name); dev->stats.rx_dropped++; diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c index f955a19eb22f..bb8c8222122b 100644 --- a/drivers/net/ethernet/seeq/sgiseeq.c +++ b/drivers/net/ethernet/seeq/sgiseeq.c @@ -733,7 +733,6 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev) dev = alloc_etherdev(sizeof (struct sgiseeq_private)); if (!dev) { - printk(KERN_ERR "Sgiseeq: Etherdev alloc failed, aborting.\n"); err = -ENOMEM; goto err_out; } diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig index 5d18841f0f3d..8d423544a7e6 100644 --- a/drivers/net/ethernet/sfc/Kconfig +++ b/drivers/net/ethernet/sfc/Kconfig @@ -16,6 +16,13 @@ config SFC_MTD depends on SFC && MTD && !(SFC=y && MTD=m) default y ---help--- - This exposes the on-board flash memory as MTD devices (e.g. - /dev/mtd1). This makes it possible to upload new firmware - to the NIC. + This exposes the on-board flash and/or EEPROM as MTD devices + (e.g. /dev/mtd1). This is required to update the firmware or + the boot configuration under Linux. +config SFC_MCDI_MON + bool "Solarflare SFC9000-family hwmon support" + depends on SFC && HWMON && !(SFC=y && HWMON=m) + default y + ----help--- + This exposes the on-board firmware-managed sensors as a + hardware monitor device. diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile index ab31c7124db1..3fa2e25ccc45 100644 --- a/drivers/net/ethernet/sfc/Makefile +++ b/drivers/net/ethernet/sfc/Makefile @@ -2,7 +2,7 @@ sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \ falcon_xmac.o mcdi_mac.o \ selftest.o ethtool.o qt202x_phy.o mdio_10g.o \ tenxpress.o txc43128_phy.o falcon_boards.o \ - mcdi.o mcdi_phy.o + mcdi.o mcdi_phy.o mcdi_mon.o sfc-$(CONFIG_SFC_MTD) += mtd.o obj-$(CONFIG_SFC) += sfc.o diff --git a/drivers/net/ethernet/sfc/bitfield.h b/drivers/net/ethernet/sfc/bitfield.h index 098ac2ad757d..a2a9f40b90cf 100644 --- a/drivers/net/ethernet/sfc/bitfield.h +++ b/drivers/net/ethernet/sfc/bitfield.h @@ -448,40 +448,40 @@ typedef union efx_oword { EFX_INSERT32(min, max, low, high, EFX_MASK32(high + 1 - low)) #define EFX_SET_OWORD64(oword, low, high, value) do { \ - (oword).u64[0] = (((oword).u64[0] \ + (oword).u64[0] = (((oword).u64[0] \ & ~EFX_INPLACE_MASK64(0, 63, low, high)) \ | EFX_INSERT64(0, 63, low, high, value)); \ - (oword).u64[1] = (((oword).u64[1] \ + (oword).u64[1] = (((oword).u64[1] \ & ~EFX_INPLACE_MASK64(64, 127, low, high)) \ | EFX_INSERT64(64, 127, low, high, value)); \ } while (0) #define EFX_SET_QWORD64(qword, low, high, value) do { \ - (qword).u64[0] = (((qword).u64[0] \ + (qword).u64[0] = (((qword).u64[0] \ & ~EFX_INPLACE_MASK64(0, 63, low, high)) \ | EFX_INSERT64(0, 63, low, high, value)); \ } while (0) #define EFX_SET_OWORD32(oword, low, high, value) do { \ - (oword).u32[0] = (((oword).u32[0] \ + (oword).u32[0] = (((oword).u32[0] \ & ~EFX_INPLACE_MASK32(0, 31, low, high)) \ | EFX_INSERT32(0, 31, low, high, value)); \ - (oword).u32[1] = (((oword).u32[1] \ + (oword).u32[1] = (((oword).u32[1] \ & ~EFX_INPLACE_MASK32(32, 63, low, high)) \ | EFX_INSERT32(32, 63, low, high, value)); \ - (oword).u32[2] = (((oword).u32[2] \ + (oword).u32[2] = (((oword).u32[2] \ & ~EFX_INPLACE_MASK32(64, 95, low, high)) \ | EFX_INSERT32(64, 95, low, high, value)); \ - (oword).u32[3] = (((oword).u32[3] \ + (oword).u32[3] = (((oword).u32[3] \ & ~EFX_INPLACE_MASK32(96, 127, low, high)) \ | EFX_INSERT32(96, 127, low, high, value)); \ } while (0) #define EFX_SET_QWORD32(qword, low, high, value) do { \ - (qword).u32[0] = (((qword).u32[0] \ + (qword).u32[0] = (((qword).u32[0] \ & ~EFX_INPLACE_MASK32(0, 31, low, high)) \ | EFX_INSERT32(0, 31, low, high, value)); \ - (qword).u32[1] = (((qword).u32[1] \ + (qword).u32[1] = (((qword).u32[1] \ & ~EFX_INPLACE_MASK32(32, 63, low, high)) \ | EFX_INSERT32(32, 63, low, high, value)); \ } while (0) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index e43702f33b62..952d0bf7695a 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -38,15 +38,15 @@ /* Loopback mode names (see LOOPBACK_MODE()) */ const unsigned int efx_loopback_mode_max = LOOPBACK_MAX; -const char *efx_loopback_mode_names[] = { +const char *const efx_loopback_mode_names[] = { [LOOPBACK_NONE] = "NONE", [LOOPBACK_DATA] = "DATAPATH", [LOOPBACK_GMAC] = "GMAC", [LOOPBACK_XGMII] = "XGMII", [LOOPBACK_XGXS] = "XGXS", - [LOOPBACK_XAUI] = "XAUI", - [LOOPBACK_GMII] = "GMII", - [LOOPBACK_SGMII] = "SGMII", + [LOOPBACK_XAUI] = "XAUI", + [LOOPBACK_GMII] = "GMII", + [LOOPBACK_SGMII] = "SGMII", [LOOPBACK_XGBR] = "XGBR", [LOOPBACK_XFI] = "XFI", [LOOPBACK_XAUI_FAR] = "XAUI_FAR", @@ -55,21 +55,21 @@ const char *efx_loopback_mode_names[] = { [LOOPBACK_XFI_FAR] = "XFI_FAR", [LOOPBACK_GPHY] = "GPHY", [LOOPBACK_PHYXS] = "PHYXS", - [LOOPBACK_PCS] = "PCS", - [LOOPBACK_PMAPMD] = "PMA/PMD", + [LOOPBACK_PCS] = "PCS", + [LOOPBACK_PMAPMD] = "PMA/PMD", [LOOPBACK_XPORT] = "XPORT", [LOOPBACK_XGMII_WS] = "XGMII_WS", - [LOOPBACK_XAUI_WS] = "XAUI_WS", + [LOOPBACK_XAUI_WS] = "XAUI_WS", [LOOPBACK_XAUI_WS_FAR] = "XAUI_WS_FAR", [LOOPBACK_XAUI_WS_NEAR] = "XAUI_WS_NEAR", - [LOOPBACK_GMII_WS] = "GMII_WS", + [LOOPBACK_GMII_WS] = "GMII_WS", [LOOPBACK_XFI_WS] = "XFI_WS", [LOOPBACK_XFI_WS_FAR] = "XFI_WS_FAR", - [LOOPBACK_PHYXS_WS] = "PHYXS_WS", + [LOOPBACK_PHYXS_WS] = "PHYXS_WS", }; const unsigned int efx_reset_type_max = RESET_TYPE_MAX; -const char *efx_reset_type_names[] = { +const char *const efx_reset_type_names[] = { [RESET_TYPE_INVISIBLE] = "INVISIBLE", [RESET_TYPE_ALL] = "ALL", [RESET_TYPE_WORLD] = "WORLD", @@ -122,15 +122,6 @@ static int napi_weight = 64; */ static unsigned int efx_monitor_interval = 1 * HZ; -/* This controls whether or not the driver will initialise devices - * with invalid MAC addresses stored in the EEPROM or flash. If true, - * such devices will be initialised with a random locally-generated - * MAC address. This allows for loading the sfc_mtd driver to - * reprogram the flash, even if the flash contents (including the MAC - * address) have previously been erased. - */ -static unsigned int allow_bad_hwaddr; - /* Initial interrupt moderation settings. They can be modified after * module load with ethtool. * @@ -162,7 +153,7 @@ static unsigned int interrupt_mode; * interrupt handling. * * Cards without MSI-X will only target one CPU via legacy or MSI interrupt. - * The default (0) means to assign an interrupt to each package (level II cache) + * The default (0) means to assign an interrupt to each core. */ static unsigned int rss_cpus; module_param(rss_cpus, uint, 0444); @@ -238,8 +229,7 @@ static int efx_process_channel(struct efx_channel *channel, int budget) /* Deliver last RX packet. */ if (channel->rx_pkt) { - __efx_rx_packet(channel, channel->rx_pkt, - channel->rx_pkt_csummed); + __efx_rx_packet(channel, channel->rx_pkt); channel->rx_pkt = NULL; } @@ -373,7 +363,7 @@ static int efx_probe_eventq(struct efx_channel *channel) struct efx_nic *efx = channel->efx; unsigned long entries; - netif_dbg(channel->efx, probe, channel->efx->net_dev, + netif_dbg(efx, probe, efx->net_dev, "chan %d create event queue\n", channel->channel); /* Build an event queue with room for one event per tx and rx buffer, @@ -807,16 +797,14 @@ void efx_link_status_changed(struct efx_nic *efx) } /* Status message for kernel log */ - if (link_state->up) { + if (link_state->up) netif_info(efx, link, efx->net_dev, "link up at %uMbps %s-duplex (MTU %d)%s\n", link_state->speed, link_state->fd ? "full" : "half", efx->net_dev->mtu, (efx->promiscuous ? " [PROMISC]" : "")); - } else { + else netif_info(efx, link, efx->net_dev, "link down\n"); - } - } void efx_link_set_advertising(struct efx_nic *efx, u32 advertising) @@ -863,11 +851,9 @@ int __efx_reconfigure_port(struct efx_nic *efx) WARN_ON(!mutex_is_locked(&efx->mac_lock)); - /* Serialise the promiscuous flag with efx_set_multicast_list. */ - if (efx_dev_registered(efx)) { - netif_addr_lock_bh(efx->net_dev); - netif_addr_unlock_bh(efx->net_dev); - } + /* Serialise the promiscuous flag with efx_set_rx_mode. */ + netif_addr_lock_bh(efx->net_dev); + netif_addr_unlock_bh(efx->net_dev); /* Disable PHY transmit in mac level loopbacks */ phy_mode = efx->phy_mode; @@ -907,16 +893,13 @@ static void efx_mac_work(struct work_struct *data) struct efx_nic *efx = container_of(data, struct efx_nic, mac_work); mutex_lock(&efx->mac_lock); - if (efx->port_enabled) { - efx->type->push_multicast_hash(efx); - efx->mac_op->reconfigure(efx); - } + if (efx->port_enabled) + efx->type->reconfigure_mac(efx); mutex_unlock(&efx->mac_lock); } static int efx_probe_port(struct efx_nic *efx) { - unsigned char *perm_addr; int rc; netif_dbg(efx, probe, efx->net_dev, "create port\n"); @@ -929,28 +912,10 @@ static int efx_probe_port(struct efx_nic *efx) if (rc) return rc; - /* Sanity check MAC address */ - perm_addr = efx->net_dev->perm_addr; - if (is_valid_ether_addr(perm_addr)) { - memcpy(efx->net_dev->dev_addr, perm_addr, ETH_ALEN); - } else { - netif_err(efx, probe, efx->net_dev, "invalid MAC address %pM\n", - perm_addr); - if (!allow_bad_hwaddr) { - rc = -EINVAL; - goto err; - } - random_ether_addr(efx->net_dev->dev_addr); - netif_info(efx, probe, efx->net_dev, - "using locally-generated MAC %pM\n", - efx->net_dev->dev_addr); - } + /* Initialise MAC address to permanent address */ + memcpy(efx->net_dev->dev_addr, efx->net_dev->perm_addr, ETH_ALEN); return 0; - - err: - efx->type->remove_port(efx); - return rc; } static int efx_init_port(struct efx_nic *efx) @@ -969,7 +934,7 @@ static int efx_init_port(struct efx_nic *efx) /* Reconfigure the MAC before creating dma queues (required for * Falcon/A1 where RX_INGR_EN/TX_DRAIN_EN isn't supported) */ - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); /* Ensure the PHY advertises the correct flow control settings */ rc = efx->phy_op->reconfigure(efx); @@ -996,8 +961,7 @@ static void efx_start_port(struct efx_nic *efx) /* efx_mac_work() might have been scheduled after efx_stop_port(), * and then cancelled by efx_flush_all() */ - efx->type->push_multicast_hash(efx); - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); mutex_unlock(&efx->mac_lock); } @@ -1012,10 +976,8 @@ static void efx_stop_port(struct efx_nic *efx) mutex_unlock(&efx->mac_lock); /* Serialise against efx_set_multicast_list() */ - if (efx_dev_registered(efx)) { - netif_addr_lock_bh(efx->net_dev); - netif_addr_unlock_bh(efx->net_dev); - } + netif_addr_lock_bh(efx->net_dev); + netif_addr_unlock_bh(efx->net_dev); } static void efx_fini_port(struct efx_nic *efx) @@ -1069,9 +1031,11 @@ static int efx_init_io(struct efx_nic *efx) * masks event though they reject 46 bit masks. */ while (dma_mask > 0x7fffffffUL) { - if (pci_dma_supported(pci_dev, dma_mask) && - ((rc = pci_set_dma_mask(pci_dev, dma_mask)) == 0)) - break; + if (pci_dma_supported(pci_dev, dma_mask)) { + rc = pci_set_dma_mask(pci_dev, dma_mask); + if (rc == 0) + break; + } dma_mask >>= 1; } if (rc) { @@ -1144,18 +1108,16 @@ static void efx_fini_io(struct efx_nic *efx) pci_disable_device(efx->pci_dev); } -/* Get number of channels wanted. Each channel will have its own IRQ, - * 1 RX queue and/or 2 TX queues. */ -static int efx_wanted_channels(void) +static int efx_wanted_parallelism(void) { - cpumask_var_t core_mask; + cpumask_var_t thread_mask; int count; int cpu; if (rss_cpus) return rss_cpus; - if (unlikely(!zalloc_cpumask_var(&core_mask, GFP_KERNEL))) { + if (unlikely(!zalloc_cpumask_var(&thread_mask, GFP_KERNEL))) { printk(KERN_WARNING "sfc: RSS disabled due to allocation failure\n"); return 1; @@ -1163,14 +1125,14 @@ static int efx_wanted_channels(void) count = 0; for_each_online_cpu(cpu) { - if (!cpumask_test_cpu(cpu, core_mask)) { + if (!cpumask_test_cpu(cpu, thread_mask)) { ++count; - cpumask_or(core_mask, core_mask, - topology_core_cpumask(cpu)); + cpumask_or(thread_mask, thread_mask, + topology_thread_cpumask(cpu)); } } - free_cpumask_var(core_mask); + free_cpumask_var(thread_mask); return count; } @@ -1209,7 +1171,7 @@ static int efx_probe_interrupts(struct efx_nic *efx) struct msix_entry xentries[EFX_MAX_CHANNELS]; int n_channels; - n_channels = efx_wanted_channels(); + n_channels = efx_wanted_parallelism(); if (separate_tx_channels) n_channels *= 2; n_channels = min(n_channels, max_channels); @@ -1425,14 +1387,14 @@ static void efx_start_all(struct efx_nic *efx) return; if ((efx->state != STATE_RUNNING) && (efx->state != STATE_INIT)) return; - if (efx_dev_registered(efx) && !netif_running(efx->net_dev)) + if (!netif_running(efx->net_dev)) return; /* Mark the port as enabled so port reconfigurations can start, then * restart the transmit interface early so the watchdog timer stops */ efx_start_port(efx); - if (efx_dev_registered(efx) && netif_device_present(efx->net_dev)) + if (netif_device_present(efx->net_dev)) netif_tx_wake_all_queues(efx->net_dev); efx_for_each_channel(channel, efx) @@ -1523,11 +1485,9 @@ static void efx_stop_all(struct efx_nic *efx) /* Stop the kernel transmit interface late, so the watchdog * timer isn't ticking over the flush */ - if (efx_dev_registered(efx)) { - netif_tx_stop_all_queues(efx->net_dev); - netif_tx_lock_bh(efx->net_dev); - netif_tx_unlock_bh(efx->net_dev); - } + netif_tx_stop_all_queues(efx->net_dev); + netif_tx_lock_bh(efx->net_dev); + netif_tx_unlock_bh(efx->net_dev); } static void efx_remove_all(struct efx_nic *efx) @@ -1544,13 +1504,13 @@ static void efx_remove_all(struct efx_nic *efx) * **************************************************************************/ -static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int resolution) +static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int quantum_ns) { if (usecs == 0) return 0; - if (usecs < resolution) + if (usecs * 1000 < quantum_ns) return 1; /* never round down to 0 */ - return usecs / resolution; + return usecs * 1000 / quantum_ns; } /* Set interrupt moderation parameters */ @@ -1559,14 +1519,20 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs, bool rx_may_override_tx) { struct efx_channel *channel; - unsigned tx_ticks = irq_mod_ticks(tx_usecs, EFX_IRQ_MOD_RESOLUTION); - unsigned rx_ticks = irq_mod_ticks(rx_usecs, EFX_IRQ_MOD_RESOLUTION); + unsigned int irq_mod_max = DIV_ROUND_UP(efx->type->timer_period_max * + efx->timer_quantum_ns, + 1000); + unsigned int tx_ticks; + unsigned int rx_ticks; EFX_ASSERT_RESET_SERIALISED(efx); - if (tx_ticks > EFX_IRQ_MOD_MAX || rx_ticks > EFX_IRQ_MOD_MAX) + if (tx_usecs > irq_mod_max || rx_usecs > irq_mod_max) return -EINVAL; + tx_ticks = irq_mod_ticks(tx_usecs, efx->timer_quantum_ns); + rx_ticks = irq_mod_ticks(rx_usecs, efx->timer_quantum_ns); + if (tx_ticks != rx_ticks && efx->tx_channel_offset == 0 && !rx_may_override_tx) { netif_err(efx, drv, efx->net_dev, "Channels are shared. " @@ -1589,8 +1555,14 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs, void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs, unsigned int *rx_usecs, bool *rx_adaptive) { + /* We must round up when converting ticks to microseconds + * because we round down when converting the other way. + */ + *rx_adaptive = efx->irq_rx_adaptive; - *rx_usecs = efx->irq_rx_moderation * EFX_IRQ_MOD_RESOLUTION; + *rx_usecs = DIV_ROUND_UP(efx->irq_rx_moderation * + efx->timer_quantum_ns, + 1000); /* If channels are shared between RX and TX, so is IRQ * moderation. Otherwise, IRQ moderation is the same for all @@ -1599,9 +1571,10 @@ void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs, if (efx->tx_channel_offset == 0) *tx_usecs = *rx_usecs; else - *tx_usecs = + *tx_usecs = DIV_ROUND_UP( efx->channel[efx->tx_channel_offset]->irq_moderation * - EFX_IRQ_MOD_RESOLUTION; + efx->timer_quantum_ns, + 1000); } /************************************************************************** @@ -1765,14 +1738,15 @@ static int efx_net_stop(struct net_device *net_dev) } /* Context: process, dev_base_lock or RTNL held, non-blocking. */ -static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, struct rtnl_link_stats64 *stats) +static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, + struct rtnl_link_stats64 *stats) { struct efx_nic *efx = netdev_priv(net_dev); struct efx_mac_stats *mac_stats = &efx->mac_stats; spin_lock_bh(&efx->stats_lock); + efx->type->update_stats(efx); - spin_unlock_bh(&efx->stats_lock); stats->rx_packets = mac_stats->rx_packets; stats->tx_packets = mac_stats->tx_packets; @@ -1796,6 +1770,8 @@ static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, struc stats->tx_errors = (stats->tx_window_errors + mac_stats->tx_bad); + spin_unlock_bh(&efx->stats_lock); + return stats; } @@ -1816,7 +1792,6 @@ static void efx_watchdog(struct net_device *net_dev) static int efx_change_mtu(struct net_device *net_dev, int new_mtu) { struct efx_nic *efx = netdev_priv(net_dev); - int rc = 0; EFX_ASSERT_RESET_SERIALISED(efx); @@ -1833,13 +1808,13 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu) /* Reconfigure the MAC before enabling the dma queues so that * the RX buffers don't overflow */ net_dev->mtu = new_mtu; - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); mutex_unlock(&efx->mac_lock); efx_init_channels(efx); efx_start_all(efx); - return rc; + return 0; } static int efx_set_mac_address(struct net_device *net_dev, void *data) @@ -1861,14 +1836,14 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) /* Reconfigure the MAC */ mutex_lock(&efx->mac_lock); - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); mutex_unlock(&efx->mac_lock); return 0; } /* Context: netif_addr_lock held, BHs disabled. */ -static void efx_set_multicast_list(struct net_device *net_dev) +static void efx_set_rx_mode(struct net_device *net_dev) { struct efx_nic *efx = netdev_priv(net_dev); struct netdev_hw_addr *ha; @@ -1922,7 +1897,7 @@ static const struct net_device_ops efx_netdev_ops = { .ndo_do_ioctl = efx_ioctl, .ndo_change_mtu = efx_change_mtu, .ndo_set_mac_address = efx_set_mac_address, - .ndo_set_rx_mode = efx_set_multicast_list, + .ndo_set_rx_mode = efx_set_rx_mode, .ndo_set_features = efx_set_features, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = efx_netpoll, @@ -1975,10 +1950,6 @@ static int efx_register_netdev(struct efx_nic *efx) net_dev->netdev_ops = &efx_netdev_ops; SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops); - /* Clear MAC statistics */ - efx->mac_op->update_stats(efx); - memset(&efx->mac_stats, 0, sizeof(efx->mac_stats)); - rtnl_lock(); rc = dev_alloc_name(net_dev, net_dev->name); @@ -1997,7 +1968,7 @@ static int efx_register_netdev(struct efx_nic *efx) } /* Always start with carrier off; PHY events will detect the link */ - netif_carrier_off(efx->net_dev); + netif_carrier_off(net_dev); rtnl_unlock(); @@ -2038,11 +2009,9 @@ static void efx_unregister_netdev(struct efx_nic *efx) efx_release_tx_buffers(tx_queue); } - if (efx_dev_registered(efx)) { - strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name)); - device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type); - unregister_netdev(efx->net_dev); - } + strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name)); + device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type); + unregister_netdev(efx->net_dev); } /************************************************************************** @@ -2095,7 +2064,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) "could not restore PHY settings\n"); } - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); efx_init_channels(efx); efx_restore_filters(efx); @@ -2300,7 +2269,6 @@ static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type, efx->net_dev = net_dev; spin_lock_init(&efx->stats_lock); mutex_init(&efx->mac_lock); - efx->mac_op = type->default_mac_ops; efx->phy_op = &efx_dummy_phy_operations; efx->mdio.dev = net_dev; INIT_WORK(&efx->mac_work, efx_mac_work); @@ -2459,7 +2427,7 @@ static int efx_pci_probe_main(struct efx_nic *efx) /* NIC initialisation * * This is called at module load (or hotplug insertion, - * theoretically). It sets up PCI mappings, tests and resets the NIC, + * theoretically). It sets up PCI mappings, resets the NIC, * sets up and registers the network devices with the kernel and hooks * the interrupt service routine. It does not prepare the device for * transmission; this is left to the first time one of the network @@ -2658,7 +2626,7 @@ static int efx_pm_suspend(struct device *dev) return rc; } -static struct dev_pm_ops efx_pm_ops = { +static const struct dev_pm_ops efx_pm_ops = { .suspend = efx_pm_suspend, .resume = efx_pm_resume, .freeze = efx_pm_freeze, diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index a3541ac6ea01..7f546e2c39e2 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -40,9 +40,9 @@ extern void efx_rx_strategy(struct efx_channel *channel); extern void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue); extern void efx_rx_slow_fill(unsigned long context); extern void __efx_rx_packet(struct efx_channel *channel, - struct efx_rx_buffer *rx_buf, bool checksummed); + struct efx_rx_buffer *rx_buf); extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, - unsigned int len, bool checksummed, bool discard); + unsigned int len, u16 flags); extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); #define EFX_MAX_DMAQ_SIZE 4096UL @@ -145,6 +145,12 @@ static inline void efx_schedule_channel(struct efx_channel *channel) napi_schedule(&channel->napi_str); } +static inline void efx_schedule_channel_irq(struct efx_channel *channel) +{ + channel->last_irq_cpu = raw_smp_processor_id(); + efx_schedule_channel(channel); +} + extern void efx_link_status_changed(struct efx_nic *efx); extern void efx_link_set_advertising(struct efx_nic *efx, u32); extern void efx_link_set_wanted_fc(struct efx_nic *efx, u8); diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 29b2ebfef19f..f887f65e4189 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -52,11 +52,6 @@ static u64 efx_get_uint_stat(void *field) return *(unsigned int *)field; } -static u64 efx_get_ulong_stat(void *field) -{ - return *(unsigned long *)field; -} - static u64 efx_get_u64_stat(void *field) { return *(u64 *) field; @@ -67,12 +62,8 @@ static u64 efx_get_atomic_stat(void *field) return atomic_read((atomic_t *) field); } -#define EFX_ETHTOOL_ULONG_MAC_STAT(field) \ - EFX_ETHTOOL_STAT(field, mac_stats, field, \ - unsigned long, efx_get_ulong_stat) - #define EFX_ETHTOOL_U64_MAC_STAT(field) \ - EFX_ETHTOOL_STAT(field, mac_stats, field, \ + EFX_ETHTOOL_STAT(field, mac_stats, field, \ u64, efx_get_u64_stat) #define EFX_ETHTOOL_UINT_NIC_STAT(name) \ @@ -91,36 +82,36 @@ static u64 efx_get_atomic_stat(void *field) EFX_ETHTOOL_STAT(tx_##field, tx_queue, field, \ unsigned int, efx_get_uint_stat) -static struct efx_ethtool_stat efx_ethtool_stats[] = { +static const struct efx_ethtool_stat efx_ethtool_stats[] = { EFX_ETHTOOL_U64_MAC_STAT(tx_bytes), EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes), EFX_ETHTOOL_U64_MAC_STAT(tx_bad_bytes), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_packets), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_bad), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_pause), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_control), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_unicast), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_multicast), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_broadcast), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_lt64), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_64), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_65_to_127), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_128_to_255), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_256_to_511), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_512_to_1023), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_1024_to_15xx), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_15xx_to_jumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_gtjumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_collision), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_single_collision), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_multiple_collision), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_collision), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_deferred), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_late_collision), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_deferred), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_non_tcpudp), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_mac_src_error), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_ip_src_error), + EFX_ETHTOOL_U64_MAC_STAT(tx_packets), + EFX_ETHTOOL_U64_MAC_STAT(tx_bad), + EFX_ETHTOOL_U64_MAC_STAT(tx_pause), + EFX_ETHTOOL_U64_MAC_STAT(tx_control), + EFX_ETHTOOL_U64_MAC_STAT(tx_unicast), + EFX_ETHTOOL_U64_MAC_STAT(tx_multicast), + EFX_ETHTOOL_U64_MAC_STAT(tx_broadcast), + EFX_ETHTOOL_U64_MAC_STAT(tx_lt64), + EFX_ETHTOOL_U64_MAC_STAT(tx_64), + EFX_ETHTOOL_U64_MAC_STAT(tx_65_to_127), + EFX_ETHTOOL_U64_MAC_STAT(tx_128_to_255), + EFX_ETHTOOL_U64_MAC_STAT(tx_256_to_511), + EFX_ETHTOOL_U64_MAC_STAT(tx_512_to_1023), + EFX_ETHTOOL_U64_MAC_STAT(tx_1024_to_15xx), + EFX_ETHTOOL_U64_MAC_STAT(tx_15xx_to_jumbo), + EFX_ETHTOOL_U64_MAC_STAT(tx_gtjumbo), + EFX_ETHTOOL_U64_MAC_STAT(tx_collision), + EFX_ETHTOOL_U64_MAC_STAT(tx_single_collision), + EFX_ETHTOOL_U64_MAC_STAT(tx_multiple_collision), + EFX_ETHTOOL_U64_MAC_STAT(tx_excessive_collision), + EFX_ETHTOOL_U64_MAC_STAT(tx_deferred), + EFX_ETHTOOL_U64_MAC_STAT(tx_late_collision), + EFX_ETHTOOL_U64_MAC_STAT(tx_excessive_deferred), + EFX_ETHTOOL_U64_MAC_STAT(tx_non_tcpudp), + EFX_ETHTOOL_U64_MAC_STAT(tx_mac_src_error), + EFX_ETHTOOL_U64_MAC_STAT(tx_ip_src_error), EFX_ETHTOOL_UINT_TXQ_STAT(tso_bursts), EFX_ETHTOOL_UINT_TXQ_STAT(tso_long_headers), EFX_ETHTOOL_UINT_TXQ_STAT(tso_packets), @@ -128,34 +119,34 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = { EFX_ETHTOOL_U64_MAC_STAT(rx_bytes), EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes), EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_packets), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_good), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_pause), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_control), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_unicast), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_multicast), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_broadcast), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_lt64), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_64), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_65_to_127), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_128_to_255), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_256_to_511), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_512_to_1023), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_1024_to_15xx), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_15xx_to_jumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_gtjumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_lt64), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_64_to_15xx), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_15xx_to_jumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_gtjumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_overflow), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_missed), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_false_carrier), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_symbol_error), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_align_error), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_length_error), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_internal_error), + EFX_ETHTOOL_U64_MAC_STAT(rx_packets), + EFX_ETHTOOL_U64_MAC_STAT(rx_good), + EFX_ETHTOOL_U64_MAC_STAT(rx_bad), + EFX_ETHTOOL_U64_MAC_STAT(rx_pause), + EFX_ETHTOOL_U64_MAC_STAT(rx_control), + EFX_ETHTOOL_U64_MAC_STAT(rx_unicast), + EFX_ETHTOOL_U64_MAC_STAT(rx_multicast), + EFX_ETHTOOL_U64_MAC_STAT(rx_broadcast), + EFX_ETHTOOL_U64_MAC_STAT(rx_lt64), + EFX_ETHTOOL_U64_MAC_STAT(rx_64), + EFX_ETHTOOL_U64_MAC_STAT(rx_65_to_127), + EFX_ETHTOOL_U64_MAC_STAT(rx_128_to_255), + EFX_ETHTOOL_U64_MAC_STAT(rx_256_to_511), + EFX_ETHTOOL_U64_MAC_STAT(rx_512_to_1023), + EFX_ETHTOOL_U64_MAC_STAT(rx_1024_to_15xx), + EFX_ETHTOOL_U64_MAC_STAT(rx_15xx_to_jumbo), + EFX_ETHTOOL_U64_MAC_STAT(rx_gtjumbo), + EFX_ETHTOOL_U64_MAC_STAT(rx_bad_lt64), + EFX_ETHTOOL_U64_MAC_STAT(rx_bad_64_to_15xx), + EFX_ETHTOOL_U64_MAC_STAT(rx_bad_15xx_to_jumbo), + EFX_ETHTOOL_U64_MAC_STAT(rx_bad_gtjumbo), + EFX_ETHTOOL_U64_MAC_STAT(rx_overflow), + EFX_ETHTOOL_U64_MAC_STAT(rx_missed), + EFX_ETHTOOL_U64_MAC_STAT(rx_false_carrier), + EFX_ETHTOOL_U64_MAC_STAT(rx_symbol_error), + EFX_ETHTOOL_U64_MAC_STAT(rx_align_error), + EFX_ETHTOOL_U64_MAC_STAT(rx_length_error), + EFX_ETHTOOL_U64_MAC_STAT(rx_internal_error), EFX_ETHTOOL_UINT_NIC_STAT(rx_nodesc_drop_cnt), EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset), EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc), @@ -404,10 +395,6 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, &tests->eventq_int[channel->channel], EFX_CHANNEL_NAME(channel), "eventq.int", NULL); - efx_fill_test(n++, strings, data, - &tests->eventq_poll[channel->channel], - EFX_CHANNEL_NAME(channel), - "eventq.poll", NULL); } efx_fill_test(n++, strings, data, &tests->registers, @@ -486,16 +473,17 @@ static void efx_ethtool_get_stats(struct net_device *net_dev, { struct efx_nic *efx = netdev_priv(net_dev); struct efx_mac_stats *mac_stats = &efx->mac_stats; - struct efx_ethtool_stat *stat; + const struct efx_ethtool_stat *stat; struct efx_channel *channel; struct efx_tx_queue *tx_queue; - struct rtnl_link_stats64 temp; int i; EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS); + spin_lock_bh(&efx->stats_lock); + /* Update MAC and NIC statistics */ - dev_get_stats(net_dev, &temp); + efx->type->update_stats(efx); /* Fill detailed statistics buffer */ for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) { @@ -525,6 +513,8 @@ static void efx_ethtool_get_stats(struct net_device *net_dev, break; } } + + spin_unlock_bh(&efx->stats_lock); } static void efx_ethtool_self_test(struct net_device *net_dev, @@ -747,7 +737,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, /* Recover by resetting the EM block */ falcon_stop_nic_stats(efx); falcon_drain_tx_fifo(efx); - efx->mac_op->reconfigure(efx); + falcon_reconfigure_xmac(efx); falcon_start_nic_stats(efx); } else { /* Schedule a reset to recover */ @@ -772,7 +762,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, /* Reconfigure the MAC. The PHY *may* generate a link state change event * if the user just changed the advertised capabilities, but there's no * harm doing this twice */ - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); out: mutex_unlock(&efx->mac_lock); diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 8ae1ebd35397..98285115df10 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -19,7 +19,6 @@ #include "net_driver.h" #include "bitfield.h" #include "efx.h" -#include "mac.h" #include "spi.h" #include "nic.h" #include "regs.h" @@ -89,7 +88,7 @@ static int falcon_getscl(void *data) return EFX_OWORD_FIELD(reg, FRF_AB_GPIO0_IN); } -static struct i2c_algo_bit_data falcon_i2c_bit_operations = { +static const struct i2c_algo_bit_data falcon_i2c_bit_operations = { .setsda = falcon_setsda, .setscl = falcon_setscl, .getsda = falcon_getsda, @@ -104,8 +103,6 @@ static void falcon_push_irq_moderation(struct efx_channel *channel) efx_dword_t timer_cmd; struct efx_nic *efx = channel->efx; - BUILD_BUG_ON(EFX_IRQ_MOD_MAX > (1 << FRF_AB_TC_TIMER_VAL_WIDTH)); - /* Set timer register */ if (channel->irq_moderation) { EFX_POPULATE_DWORD_2(timer_cmd, @@ -177,27 +174,24 @@ irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n", irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker)); + /* Check to see if we have a serious error condition */ + syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); + if (unlikely(syserr)) + return efx_nic_fatal_interrupt(efx); + /* Determine interrupting queues, clear interrupt status * register and acknowledge the device interrupt. */ BUILD_BUG_ON(FSF_AZ_NET_IVEC_INT_Q_WIDTH > EFX_MAX_CHANNELS); queues = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_INT_Q); - - /* Check to see if we have a serious error condition */ - if (queues & (1U << efx->fatal_irq_level)) { - syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); - if (unlikely(syserr)) - return efx_nic_fatal_interrupt(efx); - } - EFX_ZERO_OWORD(*int_ker); wmb(); /* Ensure the vector is cleared before interrupt ack */ falcon_irq_ack_a1(efx); if (queues & 1) - efx_schedule_channel(efx_get_channel(efx, 0)); + efx_schedule_channel_irq(efx_get_channel(efx, 0)); if (queues & 2) - efx_schedule_channel(efx_get_channel(efx, 1)); + efx_schedule_channel_irq(efx_get_channel(efx, 1)); return IRQ_HANDLED; } /************************************************************************** @@ -613,7 +607,7 @@ static void falcon_stats_complete(struct efx_nic *efx) nic_data->stats_pending = false; if (*nic_data->stats_dma_done == FALCON_STATS_DONE) { rmb(); /* read the done flag before the stats */ - efx->mac_op->update_stats(efx); + falcon_update_stats_xmac(efx); } else { netif_err(efx, hw, efx->net_dev, "timed out waiting for statistics\n"); @@ -670,7 +664,7 @@ static int falcon_reconfigure_port(struct efx_nic *efx) falcon_reset_macs(efx); efx->phy_op->reconfigure(efx); - rc = efx->mac_op->reconfigure(efx); + rc = falcon_reconfigure_xmac(efx); BUG_ON(rc); falcon_start_nic_stats(efx); @@ -1218,7 +1212,7 @@ static void falcon_monitor(struct efx_nic *efx) falcon_deconfigure_mac_wrapper(efx); falcon_reset_macs(efx); - rc = efx->mac_op->reconfigure(efx); + rc = falcon_reconfigure_xmac(efx); BUG_ON(rc); falcon_start_nic_stats(efx); @@ -1472,6 +1466,8 @@ static int falcon_probe_nic(struct efx_nic *efx) goto fail5; } + efx->timer_quantum_ns = 4968; /* 621 cycles */ + /* Initialise I2C adapter */ board = falcon_board(efx); board->i2c_adap.owner = THIS_MODULE; @@ -1676,7 +1672,7 @@ static void falcon_update_nic_stats(struct efx_nic *efx) *nic_data->stats_dma_done == FALCON_STATS_DONE) { nic_data->stats_pending = false; rmb(); /* read the done flag before the stats */ - efx->mac_op->update_stats(efx); + falcon_update_stats_xmac(efx); } } @@ -1767,13 +1763,13 @@ const struct efx_nic_type falcon_a1_nic_type = { .stop_stats = falcon_stop_nic_stats, .set_id_led = falcon_set_id_led, .push_irq_moderation = falcon_push_irq_moderation, - .push_multicast_hash = falcon_push_multicast_hash, .reconfigure_port = falcon_reconfigure_port, + .reconfigure_mac = falcon_reconfigure_xmac, + .check_mac_fault = falcon_xmac_check_fault, .get_wol = falcon_get_wol, .set_wol = falcon_set_wol, .resume_wol = efx_port_dummy_op_void, .test_nvram = falcon_test_nvram, - .default_mac_ops = &falcon_xmac_operations, .revision = EFX_REV_FALCON_A1, .mem_map_size = 0x20000, @@ -1786,6 +1782,7 @@ const struct efx_nic_type falcon_a1_nic_type = { .rx_buffer_padding = 0x24, .max_interrupt_mode = EFX_INT_MODE_MSI, .phys_addr_channels = 4, + .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, .tx_dc_base = 0x130000, .rx_dc_base = 0x100000, .offload_features = NETIF_F_IP_CSUM, @@ -1809,14 +1806,14 @@ const struct efx_nic_type falcon_b0_nic_type = { .stop_stats = falcon_stop_nic_stats, .set_id_led = falcon_set_id_led, .push_irq_moderation = falcon_push_irq_moderation, - .push_multicast_hash = falcon_push_multicast_hash, .reconfigure_port = falcon_reconfigure_port, + .reconfigure_mac = falcon_reconfigure_xmac, + .check_mac_fault = falcon_xmac_check_fault, .get_wol = falcon_get_wol, .set_wol = falcon_set_wol, .resume_wol = efx_port_dummy_op_void, .test_registers = falcon_b0_test_registers, .test_nvram = falcon_test_nvram, - .default_mac_ops = &falcon_xmac_operations, .revision = EFX_REV_FALCON_B0, /* Map everything up to and including the RSS indirection @@ -1837,6 +1834,7 @@ const struct efx_nic_type falcon_b0_nic_type = { .phys_addr_channels = 32, /* Hardware limit is 64, but the legacy * interrupt handler only supports 32 * channels */ + .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, .tx_dc_base = 0x130000, .rx_dc_base = 0x100000, .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, diff --git a/drivers/net/ethernet/sfc/falcon_boards.c b/drivers/net/ethernet/sfc/falcon_boards.c index 6cc16b8cc6f4..2084cc6ede52 100644 --- a/drivers/net/ethernet/sfc/falcon_boards.c +++ b/drivers/net/ethernet/sfc/falcon_boards.c @@ -87,7 +87,7 @@ static const u8 falcon_lm87_common_regs[] = { 0 }; -static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info, +static int efx_init_lm87(struct efx_nic *efx, const struct i2c_board_info *info, const u8 *reg_values) { struct falcon_board *board = falcon_board(efx); @@ -179,7 +179,7 @@ static int efx_check_lm87(struct efx_nic *efx, unsigned mask) #else /* !CONFIG_SENSORS_LM87 */ static inline int -efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info, +efx_init_lm87(struct efx_nic *efx, const struct i2c_board_info *info, const u8 *reg_values) { return 0; @@ -442,7 +442,7 @@ static int sfe4001_check_hw(struct efx_nic *efx) return (status < 0) ? -EIO : -ERANGE; } -static struct i2c_board_info sfe4001_hwmon_info = { +static const struct i2c_board_info sfe4001_hwmon_info = { I2C_BOARD_INFO("max6647", 0x4e), }; @@ -522,7 +522,7 @@ static const u8 sfe4002_lm87_regs[] = { 0 }; -static struct i2c_board_info sfe4002_hwmon_info = { +static const struct i2c_board_info sfe4002_hwmon_info = { I2C_BOARD_INFO("lm87", 0x2e), .platform_data = &sfe4002_lm87_channel, }; @@ -591,7 +591,7 @@ static const u8 sfn4112f_lm87_regs[] = { 0 }; -static struct i2c_board_info sfn4112f_hwmon_info = { +static const struct i2c_board_info sfn4112f_hwmon_info = { I2C_BOARD_INFO("lm87", 0x2e), .platform_data = &sfn4112f_lm87_channel, }; @@ -653,7 +653,7 @@ static const u8 sfe4003_lm87_regs[] = { 0 }; -static struct i2c_board_info sfe4003_hwmon_info = { +static const struct i2c_board_info sfe4003_hwmon_info = { I2C_BOARD_INFO("lm87", 0x2e), .platform_data = &sfe4003_lm87_channel, }; diff --git a/drivers/net/ethernet/sfc/falcon_xmac.c b/drivers/net/ethernet/sfc/falcon_xmac.c index 9516452c079c..6106ef15dee3 100644 --- a/drivers/net/ethernet/sfc/falcon_xmac.c +++ b/drivers/net/ethernet/sfc/falcon_xmac.c @@ -14,7 +14,6 @@ #include "nic.h" #include "regs.h" #include "io.h" -#include "mac.h" #include "mdio_10g.h" #include "workarounds.h" @@ -139,7 +138,7 @@ static bool falcon_xmac_link_ok(struct efx_nic *efx) return (efx->loopback_mode == LOOPBACK_XGMII || falcon_xgxs_link_ok(efx)) && (!(efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) || - LOOPBACK_INTERNAL(efx) || + LOOPBACK_INTERNAL(efx) || efx_mdio_phyxgxs_lane_sync(efx)); } @@ -270,12 +269,12 @@ static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries) return mac_up; } -static bool falcon_xmac_check_fault(struct efx_nic *efx) +bool falcon_xmac_check_fault(struct efx_nic *efx) { return !falcon_xmac_link_ok_retry(efx, 5); } -static int falcon_reconfigure_xmac(struct efx_nic *efx) +int falcon_reconfigure_xmac(struct efx_nic *efx) { struct falcon_nic_data *nic_data = efx->nic_data; @@ -290,7 +289,7 @@ static int falcon_reconfigure_xmac(struct efx_nic *efx) return 0; } -static void falcon_update_stats_xmac(struct efx_nic *efx) +void falcon_update_stats_xmac(struct efx_nic *efx) { struct efx_mac_stats *mac_stats = &efx->mac_stats; @@ -361,9 +360,3 @@ void falcon_poll_xmac(struct efx_nic *efx) nic_data->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1); falcon_ack_status_intr(efx); } - -const struct efx_mac_operations falcon_xmac_operations = { - .reconfigure = falcon_reconfigure_xmac, - .update_stats = falcon_update_stats_xmac, - .check_fault = falcon_xmac_check_fault, -}; diff --git a/drivers/net/ethernet/sfc/mac.h b/drivers/net/ethernet/sfc/mac.h deleted file mode 100644 index d6a255d0856b..000000000000 --- a/drivers/net/ethernet/sfc/mac.h +++ /dev/null @@ -1,21 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2009 Solarflare Communications Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, incorporated herein by reference. - */ - -#ifndef EFX_MAC_H -#define EFX_MAC_H - -#include "net_driver.h" - -extern const struct efx_mac_operations falcon_xmac_operations; -extern const struct efx_mac_operations efx_mcdi_mac_operations; -extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, - u32 dma_len, int enable, int clear); - -#endif diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 81a425397468..619f63a66ce7 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -22,22 +22,22 @@ ************************************************************************** */ -/* Software-defined structure to the shared-memory */ -#define CMD_NOTIFY_PORT0 0 -#define CMD_NOTIFY_PORT1 4 -#define CMD_PDU_PORT0 0x008 -#define CMD_PDU_PORT1 0x108 -#define REBOOT_FLAG_PORT0 0x3f8 -#define REBOOT_FLAG_PORT1 0x3fc - #define MCDI_RPC_TIMEOUT 10 /*seconds */ #define MCDI_PDU(efx) \ - (efx_port_num(efx) ? CMD_PDU_PORT1 : CMD_PDU_PORT0) + (efx_port_num(efx) ? MC_SMEM_P1_PDU_OFST : MC_SMEM_P0_PDU_OFST) #define MCDI_DOORBELL(efx) \ - (efx_port_num(efx) ? CMD_NOTIFY_PORT1 : CMD_NOTIFY_PORT0) -#define MCDI_REBOOT_FLAG(efx) \ - (efx_port_num(efx) ? REBOOT_FLAG_PORT1 : REBOOT_FLAG_PORT0) + (efx_port_num(efx) ? MC_SMEM_P1_DOORBELL_OFST : MC_SMEM_P0_DOORBELL_OFST) +#define MCDI_STATUS(efx) \ + (efx_port_num(efx) ? MC_SMEM_P1_STATUS_OFST : MC_SMEM_P0_STATUS_OFST) + +/* A reboot/assertion causes the MCDI status word to be set after the + * command word is set or a REBOOT event is sent. If we notice a reboot + * via these mechanisms then wait 10ms for the status word to be set. */ +#define MCDI_STATUS_DELAY_US 100 +#define MCDI_STATUS_DELAY_COUNT 100 +#define MCDI_STATUS_SLEEP_MS \ + (MCDI_STATUS_DELAY_US * MCDI_STATUS_DELAY_COUNT / 1000) #define SEQ_MASK \ EFX_MASK32(EFX_WIDTH(MCDI_HEADER_SEQ)) @@ -77,7 +77,7 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd, u32 xflags, seqno; BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT); - BUG_ON(inlen & 3 || inlen >= 0x100); + BUG_ON(inlen & 3 || inlen >= MC_SMEM_PDU_LEN); seqno = mcdi->seqno & SEQ_MASK; xflags = 0; @@ -111,7 +111,7 @@ static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen) int i; BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT); - BUG_ON(outlen & 3 || outlen >= 0x100); + BUG_ON(outlen & 3 || outlen >= MC_SMEM_PDU_LEN); for (i = 0; i < outlen; i += 4) *((__le32 *)(outbuf + i)) = _efx_readd(efx, pdu + 4 + i); @@ -210,7 +210,7 @@ out: /* Test and clear MC-rebooted flag for this port/function */ int efx_mcdi_poll_reboot(struct efx_nic *efx) { - unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_REBOOT_FLAG(efx); + unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx); efx_dword_t reg; uint32_t value; @@ -384,6 +384,11 @@ int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, netif_dbg(efx, hw, efx->net_dev, "MC command 0x%x inlen %d failed rc=%d\n", cmd, (int)inlen, -rc); + + if (rc == -EIO || rc == -EINTR) { + msleep(MCDI_STATUS_SLEEP_MS); + efx_mcdi_poll_reboot(efx); + } } efx_mcdi_release(mcdi); @@ -465,10 +470,20 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc) mcdi->resplen = 0; ++mcdi->credits; } - } else + } else { + int count; + /* Nobody was waiting for an MCDI request, so trigger a reset */ efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE); + /* Consume the status word since efx_mcdi_rpc_finish() won't */ + for (count = 0; count < MCDI_STATUS_DELAY_COUNT; ++count) { + if (efx_mcdi_poll_reboot(efx)) + break; + udelay(MCDI_STATUS_DELAY_US); + } + } + spin_unlock(&mcdi->iface_lock); } @@ -502,49 +517,6 @@ static void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev) efx_link_status_changed(efx); } -static const char *sensor_names[] = { - [MC_CMD_SENSOR_CONTROLLER_TEMP] = "Controller temp. sensor", - [MC_CMD_SENSOR_PHY_COMMON_TEMP] = "PHY shared temp. sensor", - [MC_CMD_SENSOR_CONTROLLER_COOLING] = "Controller cooling", - [MC_CMD_SENSOR_PHY0_TEMP] = "PHY 0 temp. sensor", - [MC_CMD_SENSOR_PHY0_COOLING] = "PHY 0 cooling", - [MC_CMD_SENSOR_PHY1_TEMP] = "PHY 1 temp. sensor", - [MC_CMD_SENSOR_PHY1_COOLING] = "PHY 1 cooling", - [MC_CMD_SENSOR_IN_1V0] = "1.0V supply sensor", - [MC_CMD_SENSOR_IN_1V2] = "1.2V supply sensor", - [MC_CMD_SENSOR_IN_1V8] = "1.8V supply sensor", - [MC_CMD_SENSOR_IN_2V5] = "2.5V supply sensor", - [MC_CMD_SENSOR_IN_3V3] = "3.3V supply sensor", - [MC_CMD_SENSOR_IN_12V0] = "12V supply sensor" -}; - -static const char *sensor_status_names[] = { - [MC_CMD_SENSOR_STATE_OK] = "OK", - [MC_CMD_SENSOR_STATE_WARNING] = "Warning", - [MC_CMD_SENSOR_STATE_FATAL] = "Fatal", - [MC_CMD_SENSOR_STATE_BROKEN] = "Device failure", -}; - -static void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev) -{ - unsigned int monitor, state, value; - const char *name, *state_txt; - monitor = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR); - state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE); - value = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_VALUE); - /* Deal gracefully with the board having more drivers than we - * know about, but do not expect new sensor states. */ - name = (monitor >= ARRAY_SIZE(sensor_names)) - ? "No sensor name available" : - sensor_names[monitor]; - EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names)); - state_txt = sensor_status_names[state]; - - netif_err(efx, hw, efx->net_dev, - "Sensor %d (%s) reports condition '%s' for raw value %d\n", - monitor, name, state_txt, value); -} - /* Called from falcon_process_eventq for MCDI events */ void efx_mcdi_process_event(struct efx_channel *channel, efx_qword_t *event) @@ -604,7 +576,7 @@ void efx_mcdi_process_event(struct efx_channel *channel, void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len) { - u8 outbuf[ALIGN(MC_CMD_GET_VERSION_V1_OUT_LEN, 4)]; + u8 outbuf[ALIGN(MC_CMD_GET_VERSION_OUT_LEN, 4)]; size_t outlength; const __le16 *ver_words; int rc; @@ -616,7 +588,7 @@ void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len) if (rc) goto fail; - if (outlength < MC_CMD_GET_VERSION_V1_OUT_LEN) { + if (outlength < MC_CMD_GET_VERSION_OUT_LEN) { rc = -EIO; goto fail; } @@ -663,9 +635,9 @@ fail: } int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, - u16 *fw_subtype_list) + u16 *fw_subtype_list, u32 *capabilities) { - uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LEN]; + uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LENMIN]; size_t outlen; int port_num = efx_port_num(efx); int offset; @@ -678,7 +650,7 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, if (rc) goto fail; - if (outlen < MC_CMD_GET_BOARD_CFG_OUT_LEN) { + if (outlen < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) { rc = -EIO; goto fail; } @@ -691,7 +663,16 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, if (fw_subtype_list) memcpy(fw_subtype_list, outbuf + MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST, - MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN); + MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM * + sizeof(fw_subtype_list[0])); + if (capabilities) { + if (port_num) + *capabilities = MCDI_DWORD(outbuf, + GET_BOARD_CFG_OUT_CAPABILITIES_PORT1); + else + *capabilities = MCDI_DWORD(outbuf, + GET_BOARD_CFG_OUT_CAPABILITIES_PORT0); + } return 0; @@ -779,7 +760,7 @@ int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type, *size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_SIZE); *erase_size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_ERASESIZE); *protected_out = !!(MCDI_DWORD(outbuf, NVRAM_INFO_OUT_FLAGS) & - (1 << MC_CMD_NVRAM_PROTECTED_LBN)); + (1 << MC_CMD_NVRAM_INFO_OUT_PROTECTED_LBN)); return 0; fail: @@ -1060,7 +1041,7 @@ void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) int efx_mcdi_reset_port(struct efx_nic *efx) { - int rc = efx_mcdi_rpc(efx, MC_CMD_PORT_RESET, NULL, 0, NULL, 0, NULL); + int rc = efx_mcdi_rpc(efx, MC_CMD_ENTITY_RESET, NULL, 0, NULL, 0, NULL); if (rc) netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index aced2a7856fc..fbaa6efcd744 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -56,6 +56,15 @@ struct efx_mcdi_iface { size_t resplen; }; +struct efx_mcdi_mon { + struct efx_buffer dma_buf; + struct mutex update_lock; + unsigned long last_update; + struct device *device; + struct efx_mcdi_mon_attribute *attrs; + unsigned int n_attrs; +}; + extern void efx_mcdi_init(struct efx_nic *efx); extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, const u8 *inbuf, @@ -68,6 +77,7 @@ extern void efx_mcdi_mode_event(struct efx_nic *efx); extern void efx_mcdi_process_event(struct efx_channel *channel, efx_qword_t *event); +extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); #define MCDI_PTR2(_buf, _ofst) \ (((u8 *)_buf) + _ofst) @@ -83,6 +93,10 @@ extern void efx_mcdi_process_event(struct efx_channel *channel, #define MCDI_PTR(_buf, _ofst) \ MCDI_PTR2(_buf, MC_CMD_ ## _ofst ## _OFST) +#define MCDI_ARRAY_PTR(_buf, _field, _type, _index) \ + MCDI_PTR2(_buf, \ + MC_CMD_ ## _field ## _OFST + \ + (_index) * MC_CMD_ ## _type ## _TYPEDEF_LEN) #define MCDI_SET_DWORD(_buf, _ofst, _value) \ MCDI_SET_DWORD2(_buf, MC_CMD_ ## _ofst ## _OFST, _value) #define MCDI_DWORD(_buf, _ofst) \ @@ -92,12 +106,18 @@ extern void efx_mcdi_process_event(struct efx_channel *channel, #define MCDI_EVENT_FIELD(_ev, _field) \ EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field) +#define MCDI_ARRAY_FIELD(_buf, _field1, _type, _index, _field2) \ + EFX_DWORD_FIELD( \ + *((efx_dword_t *) \ + (MCDI_ARRAY_PTR(_buf, _field1, _type, _index) + \ + (MC_CMD_ ## _type ## _TYPEDEF_ ## _field2 ## _OFST & ~3))), \ + MC_CMD_ ## _type ## _TYPEDEF_ ## _field2) extern void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len); extern int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, bool *was_attached_out); extern int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, - u16 *fw_subtype_list); + u16 *fw_subtype_list, u32 *capabilities); extern int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart, u32 dest_evq); extern int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out); @@ -126,5 +146,17 @@ extern int efx_mcdi_wol_filter_set_magic(struct efx_nic *efx, extern int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out); extern int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id); extern int efx_mcdi_wol_filter_reset(struct efx_nic *efx); +extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, + u32 dma_len, int enable, int clear); +extern int efx_mcdi_mac_reconfigure(struct efx_nic *efx); +extern bool efx_mcdi_mac_check_fault(struct efx_nic *efx); + +#ifdef CONFIG_SFC_MCDI_MON +extern int efx_mcdi_mon_probe(struct efx_nic *efx); +extern void efx_mcdi_mon_remove(struct efx_nic *efx); +#else +static inline int efx_mcdi_mon_probe(struct efx_nic *efx) { return 0; } +static inline void efx_mcdi_mon_remove(struct efx_nic *efx) {} +#endif #endif /* EFX_MCDI_H */ diff --git a/drivers/net/ethernet/sfc/mcdi_mac.c b/drivers/net/ethernet/sfc/mcdi_mac.c index 50c20777a564..f67cf921bd1b 100644 --- a/drivers/net/ethernet/sfc/mcdi_mac.c +++ b/drivers/net/ethernet/sfc/mcdi_mac.c @@ -9,7 +9,6 @@ #include "net_driver.h" #include "efx.h" -#include "mac.h" #include "mcdi.h" #include "mcdi_pcol.h" @@ -52,7 +51,7 @@ static int efx_mcdi_set_mac(struct efx_nic *efx) NULL, 0, NULL); } -static int efx_mcdi_get_mac_faults(struct efx_nic *efx, u32 *faults) +bool efx_mcdi_mac_check_fault(struct efx_nic *efx) { u8 outbuf[MC_CMD_GET_LINK_OUT_LEN]; size_t outlength; @@ -62,16 +61,13 @@ static int efx_mcdi_get_mac_faults(struct efx_nic *efx, u32 *faults) rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, outbuf, sizeof(outbuf), &outlength); - if (rc) - goto fail; - - *faults = MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT); - return 0; + if (rc) { + netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", + __func__, rc); + return true; + } -fail: - netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", - __func__, rc); - return rc; + return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0; } int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, @@ -84,7 +80,7 @@ int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, u32 addr_hi; u32 addr_lo; - BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_LEN != 0); + BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0); addr_lo = ((u64)dma_addr) >> 0; addr_hi = ((u64)dma_addr) >> 32; @@ -93,13 +89,13 @@ int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_ADDR_HI, addr_hi); cmd_ptr = (efx_dword_t *)MCDI_PTR(inbuf, MAC_STATS_IN_CMD); EFX_POPULATE_DWORD_7(*cmd_ptr, - MC_CMD_MAC_STATS_CMD_DMA, !!enable, - MC_CMD_MAC_STATS_CMD_CLEAR, clear, - MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE, 1, - MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE, !!enable, - MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR, 0, - MC_CMD_MAC_STATS_CMD_PERIODIC_NOEVENT, 1, - MC_CMD_MAC_STATS_CMD_PERIOD_MS, period); + MC_CMD_MAC_STATS_IN_DMA, !!enable, + MC_CMD_MAC_STATS_IN_CLEAR, clear, + MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE, 1, + MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE, !!enable, + MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR, 0, + MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT, 1, + MC_CMD_MAC_STATS_IN_PERIOD_MS, period); MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len); rc = efx_mcdi_rpc(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf), @@ -115,31 +111,18 @@ fail: return rc; } -static int efx_mcdi_mac_reconfigure(struct efx_nic *efx) +int efx_mcdi_mac_reconfigure(struct efx_nic *efx) { int rc; + WARN_ON(!mutex_is_locked(&efx->mac_lock)); + rc = efx_mcdi_set_mac(efx); if (rc != 0) return rc; - /* Restore the multicast hash registers. */ - efx->type->push_multicast_hash(efx); - - return 0; -} - - -static bool efx_mcdi_mac_check_fault(struct efx_nic *efx) -{ - u32 faults; - int rc = efx_mcdi_get_mac_faults(efx, &faults); - return (rc != 0) || (faults != 0); + return efx_mcdi_rpc(efx, MC_CMD_SET_MCAST_HASH, + efx->multicast_hash.byte, + sizeof(efx->multicast_hash), + NULL, 0, NULL); } - - -const struct efx_mac_operations efx_mcdi_mac_operations = { - .reconfigure = efx_mcdi_mac_reconfigure, - .update_stats = efx_port_dummy_op_void, - .check_fault = efx_mcdi_mac_check_fault, -}; diff --git a/drivers/net/ethernet/sfc/mcdi_mon.c b/drivers/net/ethernet/sfc/mcdi_mon.c new file mode 100644 index 000000000000..8a72c10b9a6c --- /dev/null +++ b/drivers/net/ethernet/sfc/mcdi_mon.c @@ -0,0 +1,415 @@ +/**************************************************************************** + * Driver for Solarflare Solarstorm network controllers and boards + * Copyright 2011 Solarflare Communications Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#include <linux/bitops.h> +#include <linux/slab.h> +#include <linux/hwmon.h> +#include <linux/stat.h> + +#include "net_driver.h" +#include "mcdi.h" +#include "mcdi_pcol.h" +#include "nic.h" + +enum efx_hwmon_type { + EFX_HWMON_UNKNOWN, + EFX_HWMON_TEMP, /* temperature */ + EFX_HWMON_COOL, /* cooling device, probably a heatsink */ + EFX_HWMON_IN /* input voltage */ +}; + +static const struct { + const char *label; + enum efx_hwmon_type hwmon_type; + int port; +} efx_mcdi_sensor_type[MC_CMD_SENSOR_ENTRY_MAXNUM] = { +#define SENSOR(name, label, hwmon_type, port) \ + [MC_CMD_SENSOR_##name] = { label, hwmon_type, port } + SENSOR(CONTROLLER_TEMP, "Controller temp.", EFX_HWMON_TEMP, -1), + SENSOR(PHY_COMMON_TEMP, "PHY temp.", EFX_HWMON_TEMP, -1), + SENSOR(CONTROLLER_COOLING, "Controller cooling", EFX_HWMON_COOL, -1), + SENSOR(PHY0_TEMP, "PHY temp.", EFX_HWMON_TEMP, 0), + SENSOR(PHY0_COOLING, "PHY cooling", EFX_HWMON_COOL, 0), + SENSOR(PHY1_TEMP, "PHY temp.", EFX_HWMON_TEMP, 1), + SENSOR(PHY1_COOLING, "PHY cooling", EFX_HWMON_COOL, 1), + SENSOR(IN_1V0, "1.0V supply", EFX_HWMON_IN, -1), + SENSOR(IN_1V2, "1.2V supply", EFX_HWMON_IN, -1), + SENSOR(IN_1V8, "1.8V supply", EFX_HWMON_IN, -1), + SENSOR(IN_2V5, "2.5V supply", EFX_HWMON_IN, -1), + SENSOR(IN_3V3, "3.3V supply", EFX_HWMON_IN, -1), + SENSOR(IN_12V0, "12.0V supply", EFX_HWMON_IN, -1), + SENSOR(IN_1V2A, "1.2V analogue supply", EFX_HWMON_IN, -1), + SENSOR(IN_VREF, "ref. voltage", EFX_HWMON_IN, -1), +#undef SENSOR +}; + +static const char *const sensor_status_names[] = { + [MC_CMD_SENSOR_STATE_OK] = "OK", + [MC_CMD_SENSOR_STATE_WARNING] = "Warning", + [MC_CMD_SENSOR_STATE_FATAL] = "Fatal", + [MC_CMD_SENSOR_STATE_BROKEN] = "Device failure", +}; + +void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev) +{ + unsigned int type, state, value; + const char *name = NULL, *state_txt; + + type = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR); + state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE); + value = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_VALUE); + + /* Deal gracefully with the board having more drivers than we + * know about, but do not expect new sensor states. */ + if (type < ARRAY_SIZE(efx_mcdi_sensor_type)) + name = efx_mcdi_sensor_type[type].label; + if (!name) + name = "No sensor name available"; + EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names)); + state_txt = sensor_status_names[state]; + + netif_err(efx, hw, efx->net_dev, + "Sensor %d (%s) reports condition '%s' for raw value %d\n", + type, name, state_txt, value); +} + +#ifdef CONFIG_SFC_MCDI_MON + +struct efx_mcdi_mon_attribute { + struct device_attribute dev_attr; + unsigned int index; + unsigned int type; + unsigned int limit_value; + char name[12]; +}; + +static int efx_mcdi_mon_update(struct efx_nic *efx) +{ + struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); + u8 inbuf[MC_CMD_READ_SENSORS_IN_LEN]; + int rc; + + MCDI_SET_DWORD(inbuf, READ_SENSORS_IN_DMA_ADDR_LO, + hwmon->dma_buf.dma_addr & 0xffffffff); + MCDI_SET_DWORD(inbuf, READ_SENSORS_IN_DMA_ADDR_HI, + (u64)hwmon->dma_buf.dma_addr >> 32); + + rc = efx_mcdi_rpc(efx, MC_CMD_READ_SENSORS, + inbuf, sizeof(inbuf), NULL, 0, NULL); + if (rc == 0) + hwmon->last_update = jiffies; + return rc; +} + +static ssize_t efx_mcdi_mon_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%s\n", KBUILD_MODNAME); +} + +static int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index, + efx_dword_t *entry) +{ + struct efx_nic *efx = dev_get_drvdata(dev); + struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); + int rc; + + BUILD_BUG_ON(MC_CMD_READ_SENSORS_OUT_LEN != 0); + + mutex_lock(&hwmon->update_lock); + + /* Use cached value if last update was < 1 s ago */ + if (time_before(jiffies, hwmon->last_update + HZ)) + rc = 0; + else + rc = efx_mcdi_mon_update(efx); + + /* Copy out the requested entry */ + *entry = ((efx_dword_t *)hwmon->dma_buf.addr)[index]; + + mutex_unlock(&hwmon->update_lock); + + return rc; +} + +static ssize_t efx_mcdi_mon_show_value(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct efx_mcdi_mon_attribute *mon_attr = + container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); + efx_dword_t entry; + unsigned int value; + int rc; + + rc = efx_mcdi_mon_get_entry(dev, mon_attr->index, &entry); + if (rc) + return rc; + + value = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE); + + /* Convert temperature from degrees to milli-degrees Celsius */ + if (efx_mcdi_sensor_type[mon_attr->type].hwmon_type == EFX_HWMON_TEMP) + value *= 1000; + + return sprintf(buf, "%u\n", value); +} + +static ssize_t efx_mcdi_mon_show_limit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct efx_mcdi_mon_attribute *mon_attr = + container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); + unsigned int value; + + value = mon_attr->limit_value; + + /* Convert temperature from degrees to milli-degrees Celsius */ + if (efx_mcdi_sensor_type[mon_attr->type].hwmon_type == EFX_HWMON_TEMP) + value *= 1000; + + return sprintf(buf, "%u\n", value); +} + +static ssize_t efx_mcdi_mon_show_alarm(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct efx_mcdi_mon_attribute *mon_attr = + container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); + efx_dword_t entry; + int state; + int rc; + + rc = efx_mcdi_mon_get_entry(dev, mon_attr->index, &entry); + if (rc) + return rc; + + state = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE); + return sprintf(buf, "%d\n", state != MC_CMD_SENSOR_STATE_OK); +} + +static ssize_t efx_mcdi_mon_show_label(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct efx_mcdi_mon_attribute *mon_attr = + container_of(attr, struct efx_mcdi_mon_attribute, dev_attr); + return sprintf(buf, "%s\n", + efx_mcdi_sensor_type[mon_attr->type].label); +} + +static int +efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name, + ssize_t (*reader)(struct device *, + struct device_attribute *, char *), + unsigned int index, unsigned int type, + unsigned int limit_value) +{ + struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); + struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs]; + int rc; + + strlcpy(attr->name, name, sizeof(attr->name)); + attr->index = index; + attr->type = type; + attr->limit_value = limit_value; + attr->dev_attr.attr.name = attr->name; + attr->dev_attr.attr.mode = S_IRUGO; + attr->dev_attr.show = reader; + rc = device_create_file(&efx->pci_dev->dev, &attr->dev_attr); + if (rc == 0) + ++hwmon->n_attrs; + return rc; +} + +int efx_mcdi_mon_probe(struct efx_nic *efx) +{ + struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx); + unsigned int n_attrs, n_temp = 0, n_cool = 0, n_in = 0; + u8 outbuf[MC_CMD_SENSOR_INFO_OUT_LENMAX]; + size_t outlen; + char name[12]; + u32 mask; + int rc, i, type; + + BUILD_BUG_ON(MC_CMD_SENSOR_INFO_IN_LEN != 0); + + rc = efx_mcdi_rpc(efx, MC_CMD_SENSOR_INFO, NULL, 0, + outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < MC_CMD_SENSOR_INFO_OUT_LENMIN) + return -EIO; + + /* Find out which sensors are present. Don't create a device + * if there are none. + */ + mask = MCDI_DWORD(outbuf, SENSOR_INFO_OUT_MASK); + if (mask == 0) + return 0; + + /* Check again for short response */ + if (outlen < MC_CMD_SENSOR_INFO_OUT_LEN(hweight32(mask))) + return -EIO; + + rc = efx_nic_alloc_buffer(efx, &hwmon->dma_buf, + 4 * MC_CMD_SENSOR_ENTRY_MAXNUM); + if (rc) + return rc; + + mutex_init(&hwmon->update_lock); + efx_mcdi_mon_update(efx); + + /* Allocate space for the maximum possible number of + * attributes for this set of sensors: name of the driver plus + * value, min, max, crit, alarm and label for each sensor. + */ + n_attrs = 1 + 6 * hweight32(mask); + hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL); + if (!hwmon->attrs) { + rc = -ENOMEM; + goto fail; + } + + hwmon->device = hwmon_device_register(&efx->pci_dev->dev); + if (IS_ERR(hwmon->device)) { + rc = PTR_ERR(hwmon->device); + goto fail; + } + + rc = efx_mcdi_mon_add_attr(efx, "name", efx_mcdi_mon_show_name, 0, 0, 0); + if (rc) + goto fail; + + for (i = 0, type = -1; ; i++) { + const char *hwmon_prefix; + unsigned hwmon_index; + u16 min1, max1, min2, max2; + + /* Find next sensor type or exit if there is none */ + type++; + while (!(mask & (1 << type))) { + type++; + if (type == 32) + return 0; + } + + /* Skip sensors specific to a different port */ + if (efx_mcdi_sensor_type[type].hwmon_type != EFX_HWMON_UNKNOWN && + efx_mcdi_sensor_type[type].port >= 0 && + efx_mcdi_sensor_type[type].port != efx_port_num(efx)) + continue; + + switch (efx_mcdi_sensor_type[type].hwmon_type) { + case EFX_HWMON_TEMP: + hwmon_prefix = "temp"; + hwmon_index = ++n_temp; /* 1-based */ + break; + case EFX_HWMON_COOL: + /* This is likely to be a heatsink, but there + * is no convention for representing cooling + * devices other than fans. + */ + hwmon_prefix = "fan"; + hwmon_index = ++n_cool; /* 1-based */ + break; + default: + hwmon_prefix = "in"; + hwmon_index = n_in++; /* 0-based */ + break; + } + + min1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, + SENSOR_INFO_ENTRY, i, MIN1); + max1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, + SENSOR_INFO_ENTRY, i, MAX1); + min2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, + SENSOR_INFO_ENTRY, i, MIN2); + max2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY, + SENSOR_INFO_ENTRY, i, MAX2); + + if (min1 != max1) { + snprintf(name, sizeof(name), "%s%u_input", + hwmon_prefix, hwmon_index); + rc = efx_mcdi_mon_add_attr( + efx, name, efx_mcdi_mon_show_value, i, type, 0); + if (rc) + goto fail; + + snprintf(name, sizeof(name), "%s%u_min", + hwmon_prefix, hwmon_index); + rc = efx_mcdi_mon_add_attr( + efx, name, efx_mcdi_mon_show_limit, + i, type, min1); + if (rc) + goto fail; + + snprintf(name, sizeof(name), "%s%u_max", + hwmon_prefix, hwmon_index); + rc = efx_mcdi_mon_add_attr( + efx, name, efx_mcdi_mon_show_limit, + i, type, max1); + if (rc) + goto fail; + + if (min2 != max2) { + /* Assume max2 is critical value. + * But we have no good way to expose min2. + */ + snprintf(name, sizeof(name), "%s%u_crit", + hwmon_prefix, hwmon_index); + rc = efx_mcdi_mon_add_attr( + efx, name, efx_mcdi_mon_show_limit, + i, type, max2); + if (rc) + goto fail; + } + } + + snprintf(name, sizeof(name), "%s%u_alarm", + hwmon_prefix, hwmon_index); + rc = efx_mcdi_mon_add_attr( + efx, name, efx_mcdi_mon_show_alarm, i, type, 0); + if (rc) + goto fail; + + if (efx_mcdi_sensor_type[type].label) { + snprintf(name, sizeof(name), "%s%u_label", + hwmon_prefix, hwmon_index); + rc = efx_mcdi_mon_add_attr( + efx, name, efx_mcdi_mon_show_label, i, type, 0); + if (rc) + goto fail; + } + } + +fail: + efx_mcdi_mon_remove(efx); + return rc; +} + +void efx_mcdi_mon_remove(struct efx_nic *efx) +{ + struct siena_nic_data *nic_data = efx->nic_data; + struct efx_mcdi_mon *hwmon = &nic_data->hwmon; + unsigned int i; + + for (i = 0; i < hwmon->n_attrs; i++) + device_remove_file(&efx->pci_dev->dev, + &hwmon->attrs[i].dev_attr); + kfree(hwmon->attrs); + if (hwmon->device) + hwmon_device_unregister(hwmon->device); + efx_nic_free_buffer(efx, &hwmon->dma_buf); +} + +#endif /* CONFIG_SFC_MCDI_MON */ diff --git a/drivers/net/ethernet/sfc/mcdi_pcol.h b/drivers/net/ethernet/sfc/mcdi_pcol.h index 41fe06fa0600..0310b9f08c9b 100644 --- a/drivers/net/ethernet/sfc/mcdi_pcol.h +++ b/drivers/net/ethernet/sfc/mcdi_pcol.h @@ -22,6 +22,18 @@ /* The Scheduler has started. */ #define MC_FW_STATE_SCHED (8) +/* Siena MC shared memmory offsets */ +/* The 'doorbell' addresses are hard-wired to alert the MC when written */ +#define MC_SMEM_P0_DOORBELL_OFST 0x000 +#define MC_SMEM_P1_DOORBELL_OFST 0x004 +/* The rest of these are firmware-defined */ +#define MC_SMEM_P0_PDU_OFST 0x008 +#define MC_SMEM_P1_PDU_OFST 0x108 +#define MC_SMEM_PDU_LEN 0x100 +#define MC_SMEM_P0_PTP_TIME_OFST 0x7f0 +#define MC_SMEM_P0_STATUS_OFST 0x7f8 +#define MC_SMEM_P1_STATUS_OFST 0x7fc + /* Values to be written to the per-port status dword in shared * memory on reboot and assert */ #define MC_STATUS_DWORD_REBOOT (0xb007b007) @@ -34,6 +46,8 @@ */ #define MCDI_PCOL_VERSION 1 +/* Unused commands: 0x23, 0x27, 0x30, 0x31 */ + /** * MCDI version 1 * @@ -131,53 +145,6 @@ */ #define FSE_AZ_EV_CODE_MCDI_EVRESPONSE 0xc -#define MCDI_EVENT_DATA_LBN 0 -#define MCDI_EVENT_DATA_WIDTH 32 -#define MCDI_EVENT_CONT_LBN 32 -#define MCDI_EVENT_CONT_WIDTH 1 -#define MCDI_EVENT_LEVEL_LBN 33 -#define MCDI_EVENT_LEVEL_WIDTH 3 -#define MCDI_EVENT_LEVEL_INFO (0) -#define MCDI_EVENT_LEVEL_WARN (1) -#define MCDI_EVENT_LEVEL_ERR (2) -#define MCDI_EVENT_LEVEL_FATAL (3) -#define MCDI_EVENT_SRC_LBN 36 -#define MCDI_EVENT_SRC_WIDTH 8 -#define MCDI_EVENT_CODE_LBN 44 -#define MCDI_EVENT_CODE_WIDTH 8 -#define MCDI_EVENT_CODE_BADSSERT (1) -#define MCDI_EVENT_CODE_PMNOTICE (2) -#define MCDI_EVENT_CODE_CMDDONE (3) -#define MCDI_EVENT_CMDDONE_SEQ_LBN 0 -#define MCDI_EVENT_CMDDONE_SEQ_WIDTH 8 -#define MCDI_EVENT_CMDDONE_DATALEN_LBN 8 -#define MCDI_EVENT_CMDDONE_DATALEN_WIDTH 8 -#define MCDI_EVENT_CMDDONE_ERRNO_LBN 16 -#define MCDI_EVENT_CMDDONE_ERRNO_WIDTH 8 -#define MCDI_EVENT_CODE_LINKCHANGE (4) -#define MCDI_EVENT_LINKCHANGE_LP_CAP_LBN 0 -#define MCDI_EVENT_LINKCHANGE_LP_CAP_WIDTH 16 -#define MCDI_EVENT_LINKCHANGE_SPEED_LBN 16 -#define MCDI_EVENT_LINKCHANGE_SPEED_WIDTH 4 -#define MCDI_EVENT_LINKCHANGE_SPEED_100M 1 -#define MCDI_EVENT_LINKCHANGE_SPEED_1G 2 -#define MCDI_EVENT_LINKCHANGE_SPEED_10G 3 -#define MCDI_EVENT_LINKCHANGE_FCNTL_LBN 20 -#define MCDI_EVENT_LINKCHANGE_FCNTL_WIDTH 4 -#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_LBN 24 -#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_WIDTH 8 -#define MCDI_EVENT_CODE_SENSOREVT (5) -#define MCDI_EVENT_SENSOREVT_MONITOR_LBN 0 -#define MCDI_EVENT_SENSOREVT_MONITOR_WIDTH 8 -#define MCDI_EVENT_SENSOREVT_STATE_LBN 8 -#define MCDI_EVENT_SENSOREVT_STATE_WIDTH 8 -#define MCDI_EVENT_SENSOREVT_VALUE_LBN 16 -#define MCDI_EVENT_SENSOREVT_VALUE_WIDTH 16 -#define MCDI_EVENT_CODE_SCHEDERR (6) -#define MCDI_EVENT_CODE_REBOOT (7) -#define MCDI_EVENT_CODE_MAC_STATS_DMA (8) -#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_LBN 0 -#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_WIDTH 32 /* Non-existent command target */ #define MC_CMD_ERR_ENOENT 2 @@ -198,121 +165,24 @@ #define MC_CMD_ERR_CODE_OFST 0 +/* We define 8 "escape" commands to allow + for command number space extension */ + +#define MC_CMD_CMD_SPACE_ESCAPE_0 0x78 +#define MC_CMD_CMD_SPACE_ESCAPE_1 0x79 +#define MC_CMD_CMD_SPACE_ESCAPE_2 0x7A +#define MC_CMD_CMD_SPACE_ESCAPE_3 0x7B +#define MC_CMD_CMD_SPACE_ESCAPE_4 0x7C +#define MC_CMD_CMD_SPACE_ESCAPE_5 0x7D +#define MC_CMD_CMD_SPACE_ESCAPE_6 0x7E +#define MC_CMD_CMD_SPACE_ESCAPE_7 0x7F + +/* Vectors in the boot ROM */ +/* Point to the copycode entry point. */ +#define MC_BOOTROM_COPYCODE_VEC (0x7f4) +/* Points to the recovery mode entry point. */ +#define MC_BOOTROM_NOFLASH_VEC (0x7f8) -/* MC_CMD_READ32: (debug, variadic out) - * Read multiple 32byte words from MC memory - */ -#define MC_CMD_READ32 0x01 -#define MC_CMD_READ32_IN_LEN 8 -#define MC_CMD_READ32_IN_ADDR_OFST 0 -#define MC_CMD_READ32_IN_NUMWORDS_OFST 4 -#define MC_CMD_READ32_OUT_LEN(_numwords) \ - (4 * (_numwords)) -#define MC_CMD_READ32_OUT_BUFFER_OFST 0 - -/* MC_CMD_WRITE32: (debug, variadic in) - * Write multiple 32byte words to MC memory - */ -#define MC_CMD_WRITE32 0x02 -#define MC_CMD_WRITE32_IN_LEN(_numwords) (((_numwords) * 4) + 4) -#define MC_CMD_WRITE32_IN_ADDR_OFST 0 -#define MC_CMD_WRITE32_IN_BUFFER_OFST 4 -#define MC_CMD_WRITE32_OUT_LEN 0 - -/* MC_CMD_COPYCODE: (debug) - * Copy MC code between two locations and jump - */ -#define MC_CMD_COPYCODE 0x03 -#define MC_CMD_COPYCODE_IN_LEN 16 -#define MC_CMD_COPYCODE_IN_SRC_ADDR_OFST 0 -#define MC_CMD_COPYCODE_IN_DEST_ADDR_OFST 4 -#define MC_CMD_COPYCODE_IN_NUMWORDS_OFST 8 -#define MC_CMD_COPYCODE_IN_JUMP_OFST 12 -/* Control should return to the caller rather than jumping */ -#define MC_CMD_COPYCODE_JUMP_NONE 1 -#define MC_CMD_COPYCODE_OUT_LEN 0 - -/* MC_CMD_SET_FUNC: (debug) - * Select function for function-specific commands. - */ -#define MC_CMD_SET_FUNC 0x04 -#define MC_CMD_SET_FUNC_IN_LEN 4 -#define MC_CMD_SET_FUNC_IN_FUNC_OFST 0 -#define MC_CMD_SET_FUNC_OUT_LEN 0 - -/* MC_CMD_GET_BOOT_STATUS: - * Get the instruction address from which the MC booted. - */ -#define MC_CMD_GET_BOOT_STATUS 0x05 -#define MC_CMD_GET_BOOT_STATUS_IN_LEN 0 -#define MC_CMD_GET_BOOT_STATUS_OUT_LEN 8 -#define MC_CMD_GET_BOOT_STATUS_OUT_BOOT_OFFSET_OFST 0 -#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_OFST 4 -/* Reboot caused by watchdog */ -#define MC_CMD_GET_BOOT_STATUS_FLAGS_WATCHDOG_LBN (0) -#define MC_CMD_GET_BOOT_STATUS_FLAGS_WATCHDOG_WIDTH (1) -/* MC booted from primary flash partition */ -#define MC_CMD_GET_BOOT_STATUS_FLAGS_PRIMARY_LBN (1) -#define MC_CMD_GET_BOOT_STATUS_FLAGS_PRIMARY_WIDTH (1) -/* MC booted from backup flash partition */ -#define MC_CMD_GET_BOOT_STATUS_FLAGS_BACKUP_LBN (2) -#define MC_CMD_GET_BOOT_STATUS_FLAGS_BACKUP_WIDTH (1) - -/* MC_CMD_GET_ASSERTS: (debug, variadic out) - * Get (and optionally clear) the current assertion status. - * - * Only OUT.GLOBAL_FLAGS is guaranteed to exist in the completion - * payload. The other fields will only be present if - * OUT.GLOBAL_FLAGS != NO_FAILS - */ -#define MC_CMD_GET_ASSERTS 0x06 -#define MC_CMD_GET_ASSERTS_IN_LEN 4 -#define MC_CMD_GET_ASSERTS_IN_CLEAR_OFST 0 -#define MC_CMD_GET_ASSERTS_OUT_LEN 140 -/* Assertion status flag */ -#define MC_CMD_GET_ASSERTS_OUT_GLOBAL_FLAGS_OFST 0 -/*! No assertions have failed. */ -#define MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS 1 -/*! A system-level assertion has failed. */ -#define MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL 2 -/*! A thread-level assertion has failed. */ -#define MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL 3 -/*! The system was reset by the watchdog. */ -#define MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED 4 -/* Failing PC value */ -#define MC_CMD_GET_ASSERTS_OUT_SAVED_PC_OFFS_OFST 4 -/* Saved GP regs */ -#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST 8 -#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_LEN 124 -/* Failing thread address */ -#define MC_CMD_GET_ASSERTS_OUT_THREAD_OFFS_OFST 132 - -/* MC_CMD_LOG_CTRL: - * Determine the output stream for various events and messages - */ -#define MC_CMD_LOG_CTRL 0x07 -#define MC_CMD_LOG_CTRL_IN_LEN 8 -#define MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0 -#define MC_CMD_LOG_CTRL_IN_LOG_DEST_UART (1) -#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ (2) -#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ_OFST 4 -#define MC_CMD_LOG_CTRL_OUT_LEN 0 - -/* MC_CMD_GET_VERSION: - * Get version information about the MC firmware - */ -#define MC_CMD_GET_VERSION 0x08 -#define MC_CMD_GET_VERSION_IN_LEN 0 -#define MC_CMD_GET_VERSION_V0_OUT_LEN 4 -#define MC_CMD_GET_VERSION_V1_OUT_LEN 32 -#define MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 -/* Reserved version number to indicate "any" version. */ -#define MC_CMD_GET_VERSION_OUT_FIRMWARE_ANY 0xffffffff -/* The version response of a boot ROM awaiting rescue */ -#define MC_CMD_GET_VERSION_OUT_FIRMWARE_BOOTROM 0xb0070000 -#define MC_CMD_GET_VERSION_V1_OUT_PCOL_OFST 4 -/* 128bit mask of functions supported by the current firmware */ -#define MC_CMD_GET_VERSION_V1_OUT_SUPPORTED_FUNCS_OFST 8 /* The command set exported by the boot ROM (MCDI v0) */ #define MC_CMD_GET_VERSION_V0_SUPPORTED_FUNCS { \ (1 << MC_CMD_READ32) | \ @@ -320,1456 +190,2214 @@ (1 << MC_CMD_COPYCODE) | \ (1 << MC_CMD_GET_VERSION), \ 0, 0, 0 } -#define MC_CMD_GET_VERSION_OUT_VERSION_OFST 24 -/* Vectors in the boot ROM */ -/* Point to the copycode entry point. */ -#define MC_BOOTROM_COPYCODE_VEC (0x7f4) -/* Points to the recovery mode entry point. */ -#define MC_BOOTROM_NOFLASH_VEC (0x7f8) +#define MC_CMD_SENSOR_INFO_OUT_OFFSET_OFST(_x) \ + (MC_CMD_SENSOR_ENTRY_OFST + (_x)) + +#define MC_CMD_DBI_WRITE_IN_ADDRESS_OFST(n) \ + (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST + \ + MC_CMD_DBIWROP_TYPEDEF_ADDRESS_OFST + \ + (n) * MC_CMD_DBIWROP_TYPEDEF_LEN) + +#define MC_CMD_DBI_WRITE_IN_BYTE_MASK_OFST(n) \ + (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST + \ + MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_OFST + \ + (n) * MC_CMD_DBIWROP_TYPEDEF_LEN) + +#define MC_CMD_DBI_WRITE_IN_VALUE_OFST(n) \ + (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST + \ + MC_CMD_DBIWROP_TYPEDEF_VALUE_OFST + \ + (n) * MC_CMD_DBIWROP_TYPEDEF_LEN) + + +/* MCDI_EVENT structuredef */ +#define MCDI_EVENT_LEN 8 +#define MCDI_EVENT_CONT_LBN 32 +#define MCDI_EVENT_CONT_WIDTH 1 +#define MCDI_EVENT_LEVEL_LBN 33 +#define MCDI_EVENT_LEVEL_WIDTH 3 +#define MCDI_EVENT_LEVEL_INFO 0x0 /* enum */ +#define MCDI_EVENT_LEVEL_WARN 0x1 /* enum */ +#define MCDI_EVENT_LEVEL_ERR 0x2 /* enum */ +#define MCDI_EVENT_LEVEL_FATAL 0x3 /* enum */ +#define MCDI_EVENT_DATA_OFST 0 +#define MCDI_EVENT_CMDDONE_SEQ_LBN 0 +#define MCDI_EVENT_CMDDONE_SEQ_WIDTH 8 +#define MCDI_EVENT_CMDDONE_DATALEN_LBN 8 +#define MCDI_EVENT_CMDDONE_DATALEN_WIDTH 8 +#define MCDI_EVENT_CMDDONE_ERRNO_LBN 16 +#define MCDI_EVENT_CMDDONE_ERRNO_WIDTH 8 +#define MCDI_EVENT_LINKCHANGE_LP_CAP_LBN 0 +#define MCDI_EVENT_LINKCHANGE_LP_CAP_WIDTH 16 +#define MCDI_EVENT_LINKCHANGE_SPEED_LBN 16 +#define MCDI_EVENT_LINKCHANGE_SPEED_WIDTH 4 +#define MCDI_EVENT_LINKCHANGE_SPEED_100M 0x1 /* enum */ +#define MCDI_EVENT_LINKCHANGE_SPEED_1G 0x2 /* enum */ +#define MCDI_EVENT_LINKCHANGE_SPEED_10G 0x3 /* enum */ +#define MCDI_EVENT_LINKCHANGE_FCNTL_LBN 20 +#define MCDI_EVENT_LINKCHANGE_FCNTL_WIDTH 4 +#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_LBN 24 +#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_WIDTH 8 +#define MCDI_EVENT_SENSOREVT_MONITOR_LBN 0 +#define MCDI_EVENT_SENSOREVT_MONITOR_WIDTH 8 +#define MCDI_EVENT_SENSOREVT_STATE_LBN 8 +#define MCDI_EVENT_SENSOREVT_STATE_WIDTH 8 +#define MCDI_EVENT_SENSOREVT_VALUE_LBN 16 +#define MCDI_EVENT_SENSOREVT_VALUE_WIDTH 16 +#define MCDI_EVENT_FWALERT_DATA_LBN 8 +#define MCDI_EVENT_FWALERT_DATA_WIDTH 24 +#define MCDI_EVENT_FWALERT_REASON_LBN 0 +#define MCDI_EVENT_FWALERT_REASON_WIDTH 8 +#define MCDI_EVENT_FWALERT_REASON_SRAM_ACCESS 0x1 /* enum */ +#define MCDI_EVENT_FLR_VF_LBN 0 +#define MCDI_EVENT_FLR_VF_WIDTH 8 +#define MCDI_EVENT_TX_ERR_TXQ_LBN 0 +#define MCDI_EVENT_TX_ERR_TXQ_WIDTH 12 +#define MCDI_EVENT_TX_ERR_TYPE_LBN 12 +#define MCDI_EVENT_TX_ERR_TYPE_WIDTH 4 +#define MCDI_EVENT_TX_ERR_DL_FAIL 0x1 /* enum */ +#define MCDI_EVENT_TX_ERR_NO_EOP 0x2 /* enum */ +#define MCDI_EVENT_TX_ERR_2BIG 0x3 /* enum */ +#define MCDI_EVENT_TX_ERR_INFO_LBN 16 +#define MCDI_EVENT_TX_ERR_INFO_WIDTH 16 +#define MCDI_EVENT_TX_FLUSH_TXQ_LBN 0 +#define MCDI_EVENT_TX_FLUSH_TXQ_WIDTH 12 +#define MCDI_EVENT_PTP_ERR_TYPE_LBN 0 +#define MCDI_EVENT_PTP_ERR_TYPE_WIDTH 8 +#define MCDI_EVENT_PTP_ERR_PLL_LOST 0x1 /* enum */ +#define MCDI_EVENT_PTP_ERR_FILTER 0x2 /* enum */ +#define MCDI_EVENT_PTP_ERR_FIFO 0x3 /* enum */ +#define MCDI_EVENT_PTP_ERR_QUEUE 0x4 /* enum */ +#define MCDI_EVENT_DATA_LBN 0 +#define MCDI_EVENT_DATA_WIDTH 32 +#define MCDI_EVENT_SRC_LBN 36 +#define MCDI_EVENT_SRC_WIDTH 8 +#define MCDI_EVENT_EV_CODE_LBN 60 +#define MCDI_EVENT_EV_CODE_WIDTH 4 +#define MCDI_EVENT_CODE_LBN 44 +#define MCDI_EVENT_CODE_WIDTH 8 +#define MCDI_EVENT_CODE_BADSSERT 0x1 /* enum */ +#define MCDI_EVENT_CODE_PMNOTICE 0x2 /* enum */ +#define MCDI_EVENT_CODE_CMDDONE 0x3 /* enum */ +#define MCDI_EVENT_CODE_LINKCHANGE 0x4 /* enum */ +#define MCDI_EVENT_CODE_SENSOREVT 0x5 /* enum */ +#define MCDI_EVENT_CODE_SCHEDERR 0x6 /* enum */ +#define MCDI_EVENT_CODE_REBOOT 0x7 /* enum */ +#define MCDI_EVENT_CODE_MAC_STATS_DMA 0x8 /* enum */ +#define MCDI_EVENT_CODE_FWALERT 0x9 /* enum */ +#define MCDI_EVENT_CODE_FLR 0xa /* enum */ +#define MCDI_EVENT_CODE_TX_ERR 0xb /* enum */ +#define MCDI_EVENT_CODE_TX_FLUSH 0xc /* enum */ +#define MCDI_EVENT_CODE_PTP_RX 0xd /* enum */ +#define MCDI_EVENT_CODE_PTP_FAULT 0xe /* enum */ +#define MCDI_EVENT_CMDDONE_DATA_OFST 0 +#define MCDI_EVENT_CMDDONE_DATA_LBN 0 +#define MCDI_EVENT_CMDDONE_DATA_WIDTH 32 +#define MCDI_EVENT_LINKCHANGE_DATA_OFST 0 +#define MCDI_EVENT_LINKCHANGE_DATA_LBN 0 +#define MCDI_EVENT_LINKCHANGE_DATA_WIDTH 32 +#define MCDI_EVENT_SENSOREVT_DATA_OFST 0 +#define MCDI_EVENT_SENSOREVT_DATA_LBN 0 +#define MCDI_EVENT_SENSOREVT_DATA_WIDTH 32 +#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_OFST 0 +#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_LBN 0 +#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_WIDTH 32 +#define MCDI_EVENT_TX_ERR_DATA_OFST 0 +#define MCDI_EVENT_TX_ERR_DATA_LBN 0 +#define MCDI_EVENT_TX_ERR_DATA_WIDTH 32 +#define MCDI_EVENT_PTP_SECONDS_OFST 0 +#define MCDI_EVENT_PTP_SECONDS_LBN 0 +#define MCDI_EVENT_PTP_SECONDS_WIDTH 32 +#define MCDI_EVENT_PTP_NANOSECONDS_OFST 0 +#define MCDI_EVENT_PTP_NANOSECONDS_LBN 0 +#define MCDI_EVENT_PTP_NANOSECONDS_WIDTH 32 +#define MCDI_EVENT_PTP_UUID_OFST 0 +#define MCDI_EVENT_PTP_UUID_LBN 0 +#define MCDI_EVENT_PTP_UUID_WIDTH 32 + + +/***********************************/ +/* MC_CMD_READ32 + * Read multiple 32byte words from MC memory. + */ +#define MC_CMD_READ32 0x1 + +/* MC_CMD_READ32_IN msgrequest */ +#define MC_CMD_READ32_IN_LEN 8 +#define MC_CMD_READ32_IN_ADDR_OFST 0 +#define MC_CMD_READ32_IN_NUMWORDS_OFST 4 + +/* MC_CMD_READ32_OUT msgresponse */ +#define MC_CMD_READ32_OUT_LENMIN 4 +#define MC_CMD_READ32_OUT_LENMAX 252 +#define MC_CMD_READ32_OUT_LEN(num) (0+4*(num)) +#define MC_CMD_READ32_OUT_BUFFER_OFST 0 +#define MC_CMD_READ32_OUT_BUFFER_LEN 4 +#define MC_CMD_READ32_OUT_BUFFER_MINNUM 1 +#define MC_CMD_READ32_OUT_BUFFER_MAXNUM 63 + + +/***********************************/ +/* MC_CMD_WRITE32 + * Write multiple 32byte words to MC memory. + */ +#define MC_CMD_WRITE32 0x2 + +/* MC_CMD_WRITE32_IN msgrequest */ +#define MC_CMD_WRITE32_IN_LENMIN 8 +#define MC_CMD_WRITE32_IN_LENMAX 252 +#define MC_CMD_WRITE32_IN_LEN(num) (4+4*(num)) +#define MC_CMD_WRITE32_IN_ADDR_OFST 0 +#define MC_CMD_WRITE32_IN_BUFFER_OFST 4 +#define MC_CMD_WRITE32_IN_BUFFER_LEN 4 +#define MC_CMD_WRITE32_IN_BUFFER_MINNUM 1 +#define MC_CMD_WRITE32_IN_BUFFER_MAXNUM 62 + +/* MC_CMD_WRITE32_OUT msgresponse */ +#define MC_CMD_WRITE32_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_COPYCODE + * Copy MC code between two locations and jump. + */ +#define MC_CMD_COPYCODE 0x3 + +/* MC_CMD_COPYCODE_IN msgrequest */ +#define MC_CMD_COPYCODE_IN_LEN 16 +#define MC_CMD_COPYCODE_IN_SRC_ADDR_OFST 0 +#define MC_CMD_COPYCODE_IN_DEST_ADDR_OFST 4 +#define MC_CMD_COPYCODE_IN_NUMWORDS_OFST 8 +#define MC_CMD_COPYCODE_IN_JUMP_OFST 12 +#define MC_CMD_COPYCODE_JUMP_NONE 0x1 /* enum */ + +/* MC_CMD_COPYCODE_OUT msgresponse */ +#define MC_CMD_COPYCODE_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SET_FUNC + */ +#define MC_CMD_SET_FUNC 0x4 + +/* MC_CMD_SET_FUNC_IN msgrequest */ +#define MC_CMD_SET_FUNC_IN_LEN 4 +#define MC_CMD_SET_FUNC_IN_FUNC_OFST 0 + +/* MC_CMD_SET_FUNC_OUT msgresponse */ +#define MC_CMD_SET_FUNC_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_BOOT_STATUS + */ +#define MC_CMD_GET_BOOT_STATUS 0x5 + +/* MC_CMD_GET_BOOT_STATUS_IN msgrequest */ +#define MC_CMD_GET_BOOT_STATUS_IN_LEN 0 + +/* MC_CMD_GET_BOOT_STATUS_OUT msgresponse */ +#define MC_CMD_GET_BOOT_STATUS_OUT_LEN 8 +#define MC_CMD_GET_BOOT_STATUS_OUT_BOOT_OFFSET_OFST 0 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_OFST 4 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_WATCHDOG_LBN 0 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_WATCHDOG_WIDTH 1 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_PRIMARY_LBN 1 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_PRIMARY_WIDTH 1 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_BACKUP_LBN 2 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_BACKUP_WIDTH 1 -/* Test execution limits */ -#define MC_TESTEXEC_VARIANT_COUNT 16 -#define MC_TESTEXEC_RESULT_COUNT 7 -/* MC_CMD_SET_TESTVARS: (debug, variadic in) - * Write variant words for test. - * - * The user supplies a bitmap of the variants they wish to set. - * They must ensure that IN.LEN >= 4 + 4 * ffs(BITMAP) - */ -#define MC_CMD_SET_TESTVARS 0x09 -#define MC_CMD_SET_TESTVARS_IN_LEN(_numwords) \ - (4 + 4*(_numwords)) -#define MC_CMD_SET_TESTVARS_IN_ARGS_BITMAP_OFST 0 -/* Up to MC_TESTEXEC_VARIANT_COUNT of 32byte words start here */ -#define MC_CMD_SET_TESTVARS_IN_ARGS_BUFFER_OFST 4 -#define MC_CMD_SET_TESTVARS_OUT_LEN 0 - -/* MC_CMD_GET_TESTRCS: (debug, variadic out) - * Return result words from test. - */ -#define MC_CMD_GET_TESTRCS 0x0a -#define MC_CMD_GET_TESTRCS_IN_LEN 4 -#define MC_CMD_GET_TESTRCS_IN_NUMWORDS_OFST 0 -#define MC_CMD_GET_TESTRCS_OUT_LEN(_numwords) \ - (4 * (_numwords)) -#define MC_CMD_GET_TESTRCS_OUT_BUFFER_OFST 0 - -/* MC_CMD_RUN_TEST: (debug) - * Run the test exported by this firmware image - */ -#define MC_CMD_RUN_TEST 0x0b -#define MC_CMD_RUN_TEST_IN_LEN 0 -#define MC_CMD_RUN_TEST_OUT_LEN 0 - -/* MC_CMD_CSR_READ32: (debug, variadic out) - * Read 32bit words from the indirect memory map - */ -#define MC_CMD_CSR_READ32 0x0c -#define MC_CMD_CSR_READ32_IN_LEN 12 -#define MC_CMD_CSR_READ32_IN_ADDR_OFST 0 -#define MC_CMD_CSR_READ32_IN_STEP_OFST 4 -#define MC_CMD_CSR_READ32_IN_NUMWORDS_OFST 8 -#define MC_CMD_CSR_READ32_OUT_LEN(_numwords) \ - (((_numwords) * 4) + 4) -/* IN.NUMWORDS of 32bit words start here */ -#define MC_CMD_CSR_READ32_OUT_BUFFER_OFST 0 -#define MC_CMD_CSR_READ32_OUT_IREG_STATUS_OFST(_numwords) \ - ((_numwords) * 4) - -/* MC_CMD_CSR_WRITE32: (debug, variadic in) - * Write 32bit dwords to the indirect memory map - */ -#define MC_CMD_CSR_WRITE32 0x0d -#define MC_CMD_CSR_WRITE32_IN_LEN(_numwords) \ - (((_numwords) * 4) + 8) -#define MC_CMD_CSR_WRITE32_IN_ADDR_OFST 0 -#define MC_CMD_CSR_WRITE32_IN_STEP_OFST 4 -/* Multiple 32bit words of data to write start here */ -#define MC_CMD_CSR_WRITE32_IN_BUFFER_OFST 8 -#define MC_CMD_CSR_WRITE32_OUT_LEN 4 -#define MC_CMD_CSR_WRITE32_OUT_STATUS_OFST 0 - -/* MC_CMD_JTAG_WORK: (debug, fpga only) - * Process JTAG work buffer for RBF acceleration. - * - * Host: bit count, (up to) 32 words of data to clock out to JTAG - * (bits 1,0=TMS,TDO for first bit; bits 3,2=TMS,TDO for second bit, etc.) - * MC: bit count, (up to) 32 words of data clocked in from JTAG - * (bit 0=TDI for first bit, bit 1=TDI for second bit, etc.; [31:16] unused) +/***********************************/ +/* MC_CMD_GET_ASSERTS + * Get and clear any assertion status. */ -#define MC_CMD_JTAG_WORK 0x0e +#define MC_CMD_GET_ASSERTS 0x6 -/* MC_CMD_STACKINFO: (debug, variadic out) - * Get stack information - * - * Host: nothing - * MC: (thread ptr, stack size, free space) for each thread in system - */ -#define MC_CMD_STACKINFO 0x0f +/* MC_CMD_GET_ASSERTS_IN msgrequest */ +#define MC_CMD_GET_ASSERTS_IN_LEN 4 +#define MC_CMD_GET_ASSERTS_IN_CLEAR_OFST 0 + +/* MC_CMD_GET_ASSERTS_OUT msgresponse */ +#define MC_CMD_GET_ASSERTS_OUT_LEN 140 +#define MC_CMD_GET_ASSERTS_OUT_GLOBAL_FLAGS_OFST 0 +#define MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS 0x1 /* enum */ +#define MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL 0x2 /* enum */ +#define MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL 0x3 /* enum */ +#define MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED 0x4 /* enum */ +#define MC_CMD_GET_ASSERTS_OUT_SAVED_PC_OFFS_OFST 4 +#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST 8 +#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_LEN 4 +#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_NUM 31 +#define MC_CMD_GET_ASSERTS_OUT_THREAD_OFFS_OFST 132 +#define MC_CMD_GET_ASSERTS_OUT_RESERVED_OFST 136 -/* MC_CMD_MDIO_READ: - * MDIO register read + +/***********************************/ +/* MC_CMD_LOG_CTRL + * Configure the output stream for various events and messages. + */ +#define MC_CMD_LOG_CTRL 0x7 + +/* MC_CMD_LOG_CTRL_IN msgrequest */ +#define MC_CMD_LOG_CTRL_IN_LEN 8 +#define MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0 +#define MC_CMD_LOG_CTRL_IN_LOG_DEST_UART 0x1 /* enum */ +#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ 0x2 /* enum */ +#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ_OFST 4 + +/* MC_CMD_LOG_CTRL_OUT msgresponse */ +#define MC_CMD_LOG_CTRL_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_VERSION + * Get version information about the MC firmware. + */ +#define MC_CMD_GET_VERSION 0x8 + +/* MC_CMD_GET_VERSION_IN msgrequest */ +#define MC_CMD_GET_VERSION_IN_LEN 0 + +/* MC_CMD_GET_VERSION_V0_OUT msgresponse */ +#define MC_CMD_GET_VERSION_V0_OUT_LEN 4 +#define MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 +#define MC_CMD_GET_VERSION_OUT_FIRMWARE_ANY 0xffffffff /* enum */ +#define MC_CMD_GET_VERSION_OUT_FIRMWARE_BOOTROM 0xb0070000 /* enum */ + +/* MC_CMD_GET_VERSION_OUT msgresponse */ +#define MC_CMD_GET_VERSION_OUT_LEN 32 +/* MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */ +/* Enum values, see field(s): */ +/* MC_CMD_GET_VERSION_V0_OUT/MC_CMD_GET_VERSION_OUT_FIRMWARE */ +#define MC_CMD_GET_VERSION_OUT_PCOL_OFST 4 +#define MC_CMD_GET_VERSION_OUT_SUPPORTED_FUNCS_OFST 8 +#define MC_CMD_GET_VERSION_OUT_SUPPORTED_FUNCS_LEN 16 +#define MC_CMD_GET_VERSION_OUT_VERSION_OFST 24 +#define MC_CMD_GET_VERSION_OUT_VERSION_LEN 8 +#define MC_CMD_GET_VERSION_OUT_VERSION_LO_OFST 24 +#define MC_CMD_GET_VERSION_OUT_VERSION_HI_OFST 28 + + +/***********************************/ +/* MC_CMD_GET_FPGAREG + * Read multiple bytes from PTP FPGA. + */ +#define MC_CMD_GET_FPGAREG 0x9 + +/* MC_CMD_GET_FPGAREG_IN msgrequest */ +#define MC_CMD_GET_FPGAREG_IN_LEN 8 +#define MC_CMD_GET_FPGAREG_IN_ADDR_OFST 0 +#define MC_CMD_GET_FPGAREG_IN_NUMBYTES_OFST 4 + +/* MC_CMD_GET_FPGAREG_OUT msgresponse */ +#define MC_CMD_GET_FPGAREG_OUT_LENMIN 1 +#define MC_CMD_GET_FPGAREG_OUT_LENMAX 255 +#define MC_CMD_GET_FPGAREG_OUT_LEN(num) (0+1*(num)) +#define MC_CMD_GET_FPGAREG_OUT_BUFFER_OFST 0 +#define MC_CMD_GET_FPGAREG_OUT_BUFFER_LEN 1 +#define MC_CMD_GET_FPGAREG_OUT_BUFFER_MINNUM 1 +#define MC_CMD_GET_FPGAREG_OUT_BUFFER_MAXNUM 255 + + +/***********************************/ +/* MC_CMD_PUT_FPGAREG + * Write multiple bytes to PTP FPGA. + */ +#define MC_CMD_PUT_FPGAREG 0xa + +/* MC_CMD_PUT_FPGAREG_IN msgrequest */ +#define MC_CMD_PUT_FPGAREG_IN_LENMIN 5 +#define MC_CMD_PUT_FPGAREG_IN_LENMAX 255 +#define MC_CMD_PUT_FPGAREG_IN_LEN(num) (4+1*(num)) +#define MC_CMD_PUT_FPGAREG_IN_ADDR_OFST 0 +#define MC_CMD_PUT_FPGAREG_IN_BUFFER_OFST 4 +#define MC_CMD_PUT_FPGAREG_IN_BUFFER_LEN 1 +#define MC_CMD_PUT_FPGAREG_IN_BUFFER_MINNUM 1 +#define MC_CMD_PUT_FPGAREG_IN_BUFFER_MAXNUM 251 + +/* MC_CMD_PUT_FPGAREG_OUT msgresponse */ +#define MC_CMD_PUT_FPGAREG_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_PTP + * Perform PTP operation + */ +#define MC_CMD_PTP 0xb + +/* MC_CMD_PTP_IN msgrequest */ +#define MC_CMD_PTP_IN_LEN 1 +#define MC_CMD_PTP_IN_OP_OFST 0 +#define MC_CMD_PTP_IN_OP_LEN 1 +#define MC_CMD_PTP_OP_ENABLE 0x1 /* enum */ +#define MC_CMD_PTP_OP_DISABLE 0x2 /* enum */ +#define MC_CMD_PTP_OP_TRANSMIT 0x3 /* enum */ +#define MC_CMD_PTP_OP_READ_NIC_TIME 0x4 /* enum */ +#define MC_CMD_PTP_OP_STATUS 0x5 /* enum */ +#define MC_CMD_PTP_OP_ADJUST 0x6 /* enum */ +#define MC_CMD_PTP_OP_SYNCHRONIZE 0x7 /* enum */ +#define MC_CMD_PTP_OP_MANFTEST_BASIC 0x8 /* enum */ +#define MC_CMD_PTP_OP_MANFTEST_PACKET 0x9 /* enum */ +#define MC_CMD_PTP_OP_RESET_STATS 0xa /* enum */ +#define MC_CMD_PTP_OP_DEBUG 0xb /* enum */ +#define MC_CMD_PTP_OP_MAX 0xc /* enum */ + +/* MC_CMD_PTP_IN_ENABLE msgrequest */ +#define MC_CMD_PTP_IN_ENABLE_LEN 16 +#define MC_CMD_PTP_IN_CMD_OFST 0 +#define MC_CMD_PTP_IN_PERIPH_ID_OFST 4 +#define MC_CMD_PTP_IN_ENABLE_QUEUE_OFST 8 +#define MC_CMD_PTP_IN_ENABLE_MODE_OFST 12 +#define MC_CMD_PTP_MODE_V1 0x0 /* enum */ +#define MC_CMD_PTP_MODE_V1_VLAN 0x1 /* enum */ +#define MC_CMD_PTP_MODE_V2 0x2 /* enum */ +#define MC_CMD_PTP_MODE_V2_VLAN 0x3 /* enum */ + +/* MC_CMD_PTP_IN_DISABLE msgrequest */ +#define MC_CMD_PTP_IN_DISABLE_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_TRANSMIT msgrequest */ +#define MC_CMD_PTP_IN_TRANSMIT_LENMIN 13 +#define MC_CMD_PTP_IN_TRANSMIT_LENMAX 255 +#define MC_CMD_PTP_IN_TRANSMIT_LEN(num) (12+1*(num)) +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +#define MC_CMD_PTP_IN_TRANSMIT_LENGTH_OFST 8 +#define MC_CMD_PTP_IN_TRANSMIT_PACKET_OFST 12 +#define MC_CMD_PTP_IN_TRANSMIT_PACKET_LEN 1 +#define MC_CMD_PTP_IN_TRANSMIT_PACKET_MINNUM 1 +#define MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM 243 + +/* MC_CMD_PTP_IN_READ_NIC_TIME msgrequest */ +#define MC_CMD_PTP_IN_READ_NIC_TIME_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_STATUS msgrequest */ +#define MC_CMD_PTP_IN_STATUS_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_ADJUST msgrequest */ +#define MC_CMD_PTP_IN_ADJUST_LEN 24 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +#define MC_CMD_PTP_IN_ADJUST_FREQ_OFST 8 +#define MC_CMD_PTP_IN_ADJUST_FREQ_LEN 8 +#define MC_CMD_PTP_IN_ADJUST_FREQ_LO_OFST 8 +#define MC_CMD_PTP_IN_ADJUST_FREQ_HI_OFST 12 +#define MC_CMD_PTP_IN_ADJUST_BITS 0x28 /* enum */ +#define MC_CMD_PTP_IN_ADJUST_SECONDS_OFST 16 +#define MC_CMD_PTP_IN_ADJUST_NANOSECONDS_OFST 20 + +/* MC_CMD_PTP_IN_SYNCHRONIZE msgrequest */ +#define MC_CMD_PTP_IN_SYNCHRONIZE_LEN 20 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +#define MC_CMD_PTP_IN_SYNCHRONIZE_NUMTIMESETS_OFST 8 +#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_OFST 12 +#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_LEN 8 +#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_LO_OFST 12 +#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_HI_OFST 16 + +/* MC_CMD_PTP_IN_MANFTEST_BASIC msgrequest */ +#define MC_CMD_PTP_IN_MANFTEST_BASIC_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_MANFTEST_PACKET msgrequest */ +#define MC_CMD_PTP_IN_MANFTEST_PACKET_LEN 12 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +#define MC_CMD_PTP_IN_MANFTEST_PACKET_TEST_ENABLE_OFST 8 + +/* MC_CMD_PTP_IN_RESET_STATS msgrequest */ +#define MC_CMD_PTP_IN_RESET_STATS_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_DEBUG msgrequest */ +#define MC_CMD_PTP_IN_DEBUG_LEN 12 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +#define MC_CMD_PTP_IN_DEBUG_DEBUG_PARAM_OFST 8 + +/* MC_CMD_PTP_OUT msgresponse */ +#define MC_CMD_PTP_OUT_LEN 0 + +/* MC_CMD_PTP_OUT_TRANSMIT msgresponse */ +#define MC_CMD_PTP_OUT_TRANSMIT_LEN 8 +#define MC_CMD_PTP_OUT_TRANSMIT_SECONDS_OFST 0 +#define MC_CMD_PTP_OUT_TRANSMIT_NANOSECONDS_OFST 4 + +/* MC_CMD_PTP_OUT_READ_NIC_TIME msgresponse */ +#define MC_CMD_PTP_OUT_READ_NIC_TIME_LEN 8 +#define MC_CMD_PTP_OUT_READ_NIC_TIME_SECONDS_OFST 0 +#define MC_CMD_PTP_OUT_READ_NIC_TIME_NANOSECONDS_OFST 4 + +/* MC_CMD_PTP_OUT_STATUS msgresponse */ +#define MC_CMD_PTP_OUT_STATUS_LEN 64 +#define MC_CMD_PTP_OUT_STATUS_CLOCK_FREQ_OFST 0 +#define MC_CMD_PTP_OUT_STATUS_STATS_TX_OFST 4 +#define MC_CMD_PTP_OUT_STATUS_STATS_RX_OFST 8 +#define MC_CMD_PTP_OUT_STATUS_STATS_TS_OFST 12 +#define MC_CMD_PTP_OUT_STATUS_STATS_FM_OFST 16 +#define MC_CMD_PTP_OUT_STATUS_STATS_NFM_OFST 20 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFLOW_OFST 24 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_BAD_OFST 28 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MIN_OFST 32 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MAX_OFST 36 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_LAST_OFST 40 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MEAN_OFST 44 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MIN_OFST 48 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MAX_OFST 52 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_LAST_OFST 56 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MEAN_OFST 60 + +/* MC_CMD_PTP_OUT_SYNCHRONIZE msgresponse */ +#define MC_CMD_PTP_OUT_SYNCHRONIZE_LENMIN 20 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_LENMAX 240 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_LEN(num) (0+20*(num)) +#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_OFST 0 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_LEN 20 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_MINNUM 1 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_MAXNUM 12 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_HOSTSTART_OFST 0 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_SECONDS_OFST 4 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_NANOSECONDS_OFST 8 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_HOSTEND_OFST 12 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_WAITNS_OFST 16 + +/* MC_CMD_PTP_OUT_MANFTEST_BASIC msgresponse */ +#define MC_CMD_PTP_OUT_MANFTEST_BASIC_LEN 8 +#define MC_CMD_PTP_OUT_MANFTEST_BASIC_TEST_RESULT_OFST 0 +#define MC_CMD_PTP_MANF_SUCCESS 0x0 /* enum */ +#define MC_CMD_PTP_MANF_FPGA_LOAD 0x1 /* enum */ +#define MC_CMD_PTP_MANF_FPGA_VERSION 0x2 /* enum */ +#define MC_CMD_PTP_MANF_FPGA_REGISTERS 0x3 /* enum */ +#define MC_CMD_PTP_MANF_OSCILLATOR 0x4 /* enum */ +#define MC_CMD_PTP_MANF_TIMESTAMPS 0x5 /* enum */ +#define MC_CMD_PTP_MANF_PACKET_COUNT 0x6 /* enum */ +#define MC_CMD_PTP_MANF_FILTER_COUNT 0x7 /* enum */ +#define MC_CMD_PTP_MANF_PACKET_ENOUGH 0x8 /* enum */ +#define MC_CMD_PTP_MANF_GPIO_TRIGGER 0x9 /* enum */ +#define MC_CMD_PTP_OUT_MANFTEST_BASIC_TEST_EXTOSC_OFST 4 + +/* MC_CMD_PTP_OUT_MANFTEST_PACKET msgresponse */ +#define MC_CMD_PTP_OUT_MANFTEST_PACKET_LEN 12 +#define MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_RESULT_OFST 0 +#define MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_FPGACOUNT_OFST 4 +#define MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_FILTERCOUNT_OFST 8 + + +/***********************************/ +/* MC_CMD_CSR_READ32 + * Read 32bit words from the indirect memory map. + */ +#define MC_CMD_CSR_READ32 0xc + +/* MC_CMD_CSR_READ32_IN msgrequest */ +#define MC_CMD_CSR_READ32_IN_LEN 12 +#define MC_CMD_CSR_READ32_IN_ADDR_OFST 0 +#define MC_CMD_CSR_READ32_IN_STEP_OFST 4 +#define MC_CMD_CSR_READ32_IN_NUMWORDS_OFST 8 + +/* MC_CMD_CSR_READ32_OUT msgresponse */ +#define MC_CMD_CSR_READ32_OUT_LENMIN 4 +#define MC_CMD_CSR_READ32_OUT_LENMAX 252 +#define MC_CMD_CSR_READ32_OUT_LEN(num) (0+4*(num)) +#define MC_CMD_CSR_READ32_OUT_BUFFER_OFST 0 +#define MC_CMD_CSR_READ32_OUT_BUFFER_LEN 4 +#define MC_CMD_CSR_READ32_OUT_BUFFER_MINNUM 1 +#define MC_CMD_CSR_READ32_OUT_BUFFER_MAXNUM 63 + + +/***********************************/ +/* MC_CMD_CSR_WRITE32 + * Write 32bit dwords to the indirect memory map. + */ +#define MC_CMD_CSR_WRITE32 0xd + +/* MC_CMD_CSR_WRITE32_IN msgrequest */ +#define MC_CMD_CSR_WRITE32_IN_LENMIN 12 +#define MC_CMD_CSR_WRITE32_IN_LENMAX 252 +#define MC_CMD_CSR_WRITE32_IN_LEN(num) (8+4*(num)) +#define MC_CMD_CSR_WRITE32_IN_ADDR_OFST 0 +#define MC_CMD_CSR_WRITE32_IN_STEP_OFST 4 +#define MC_CMD_CSR_WRITE32_IN_BUFFER_OFST 8 +#define MC_CMD_CSR_WRITE32_IN_BUFFER_LEN 4 +#define MC_CMD_CSR_WRITE32_IN_BUFFER_MINNUM 1 +#define MC_CMD_CSR_WRITE32_IN_BUFFER_MAXNUM 61 + +/* MC_CMD_CSR_WRITE32_OUT msgresponse */ +#define MC_CMD_CSR_WRITE32_OUT_LEN 4 +#define MC_CMD_CSR_WRITE32_OUT_STATUS_OFST 0 + + +/***********************************/ +/* MC_CMD_STACKINFO + * Get stack information. + */ +#define MC_CMD_STACKINFO 0xf + +/* MC_CMD_STACKINFO_IN msgrequest */ +#define MC_CMD_STACKINFO_IN_LEN 0 + +/* MC_CMD_STACKINFO_OUT msgresponse */ +#define MC_CMD_STACKINFO_OUT_LENMIN 12 +#define MC_CMD_STACKINFO_OUT_LENMAX 252 +#define MC_CMD_STACKINFO_OUT_LEN(num) (0+12*(num)) +#define MC_CMD_STACKINFO_OUT_THREAD_INFO_OFST 0 +#define MC_CMD_STACKINFO_OUT_THREAD_INFO_LEN 12 +#define MC_CMD_STACKINFO_OUT_THREAD_INFO_MINNUM 1 +#define MC_CMD_STACKINFO_OUT_THREAD_INFO_MAXNUM 21 + + +/***********************************/ +/* MC_CMD_MDIO_READ + * MDIO register read. */ #define MC_CMD_MDIO_READ 0x10 -#define MC_CMD_MDIO_READ_IN_LEN 16 -#define MC_CMD_MDIO_READ_IN_BUS_OFST 0 -#define MC_CMD_MDIO_READ_IN_PRTAD_OFST 4 -#define MC_CMD_MDIO_READ_IN_DEVAD_OFST 8 -#define MC_CMD_MDIO_READ_IN_ADDR_OFST 12 -#define MC_CMD_MDIO_READ_OUT_LEN 8 -#define MC_CMD_MDIO_READ_OUT_VALUE_OFST 0 -#define MC_CMD_MDIO_READ_OUT_STATUS_OFST 4 - -/* MC_CMD_MDIO_WRITE: - * MDIO register write - */ -#define MC_CMD_MDIO_WRITE 0x11 -#define MC_CMD_MDIO_WRITE_IN_LEN 20 -#define MC_CMD_MDIO_WRITE_IN_BUS_OFST 0 -#define MC_CMD_MDIO_WRITE_IN_PRTAD_OFST 4 -#define MC_CMD_MDIO_WRITE_IN_DEVAD_OFST 8 -#define MC_CMD_MDIO_WRITE_IN_ADDR_OFST 12 -#define MC_CMD_MDIO_WRITE_IN_VALUE_OFST 16 -#define MC_CMD_MDIO_WRITE_OUT_LEN 4 -#define MC_CMD_MDIO_WRITE_OUT_STATUS_OFST 0 -/* By default all the MCDI MDIO operations perform clause45 mode. - * If you want to use clause22 then set DEVAD = MC_CMD_MDIO_CLAUSE22. - */ -#define MC_CMD_MDIO_CLAUSE22 32 +/* MC_CMD_MDIO_READ_IN msgrequest */ +#define MC_CMD_MDIO_READ_IN_LEN 16 +#define MC_CMD_MDIO_READ_IN_BUS_OFST 0 +#define MC_CMD_MDIO_BUS_INTERNAL 0x0 /* enum */ +#define MC_CMD_MDIO_BUS_EXTERNAL 0x1 /* enum */ +#define MC_CMD_MDIO_READ_IN_PRTAD_OFST 4 +#define MC_CMD_MDIO_READ_IN_DEVAD_OFST 8 +#define MC_CMD_MDIO_CLAUSE22 0x20 /* enum */ +#define MC_CMD_MDIO_READ_IN_ADDR_OFST 12 -/* There are two MDIO buses: one for the internal PHY, and one for external - * devices. - */ -#define MC_CMD_MDIO_BUS_INTERNAL 0 -#define MC_CMD_MDIO_BUS_EXTERNAL 1 +/* MC_CMD_MDIO_READ_OUT msgresponse */ +#define MC_CMD_MDIO_READ_OUT_LEN 8 +#define MC_CMD_MDIO_READ_OUT_VALUE_OFST 0 +#define MC_CMD_MDIO_READ_OUT_STATUS_OFST 4 +#define MC_CMD_MDIO_STATUS_GOOD 0x8 /* enum */ -/* The MDIO commands return the raw status bits from the MDIO block. A "good" - * transaction should have the DONE bit set and all other bits clear. + +/***********************************/ +/* MC_CMD_MDIO_WRITE + * MDIO register write. */ -#define MC_CMD_MDIO_STATUS_GOOD 0x08 +#define MC_CMD_MDIO_WRITE 0x11 +/* MC_CMD_MDIO_WRITE_IN msgrequest */ +#define MC_CMD_MDIO_WRITE_IN_LEN 20 +#define MC_CMD_MDIO_WRITE_IN_BUS_OFST 0 +/* MC_CMD_MDIO_BUS_INTERNAL 0x0 */ +/* MC_CMD_MDIO_BUS_EXTERNAL 0x1 */ +#define MC_CMD_MDIO_WRITE_IN_PRTAD_OFST 4 +#define MC_CMD_MDIO_WRITE_IN_DEVAD_OFST 8 +/* MC_CMD_MDIO_CLAUSE22 0x20 */ +#define MC_CMD_MDIO_WRITE_IN_ADDR_OFST 12 +#define MC_CMD_MDIO_WRITE_IN_VALUE_OFST 16 -/* MC_CMD_DBI_WRITE: (debug) - * Write DBI register(s) - * - * Host: address, byte-enables (and VF selection, and cs2 flag), - * value [,address ...] - * MC: nothing +/* MC_CMD_MDIO_WRITE_OUT msgresponse */ +#define MC_CMD_MDIO_WRITE_OUT_LEN 4 +#define MC_CMD_MDIO_WRITE_OUT_STATUS_OFST 0 +/* MC_CMD_MDIO_STATUS_GOOD 0x8 */ + + +/***********************************/ +/* MC_CMD_DBI_WRITE + * Write DBI register(s). */ #define MC_CMD_DBI_WRITE 0x12 -#define MC_CMD_DBI_WRITE_IN_LEN(_numwords) \ - (12 * (_numwords)) -#define MC_CMD_DBI_WRITE_IN_ADDRESS_OFST(_word) \ - (((_word) * 12) + 0) -#define MC_CMD_DBI_WRITE_IN_BYTE_MASK_OFST(_word) \ - (((_word) * 12) + 4) -#define MC_CMD_DBI_WRITE_IN_VALUE_OFST(_word) \ - (((_word) * 12) + 8) -#define MC_CMD_DBI_WRITE_OUT_LEN 0 - -/* MC_CMD_DBI_READ: (debug) - * Read DBI register(s) - * - * Host: address, [,address ...] - * MC: value [,value ...] - * (note: this does not support reading from VFs, but is retained for backwards - * compatibility; see MC_CMD_DBI_READX below) - */ -#define MC_CMD_DBI_READ 0x13 -#define MC_CMD_DBI_READ_IN_LEN(_numwords) \ - (4 * (_numwords)) -#define MC_CMD_DBI_READ_OUT_LEN(_numwords) \ - (4 * (_numwords)) - -/* MC_CMD_PORT_READ32: (debug) + +/* MC_CMD_DBI_WRITE_IN msgrequest */ +#define MC_CMD_DBI_WRITE_IN_LENMIN 12 +#define MC_CMD_DBI_WRITE_IN_LENMAX 252 +#define MC_CMD_DBI_WRITE_IN_LEN(num) (0+12*(num)) +#define MC_CMD_DBI_WRITE_IN_DBIWROP_OFST 0 +#define MC_CMD_DBI_WRITE_IN_DBIWROP_LEN 12 +#define MC_CMD_DBI_WRITE_IN_DBIWROP_MINNUM 1 +#define MC_CMD_DBI_WRITE_IN_DBIWROP_MAXNUM 21 + +/* MC_CMD_DBI_WRITE_OUT msgresponse */ +#define MC_CMD_DBI_WRITE_OUT_LEN 0 + +/* MC_CMD_DBIWROP_TYPEDEF structuredef */ +#define MC_CMD_DBIWROP_TYPEDEF_LEN 12 +#define MC_CMD_DBIWROP_TYPEDEF_ADDRESS_OFST 0 +#define MC_CMD_DBIWROP_TYPEDEF_ADDRESS_LBN 0 +#define MC_CMD_DBIWROP_TYPEDEF_ADDRESS_WIDTH 32 +#define MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_OFST 4 +#define MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_LBN 32 +#define MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_WIDTH 32 +#define MC_CMD_DBIWROP_TYPEDEF_VALUE_OFST 8 +#define MC_CMD_DBIWROP_TYPEDEF_VALUE_LBN 64 +#define MC_CMD_DBIWROP_TYPEDEF_VALUE_WIDTH 32 + + +/***********************************/ +/* MC_CMD_PORT_READ32 * Read a 32-bit register from the indirect port register map. - * - * The port to access is implied by the Shared memory channel used. */ #define MC_CMD_PORT_READ32 0x14 -#define MC_CMD_PORT_READ32_IN_LEN 4 -#define MC_CMD_PORT_READ32_IN_ADDR_OFST 0 -#define MC_CMD_PORT_READ32_OUT_LEN 8 -#define MC_CMD_PORT_READ32_OUT_VALUE_OFST 0 -#define MC_CMD_PORT_READ32_OUT_STATUS_OFST 4 -/* MC_CMD_PORT_WRITE32: (debug) +/* MC_CMD_PORT_READ32_IN msgrequest */ +#define MC_CMD_PORT_READ32_IN_LEN 4 +#define MC_CMD_PORT_READ32_IN_ADDR_OFST 0 + +/* MC_CMD_PORT_READ32_OUT msgresponse */ +#define MC_CMD_PORT_READ32_OUT_LEN 8 +#define MC_CMD_PORT_READ32_OUT_VALUE_OFST 0 +#define MC_CMD_PORT_READ32_OUT_STATUS_OFST 4 + + +/***********************************/ +/* MC_CMD_PORT_WRITE32 * Write a 32-bit register to the indirect port register map. - * - * The port to access is implied by the Shared memory channel used. */ #define MC_CMD_PORT_WRITE32 0x15 -#define MC_CMD_PORT_WRITE32_IN_LEN 8 -#define MC_CMD_PORT_WRITE32_IN_ADDR_OFST 0 -#define MC_CMD_PORT_WRITE32_IN_VALUE_OFST 4 -#define MC_CMD_PORT_WRITE32_OUT_LEN 4 -#define MC_CMD_PORT_WRITE32_OUT_STATUS_OFST 0 - -/* MC_CMD_PORT_READ128: (debug) - * Read a 128-bit register from indirect port register map - * - * The port to access is implied by the Shared memory channel used. + +/* MC_CMD_PORT_WRITE32_IN msgrequest */ +#define MC_CMD_PORT_WRITE32_IN_LEN 8 +#define MC_CMD_PORT_WRITE32_IN_ADDR_OFST 0 +#define MC_CMD_PORT_WRITE32_IN_VALUE_OFST 4 + +/* MC_CMD_PORT_WRITE32_OUT msgresponse */ +#define MC_CMD_PORT_WRITE32_OUT_LEN 4 +#define MC_CMD_PORT_WRITE32_OUT_STATUS_OFST 0 + + +/***********************************/ +/* MC_CMD_PORT_READ128 + * Read a 128-bit register from the indirect port register map. */ #define MC_CMD_PORT_READ128 0x16 -#define MC_CMD_PORT_READ128_IN_LEN 4 -#define MC_CMD_PORT_READ128_IN_ADDR_OFST 0 -#define MC_CMD_PORT_READ128_OUT_LEN 20 -#define MC_CMD_PORT_READ128_OUT_VALUE_OFST 0 -#define MC_CMD_PORT_READ128_OUT_STATUS_OFST 16 - -/* MC_CMD_PORT_WRITE128: (debug) - * Write a 128-bit register to indirect port register map. - * - * The port to access is implied by the Shared memory channel used. + +/* MC_CMD_PORT_READ128_IN msgrequest */ +#define MC_CMD_PORT_READ128_IN_LEN 4 +#define MC_CMD_PORT_READ128_IN_ADDR_OFST 0 + +/* MC_CMD_PORT_READ128_OUT msgresponse */ +#define MC_CMD_PORT_READ128_OUT_LEN 20 +#define MC_CMD_PORT_READ128_OUT_VALUE_OFST 0 +#define MC_CMD_PORT_READ128_OUT_VALUE_LEN 16 +#define MC_CMD_PORT_READ128_OUT_STATUS_OFST 16 + + +/***********************************/ +/* MC_CMD_PORT_WRITE128 + * Write a 128-bit register to the indirect port register map. */ #define MC_CMD_PORT_WRITE128 0x17 -#define MC_CMD_PORT_WRITE128_IN_LEN 20 -#define MC_CMD_PORT_WRITE128_IN_ADDR_OFST 0 -#define MC_CMD_PORT_WRITE128_IN_VALUE_OFST 4 -#define MC_CMD_PORT_WRITE128_OUT_LEN 4 -#define MC_CMD_PORT_WRITE128_OUT_STATUS_OFST 0 - -/* MC_CMD_GET_BOARD_CFG: - * Returns the MC firmware configuration structure - * - * The FW_SUBTYPE_LIST contains a 16-bit value for each of the 12 types of - * NVRAM area. The values are defined in the firmware/mc/platform/<xxx>.c file - * for a specific board type, but otherwise have no meaning to the MC; they - * are used by the driver to manage selection of appropriate firmware updates. + +/* MC_CMD_PORT_WRITE128_IN msgrequest */ +#define MC_CMD_PORT_WRITE128_IN_LEN 20 +#define MC_CMD_PORT_WRITE128_IN_ADDR_OFST 0 +#define MC_CMD_PORT_WRITE128_IN_VALUE_OFST 4 +#define MC_CMD_PORT_WRITE128_IN_VALUE_LEN 16 + +/* MC_CMD_PORT_WRITE128_OUT msgresponse */ +#define MC_CMD_PORT_WRITE128_OUT_LEN 4 +#define MC_CMD_PORT_WRITE128_OUT_STATUS_OFST 0 + + +/***********************************/ +/* MC_CMD_GET_BOARD_CFG + * Returns the MC firmware configuration structure. */ #define MC_CMD_GET_BOARD_CFG 0x18 -#define MC_CMD_GET_BOARD_CFG_IN_LEN 0 -#define MC_CMD_GET_BOARD_CFG_OUT_LEN 96 -#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_TYPE_OFST 0 -#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_OFST 4 -#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_LEN 32 -#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT0_OFST 36 -#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT1_OFST 40 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST 44 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_LEN 6 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST 50 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_LEN 6 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT0_OFST 56 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT1_OFST 60 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT0_OFST 64 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT1_OFST 68 -#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST 72 -#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN 24 - -/* MC_CMD_DBI_READX: (debug) - * Read DBI register(s) -- extended functionality - * - * Host: vf selection, address, [,vf selection ...] - * MC: value [,value ...] + +/* MC_CMD_GET_BOARD_CFG_IN msgrequest */ +#define MC_CMD_GET_BOARD_CFG_IN_LEN 0 + +/* MC_CMD_GET_BOARD_CFG_OUT msgresponse */ +#define MC_CMD_GET_BOARD_CFG_OUT_LENMIN 96 +#define MC_CMD_GET_BOARD_CFG_OUT_LENMAX 136 +#define MC_CMD_GET_BOARD_CFG_OUT_LEN(num) (72+2*(num)) +#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_TYPE_OFST 0 +#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_OFST 4 +#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_LEN 32 +#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT0_OFST 36 +#define MC_CMD_CAPABILITIES_SMALL_BUF_TBL_LBN 0x0 /* enum */ +#define MC_CMD_CAPABILITIES_SMALL_BUF_TBL_WIDTH 0x1 /* enum */ +#define MC_CMD_CAPABILITIES_TURBO_LBN 0x1 /* enum */ +#define MC_CMD_CAPABILITIES_TURBO_WIDTH 0x1 /* enum */ +#define MC_CMD_CAPABILITIES_TURBO_ACTIVE_LBN 0x2 /* enum */ +#define MC_CMD_CAPABILITIES_TURBO_ACTIVE_WIDTH 0x1 /* enum */ +#define MC_CMD_CAPABILITIES_PTP_LBN 0x3 /* enum */ +#define MC_CMD_CAPABILITIES_PTP_WIDTH 0x1 /* enum */ +#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT1_OFST 40 +/* Enum values, see field(s): */ +/* CAPABILITIES_PORT0 */ +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST 44 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_LEN 6 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST 50 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_LEN 6 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT0_OFST 56 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT1_OFST 60 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT0_OFST 64 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT1_OFST 68 +#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST 72 +#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN 2 +#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM 12 +#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM 32 + + +/***********************************/ +/* MC_CMD_DBI_READX + * Read DBI register(s). */ #define MC_CMD_DBI_READX 0x19 -#define MC_CMD_DBI_READX_IN_LEN(_numwords) \ - (8*(_numwords)) -#define MC_CMD_DBI_READX_OUT_LEN(_numwords) \ - (4*(_numwords)) -/* MC_CMD_SET_RAND_SEED: - * Set the 16byte seed for the MC pseudo-random generator +/* MC_CMD_DBI_READX_IN msgrequest */ +#define MC_CMD_DBI_READX_IN_LENMIN 8 +#define MC_CMD_DBI_READX_IN_LENMAX 248 +#define MC_CMD_DBI_READX_IN_LEN(num) (0+8*(num)) +#define MC_CMD_DBI_READX_IN_DBIRDOP_OFST 0 +#define MC_CMD_DBI_READX_IN_DBIRDOP_LEN 8 +#define MC_CMD_DBI_READX_IN_DBIRDOP_LO_OFST 0 +#define MC_CMD_DBI_READX_IN_DBIRDOP_HI_OFST 4 +#define MC_CMD_DBI_READX_IN_DBIRDOP_MINNUM 1 +#define MC_CMD_DBI_READX_IN_DBIRDOP_MAXNUM 31 + +/* MC_CMD_DBI_READX_OUT msgresponse */ +#define MC_CMD_DBI_READX_OUT_LENMIN 4 +#define MC_CMD_DBI_READX_OUT_LENMAX 252 +#define MC_CMD_DBI_READX_OUT_LEN(num) (0+4*(num)) +#define MC_CMD_DBI_READX_OUT_VALUE_OFST 0 +#define MC_CMD_DBI_READX_OUT_VALUE_LEN 4 +#define MC_CMD_DBI_READX_OUT_VALUE_MINNUM 1 +#define MC_CMD_DBI_READX_OUT_VALUE_MAXNUM 63 + + +/***********************************/ +/* MC_CMD_SET_RAND_SEED + * Set the 16byte seed for the MC pseudo-random generator. */ #define MC_CMD_SET_RAND_SEED 0x1a -#define MC_CMD_SET_RAND_SEED_IN_LEN 16 -#define MC_CMD_SET_RAND_SEED_IN_SEED_OFST 0 -#define MC_CMD_SET_RAND_SEED_OUT_LEN 0 -/* MC_CMD_LTSSM_HIST: (debug) - * Retrieve the history of the LTSSM, if the build supports it. - * - * Host: nothing - * MC: variable number of LTSSM values, as bytes - * The history is read-to-clear. +/* MC_CMD_SET_RAND_SEED_IN msgrequest */ +#define MC_CMD_SET_RAND_SEED_IN_LEN 16 +#define MC_CMD_SET_RAND_SEED_IN_SEED_OFST 0 +#define MC_CMD_SET_RAND_SEED_IN_SEED_LEN 16 + +/* MC_CMD_SET_RAND_SEED_OUT msgresponse */ +#define MC_CMD_SET_RAND_SEED_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_LTSSM_HIST + * Retrieve the history of the PCIE LTSSM. */ #define MC_CMD_LTSSM_HIST 0x1b -/* MC_CMD_DRV_ATTACH: - * Inform MCPU that this port is managed on the host (i.e. driver active) +/* MC_CMD_LTSSM_HIST_IN msgrequest */ +#define MC_CMD_LTSSM_HIST_IN_LEN 0 + +/* MC_CMD_LTSSM_HIST_OUT msgresponse */ +#define MC_CMD_LTSSM_HIST_OUT_LENMIN 0 +#define MC_CMD_LTSSM_HIST_OUT_LENMAX 252 +#define MC_CMD_LTSSM_HIST_OUT_LEN(num) (0+4*(num)) +#define MC_CMD_LTSSM_HIST_OUT_DATA_OFST 0 +#define MC_CMD_LTSSM_HIST_OUT_DATA_LEN 4 +#define MC_CMD_LTSSM_HIST_OUT_DATA_MINNUM 0 +#define MC_CMD_LTSSM_HIST_OUT_DATA_MAXNUM 63 + + +/***********************************/ +/* MC_CMD_DRV_ATTACH + * Inform MCPU that this port is managed on the host. */ #define MC_CMD_DRV_ATTACH 0x1c -#define MC_CMD_DRV_ATTACH_IN_LEN 8 -#define MC_CMD_DRV_ATTACH_IN_NEW_STATE_OFST 0 -#define MC_CMD_DRV_ATTACH_IN_UPDATE_OFST 4 -#define MC_CMD_DRV_ATTACH_OUT_LEN 4 -#define MC_CMD_DRV_ATTACH_OUT_OLD_STATE_OFST 0 -/* MC_CMD_NCSI_PROD: (debug) - * Trigger an NC-SI event (and possibly an AEN in response) +/* MC_CMD_DRV_ATTACH_IN msgrequest */ +#define MC_CMD_DRV_ATTACH_IN_LEN 8 +#define MC_CMD_DRV_ATTACH_IN_NEW_STATE_OFST 0 +#define MC_CMD_DRV_ATTACH_IN_UPDATE_OFST 4 + +/* MC_CMD_DRV_ATTACH_OUT msgresponse */ +#define MC_CMD_DRV_ATTACH_OUT_LEN 4 +#define MC_CMD_DRV_ATTACH_OUT_OLD_STATE_OFST 0 + + +/***********************************/ +/* MC_CMD_NCSI_PROD + * Trigger an NC-SI event. */ #define MC_CMD_NCSI_PROD 0x1d -#define MC_CMD_NCSI_PROD_IN_LEN 4 -#define MC_CMD_NCSI_PROD_IN_EVENTS_OFST 0 -#define MC_CMD_NCSI_PROD_LINKCHANGE_LBN 0 -#define MC_CMD_NCSI_PROD_LINKCHANGE_WIDTH 1 -#define MC_CMD_NCSI_PROD_RESET_LBN 1 -#define MC_CMD_NCSI_PROD_RESET_WIDTH 1 -#define MC_CMD_NCSI_PROD_DRVATTACH_LBN 2 -#define MC_CMD_NCSI_PROD_DRVATTACH_WIDTH 1 -#define MC_CMD_NCSI_PROD_OUT_LEN 0 - -/* Enumeration */ -#define MC_CMD_NCSI_PROD_LINKCHANGE 0 -#define MC_CMD_NCSI_PROD_RESET 1 -#define MC_CMD_NCSI_PROD_DRVATTACH 2 - -/* MC_CMD_DEVEL: (debug) - * Reserved for development - */ -#define MC_CMD_DEVEL 0x1e - -/* MC_CMD_SHMUART: (debug) + +/* MC_CMD_NCSI_PROD_IN msgrequest */ +#define MC_CMD_NCSI_PROD_IN_LEN 4 +#define MC_CMD_NCSI_PROD_IN_EVENTS_OFST 0 +#define MC_CMD_NCSI_PROD_LINKCHANGE 0x0 /* enum */ +#define MC_CMD_NCSI_PROD_RESET 0x1 /* enum */ +#define MC_CMD_NCSI_PROD_DRVATTACH 0x2 /* enum */ +#define MC_CMD_NCSI_PROD_IN_LINKCHANGE_LBN 0 +#define MC_CMD_NCSI_PROD_IN_LINKCHANGE_WIDTH 1 +#define MC_CMD_NCSI_PROD_IN_RESET_LBN 1 +#define MC_CMD_NCSI_PROD_IN_RESET_WIDTH 1 +#define MC_CMD_NCSI_PROD_IN_DRVATTACH_LBN 2 +#define MC_CMD_NCSI_PROD_IN_DRVATTACH_WIDTH 1 + +/* MC_CMD_NCSI_PROD_OUT msgresponse */ +#define MC_CMD_NCSI_PROD_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SHMUART * Route UART output to circular buffer in shared memory instead. */ #define MC_CMD_SHMUART 0x1f -#define MC_CMD_SHMUART_IN_FLAG_OFST 0 -#define MC_CMD_SHMUART_IN_LEN 4 -#define MC_CMD_SHMUART_OUT_LEN 0 -/* MC_CMD_PORT_RESET: - * Generic per-port reset. There is no equivalent for per-board reset. - * - * Locks required: None - * Return code: 0, ETIME - */ -#define MC_CMD_PORT_RESET 0x20 -#define MC_CMD_PORT_RESET_IN_LEN 0 -#define MC_CMD_PORT_RESET_OUT_LEN 0 - -/* MC_CMD_RESOURCE_LOCK: - * Generic resource lock/unlock interface. - * - * Locks required: None - * Return code: 0, - * EBUSY (if trylock is contended by other port), - * EDEADLK (if trylock is already acquired by this port) - * EINVAL (if unlock doesn't own the lock) - */ -#define MC_CMD_RESOURCE_LOCK 0x21 -#define MC_CMD_RESOURCE_LOCK_IN_LEN 8 -#define MC_CMD_RESOURCE_LOCK_IN_ACTION_OFST 0 -#define MC_CMD_RESOURCE_LOCK_ACTION_TRYLOCK 1 -#define MC_CMD_RESOURCE_LOCK_ACTION_UNLOCK 0 -#define MC_CMD_RESOURCE_LOCK_IN_RESOURCE_OFST 4 -#define MC_CMD_RESOURCE_LOCK_I2C 2 -#define MC_CMD_RESOURCE_LOCK_PHY 3 -#define MC_CMD_RESOURCE_LOCK_OUT_LEN 0 - -/* MC_CMD_SPI_COMMAND: (variadic in, variadic out) - * Read/Write to/from the SPI device. - * - * Locks required: SPI_LOCK - * Return code: 0, ETIME, EINVAL, EACCES (if SPI_LOCK is not held) - */ -#define MC_CMD_SPI_COMMAND 0x22 -#define MC_CMD_SPI_COMMAND_IN_LEN(_write_bytes) (12 + (_write_bytes)) -#define MC_CMD_SPI_COMMAND_IN_ARGS_OFST 0 -#define MC_CMD_SPI_COMMAND_IN_ARGS_ADDRESS_OFST 0 -#define MC_CMD_SPI_COMMAND_IN_ARGS_READ_BYTES_OFST 4 -#define MC_CMD_SPI_COMMAND_IN_ARGS_CHIP_SELECT_OFST 8 -/* Data to write here */ -#define MC_CMD_SPI_COMMAND_IN_WRITE_BUFFER_OFST 12 -#define MC_CMD_SPI_COMMAND_OUT_LEN(_read_bytes) (_read_bytes) -/* Data read here */ -#define MC_CMD_SPI_COMMAND_OUT_READ_BUFFER_OFST 0 - -/* MC_CMD_I2C_READ_WRITE: (variadic in, variadic out) - * Read/Write to/from the I2C bus. - * - * Locks required: I2C_LOCK - * Return code: 0, ETIME, EINVAL, EACCES (if I2C_LOCK is not held) - */ -#define MC_CMD_I2C_RW 0x23 -#define MC_CMD_I2C_RW_IN_LEN(_write_bytes) (8 + (_write_bytes)) -#define MC_CMD_I2C_RW_IN_ARGS_OFST 0 -#define MC_CMD_I2C_RW_IN_ARGS_ADDR_OFST 0 -#define MC_CMD_I2C_RW_IN_ARGS_READ_BYTES_OFST 4 -/* Data to write here */ -#define MC_CMD_I2C_RW_IN_WRITE_BUFFER_OFSET 8 -#define MC_CMD_I2C_RW_OUT_LEN(_read_bytes) (_read_bytes) -/* Data read here */ -#define MC_CMD_I2C_RW_OUT_READ_BUFFER_OFST 0 - -/* Generic phy capability bitmask */ -#define MC_CMD_PHY_CAP_10HDX_LBN 1 -#define MC_CMD_PHY_CAP_10HDX_WIDTH 1 -#define MC_CMD_PHY_CAP_10FDX_LBN 2 -#define MC_CMD_PHY_CAP_10FDX_WIDTH 1 -#define MC_CMD_PHY_CAP_100HDX_LBN 3 -#define MC_CMD_PHY_CAP_100HDX_WIDTH 1 -#define MC_CMD_PHY_CAP_100FDX_LBN 4 -#define MC_CMD_PHY_CAP_100FDX_WIDTH 1 -#define MC_CMD_PHY_CAP_1000HDX_LBN 5 -#define MC_CMD_PHY_CAP_1000HDX_WIDTH 1 -#define MC_CMD_PHY_CAP_1000FDX_LBN 6 -#define MC_CMD_PHY_CAP_1000FDX_WIDTH 1 -#define MC_CMD_PHY_CAP_10000FDX_LBN 7 -#define MC_CMD_PHY_CAP_10000FDX_WIDTH 1 -#define MC_CMD_PHY_CAP_PAUSE_LBN 8 -#define MC_CMD_PHY_CAP_PAUSE_WIDTH 1 -#define MC_CMD_PHY_CAP_ASYM_LBN 9 -#define MC_CMD_PHY_CAP_ASYM_WIDTH 1 -#define MC_CMD_PHY_CAP_AN_LBN 10 -#define MC_CMD_PHY_CAP_AN_WIDTH 1 - -/* Generic loopback enumeration */ -#define MC_CMD_LOOPBACK_NONE 0 -#define MC_CMD_LOOPBACK_DATA 1 -#define MC_CMD_LOOPBACK_GMAC 2 -#define MC_CMD_LOOPBACK_XGMII 3 -#define MC_CMD_LOOPBACK_XGXS 4 -#define MC_CMD_LOOPBACK_XAUI 5 -#define MC_CMD_LOOPBACK_GMII 6 -#define MC_CMD_LOOPBACK_SGMII 7 -#define MC_CMD_LOOPBACK_XGBR 8 -#define MC_CMD_LOOPBACK_XFI 9 -#define MC_CMD_LOOPBACK_XAUI_FAR 10 -#define MC_CMD_LOOPBACK_GMII_FAR 11 -#define MC_CMD_LOOPBACK_SGMII_FAR 12 -#define MC_CMD_LOOPBACK_XFI_FAR 13 -#define MC_CMD_LOOPBACK_GPHY 14 -#define MC_CMD_LOOPBACK_PHYXS 15 -#define MC_CMD_LOOPBACK_PCS 16 -#define MC_CMD_LOOPBACK_PMAPMD 17 -#define MC_CMD_LOOPBACK_XPORT 18 -#define MC_CMD_LOOPBACK_XGMII_WS 19 -#define MC_CMD_LOOPBACK_XAUI_WS 20 -#define MC_CMD_LOOPBACK_XAUI_WS_FAR 21 -#define MC_CMD_LOOPBACK_XAUI_WS_NEAR 22 -#define MC_CMD_LOOPBACK_GMII_WS 23 -#define MC_CMD_LOOPBACK_XFI_WS 24 -#define MC_CMD_LOOPBACK_XFI_WS_FAR 25 -#define MC_CMD_LOOPBACK_PHYXS_WS 26 - -/* Generic PHY statistics enumeration */ -#define MC_CMD_OUI 0 -#define MC_CMD_PMA_PMD_LINK_UP 1 -#define MC_CMD_PMA_PMD_RX_FAULT 2 -#define MC_CMD_PMA_PMD_TX_FAULT 3 -#define MC_CMD_PMA_PMD_SIGNAL 4 -#define MC_CMD_PMA_PMD_SNR_A 5 -#define MC_CMD_PMA_PMD_SNR_B 6 -#define MC_CMD_PMA_PMD_SNR_C 7 -#define MC_CMD_PMA_PMD_SNR_D 8 -#define MC_CMD_PCS_LINK_UP 9 -#define MC_CMD_PCS_RX_FAULT 10 -#define MC_CMD_PCS_TX_FAULT 11 -#define MC_CMD_PCS_BER 12 -#define MC_CMD_PCS_BLOCK_ERRORS 13 -#define MC_CMD_PHYXS_LINK_UP 14 -#define MC_CMD_PHYXS_RX_FAULT 15 -#define MC_CMD_PHYXS_TX_FAULT 16 -#define MC_CMD_PHYXS_ALIGN 17 -#define MC_CMD_PHYXS_SYNC 18 -#define MC_CMD_AN_LINK_UP 19 -#define MC_CMD_AN_COMPLETE 20 -#define MC_CMD_AN_10GBT_STATUS 21 -#define MC_CMD_CL22_LINK_UP 22 -#define MC_CMD_PHY_NSTATS 23 - -/* MC_CMD_GET_PHY_CFG: - * Report PHY configuration. This guarantees to succeed even if the PHY is in - * a "zombie" state. - * - * Locks required: None - * Return code: 0 +/* MC_CMD_SHMUART_IN msgrequest */ +#define MC_CMD_SHMUART_IN_LEN 4 +#define MC_CMD_SHMUART_IN_FLAG_OFST 0 + +/* MC_CMD_SHMUART_OUT msgresponse */ +#define MC_CMD_SHMUART_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_ENTITY_RESET + * Generic per-port reset. + */ +#define MC_CMD_ENTITY_RESET 0x20 + +/* MC_CMD_ENTITY_RESET_IN msgrequest */ +#define MC_CMD_ENTITY_RESET_IN_LEN 4 +#define MC_CMD_ENTITY_RESET_IN_FLAG_OFST 0 +#define MC_CMD_ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET_LBN 0 +#define MC_CMD_ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET_WIDTH 1 + +/* MC_CMD_ENTITY_RESET_OUT msgresponse */ +#define MC_CMD_ENTITY_RESET_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_PCIE_CREDITS + * Read instantaneous and minimum flow control thresholds. + */ +#define MC_CMD_PCIE_CREDITS 0x21 + +/* MC_CMD_PCIE_CREDITS_IN msgrequest */ +#define MC_CMD_PCIE_CREDITS_IN_LEN 8 +#define MC_CMD_PCIE_CREDITS_IN_POLL_PERIOD_OFST 0 +#define MC_CMD_PCIE_CREDITS_IN_WIPE_OFST 4 + +/* MC_CMD_PCIE_CREDITS_OUT msgresponse */ +#define MC_CMD_PCIE_CREDITS_OUT_LEN 16 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_HDR_OFST 0 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_HDR_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_DATA_OFST 2 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_DATA_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_HDR_OFST 4 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_HDR_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_DATA_OFST 6 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_DATA_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_HDR_OFST 8 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_HDR_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_DATA_OFST 10 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_DATA_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_HDR_OFST 12 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_HDR_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_DATA_OFST 14 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_DATA_LEN 2 + + +/***********************************/ +/* MC_CMD_RXD_MONITOR + * Get histogram of RX queue fill level. + */ +#define MC_CMD_RXD_MONITOR 0x22 + +/* MC_CMD_RXD_MONITOR_IN msgrequest */ +#define MC_CMD_RXD_MONITOR_IN_LEN 12 +#define MC_CMD_RXD_MONITOR_IN_QID_OFST 0 +#define MC_CMD_RXD_MONITOR_IN_POLL_PERIOD_OFST 4 +#define MC_CMD_RXD_MONITOR_IN_WIPE_OFST 8 + +/* MC_CMD_RXD_MONITOR_OUT msgresponse */ +#define MC_CMD_RXD_MONITOR_OUT_LEN 80 +#define MC_CMD_RXD_MONITOR_OUT_QID_OFST 0 +#define MC_CMD_RXD_MONITOR_OUT_RING_FILL_OFST 4 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_FILL_OFST 8 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_1_OFST 12 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_2_OFST 16 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_4_OFST 20 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_8_OFST 24 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_16_OFST 28 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_32_OFST 32 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_64_OFST 36 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_128_OFST 40 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_256_OFST 44 +#define MC_CMD_RXD_MONITOR_OUT_RING_GE_256_OFST 48 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_1_OFST 52 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_2_OFST 56 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_4_OFST 60 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_8_OFST 64 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_16_OFST 68 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_32_OFST 72 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_GE_32_OFST 76 + + +/***********************************/ +/* MC_CMD_PUTS + * puts(3) implementation over MCDI + */ +#define MC_CMD_PUTS 0x23 + +/* MC_CMD_PUTS_IN msgrequest */ +#define MC_CMD_PUTS_IN_LENMIN 13 +#define MC_CMD_PUTS_IN_LENMAX 255 +#define MC_CMD_PUTS_IN_LEN(num) (12+1*(num)) +#define MC_CMD_PUTS_IN_DEST_OFST 0 +#define MC_CMD_PUTS_IN_UART_LBN 0 +#define MC_CMD_PUTS_IN_UART_WIDTH 1 +#define MC_CMD_PUTS_IN_PORT_LBN 1 +#define MC_CMD_PUTS_IN_PORT_WIDTH 1 +#define MC_CMD_PUTS_IN_DHOST_OFST 4 +#define MC_CMD_PUTS_IN_DHOST_LEN 6 +#define MC_CMD_PUTS_IN_STRING_OFST 12 +#define MC_CMD_PUTS_IN_STRING_LEN 1 +#define MC_CMD_PUTS_IN_STRING_MINNUM 1 +#define MC_CMD_PUTS_IN_STRING_MAXNUM 243 + +/* MC_CMD_PUTS_OUT msgresponse */ +#define MC_CMD_PUTS_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_PHY_CFG + * Report PHY configuration. */ #define MC_CMD_GET_PHY_CFG 0x24 -#define MC_CMD_GET_PHY_CFG_IN_LEN 0 -#define MC_CMD_GET_PHY_CFG_OUT_LEN 72 - -#define MC_CMD_GET_PHY_CFG_OUT_FLAGS_OFST 0 -#define MC_CMD_GET_PHY_CFG_PRESENT_LBN 0 -#define MC_CMD_GET_PHY_CFG_PRESENT_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_LBN 1 -#define MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN 2 -#define MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_LOWPOWER_LBN 3 -#define MC_CMD_GET_PHY_CFG_LOWPOWER_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_POWEROFF_LBN 4 -#define MC_CMD_GET_PHY_CFG_POWEROFF_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_TXDIS_LBN 5 -#define MC_CMD_GET_PHY_CFG_TXDIS_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_BIST_LBN 6 -#define MC_CMD_GET_PHY_CFG_BIST_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_OUT_TYPE_OFST 4 -/* Bitmask of supported capabilities */ -#define MC_CMD_GET_PHY_CFG_OUT_SUPPORTED_CAP_OFST 8 -#define MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12 -#define MC_CMD_GET_PHY_CFG_OUT_PRT_OFST 16 -/* PHY statistics bitmap */ -#define MC_CMD_GET_PHY_CFG_OUT_STATS_MASK_OFST 20 -/* PHY type/name string */ -#define MC_CMD_GET_PHY_CFG_OUT_NAME_OFST 24 -#define MC_CMD_GET_PHY_CFG_OUT_NAME_LEN 20 -#define MC_CMD_GET_PHY_CFG_OUT_MEDIA_TYPE_OFST 44 -#define MC_CMD_MEDIA_XAUI 1 -#define MC_CMD_MEDIA_CX4 2 -#define MC_CMD_MEDIA_KX4 3 -#define MC_CMD_MEDIA_XFP 4 -#define MC_CMD_MEDIA_SFP_PLUS 5 -#define MC_CMD_MEDIA_BASE_T 6 -/* MDIO "MMDS" supported */ -#define MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48 -/* Native clause 22 */ -#define MC_CMD_MMD_CLAUSE22 0 -#define MC_CMD_MMD_CLAUSE45_PMAPMD 1 -#define MC_CMD_MMD_CLAUSE45_WIS 2 -#define MC_CMD_MMD_CLAUSE45_PCS 3 -#define MC_CMD_MMD_CLAUSE45_PHYXS 4 -#define MC_CMD_MMD_CLAUSE45_DTEXS 5 -#define MC_CMD_MMD_CLAUSE45_TC 6 -#define MC_CMD_MMD_CLAUSE45_AN 7 -/* Clause22 proxied over clause45 by PHY */ -#define MC_CMD_MMD_CLAUSE45_C22EXT 29 -#define MC_CMD_MMD_CLAUSE45_VEND1 30 -#define MC_CMD_MMD_CLAUSE45_VEND2 31 -/* PHY stepping version */ -#define MC_CMD_GET_PHY_CFG_OUT_REVISION_OFST 52 -#define MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN 20 - -/* MC_CMD_START_BIST: +/* MC_CMD_GET_PHY_CFG_IN msgrequest */ +#define MC_CMD_GET_PHY_CFG_IN_LEN 0 + +/* MC_CMD_GET_PHY_CFG_OUT msgresponse */ +#define MC_CMD_GET_PHY_CFG_OUT_LEN 72 +#define MC_CMD_GET_PHY_CFG_OUT_FLAGS_OFST 0 +#define MC_CMD_GET_PHY_CFG_OUT_PRESENT_LBN 0 +#define MC_CMD_GET_PHY_CFG_OUT_PRESENT_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN 1 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN 2 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_LBN 3 +#define MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_POWEROFF_LBN 4 +#define MC_CMD_GET_PHY_CFG_OUT_POWEROFF_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_TXDIS_LBN 5 +#define MC_CMD_GET_PHY_CFG_OUT_TXDIS_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_LBN 6 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_TYPE_OFST 4 +#define MC_CMD_GET_PHY_CFG_OUT_SUPPORTED_CAP_OFST 8 +#define MC_CMD_PHY_CAP_10HDX_LBN 1 +#define MC_CMD_PHY_CAP_10HDX_WIDTH 1 +#define MC_CMD_PHY_CAP_10FDX_LBN 2 +#define MC_CMD_PHY_CAP_10FDX_WIDTH 1 +#define MC_CMD_PHY_CAP_100HDX_LBN 3 +#define MC_CMD_PHY_CAP_100HDX_WIDTH 1 +#define MC_CMD_PHY_CAP_100FDX_LBN 4 +#define MC_CMD_PHY_CAP_100FDX_WIDTH 1 +#define MC_CMD_PHY_CAP_1000HDX_LBN 5 +#define MC_CMD_PHY_CAP_1000HDX_WIDTH 1 +#define MC_CMD_PHY_CAP_1000FDX_LBN 6 +#define MC_CMD_PHY_CAP_1000FDX_WIDTH 1 +#define MC_CMD_PHY_CAP_10000FDX_LBN 7 +#define MC_CMD_PHY_CAP_10000FDX_WIDTH 1 +#define MC_CMD_PHY_CAP_PAUSE_LBN 8 +#define MC_CMD_PHY_CAP_PAUSE_WIDTH 1 +#define MC_CMD_PHY_CAP_ASYM_LBN 9 +#define MC_CMD_PHY_CAP_ASYM_WIDTH 1 +#define MC_CMD_PHY_CAP_AN_LBN 10 +#define MC_CMD_PHY_CAP_AN_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12 +#define MC_CMD_GET_PHY_CFG_OUT_PRT_OFST 16 +#define MC_CMD_GET_PHY_CFG_OUT_STATS_MASK_OFST 20 +#define MC_CMD_GET_PHY_CFG_OUT_NAME_OFST 24 +#define MC_CMD_GET_PHY_CFG_OUT_NAME_LEN 20 +#define MC_CMD_GET_PHY_CFG_OUT_MEDIA_TYPE_OFST 44 +#define MC_CMD_MEDIA_XAUI 0x1 /* enum */ +#define MC_CMD_MEDIA_CX4 0x2 /* enum */ +#define MC_CMD_MEDIA_KX4 0x3 /* enum */ +#define MC_CMD_MEDIA_XFP 0x4 /* enum */ +#define MC_CMD_MEDIA_SFP_PLUS 0x5 /* enum */ +#define MC_CMD_MEDIA_BASE_T 0x6 /* enum */ +#define MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48 +#define MC_CMD_MMD_CLAUSE22 0x0 /* enum */ +#define MC_CMD_MMD_CLAUSE45_PMAPMD 0x1 /* enum */ +#define MC_CMD_MMD_CLAUSE45_WIS 0x2 /* enum */ +#define MC_CMD_MMD_CLAUSE45_PCS 0x3 /* enum */ +#define MC_CMD_MMD_CLAUSE45_PHYXS 0x4 /* enum */ +#define MC_CMD_MMD_CLAUSE45_DTEXS 0x5 /* enum */ +#define MC_CMD_MMD_CLAUSE45_TC 0x6 /* enum */ +#define MC_CMD_MMD_CLAUSE45_AN 0x7 /* enum */ +#define MC_CMD_MMD_CLAUSE45_C22EXT 0x1d /* enum */ +#define MC_CMD_MMD_CLAUSE45_VEND1 0x1e /* enum */ +#define MC_CMD_MMD_CLAUSE45_VEND2 0x1f /* enum */ +#define MC_CMD_GET_PHY_CFG_OUT_REVISION_OFST 52 +#define MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN 20 + + +/***********************************/ +/* MC_CMD_START_BIST * Start a BIST test on the PHY. - * - * Locks required: PHY_LOCK if doing a PHY BIST - * Return code: 0, EINVAL, EACCES (if PHY_LOCK is not held) */ #define MC_CMD_START_BIST 0x25 -#define MC_CMD_START_BIST_IN_LEN 4 -#define MC_CMD_START_BIST_IN_TYPE_OFST 0 -#define MC_CMD_START_BIST_OUT_LEN 0 - -/* Run the PHY's short cable BIST */ -#define MC_CMD_PHY_BIST_CABLE_SHORT 1 -/* Run the PHY's long cable BIST */ -#define MC_CMD_PHY_BIST_CABLE_LONG 2 -/* Run BIST on the currently selected BPX Serdes (XAUI or XFI) */ -#define MC_CMD_BPX_SERDES_BIST 3 -/* Run the MC loopback tests */ -#define MC_CMD_MC_LOOPBACK_BIST 4 -/* Run the PHY's standard BIST */ -#define MC_CMD_PHY_BIST 5 - -/* MC_CMD_POLL_PHY_BIST: (variadic output) - * Poll for BIST completion - * - * Returns a single status code, and optionally some PHY specific - * bist output. The driver should only consume the BIST output - * after validating OUTLEN and PHY_CFG.PHY_TYPE. - * - * If a driver can't successfully parse the BIST output, it should - * still respect the pass/Fail in OUT.RESULT - * - * Locks required: PHY_LOCK if doing a PHY BIST - * Return code: 0, EACCES (if PHY_LOCK is not held) + +/* MC_CMD_START_BIST_IN msgrequest */ +#define MC_CMD_START_BIST_IN_LEN 4 +#define MC_CMD_START_BIST_IN_TYPE_OFST 0 +#define MC_CMD_PHY_BIST_CABLE_SHORT 0x1 /* enum */ +#define MC_CMD_PHY_BIST_CABLE_LONG 0x2 /* enum */ +#define MC_CMD_BPX_SERDES_BIST 0x3 /* enum */ +#define MC_CMD_MC_LOOPBACK_BIST 0x4 /* enum */ +#define MC_CMD_PHY_BIST 0x5 /* enum */ + +/* MC_CMD_START_BIST_OUT msgresponse */ +#define MC_CMD_START_BIST_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_POLL_BIST + * Poll for BIST completion. */ #define MC_CMD_POLL_BIST 0x26 -#define MC_CMD_POLL_BIST_IN_LEN 0 -#define MC_CMD_POLL_BIST_OUT_LEN UNKNOWN -#define MC_CMD_POLL_BIST_OUT_SFT9001_LEN 36 -#define MC_CMD_POLL_BIST_OUT_MRSFP_LEN 8 -#define MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 -#define MC_CMD_POLL_BIST_RUNNING 1 -#define MC_CMD_POLL_BIST_PASSED 2 -#define MC_CMD_POLL_BIST_FAILED 3 -#define MC_CMD_POLL_BIST_TIMEOUT 4 -/* Generic: */ -#define MC_CMD_POLL_BIST_OUT_PRIVATE_OFST 4 -/* SFT9001-specific: */ -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A_OFST 4 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B_OFST 8 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C_OFST 12 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D_OFST 16 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_A_OFST 20 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_B_OFST 24 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_C_OFST 28 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_D_OFST 32 -#define MC_CMD_POLL_BIST_SFT9001_PAIR_OK 1 -#define MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN 2 -#define MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT 3 -#define MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT 4 -#define MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY 9 -/* mrsfp "PHY" driver: */ -#define MC_CMD_POLL_BIST_OUT_MRSFP_TEST_OFST 4 -#define MC_CMD_POLL_BIST_MRSFP_TEST_COMPLETE 0 -#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_WRITE 1 -#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_IO_EXP 2 -#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_MODULE 3 -#define MC_CMD_POLL_BIST_MRSFP_TEST_IO_EXP_I2C_CONFIGURE 4 -#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_I2C_NO_CROSSTALK 5 -#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_PRESENCE 6 -#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_I2C_ACCESS 7 -#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_SANE_VALUE 8 - -/* MC_CMD_PHY_SPI: (variadic in, variadic out) - * Read/Write/Erase the PHY SPI device - * - * Locks required: PHY_LOCK - * Return code: 0, ETIME, EINVAL, EACCES (if PHY_LOCK is not held) - */ -#define MC_CMD_PHY_SPI 0x27 -#define MC_CMD_PHY_SPI_IN_LEN(_write_bytes) (12 + (_write_bytes)) -#define MC_CMD_PHY_SPI_IN_ARGS_OFST 0 -#define MC_CMD_PHY_SPI_IN_ARGS_ADDR_OFST 0 -#define MC_CMD_PHY_SPI_IN_ARGS_READ_BYTES_OFST 4 -#define MC_CMD_PHY_SPI_IN_ARGS_ERASE_ALL_OFST 8 -/* Data to write here */ -#define MC_CMD_PHY_SPI_IN_WRITE_BUFFER_OFSET 12 -#define MC_CMD_PHY_SPI_OUT_LEN(_read_bytes) (_read_bytes) -/* Data read here */ -#define MC_CMD_PHY_SPI_OUT_READ_BUFFER_OFST 0 - - -/* MC_CMD_GET_LOOPBACK_MODES: - * Returns a bitmask of loopback modes evailable at each speed. - * - * Locks required: None - * Return code: 0 + +/* MC_CMD_POLL_BIST_IN msgrequest */ +#define MC_CMD_POLL_BIST_IN_LEN 0 + +/* MC_CMD_POLL_BIST_OUT msgresponse */ +#define MC_CMD_POLL_BIST_OUT_LEN 8 +#define MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 +#define MC_CMD_POLL_BIST_RUNNING 0x1 /* enum */ +#define MC_CMD_POLL_BIST_PASSED 0x2 /* enum */ +#define MC_CMD_POLL_BIST_FAILED 0x3 /* enum */ +#define MC_CMD_POLL_BIST_TIMEOUT 0x4 /* enum */ +#define MC_CMD_POLL_BIST_OUT_PRIVATE_OFST 4 + +/* MC_CMD_POLL_BIST_OUT_SFT9001 msgresponse */ +#define MC_CMD_POLL_BIST_OUT_SFT9001_LEN 36 +/* MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 */ +/* Enum values, see field(s): */ +/* MC_CMD_POLL_BIST_OUT/MC_CMD_POLL_BIST_OUT_RESULT */ +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A_OFST 4 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B_OFST 8 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C_OFST 12 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D_OFST 16 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_A_OFST 20 +#define MC_CMD_POLL_BIST_SFT9001_PAIR_OK 0x1 /* enum */ +#define MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN 0x2 /* enum */ +#define MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT 0x3 /* enum */ +#define MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT 0x4 /* enum */ +#define MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY 0x9 /* enum */ +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_B_OFST 24 +/* Enum values, see field(s): */ +/* CABLE_STATUS_A */ +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_C_OFST 28 +/* Enum values, see field(s): */ +/* CABLE_STATUS_A */ +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_D_OFST 32 +/* Enum values, see field(s): */ +/* CABLE_STATUS_A */ + +/* MC_CMD_POLL_BIST_OUT_MRSFP msgresponse */ +#define MC_CMD_POLL_BIST_OUT_MRSFP_LEN 8 +/* MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 */ +/* Enum values, see field(s): */ +/* MC_CMD_POLL_BIST_OUT/MC_CMD_POLL_BIST_OUT_RESULT */ +#define MC_CMD_POLL_BIST_OUT_MRSFP_TEST_OFST 4 +#define MC_CMD_POLL_BIST_MRSFP_TEST_COMPLETE 0x0 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_WRITE 0x1 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_IO_EXP 0x2 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_MODULE 0x3 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_IO_EXP_I2C_CONFIGURE 0x4 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_I2C_NO_CROSSTALK 0x5 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_PRESENCE 0x6 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_I2C_ACCESS 0x7 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_SANE_VALUE 0x8 /* enum */ + + +/***********************************/ +/* MC_CMD_FLUSH_RX_QUEUES + * Flush receive queue(s). + */ +#define MC_CMD_FLUSH_RX_QUEUES 0x27 + +/* MC_CMD_FLUSH_RX_QUEUES_IN msgrequest */ +#define MC_CMD_FLUSH_RX_QUEUES_IN_LENMIN 4 +#define MC_CMD_FLUSH_RX_QUEUES_IN_LENMAX 252 +#define MC_CMD_FLUSH_RX_QUEUES_IN_LEN(num) (0+4*(num)) +#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_OFST 0 +#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_LEN 4 +#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MINNUM 1 +#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM 63 + +/* MC_CMD_FLUSH_RX_QUEUES_OUT msgresponse */ +#define MC_CMD_FLUSH_RX_QUEUES_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_LOOPBACK_MODES + * Get port's loopback modes. */ #define MC_CMD_GET_LOOPBACK_MODES 0x28 -#define MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0 -#define MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 32 -#define MC_CMD_GET_LOOPBACK_MODES_100M_OFST 0 -#define MC_CMD_GET_LOOPBACK_MODES_1G_OFST 8 -#define MC_CMD_GET_LOOPBACK_MODES_10G_OFST 16 -#define MC_CMD_GET_LOOPBACK_MODES_SUGGESTED_OFST 24 - -/* Flow control enumeration */ -#define MC_CMD_FCNTL_OFF 0 -#define MC_CMD_FCNTL_RESPOND 1 -#define MC_CMD_FCNTL_BIDIR 2 -/* Auto - Use what the link has autonegotiated - * - The driver should modify the advertised capabilities via SET_LINK.CAP - * to control the negotiated flow control mode. - * - Can only be set if the PHY supports PAUSE+ASYM capabilities - * - Never returned by GET_LINK as the value programmed into the MAC - */ -#define MC_CMD_FCNTL_AUTO 3 - -/* Generic mac fault bitmask */ -#define MC_CMD_MAC_FAULT_XGMII_LOCAL_LBN 0 -#define MC_CMD_MAC_FAULT_XGMII_LOCAL_WIDTH 1 -#define MC_CMD_MAC_FAULT_XGMII_REMOTE_LBN 1 -#define MC_CMD_MAC_FAULT_XGMII_REMOTE_WIDTH 1 -#define MC_CMD_MAC_FAULT_SGMII_REMOTE_LBN 2 -#define MC_CMD_MAC_FAULT_SGMII_REMOTE_WIDTH 1 - -/* MC_CMD_GET_LINK: - * Read the unified MAC/PHY link state - * - * Locks required: None - * Return code: 0, ETIME + +/* MC_CMD_GET_LOOPBACK_MODES_IN msgrequest */ +#define MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0 + +/* MC_CMD_GET_LOOPBACK_MODES_OUT msgresponse */ +#define MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 32 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_OFST 0 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_LEN 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_LO_OFST 0 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_OFST 4 +#define MC_CMD_LOOPBACK_NONE 0x0 /* enum */ +#define MC_CMD_LOOPBACK_DATA 0x1 /* enum */ +#define MC_CMD_LOOPBACK_GMAC 0x2 /* enum */ +#define MC_CMD_LOOPBACK_XGMII 0x3 /* enum */ +#define MC_CMD_LOOPBACK_XGXS 0x4 /* enum */ +#define MC_CMD_LOOPBACK_XAUI 0x5 /* enum */ +#define MC_CMD_LOOPBACK_GMII 0x6 /* enum */ +#define MC_CMD_LOOPBACK_SGMII 0x7 /* enum */ +#define MC_CMD_LOOPBACK_XGBR 0x8 /* enum */ +#define MC_CMD_LOOPBACK_XFI 0x9 /* enum */ +#define MC_CMD_LOOPBACK_XAUI_FAR 0xa /* enum */ +#define MC_CMD_LOOPBACK_GMII_FAR 0xb /* enum */ +#define MC_CMD_LOOPBACK_SGMII_FAR 0xc /* enum */ +#define MC_CMD_LOOPBACK_XFI_FAR 0xd /* enum */ +#define MC_CMD_LOOPBACK_GPHY 0xe /* enum */ +#define MC_CMD_LOOPBACK_PHYXS 0xf /* enum */ +#define MC_CMD_LOOPBACK_PCS 0x10 /* enum */ +#define MC_CMD_LOOPBACK_PMAPMD 0x11 /* enum */ +#define MC_CMD_LOOPBACK_XPORT 0x12 /* enum */ +#define MC_CMD_LOOPBACK_XGMII_WS 0x13 /* enum */ +#define MC_CMD_LOOPBACK_XAUI_WS 0x14 /* enum */ +#define MC_CMD_LOOPBACK_XAUI_WS_FAR 0x15 /* enum */ +#define MC_CMD_LOOPBACK_XAUI_WS_NEAR 0x16 /* enum */ +#define MC_CMD_LOOPBACK_GMII_WS 0x17 /* enum */ +#define MC_CMD_LOOPBACK_XFI_WS 0x18 /* enum */ +#define MC_CMD_LOOPBACK_XFI_WS_FAR 0x19 /* enum */ +#define MC_CMD_LOOPBACK_PHYXS_WS 0x1a /* enum */ +#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_OFST 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_LEN 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_LO_OFST 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_OFST 12 +/* Enum values, see field(s): */ +/* 100M */ +#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_OFST 16 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_LEN 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_LO_OFST 16 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_OFST 20 +/* Enum values, see field(s): */ +/* 100M */ +#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST 24 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LO_OFST 24 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_OFST 28 +/* Enum values, see field(s): */ +/* 100M */ + + +/***********************************/ +/* MC_CMD_GET_LINK + * Read the unified MAC/PHY link state. */ #define MC_CMD_GET_LINK 0x29 -#define MC_CMD_GET_LINK_IN_LEN 0 -#define MC_CMD_GET_LINK_OUT_LEN 28 -/* near-side and link-partner advertised capabilities */ -#define MC_CMD_GET_LINK_OUT_CAP_OFST 0 -#define MC_CMD_GET_LINK_OUT_LP_CAP_OFST 4 -/* Autonegotiated speed in mbit/s. The link may still be down - * even if this reads non-zero */ -#define MC_CMD_GET_LINK_OUT_LINK_SPEED_OFST 8 -#define MC_CMD_GET_LINK_OUT_LOOPBACK_MODE_OFST 12 -#define MC_CMD_GET_LINK_OUT_FLAGS_OFST 16 -/* Whether we have overall link up */ -#define MC_CMD_GET_LINK_LINK_UP_LBN 0 -#define MC_CMD_GET_LINK_LINK_UP_WIDTH 1 -#define MC_CMD_GET_LINK_FULL_DUPLEX_LBN 1 -#define MC_CMD_GET_LINK_FULL_DUPLEX_WIDTH 1 -/* Whether we have link at the layers provided by the BPX */ -#define MC_CMD_GET_LINK_BPX_LINK_LBN 2 -#define MC_CMD_GET_LINK_BPX_LINK_WIDTH 1 -/* Whether the PHY has external link */ -#define MC_CMD_GET_LINK_PHY_LINK_LBN 3 -#define MC_CMD_GET_LINK_PHY_LINK_WIDTH 1 -#define MC_CMD_GET_LINK_OUT_FCNTL_OFST 20 -#define MC_CMD_GET_LINK_OUT_MAC_FAULT_OFST 24 - -/* MC_CMD_SET_LINK: - * Write the unified MAC/PHY link configuration - * - * A loopback speed of "0" is supported, and means - * (choose any available speed) - * - * Locks required: None - * Return code: 0, EINVAL, ETIME + +/* MC_CMD_GET_LINK_IN msgrequest */ +#define MC_CMD_GET_LINK_IN_LEN 0 + +/* MC_CMD_GET_LINK_OUT msgresponse */ +#define MC_CMD_GET_LINK_OUT_LEN 28 +#define MC_CMD_GET_LINK_OUT_CAP_OFST 0 +#define MC_CMD_GET_LINK_OUT_LP_CAP_OFST 4 +#define MC_CMD_GET_LINK_OUT_LINK_SPEED_OFST 8 +#define MC_CMD_GET_LINK_OUT_LOOPBACK_MODE_OFST 12 +/* Enum values, see field(s): */ +/* MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */ +#define MC_CMD_GET_LINK_OUT_FLAGS_OFST 16 +#define MC_CMD_GET_LINK_OUT_LINK_UP_LBN 0 +#define MC_CMD_GET_LINK_OUT_LINK_UP_WIDTH 1 +#define MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN 1 +#define MC_CMD_GET_LINK_OUT_FULL_DUPLEX_WIDTH 1 +#define MC_CMD_GET_LINK_OUT_BPX_LINK_LBN 2 +#define MC_CMD_GET_LINK_OUT_BPX_LINK_WIDTH 1 +#define MC_CMD_GET_LINK_OUT_PHY_LINK_LBN 3 +#define MC_CMD_GET_LINK_OUT_PHY_LINK_WIDTH 1 +#define MC_CMD_GET_LINK_OUT_FCNTL_OFST 20 +#define MC_CMD_FCNTL_OFF 0x0 /* enum */ +#define MC_CMD_FCNTL_RESPOND 0x1 /* enum */ +#define MC_CMD_FCNTL_BIDIR 0x2 /* enum */ +#define MC_CMD_GET_LINK_OUT_MAC_FAULT_OFST 24 +#define MC_CMD_MAC_FAULT_XGMII_LOCAL_LBN 0 +#define MC_CMD_MAC_FAULT_XGMII_LOCAL_WIDTH 1 +#define MC_CMD_MAC_FAULT_XGMII_REMOTE_LBN 1 +#define MC_CMD_MAC_FAULT_XGMII_REMOTE_WIDTH 1 +#define MC_CMD_MAC_FAULT_SGMII_REMOTE_LBN 2 +#define MC_CMD_MAC_FAULT_SGMII_REMOTE_WIDTH 1 +#define MC_CMD_MAC_FAULT_PENDING_RECONFIG_LBN 3 +#define MC_CMD_MAC_FAULT_PENDING_RECONFIG_WIDTH 1 + + +/***********************************/ +/* MC_CMD_SET_LINK + * Write the unified MAC/PHY link configuration. */ #define MC_CMD_SET_LINK 0x2a -#define MC_CMD_SET_LINK_IN_LEN 16 -#define MC_CMD_SET_LINK_IN_CAP_OFST 0 -#define MC_CMD_SET_LINK_IN_FLAGS_OFST 4 -#define MC_CMD_SET_LINK_LOWPOWER_LBN 0 -#define MC_CMD_SET_LINK_LOWPOWER_WIDTH 1 -#define MC_CMD_SET_LINK_POWEROFF_LBN 1 -#define MC_CMD_SET_LINK_POWEROFF_WIDTH 1 -#define MC_CMD_SET_LINK_TXDIS_LBN 2 -#define MC_CMD_SET_LINK_TXDIS_WIDTH 1 -#define MC_CMD_SET_LINK_IN_LOOPBACK_MODE_OFST 8 -#define MC_CMD_SET_LINK_IN_LOOPBACK_SPEED_OFST 12 -#define MC_CMD_SET_LINK_OUT_LEN 0 - -/* MC_CMD_SET_ID_LED: - * Set indentification LED state - * - * Locks required: None - * Return code: 0, EINVAL + +/* MC_CMD_SET_LINK_IN msgrequest */ +#define MC_CMD_SET_LINK_IN_LEN 16 +#define MC_CMD_SET_LINK_IN_CAP_OFST 0 +#define MC_CMD_SET_LINK_IN_FLAGS_OFST 4 +#define MC_CMD_SET_LINK_IN_LOWPOWER_LBN 0 +#define MC_CMD_SET_LINK_IN_LOWPOWER_WIDTH 1 +#define MC_CMD_SET_LINK_IN_POWEROFF_LBN 1 +#define MC_CMD_SET_LINK_IN_POWEROFF_WIDTH 1 +#define MC_CMD_SET_LINK_IN_TXDIS_LBN 2 +#define MC_CMD_SET_LINK_IN_TXDIS_WIDTH 1 +#define MC_CMD_SET_LINK_IN_LOOPBACK_MODE_OFST 8 +/* Enum values, see field(s): */ +/* MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */ +#define MC_CMD_SET_LINK_IN_LOOPBACK_SPEED_OFST 12 + +/* MC_CMD_SET_LINK_OUT msgresponse */ +#define MC_CMD_SET_LINK_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SET_ID_LED + * Set indentification LED state. */ #define MC_CMD_SET_ID_LED 0x2b -#define MC_CMD_SET_ID_LED_IN_LEN 4 -#define MC_CMD_SET_ID_LED_IN_STATE_OFST 0 -#define MC_CMD_LED_OFF 0 -#define MC_CMD_LED_ON 1 -#define MC_CMD_LED_DEFAULT 2 -#define MC_CMD_SET_ID_LED_OUT_LEN 0 - -/* MC_CMD_SET_MAC: - * Set MAC configuration - * - * The MTU is the MTU programmed directly into the XMAC/GMAC - * (inclusive of EtherII, VLAN, bug16011 padding) - * - * Locks required: None - * Return code: 0, EINVAL + +/* MC_CMD_SET_ID_LED_IN msgrequest */ +#define MC_CMD_SET_ID_LED_IN_LEN 4 +#define MC_CMD_SET_ID_LED_IN_STATE_OFST 0 +#define MC_CMD_LED_OFF 0x0 /* enum */ +#define MC_CMD_LED_ON 0x1 /* enum */ +#define MC_CMD_LED_DEFAULT 0x2 /* enum */ + +/* MC_CMD_SET_ID_LED_OUT msgresponse */ +#define MC_CMD_SET_ID_LED_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SET_MAC + * Set MAC configuration. */ #define MC_CMD_SET_MAC 0x2c -#define MC_CMD_SET_MAC_IN_LEN 24 -#define MC_CMD_SET_MAC_IN_MTU_OFST 0 -#define MC_CMD_SET_MAC_IN_DRAIN_OFST 4 -#define MC_CMD_SET_MAC_IN_ADDR_OFST 8 -#define MC_CMD_SET_MAC_IN_REJECT_OFST 16 -#define MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN 0 -#define MC_CMD_SET_MAC_IN_REJECT_UNCST_WIDTH 1 -#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_LBN 1 -#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_WIDTH 1 -#define MC_CMD_SET_MAC_IN_FCNTL_OFST 20 -#define MC_CMD_SET_MAC_OUT_LEN 0 - -/* MC_CMD_PHY_STATS: - * Get generic PHY statistics - * - * This call returns the statistics for a generic PHY in a sparse - * array (indexed by the enumerate). Each value is represented by - * a 32bit number. - * - * If the DMA_ADDR is 0, then no DMA is performed, and the statistics - * may be read directly out of shared memory. If DMA_ADDR != 0, then - * the statistics are dmad to that (page-aligned location) - * - * Locks required: None - * Returns: 0, ETIME - * Response methods: shared memory, event + +/* MC_CMD_SET_MAC_IN msgrequest */ +#define MC_CMD_SET_MAC_IN_LEN 24 +#define MC_CMD_SET_MAC_IN_MTU_OFST 0 +#define MC_CMD_SET_MAC_IN_DRAIN_OFST 4 +#define MC_CMD_SET_MAC_IN_ADDR_OFST 8 +#define MC_CMD_SET_MAC_IN_ADDR_LEN 8 +#define MC_CMD_SET_MAC_IN_ADDR_LO_OFST 8 +#define MC_CMD_SET_MAC_IN_ADDR_HI_OFST 12 +#define MC_CMD_SET_MAC_IN_REJECT_OFST 16 +#define MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN 0 +#define MC_CMD_SET_MAC_IN_REJECT_UNCST_WIDTH 1 +#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_LBN 1 +#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_WIDTH 1 +#define MC_CMD_SET_MAC_IN_FCNTL_OFST 20 +/* MC_CMD_FCNTL_OFF 0x0 */ +/* MC_CMD_FCNTL_RESPOND 0x1 */ +/* MC_CMD_FCNTL_BIDIR 0x2 */ +#define MC_CMD_FCNTL_AUTO 0x3 /* enum */ + +/* MC_CMD_SET_MAC_OUT msgresponse */ +#define MC_CMD_SET_MAC_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_PHY_STATS + * Get generic PHY statistics. */ #define MC_CMD_PHY_STATS 0x2d -#define MC_CMD_PHY_STATS_IN_LEN 8 -#define MC_CMD_PHY_STATS_IN_DMA_ADDR_LO_OFST 0 -#define MC_CMD_PHY_STATS_IN_DMA_ADDR_HI_OFST 4 -#define MC_CMD_PHY_STATS_OUT_DMA_LEN 0 -#define MC_CMD_PHY_STATS_OUT_NO_DMA_LEN (MC_CMD_PHY_NSTATS * 4) - -/* Unified MAC statistics enumeration */ -#define MC_CMD_MAC_GENERATION_START 0 -#define MC_CMD_MAC_TX_PKTS 1 -#define MC_CMD_MAC_TX_PAUSE_PKTS 2 -#define MC_CMD_MAC_TX_CONTROL_PKTS 3 -#define MC_CMD_MAC_TX_UNICAST_PKTS 4 -#define MC_CMD_MAC_TX_MULTICAST_PKTS 5 -#define MC_CMD_MAC_TX_BROADCAST_PKTS 6 -#define MC_CMD_MAC_TX_BYTES 7 -#define MC_CMD_MAC_TX_BAD_BYTES 8 -#define MC_CMD_MAC_TX_LT64_PKTS 9 -#define MC_CMD_MAC_TX_64_PKTS 10 -#define MC_CMD_MAC_TX_65_TO_127_PKTS 11 -#define MC_CMD_MAC_TX_128_TO_255_PKTS 12 -#define MC_CMD_MAC_TX_256_TO_511_PKTS 13 -#define MC_CMD_MAC_TX_512_TO_1023_PKTS 14 -#define MC_CMD_MAC_TX_1024_TO_15XX_PKTS 15 -#define MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS 16 -#define MC_CMD_MAC_TX_GTJUMBO_PKTS 17 -#define MC_CMD_MAC_TX_BAD_FCS_PKTS 18 -#define MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS 19 -#define MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS 20 -#define MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS 21 -#define MC_CMD_MAC_TX_LATE_COLLISION_PKTS 22 -#define MC_CMD_MAC_TX_DEFERRED_PKTS 23 -#define MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS 24 -#define MC_CMD_MAC_TX_NON_TCPUDP_PKTS 25 -#define MC_CMD_MAC_TX_MAC_SRC_ERR_PKTS 26 -#define MC_CMD_MAC_TX_IP_SRC_ERR_PKTS 27 -#define MC_CMD_MAC_RX_PKTS 28 -#define MC_CMD_MAC_RX_PAUSE_PKTS 29 -#define MC_CMD_MAC_RX_GOOD_PKTS 30 -#define MC_CMD_MAC_RX_CONTROL_PKTS 31 -#define MC_CMD_MAC_RX_UNICAST_PKTS 32 -#define MC_CMD_MAC_RX_MULTICAST_PKTS 33 -#define MC_CMD_MAC_RX_BROADCAST_PKTS 34 -#define MC_CMD_MAC_RX_BYTES 35 -#define MC_CMD_MAC_RX_BAD_BYTES 36 -#define MC_CMD_MAC_RX_64_PKTS 37 -#define MC_CMD_MAC_RX_65_TO_127_PKTS 38 -#define MC_CMD_MAC_RX_128_TO_255_PKTS 39 -#define MC_CMD_MAC_RX_256_TO_511_PKTS 40 -#define MC_CMD_MAC_RX_512_TO_1023_PKTS 41 -#define MC_CMD_MAC_RX_1024_TO_15XX_PKTS 42 -#define MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS 43 -#define MC_CMD_MAC_RX_GTJUMBO_PKTS 44 -#define MC_CMD_MAC_RX_UNDERSIZE_PKTS 45 -#define MC_CMD_MAC_RX_BAD_FCS_PKTS 46 -#define MC_CMD_MAC_RX_OVERFLOW_PKTS 47 -#define MC_CMD_MAC_RX_FALSE_CARRIER_PKTS 48 -#define MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS 49 -#define MC_CMD_MAC_RX_ALIGN_ERROR_PKTS 50 -#define MC_CMD_MAC_RX_LENGTH_ERROR_PKTS 51 -#define MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS 52 -#define MC_CMD_MAC_RX_JABBER_PKTS 53 -#define MC_CMD_MAC_RX_NODESC_DROPS 54 -#define MC_CMD_MAC_RX_LANES01_CHAR_ERR 55 -#define MC_CMD_MAC_RX_LANES23_CHAR_ERR 56 -#define MC_CMD_MAC_RX_LANES01_DISP_ERR 57 -#define MC_CMD_MAC_RX_LANES23_DISP_ERR 58 -#define MC_CMD_MAC_RX_MATCH_FAULT 59 -#define MC_CMD_GMAC_DMABUF_START 64 -#define MC_CMD_GMAC_DMABUF_END 95 -/* Insert new members here. */ -#define MC_CMD_MAC_GENERATION_END 96 -#define MC_CMD_MAC_NSTATS (MC_CMD_MAC_GENERATION_END+1) - -/* MC_CMD_MAC_STATS: - * Get unified GMAC/XMAC statistics - * - * This call returns unified statistics maintained by the MC as it - * switches between the GMAC and XMAC. The MC will write out all - * supported stats. The driver should zero initialise the buffer to - * guarantee consistent results. - * - * Locks required: None - * Returns: 0 - * Response methods: shared memory, event - */ -#define MC_CMD_MAC_STATS 0x2e -#define MC_CMD_MAC_STATS_IN_LEN 16 -#define MC_CMD_MAC_STATS_IN_DMA_ADDR_LO_OFST 0 -#define MC_CMD_MAC_STATS_IN_DMA_ADDR_HI_OFST 4 -#define MC_CMD_MAC_STATS_IN_CMD_OFST 8 -#define MC_CMD_MAC_STATS_CMD_DMA_LBN 0 -#define MC_CMD_MAC_STATS_CMD_DMA_WIDTH 1 -#define MC_CMD_MAC_STATS_CMD_CLEAR_LBN 1 -#define MC_CMD_MAC_STATS_CMD_CLEAR_WIDTH 1 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_LBN 2 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_WIDTH 1 -/* Remaining PERIOD* fields only relevant when PERIODIC_CHANGE is set */ -#define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_LBN 3 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_WIDTH 1 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR_LBN 4 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR_WIDTH 1 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_NOEVENT_LBN 5 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_NOEVENT_WIDTH 1 -#define MC_CMD_MAC_STATS_CMD_PERIOD_MS_LBN 16 -#define MC_CMD_MAC_STATS_CMD_PERIOD_MS_WIDTH 16 -#define MC_CMD_MAC_STATS_IN_DMA_LEN_OFST 12 - -#define MC_CMD_MAC_STATS_OUT_LEN 0 - -/* Callisto flags */ -#define MC_CMD_SFT9001_ROBUST_LBN 0 -#define MC_CMD_SFT9001_ROBUST_WIDTH 1 -#define MC_CMD_SFT9001_SHORT_REACH_LBN 1 -#define MC_CMD_SFT9001_SHORT_REACH_WIDTH 1 - -/* MC_CMD_SFT9001_GET: - * Read current callisto specific setting - * - * Locks required: None - * Returns: 0, ETIME - */ -#define MC_CMD_SFT9001_GET 0x30 -#define MC_CMD_SFT9001_GET_IN_LEN 0 -#define MC_CMD_SFT9001_GET_OUT_LEN 4 -#define MC_CMD_SFT9001_GET_OUT_FLAGS_OFST 0 -/* MC_CMD_SFT9001_SET: - * Write current callisto specific setting - * - * Locks required: None - * Returns: 0, ETIME, EINVAL +/* MC_CMD_PHY_STATS_IN msgrequest */ +#define MC_CMD_PHY_STATS_IN_LEN 8 +#define MC_CMD_PHY_STATS_IN_DMA_ADDR_OFST 0 +#define MC_CMD_PHY_STATS_IN_DMA_ADDR_LEN 8 +#define MC_CMD_PHY_STATS_IN_DMA_ADDR_LO_OFST 0 +#define MC_CMD_PHY_STATS_IN_DMA_ADDR_HI_OFST 4 + +/* MC_CMD_PHY_STATS_OUT_DMA msgresponse */ +#define MC_CMD_PHY_STATS_OUT_DMA_LEN 0 + +/* MC_CMD_PHY_STATS_OUT_NO_DMA msgresponse */ +#define MC_CMD_PHY_STATS_OUT_NO_DMA_LEN (((MC_CMD_PHY_NSTATS*32))>>3) +#define MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_OFST 0 +#define MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_LEN 4 +#define MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_PHY_NSTATS +#define MC_CMD_OUI 0x0 /* enum */ +#define MC_CMD_PMA_PMD_LINK_UP 0x1 /* enum */ +#define MC_CMD_PMA_PMD_RX_FAULT 0x2 /* enum */ +#define MC_CMD_PMA_PMD_TX_FAULT 0x3 /* enum */ +#define MC_CMD_PMA_PMD_SIGNAL 0x4 /* enum */ +#define MC_CMD_PMA_PMD_SNR_A 0x5 /* enum */ +#define MC_CMD_PMA_PMD_SNR_B 0x6 /* enum */ +#define MC_CMD_PMA_PMD_SNR_C 0x7 /* enum */ +#define MC_CMD_PMA_PMD_SNR_D 0x8 /* enum */ +#define MC_CMD_PCS_LINK_UP 0x9 /* enum */ +#define MC_CMD_PCS_RX_FAULT 0xa /* enum */ +#define MC_CMD_PCS_TX_FAULT 0xb /* enum */ +#define MC_CMD_PCS_BER 0xc /* enum */ +#define MC_CMD_PCS_BLOCK_ERRORS 0xd /* enum */ +#define MC_CMD_PHYXS_LINK_UP 0xe /* enum */ +#define MC_CMD_PHYXS_RX_FAULT 0xf /* enum */ +#define MC_CMD_PHYXS_TX_FAULT 0x10 /* enum */ +#define MC_CMD_PHYXS_ALIGN 0x11 /* enum */ +#define MC_CMD_PHYXS_SYNC 0x12 /* enum */ +#define MC_CMD_AN_LINK_UP 0x13 /* enum */ +#define MC_CMD_AN_COMPLETE 0x14 /* enum */ +#define MC_CMD_AN_10GBT_STATUS 0x15 /* enum */ +#define MC_CMD_CL22_LINK_UP 0x16 /* enum */ +#define MC_CMD_PHY_NSTATS 0x17 /* enum */ + + +/***********************************/ +/* MC_CMD_MAC_STATS + * Get generic MAC statistics. */ -#define MC_CMD_SFT9001_SET 0x31 -#define MC_CMD_SFT9001_SET_IN_LEN 4 -#define MC_CMD_SFT9001_SET_IN_FLAGS_OFST 0 -#define MC_CMD_SFT9001_SET_OUT_LEN 0 - +#define MC_CMD_MAC_STATS 0x2e -/* MC_CMD_WOL_FILTER_SET: - * Set a WoL filter - * - * Locks required: None - * Returns: 0, EBUSY, EINVAL, ENOSYS +/* MC_CMD_MAC_STATS_IN msgrequest */ +#define MC_CMD_MAC_STATS_IN_LEN 16 +#define MC_CMD_MAC_STATS_IN_DMA_ADDR_OFST 0 +#define MC_CMD_MAC_STATS_IN_DMA_ADDR_LEN 8 +#define MC_CMD_MAC_STATS_IN_DMA_ADDR_LO_OFST 0 +#define MC_CMD_MAC_STATS_IN_DMA_ADDR_HI_OFST 4 +#define MC_CMD_MAC_STATS_IN_CMD_OFST 8 +#define MC_CMD_MAC_STATS_IN_DMA_LBN 0 +#define MC_CMD_MAC_STATS_IN_DMA_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_CLEAR_LBN 1 +#define MC_CMD_MAC_STATS_IN_CLEAR_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE_LBN 2 +#define MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE_LBN 3 +#define MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR_LBN 4 +#define MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT_LBN 5 +#define MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_PERIOD_MS_LBN 16 +#define MC_CMD_MAC_STATS_IN_PERIOD_MS_WIDTH 16 +#define MC_CMD_MAC_STATS_IN_DMA_LEN_OFST 12 + +/* MC_CMD_MAC_STATS_OUT_DMA msgresponse */ +#define MC_CMD_MAC_STATS_OUT_DMA_LEN 0 + +/* MC_CMD_MAC_STATS_OUT_NO_DMA msgresponse */ +#define MC_CMD_MAC_STATS_OUT_NO_DMA_LEN (((MC_CMD_MAC_NSTATS*64))>>3) +#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_OFST 0 +#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_LEN 8 +#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_LO_OFST 0 +#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_OFST 4 +#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS +#define MC_CMD_MAC_GENERATION_START 0x0 /* enum */ +#define MC_CMD_MAC_TX_PKTS 0x1 /* enum */ +#define MC_CMD_MAC_TX_PAUSE_PKTS 0x2 /* enum */ +#define MC_CMD_MAC_TX_CONTROL_PKTS 0x3 /* enum */ +#define MC_CMD_MAC_TX_UNICAST_PKTS 0x4 /* enum */ +#define MC_CMD_MAC_TX_MULTICAST_PKTS 0x5 /* enum */ +#define MC_CMD_MAC_TX_BROADCAST_PKTS 0x6 /* enum */ +#define MC_CMD_MAC_TX_BYTES 0x7 /* enum */ +#define MC_CMD_MAC_TX_BAD_BYTES 0x8 /* enum */ +#define MC_CMD_MAC_TX_LT64_PKTS 0x9 /* enum */ +#define MC_CMD_MAC_TX_64_PKTS 0xa /* enum */ +#define MC_CMD_MAC_TX_65_TO_127_PKTS 0xb /* enum */ +#define MC_CMD_MAC_TX_128_TO_255_PKTS 0xc /* enum */ +#define MC_CMD_MAC_TX_256_TO_511_PKTS 0xd /* enum */ +#define MC_CMD_MAC_TX_512_TO_1023_PKTS 0xe /* enum */ +#define MC_CMD_MAC_TX_1024_TO_15XX_PKTS 0xf /* enum */ +#define MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS 0x10 /* enum */ +#define MC_CMD_MAC_TX_GTJUMBO_PKTS 0x11 /* enum */ +#define MC_CMD_MAC_TX_BAD_FCS_PKTS 0x12 /* enum */ +#define MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS 0x13 /* enum */ +#define MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS 0x14 /* enum */ +#define MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS 0x15 /* enum */ +#define MC_CMD_MAC_TX_LATE_COLLISION_PKTS 0x16 /* enum */ +#define MC_CMD_MAC_TX_DEFERRED_PKTS 0x17 /* enum */ +#define MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS 0x18 /* enum */ +#define MC_CMD_MAC_TX_NON_TCPUDP_PKTS 0x19 /* enum */ +#define MC_CMD_MAC_TX_MAC_SRC_ERR_PKTS 0x1a /* enum */ +#define MC_CMD_MAC_TX_IP_SRC_ERR_PKTS 0x1b /* enum */ +#define MC_CMD_MAC_RX_PKTS 0x1c /* enum */ +#define MC_CMD_MAC_RX_PAUSE_PKTS 0x1d /* enum */ +#define MC_CMD_MAC_RX_GOOD_PKTS 0x1e /* enum */ +#define MC_CMD_MAC_RX_CONTROL_PKTS 0x1f /* enum */ +#define MC_CMD_MAC_RX_UNICAST_PKTS 0x20 /* enum */ +#define MC_CMD_MAC_RX_MULTICAST_PKTS 0x21 /* enum */ +#define MC_CMD_MAC_RX_BROADCAST_PKTS 0x22 /* enum */ +#define MC_CMD_MAC_RX_BYTES 0x23 /* enum */ +#define MC_CMD_MAC_RX_BAD_BYTES 0x24 /* enum */ +#define MC_CMD_MAC_RX_64_PKTS 0x25 /* enum */ +#define MC_CMD_MAC_RX_65_TO_127_PKTS 0x26 /* enum */ +#define MC_CMD_MAC_RX_128_TO_255_PKTS 0x27 /* enum */ +#define MC_CMD_MAC_RX_256_TO_511_PKTS 0x28 /* enum */ +#define MC_CMD_MAC_RX_512_TO_1023_PKTS 0x29 /* enum */ +#define MC_CMD_MAC_RX_1024_TO_15XX_PKTS 0x2a /* enum */ +#define MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS 0x2b /* enum */ +#define MC_CMD_MAC_RX_GTJUMBO_PKTS 0x2c /* enum */ +#define MC_CMD_MAC_RX_UNDERSIZE_PKTS 0x2d /* enum */ +#define MC_CMD_MAC_RX_BAD_FCS_PKTS 0x2e /* enum */ +#define MC_CMD_MAC_RX_OVERFLOW_PKTS 0x2f /* enum */ +#define MC_CMD_MAC_RX_FALSE_CARRIER_PKTS 0x30 /* enum */ +#define MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS 0x31 /* enum */ +#define MC_CMD_MAC_RX_ALIGN_ERROR_PKTS 0x32 /* enum */ +#define MC_CMD_MAC_RX_LENGTH_ERROR_PKTS 0x33 /* enum */ +#define MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS 0x34 /* enum */ +#define MC_CMD_MAC_RX_JABBER_PKTS 0x35 /* enum */ +#define MC_CMD_MAC_RX_NODESC_DROPS 0x36 /* enum */ +#define MC_CMD_MAC_RX_LANES01_CHAR_ERR 0x37 /* enum */ +#define MC_CMD_MAC_RX_LANES23_CHAR_ERR 0x38 /* enum */ +#define MC_CMD_MAC_RX_LANES01_DISP_ERR 0x39 /* enum */ +#define MC_CMD_MAC_RX_LANES23_DISP_ERR 0x3a /* enum */ +#define MC_CMD_MAC_RX_MATCH_FAULT 0x3b /* enum */ +#define MC_CMD_GMAC_DMABUF_START 0x40 /* enum */ +#define MC_CMD_GMAC_DMABUF_END 0x5f /* enum */ +#define MC_CMD_MAC_GENERATION_END 0x60 /* enum */ +#define MC_CMD_MAC_NSTATS 0x61 /* enum */ + + +/***********************************/ +/* MC_CMD_SRIOV + * to be documented + */ +#define MC_CMD_SRIOV 0x30 + +/* MC_CMD_SRIOV_IN msgrequest */ +#define MC_CMD_SRIOV_IN_LEN 12 +#define MC_CMD_SRIOV_IN_ENABLE_OFST 0 +#define MC_CMD_SRIOV_IN_VI_BASE_OFST 4 +#define MC_CMD_SRIOV_IN_VF_COUNT_OFST 8 + +/* MC_CMD_SRIOV_OUT msgresponse */ +#define MC_CMD_SRIOV_OUT_LEN 8 +#define MC_CMD_SRIOV_OUT_VI_SCALE_OFST 0 +#define MC_CMD_SRIOV_OUT_VF_TOTAL_OFST 4 + +/* MC_CMD_MEMCPY_RECORD_TYPEDEF structuredef */ +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LEN 32 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_OFST 0 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_LBN 0 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_WIDTH 32 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_OFST 4 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_LBN 32 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_WIDTH 32 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_OFST 8 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LEN 8 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LO_OFST 8 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_HI_OFST 12 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LBN 64 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_WIDTH 64 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_OFST 16 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_RID_INLINE 0x100 /* enum */ +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_LBN 128 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_WIDTH 32 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_OFST 20 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LEN 8 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LO_OFST 20 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_HI_OFST 24 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LBN 160 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_WIDTH 64 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_OFST 28 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_LBN 224 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_WIDTH 32 + + +/***********************************/ +/* MC_CMD_MEMCPY + * Perform memory copy operation. + */ +#define MC_CMD_MEMCPY 0x31 + +/* MC_CMD_MEMCPY_IN msgrequest */ +#define MC_CMD_MEMCPY_IN_LENMIN 32 +#define MC_CMD_MEMCPY_IN_LENMAX 224 +#define MC_CMD_MEMCPY_IN_LEN(num) (0+32*(num)) +#define MC_CMD_MEMCPY_IN_RECORD_OFST 0 +#define MC_CMD_MEMCPY_IN_RECORD_LEN 32 +#define MC_CMD_MEMCPY_IN_RECORD_MINNUM 1 +#define MC_CMD_MEMCPY_IN_RECORD_MAXNUM 7 + +/* MC_CMD_MEMCPY_OUT msgresponse */ +#define MC_CMD_MEMCPY_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_WOL_FILTER_SET + * Set a WoL filter. */ #define MC_CMD_WOL_FILTER_SET 0x32 -#define MC_CMD_WOL_FILTER_SET_IN_LEN 192 /* 190 rounded up to a word */ -#define MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 -#define MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 - -/* There is a union at offset 8, following defines overlap due to - * this */ -#define MC_CMD_WOL_FILTER_SET_IN_DATA_OFST 8 - -#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_OFST \ - MC_CMD_WOL_FILTER_SET_IN_DATA_OFST - -#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_IP_OFST \ - MC_CMD_WOL_FILTER_SET_IN_DATA_OFST -#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_IP_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 4) -#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 8) -#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 10) - -#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_OFST \ - MC_CMD_WOL_FILTER_SET_IN_DATA_OFST -#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 16) -#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 32) -#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 34) - -#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_OFST \ - MC_CMD_WOL_FILTER_SET_IN_DATA_OFST -#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 48) -#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 176) -#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 177) -#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 178) - -#define MC_CMD_WOL_FILTER_SET_IN_LINK_MASK_OFST \ - MC_CMD_WOL_FILTER_SET_IN_DATA_OFST -#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_LBN 0 -#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_WIDTH 1 -#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_LBN 1 -#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_WIDTH 1 - -#define MC_CMD_WOL_FILTER_SET_OUT_LEN 4 -#define MC_CMD_WOL_FILTER_SET_OUT_FILTER_ID_OFST 0 - -/* WOL Filter types enumeration */ -#define MC_CMD_WOL_TYPE_MAGIC 0x0 - /* unused 0x1 */ -#define MC_CMD_WOL_TYPE_WIN_MAGIC 0x2 -#define MC_CMD_WOL_TYPE_IPV4_SYN 0x3 -#define MC_CMD_WOL_TYPE_IPV6_SYN 0x4 -#define MC_CMD_WOL_TYPE_BITMAP 0x5 -#define MC_CMD_WOL_TYPE_LINK 0x6 -#define MC_CMD_WOL_TYPE_MAX 0x7 - -#define MC_CMD_FILTER_MODE_SIMPLE 0x0 -#define MC_CMD_FILTER_MODE_STRUCTURED 0xffffffff - -/* MC_CMD_WOL_FILTER_REMOVE: - * Remove a WoL filter - * - * Locks required: None - * Returns: 0, EINVAL, ENOSYS + +/* MC_CMD_WOL_FILTER_SET_IN msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_LEN 192 +#define MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 +#define MC_CMD_FILTER_MODE_SIMPLE 0x0 /* enum */ +#define MC_CMD_FILTER_MODE_STRUCTURED 0xffffffff /* enum */ +#define MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 +#define MC_CMD_WOL_TYPE_MAGIC 0x0 /* enum */ +#define MC_CMD_WOL_TYPE_WIN_MAGIC 0x2 /* enum */ +#define MC_CMD_WOL_TYPE_IPV4_SYN 0x3 /* enum */ +#define MC_CMD_WOL_TYPE_IPV6_SYN 0x4 /* enum */ +#define MC_CMD_WOL_TYPE_BITMAP 0x5 /* enum */ +#define MC_CMD_WOL_TYPE_LINK 0x6 /* enum */ +#define MC_CMD_WOL_TYPE_MAX 0x7 /* enum */ +#define MC_CMD_WOL_FILTER_SET_IN_DATA_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_DATA_LEN 4 +#define MC_CMD_WOL_FILTER_SET_IN_DATA_NUM 46 + +/* MC_CMD_WOL_FILTER_SET_IN_MAGIC msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_LEN 16 +/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */ +/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */ +#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_LEN 8 +#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_LO_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_HI_OFST 12 + +/* MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_LEN 20 +/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */ +/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */ +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_IP_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_IP_OFST 12 +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_OFST 16 +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_LEN 2 +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_OFST 18 +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_LEN 2 + +/* MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_LEN 44 +/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */ +/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */ +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_LEN 16 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_OFST 24 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_LEN 16 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_OFST 40 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_LEN 2 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_OFST 42 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_LEN 2 + +/* MC_CMD_WOL_FILTER_SET_IN_BITMAP msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN 187 +/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */ +/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */ +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_LEN 48 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_BITMAP_OFST 56 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_BITMAP_LEN 128 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_OFST 184 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_LEN 1 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_OFST 185 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_LEN 1 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_OFST 186 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_LEN 1 + +/* MC_CMD_WOL_FILTER_SET_IN_LINK msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_LINK_LEN 12 +/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */ +/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */ +#define MC_CMD_WOL_FILTER_SET_IN_LINK_MASK_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_LBN 0 +#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_WIDTH 1 +#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_LBN 1 +#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_WIDTH 1 + +/* MC_CMD_WOL_FILTER_SET_OUT msgresponse */ +#define MC_CMD_WOL_FILTER_SET_OUT_LEN 4 +#define MC_CMD_WOL_FILTER_SET_OUT_FILTER_ID_OFST 0 + + +/***********************************/ +/* MC_CMD_WOL_FILTER_REMOVE + * Remove a WoL filter. */ #define MC_CMD_WOL_FILTER_REMOVE 0x33 -#define MC_CMD_WOL_FILTER_REMOVE_IN_LEN 4 -#define MC_CMD_WOL_FILTER_REMOVE_IN_FILTER_ID_OFST 0 -#define MC_CMD_WOL_FILTER_REMOVE_OUT_LEN 0 +/* MC_CMD_WOL_FILTER_REMOVE_IN msgrequest */ +#define MC_CMD_WOL_FILTER_REMOVE_IN_LEN 4 +#define MC_CMD_WOL_FILTER_REMOVE_IN_FILTER_ID_OFST 0 -/* MC_CMD_WOL_FILTER_RESET: - * Reset (i.e. remove all) WoL filters - * - * Locks required: None - * Returns: 0, ENOSYS +/* MC_CMD_WOL_FILTER_REMOVE_OUT msgresponse */ +#define MC_CMD_WOL_FILTER_REMOVE_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_WOL_FILTER_RESET + * Reset (i.e. remove all) WoL filters. */ #define MC_CMD_WOL_FILTER_RESET 0x34 -#define MC_CMD_WOL_FILTER_RESET_IN_LEN 0 -#define MC_CMD_WOL_FILTER_RESET_OUT_LEN 0 -/* MC_CMD_SET_MCAST_HASH: - * Set the MCASH hash value without otherwise - * reconfiguring the MAC +/* MC_CMD_WOL_FILTER_RESET_IN msgrequest */ +#define MC_CMD_WOL_FILTER_RESET_IN_LEN 4 +#define MC_CMD_WOL_FILTER_RESET_IN_MASK_OFST 0 +#define MC_CMD_WOL_FILTER_RESET_IN_WAKE_FILTERS 0x1 /* enum */ +#define MC_CMD_WOL_FILTER_RESET_IN_LIGHTSOUT_OFFLOADS 0x2 /* enum */ + +/* MC_CMD_WOL_FILTER_RESET_OUT msgresponse */ +#define MC_CMD_WOL_FILTER_RESET_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SET_MCAST_HASH + * Set the MCASH hash value. */ #define MC_CMD_SET_MCAST_HASH 0x35 -#define MC_CMD_SET_MCAST_HASH_IN_LEN 32 -#define MC_CMD_SET_MCAST_HASH_IN_HASH0_OFST 0 -#define MC_CMD_SET_MCAST_HASH_IN_HASH1_OFST 16 -#define MC_CMD_SET_MCAST_HASH_OUT_LEN 0 -/* MC_CMD_NVRAM_TYPES: - * Return bitfield indicating available types of virtual NVRAM partitions - * - * Locks required: none - * Returns: 0 +/* MC_CMD_SET_MCAST_HASH_IN msgrequest */ +#define MC_CMD_SET_MCAST_HASH_IN_LEN 32 +#define MC_CMD_SET_MCAST_HASH_IN_HASH0_OFST 0 +#define MC_CMD_SET_MCAST_HASH_IN_HASH0_LEN 16 +#define MC_CMD_SET_MCAST_HASH_IN_HASH1_OFST 16 +#define MC_CMD_SET_MCAST_HASH_IN_HASH1_LEN 16 + +/* MC_CMD_SET_MCAST_HASH_OUT msgresponse */ +#define MC_CMD_SET_MCAST_HASH_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_NVRAM_TYPES + * Get virtual NVRAM partitions information. */ #define MC_CMD_NVRAM_TYPES 0x36 -#define MC_CMD_NVRAM_TYPES_IN_LEN 0 -#define MC_CMD_NVRAM_TYPES_OUT_LEN 4 -#define MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0 - -/* Supported NVRAM types */ -#define MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0 -#define MC_CMD_NVRAM_TYPE_MC_FW 1 -#define MC_CMD_NVRAM_TYPE_MC_FW_BACKUP 2 -#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 3 -#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1 4 -#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 5 -#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1 6 -#define MC_CMD_NVRAM_TYPE_EXP_ROM 7 -#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0 8 -#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1 9 -#define MC_CMD_NVRAM_TYPE_PHY_PORT0 10 -#define MC_CMD_NVRAM_TYPE_PHY_PORT1 11 -#define MC_CMD_NVRAM_TYPE_LOG 12 - -/* MC_CMD_NVRAM_INFO: - * Read info about a virtual NVRAM partition - * - * Locks required: none - * Returns: 0, EINVAL (bad type) + +/* MC_CMD_NVRAM_TYPES_IN msgrequest */ +#define MC_CMD_NVRAM_TYPES_IN_LEN 0 + +/* MC_CMD_NVRAM_TYPES_OUT msgresponse */ +#define MC_CMD_NVRAM_TYPES_OUT_LEN 4 +#define MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0 +#define MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0x0 /* enum */ +#define MC_CMD_NVRAM_TYPE_MC_FW 0x1 /* enum */ +#define MC_CMD_NVRAM_TYPE_MC_FW_BACKUP 0x2 /* enum */ +#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 0x3 /* enum */ +#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1 0x4 /* enum */ +#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 0x5 /* enum */ +#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1 0x6 /* enum */ +#define MC_CMD_NVRAM_TYPE_EXP_ROM 0x7 /* enum */ +#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0 0x8 /* enum */ +#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1 0x9 /* enum */ +#define MC_CMD_NVRAM_TYPE_PHY_PORT0 0xa /* enum */ +#define MC_CMD_NVRAM_TYPE_PHY_PORT1 0xb /* enum */ +#define MC_CMD_NVRAM_TYPE_LOG 0xc /* enum */ +#define MC_CMD_NVRAM_TYPE_FPGA 0xd /* enum */ + + +/***********************************/ +/* MC_CMD_NVRAM_INFO + * Read info about a virtual NVRAM partition. */ #define MC_CMD_NVRAM_INFO 0x37 -#define MC_CMD_NVRAM_INFO_IN_LEN 4 -#define MC_CMD_NVRAM_INFO_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_INFO_OUT_LEN 24 -#define MC_CMD_NVRAM_INFO_OUT_TYPE_OFST 0 -#define MC_CMD_NVRAM_INFO_OUT_SIZE_OFST 4 -#define MC_CMD_NVRAM_INFO_OUT_ERASESIZE_OFST 8 -#define MC_CMD_NVRAM_INFO_OUT_FLAGS_OFST 12 -#define MC_CMD_NVRAM_PROTECTED_LBN 0 -#define MC_CMD_NVRAM_PROTECTED_WIDTH 1 -#define MC_CMD_NVRAM_INFO_OUT_PHYSDEV_OFST 16 -#define MC_CMD_NVRAM_INFO_OUT_PHYSADDR_OFST 20 - -/* MC_CMD_NVRAM_UPDATE_START: - * Start a group of update operations on a virtual NVRAM partition - * - * Locks required: PHY_LOCK if type==*PHY* - * Returns: 0, EINVAL (bad type), EACCES (if PHY_LOCK required and not held) + +/* MC_CMD_NVRAM_INFO_IN msgrequest */ +#define MC_CMD_NVRAM_INFO_IN_LEN 4 +#define MC_CMD_NVRAM_INFO_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ + +/* MC_CMD_NVRAM_INFO_OUT msgresponse */ +#define MC_CMD_NVRAM_INFO_OUT_LEN 24 +#define MC_CMD_NVRAM_INFO_OUT_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ +#define MC_CMD_NVRAM_INFO_OUT_SIZE_OFST 4 +#define MC_CMD_NVRAM_INFO_OUT_ERASESIZE_OFST 8 +#define MC_CMD_NVRAM_INFO_OUT_FLAGS_OFST 12 +#define MC_CMD_NVRAM_INFO_OUT_PROTECTED_LBN 0 +#define MC_CMD_NVRAM_INFO_OUT_PROTECTED_WIDTH 1 +#define MC_CMD_NVRAM_INFO_OUT_PHYSDEV_OFST 16 +#define MC_CMD_NVRAM_INFO_OUT_PHYSADDR_OFST 20 + + +/***********************************/ +/* MC_CMD_NVRAM_UPDATE_START + * Start a group of update operations on a virtual NVRAM partition. */ #define MC_CMD_NVRAM_UPDATE_START 0x38 -#define MC_CMD_NVRAM_UPDATE_START_IN_LEN 4 -#define MC_CMD_NVRAM_UPDATE_START_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_UPDATE_START_OUT_LEN 0 -/* MC_CMD_NVRAM_READ: - * Read data from a virtual NVRAM partition - * - * Locks required: PHY_LOCK if type==*PHY* - * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held) +/* MC_CMD_NVRAM_UPDATE_START_IN msgrequest */ +#define MC_CMD_NVRAM_UPDATE_START_IN_LEN 4 +#define MC_CMD_NVRAM_UPDATE_START_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ + +/* MC_CMD_NVRAM_UPDATE_START_OUT msgresponse */ +#define MC_CMD_NVRAM_UPDATE_START_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_NVRAM_READ + * Read data from a virtual NVRAM partition. */ #define MC_CMD_NVRAM_READ 0x39 -#define MC_CMD_NVRAM_READ_IN_LEN 12 -#define MC_CMD_NVRAM_READ_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_READ_IN_OFFSET_OFST 4 -#define MC_CMD_NVRAM_READ_IN_LENGTH_OFST 8 -#define MC_CMD_NVRAM_READ_OUT_LEN(_read_bytes) (_read_bytes) -#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_OFST 0 - -/* MC_CMD_NVRAM_WRITE: - * Write data to a virtual NVRAM partition - * - * Locks required: PHY_LOCK if type==*PHY* - * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held) + +/* MC_CMD_NVRAM_READ_IN msgrequest */ +#define MC_CMD_NVRAM_READ_IN_LEN 12 +#define MC_CMD_NVRAM_READ_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ +#define MC_CMD_NVRAM_READ_IN_OFFSET_OFST 4 +#define MC_CMD_NVRAM_READ_IN_LENGTH_OFST 8 + +/* MC_CMD_NVRAM_READ_OUT msgresponse */ +#define MC_CMD_NVRAM_READ_OUT_LENMIN 1 +#define MC_CMD_NVRAM_READ_OUT_LENMAX 255 +#define MC_CMD_NVRAM_READ_OUT_LEN(num) (0+1*(num)) +#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_OFST 0 +#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_LEN 1 +#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MINNUM 1 +#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MAXNUM 255 + + +/***********************************/ +/* MC_CMD_NVRAM_WRITE + * Write data to a virtual NVRAM partition. */ #define MC_CMD_NVRAM_WRITE 0x3a -#define MC_CMD_NVRAM_WRITE_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_WRITE_IN_OFFSET_OFST 4 -#define MC_CMD_NVRAM_WRITE_IN_LENGTH_OFST 8 -#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_OFST 12 -#define MC_CMD_NVRAM_WRITE_IN_LEN(_write_bytes) (12 + _write_bytes) -#define MC_CMD_NVRAM_WRITE_OUT_LEN 0 - -/* MC_CMD_NVRAM_ERASE: - * Erase sector(s) from a virtual NVRAM partition - * - * Locks required: PHY_LOCK if type==*PHY* - * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held) + +/* MC_CMD_NVRAM_WRITE_IN msgrequest */ +#define MC_CMD_NVRAM_WRITE_IN_LENMIN 13 +#define MC_CMD_NVRAM_WRITE_IN_LENMAX 255 +#define MC_CMD_NVRAM_WRITE_IN_LEN(num) (12+1*(num)) +#define MC_CMD_NVRAM_WRITE_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ +#define MC_CMD_NVRAM_WRITE_IN_OFFSET_OFST 4 +#define MC_CMD_NVRAM_WRITE_IN_LENGTH_OFST 8 +#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_OFST 12 +#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN 1 +#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MINNUM 1 +#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM 243 + +/* MC_CMD_NVRAM_WRITE_OUT msgresponse */ +#define MC_CMD_NVRAM_WRITE_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_NVRAM_ERASE + * Erase sector(s) from a virtual NVRAM partition. */ #define MC_CMD_NVRAM_ERASE 0x3b -#define MC_CMD_NVRAM_ERASE_IN_LEN 12 -#define MC_CMD_NVRAM_ERASE_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_ERASE_IN_OFFSET_OFST 4 -#define MC_CMD_NVRAM_ERASE_IN_LENGTH_OFST 8 -#define MC_CMD_NVRAM_ERASE_OUT_LEN 0 - -/* MC_CMD_NVRAM_UPDATE_FINISH: - * Finish a group of update operations on a virtual NVRAM partition - * - * Locks required: PHY_LOCK if type==*PHY* - * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held) + +/* MC_CMD_NVRAM_ERASE_IN msgrequest */ +#define MC_CMD_NVRAM_ERASE_IN_LEN 12 +#define MC_CMD_NVRAM_ERASE_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ +#define MC_CMD_NVRAM_ERASE_IN_OFFSET_OFST 4 +#define MC_CMD_NVRAM_ERASE_IN_LENGTH_OFST 8 + +/* MC_CMD_NVRAM_ERASE_OUT msgresponse */ +#define MC_CMD_NVRAM_ERASE_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_NVRAM_UPDATE_FINISH + * Finish a group of update operations on a virtual NVRAM partition. */ #define MC_CMD_NVRAM_UPDATE_FINISH 0x3c -#define MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN 8 -#define MC_CMD_NVRAM_UPDATE_FINISH_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_UPDATE_FINISH_IN_REBOOT_OFST 4 -#define MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN 0 -/* MC_CMD_REBOOT: +/* MC_CMD_NVRAM_UPDATE_FINISH_IN msgrequest */ +#define MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN 8 +#define MC_CMD_NVRAM_UPDATE_FINISH_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ +#define MC_CMD_NVRAM_UPDATE_FINISH_IN_REBOOT_OFST 4 + +/* MC_CMD_NVRAM_UPDATE_FINISH_OUT msgresponse */ +#define MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_REBOOT * Reboot the MC. - * - * The AFTER_ASSERTION flag is intended to be used when the driver notices - * an assertion failure (at which point it is expected to perform a complete - * tear down and reinitialise), to allow both ports to reset the MC once - * in an atomic fashion. - * - * Production mc firmwares are generally compiled with REBOOT_ON_ASSERT=1, - * which means that they will automatically reboot out of the assertion - * handler, so this is in practise an optional operation. It is still - * recommended that drivers execute this to support custom firmwares - * with REBOOT_ON_ASSERT=0. - * - * Locks required: NONE - * Returns: Nothing. You get back a response with ERR=1, DATALEN=0 */ #define MC_CMD_REBOOT 0x3d -#define MC_CMD_REBOOT_IN_LEN 4 -#define MC_CMD_REBOOT_IN_FLAGS_OFST 0 -#define MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION 1 -#define MC_CMD_REBOOT_OUT_LEN 0 -/* MC_CMD_SCHEDINFO: - * Request scheduler info. from the MC. - * - * Locks required: NONE - * Returns: An array of (timeslice,maximum overrun), one for each thread, - * in ascending order of thread address.s +/* MC_CMD_REBOOT_IN msgrequest */ +#define MC_CMD_REBOOT_IN_LEN 4 +#define MC_CMD_REBOOT_IN_FLAGS_OFST 0 +#define MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION 0x1 /* enum */ + +/* MC_CMD_REBOOT_OUT msgresponse */ +#define MC_CMD_REBOOT_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SCHEDINFO + * Request scheduler info. */ #define MC_CMD_SCHEDINFO 0x3e -#define MC_CMD_SCHEDINFO_IN_LEN 0 +/* MC_CMD_SCHEDINFO_IN msgrequest */ +#define MC_CMD_SCHEDINFO_IN_LEN 0 -/* MC_CMD_SET_REBOOT_MODE: (debug) - * Set the mode for the next MC reboot. - * - * Locks required: NONE - * - * Sets the reboot mode to the specified value. Returns the old mode. +/* MC_CMD_SCHEDINFO_OUT msgresponse */ +#define MC_CMD_SCHEDINFO_OUT_LENMIN 4 +#define MC_CMD_SCHEDINFO_OUT_LENMAX 252 +#define MC_CMD_SCHEDINFO_OUT_LEN(num) (0+4*(num)) +#define MC_CMD_SCHEDINFO_OUT_DATA_OFST 0 +#define MC_CMD_SCHEDINFO_OUT_DATA_LEN 4 +#define MC_CMD_SCHEDINFO_OUT_DATA_MINNUM 1 +#define MC_CMD_SCHEDINFO_OUT_DATA_MAXNUM 63 + + +/***********************************/ +/* MC_CMD_REBOOT_MODE */ #define MC_CMD_REBOOT_MODE 0x3f -#define MC_CMD_REBOOT_MODE_IN_LEN 4 -#define MC_CMD_REBOOT_MODE_IN_VALUE_OFST 0 -#define MC_CMD_REBOOT_MODE_OUT_LEN 4 -#define MC_CMD_REBOOT_MODE_OUT_VALUE_OFST 0 -#define MC_CMD_REBOOT_MODE_NORMAL 0 -#define MC_CMD_REBOOT_MODE_SNAPPER 3 - -/* MC_CMD_DEBUG_LOG: - * Null request/response command (debug) - * - sequence number is always zero - * - only supported on the UART interface - * (the same set of bytes is delivered as an - * event over PCI) - */ -#define MC_CMD_DEBUG_LOG 0x40 -#define MC_CMD_DEBUG_LOG_IN_LEN 0 -#define MC_CMD_DEBUG_LOG_OUT_LEN 0 - -/* Generic sensor enumeration. Note that a dual port NIC - * will EITHER expose PHY_COMMON_TEMP OR PHY0_TEMP and - * PHY1_TEMP depending on whether there is a single sensor - * in the vicinity of the two port, or one per port. - */ -#define MC_CMD_SENSOR_CONTROLLER_TEMP 0 /* degC */ -#define MC_CMD_SENSOR_PHY_COMMON_TEMP 1 /* degC */ -#define MC_CMD_SENSOR_CONTROLLER_COOLING 2 /* bool */ -#define MC_CMD_SENSOR_PHY0_TEMP 3 /* degC */ -#define MC_CMD_SENSOR_PHY0_COOLING 4 /* bool */ -#define MC_CMD_SENSOR_PHY1_TEMP 5 /* degC */ -#define MC_CMD_SENSOR_PHY1_COOLING 6 /* bool */ -#define MC_CMD_SENSOR_IN_1V0 7 /* mV */ -#define MC_CMD_SENSOR_IN_1V2 8 /* mV */ -#define MC_CMD_SENSOR_IN_1V8 9 /* mV */ -#define MC_CMD_SENSOR_IN_2V5 10 /* mV */ -#define MC_CMD_SENSOR_IN_3V3 11 /* mV */ -#define MC_CMD_SENSOR_IN_12V0 12 /* mV */ - - -/* Sensor state */ -#define MC_CMD_SENSOR_STATE_OK 0 -#define MC_CMD_SENSOR_STATE_WARNING 1 -#define MC_CMD_SENSOR_STATE_FATAL 2 -#define MC_CMD_SENSOR_STATE_BROKEN 3 - -/* MC_CMD_SENSOR_INFO: + +/* MC_CMD_REBOOT_MODE_IN msgrequest */ +#define MC_CMD_REBOOT_MODE_IN_LEN 4 +#define MC_CMD_REBOOT_MODE_IN_VALUE_OFST 0 +#define MC_CMD_REBOOT_MODE_NORMAL 0x0 /* enum */ +#define MC_CMD_REBOOT_MODE_SNAPPER 0x3 /* enum */ + +/* MC_CMD_REBOOT_MODE_OUT msgresponse */ +#define MC_CMD_REBOOT_MODE_OUT_LEN 4 +#define MC_CMD_REBOOT_MODE_OUT_VALUE_OFST 0 + + +/***********************************/ +/* MC_CMD_SENSOR_INFO * Returns information about every available sensor. - * - * Each sensor has a single (16bit) value, and a corresponding state. - * The mapping between value and sensor is nominally determined by the - * MC, but in practise is implemented as zero (BROKEN), one (TEMPERATURE), - * or two (VOLTAGE) ranges per sensor per state. - * - * This call returns a mask (32bit) of the sensors that are supported - * by this platform, then an array (indexed by MC_CMD_SENSOR) of byte - * offsets to the per-sensor arrays. Each sensor array has four 16bit - * numbers, min1, max1, min2, max2. - * - * Locks required: None - * Returns: 0 */ #define MC_CMD_SENSOR_INFO 0x41 -#define MC_CMD_SENSOR_INFO_IN_LEN 0 -#define MC_CMD_SENSOR_INFO_OUT_MASK_OFST 0 -#define MC_CMD_SENSOR_INFO_OUT_OFFSET_OFST(_x) \ - (4 + (_x)) -#define MC_CMD_SENSOR_INFO_OUT_MIN1_OFST(_ofst) \ - ((_ofst) + 0) -#define MC_CMD_SENSOR_INFO_OUT_MAX1_OFST(_ofst) \ - ((_ofst) + 2) -#define MC_CMD_SENSOR_INFO_OUT_MIN2_OFST(_ofst) \ - ((_ofst) + 4) -#define MC_CMD_SENSOR_INFO_OUT_MAX2_OFST(_ofst) \ - ((_ofst) + 6) +/* MC_CMD_SENSOR_INFO_IN msgrequest */ +#define MC_CMD_SENSOR_INFO_IN_LEN 0 + +/* MC_CMD_SENSOR_INFO_OUT msgresponse */ +#define MC_CMD_SENSOR_INFO_OUT_LENMIN 12 +#define MC_CMD_SENSOR_INFO_OUT_LENMAX 252 +#define MC_CMD_SENSOR_INFO_OUT_LEN(num) (4+8*(num)) +#define MC_CMD_SENSOR_INFO_OUT_MASK_OFST 0 +#define MC_CMD_SENSOR_CONTROLLER_TEMP 0x0 /* enum */ +#define MC_CMD_SENSOR_PHY_COMMON_TEMP 0x1 /* enum */ +#define MC_CMD_SENSOR_CONTROLLER_COOLING 0x2 /* enum */ +#define MC_CMD_SENSOR_PHY0_TEMP 0x3 /* enum */ +#define MC_CMD_SENSOR_PHY0_COOLING 0x4 /* enum */ +#define MC_CMD_SENSOR_PHY1_TEMP 0x5 /* enum */ +#define MC_CMD_SENSOR_PHY1_COOLING 0x6 /* enum */ +#define MC_CMD_SENSOR_IN_1V0 0x7 /* enum */ +#define MC_CMD_SENSOR_IN_1V2 0x8 /* enum */ +#define MC_CMD_SENSOR_IN_1V8 0x9 /* enum */ +#define MC_CMD_SENSOR_IN_2V5 0xa /* enum */ +#define MC_CMD_SENSOR_IN_3V3 0xb /* enum */ +#define MC_CMD_SENSOR_IN_12V0 0xc /* enum */ +#define MC_CMD_SENSOR_IN_1V2A 0xd /* enum */ +#define MC_CMD_SENSOR_IN_VREF 0xe /* enum */ +#define MC_CMD_SENSOR_ENTRY_OFST 4 +#define MC_CMD_SENSOR_ENTRY_LEN 8 +#define MC_CMD_SENSOR_ENTRY_LO_OFST 4 +#define MC_CMD_SENSOR_ENTRY_HI_OFST 8 +#define MC_CMD_SENSOR_ENTRY_MINNUM 1 +#define MC_CMD_SENSOR_ENTRY_MAXNUM 31 + +/* MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF structuredef */ +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_LEN 8 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_OFST 0 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_LEN 2 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_LBN 0 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_WIDTH 16 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_OFST 2 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_LEN 2 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_LBN 16 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_WIDTH 16 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_OFST 4 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_LEN 2 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_LBN 32 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_WIDTH 16 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_OFST 6 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_LEN 2 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_LBN 48 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_WIDTH 16 + + +/***********************************/ /* MC_CMD_READ_SENSORS - * Returns the current reading from each sensor - * - * Returns a sparse array of sensor readings (indexed by the sensor - * type) into host memory. Each array element is a dword. - * - * The MC will send a SENSOREVT event every time any sensor changes state. The - * driver is responsible for ensuring that it doesn't miss any events. The board - * will function normally if all sensors are in STATE_OK or state_WARNING. - * Otherwise the board should not be expected to function. + * Returns the current reading from each sensor. */ #define MC_CMD_READ_SENSORS 0x42 -#define MC_CMD_READ_SENSORS_IN_LEN 8 -#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_LO_OFST 0 -#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_HI_OFST 4 -#define MC_CMD_READ_SENSORS_OUT_LEN 0 -/* Sensor reading fields */ -#define MC_CMD_READ_SENSOR_VALUE_LBN 0 -#define MC_CMD_READ_SENSOR_VALUE_WIDTH 16 -#define MC_CMD_READ_SENSOR_STATE_LBN 16 -#define MC_CMD_READ_SENSOR_STATE_WIDTH 8 - - -/* MC_CMD_GET_PHY_STATE: - * Report current state of PHY. A "zombie" PHY is a PHY that has failed to - * boot (e.g. due to missing or corrupted firmware). - * - * Locks required: None - * Return code: 0 +/* MC_CMD_READ_SENSORS_IN msgrequest */ +#define MC_CMD_READ_SENSORS_IN_LEN 8 +#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_OFST 0 +#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_LEN 8 +#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_LO_OFST 0 +#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_HI_OFST 4 + +/* MC_CMD_READ_SENSORS_OUT msgresponse */ +#define MC_CMD_READ_SENSORS_OUT_LEN 0 + +/* MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF structuredef */ +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_LEN 3 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_OFST 0 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_LEN 2 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_LBN 0 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_WIDTH 16 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_OFST 2 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_LEN 1 +#define MC_CMD_SENSOR_STATE_OK 0x0 /* enum */ +#define MC_CMD_SENSOR_STATE_WARNING 0x1 /* enum */ +#define MC_CMD_SENSOR_STATE_FATAL 0x2 /* enum */ +#define MC_CMD_SENSOR_STATE_BROKEN 0x3 /* enum */ +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_LBN 16 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_WIDTH 8 + + +/***********************************/ +/* MC_CMD_GET_PHY_STATE + * Report current state of PHY. */ #define MC_CMD_GET_PHY_STATE 0x43 -#define MC_CMD_GET_PHY_STATE_IN_LEN 0 -#define MC_CMD_GET_PHY_STATE_OUT_LEN 4 -#define MC_CMD_GET_PHY_STATE_STATE_OFST 0 -/* PHY state enumeration: */ -#define MC_CMD_PHY_STATE_OK 1 -#define MC_CMD_PHY_STATE_ZOMBIE 2 +/* MC_CMD_GET_PHY_STATE_IN msgrequest */ +#define MC_CMD_GET_PHY_STATE_IN_LEN 0 +/* MC_CMD_GET_PHY_STATE_OUT msgresponse */ +#define MC_CMD_GET_PHY_STATE_OUT_LEN 4 +#define MC_CMD_GET_PHY_STATE_OUT_STATE_OFST 0 +#define MC_CMD_PHY_STATE_OK 0x1 /* enum */ +#define MC_CMD_PHY_STATE_ZOMBIE 0x2 /* enum */ -/* 802.1Qbb control. 8 Tx queues that map to priorities 0 - 7. Use all 1s to - * disable 802.Qbb for a given priority. */ + +/***********************************/ +/* MC_CMD_SETUP_8021QBB + * 802.1Qbb control. + */ #define MC_CMD_SETUP_8021QBB 0x44 -#define MC_CMD_SETUP_8021QBB_IN_LEN 32 -#define MC_CMD_SETUP_8021QBB_OUT_LEN 0 -#define MC_CMD_SETUP_8021QBB_IN_TXQS_OFFST 0 +/* MC_CMD_SETUP_8021QBB_IN msgrequest */ +#define MC_CMD_SETUP_8021QBB_IN_LEN 32 +#define MC_CMD_SETUP_8021QBB_IN_TXQS_OFST 0 +#define MC_CMD_SETUP_8021QBB_IN_TXQS_LEN 32 -/* MC_CMD_WOL_FILTER_GET: - * Retrieve ID of any WoL filters - * - * Locks required: None - * Returns: 0, ENOSYS - */ -#define MC_CMD_WOL_FILTER_GET 0x45 -#define MC_CMD_WOL_FILTER_GET_IN_LEN 0 -#define MC_CMD_WOL_FILTER_GET_OUT_LEN 4 -#define MC_CMD_WOL_FILTER_GET_OUT_FILTER_ID_OFST 0 +/* MC_CMD_SETUP_8021QBB_OUT msgresponse */ +#define MC_CMD_SETUP_8021QBB_OUT_LEN 0 -/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD: - * Offload a protocol to NIC for lights-out state - * - * Locks required: None - * Returns: 0, ENOSYS +/***********************************/ +/* MC_CMD_WOL_FILTER_GET + * Retrieve ID of any WoL filters. */ -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD 0x46 +#define MC_CMD_WOL_FILTER_GET 0x45 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LEN 16 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 +/* MC_CMD_WOL_FILTER_GET_IN msgrequest */ +#define MC_CMD_WOL_FILTER_GET_IN_LEN 0 -/* There is a union at offset 4, following defines overlap due to - * this */ -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_OFST 4 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARPMAC_OFST 4 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARPIP_OFST 10 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSMAC_OFST 4 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSSNIPV6_OFST 10 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSIPV6_OFST 26 +/* MC_CMD_WOL_FILTER_GET_OUT msgresponse */ +#define MC_CMD_WOL_FILTER_GET_OUT_LEN 4 +#define MC_CMD_WOL_FILTER_GET_OUT_FILTER_ID_OFST 0 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN 4 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_FILTER_ID_OFST 0 +/***********************************/ +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD + * Add a protocol offload to NIC for lights-out state. + */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD 0x46 -/* MC_CMD_REMOVE_LIGHTSOUT_PROTOCOL_OFFLOAD: - * Offload a protocol to NIC for lights-out state - * - * Locks required: None - * Returns: 0, ENOSYS +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN msgrequest */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LENMIN 8 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LENMAX 252 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LEN(num) (4+4*(num)) +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 +#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP 0x1 /* enum */ +#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS 0x2 /* enum */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_OFST 4 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_LEN 4 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_MINNUM 1 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_MAXNUM 62 + +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP msgrequest */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_LEN 14 +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_MAC_OFST 4 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_MAC_LEN 6 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_IP_OFST 10 + +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS msgrequest */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_LEN 42 +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_MAC_OFST 4 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_MAC_LEN 6 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_SNIPV6_OFST 10 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_SNIPV6_LEN 16 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_IPV6_OFST 26 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_IPV6_LEN 16 + +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT msgresponse */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN 4 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_FILTER_ID_OFST 0 + + +/***********************************/ +/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD + * Remove a protocol offload from NIC for lights-out state. */ #define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD 0x47 -#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN 8 -#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN 0 -#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 -#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_FILTER_ID_OFST 4 +/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN msgrequest */ +#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN 8 +#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 +#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_FILTER_ID_OFST 4 -/* Lights-out offload protocols enumeration */ -#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP 0x1 -#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS 0x2 +/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT msgresponse */ +#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN 0 -/* MC_CMD_MAC_RESET_RESTORE: - * Restore MAC after block reset - * - * Locks required: None - * Returns: 0 +/***********************************/ +/* MC_CMD_MAC_RESET_RESTORE + * Restore MAC after block reset. */ - #define MC_CMD_MAC_RESET_RESTORE 0x48 -#define MC_CMD_MAC_RESET_RESTORE_IN_LEN 0 -#define MC_CMD_MAC_RESET_RESTORE_OUT_LEN 0 +/* MC_CMD_MAC_RESET_RESTORE_IN msgrequest */ +#define MC_CMD_MAC_RESET_RESTORE_IN_LEN 0 + +/* MC_CMD_MAC_RESET_RESTORE_OUT msgresponse */ +#define MC_CMD_MAC_RESET_RESTORE_OUT_LEN 0 -/* MC_CMD_TEST_ASSERT: - * Deliberately trigger an assert-detonation in the firmware for testing - * purposes (i.e. to allow tests that the driver copes gracefully). - * - * Locks required: None - * Returns: 0 - */ +/***********************************/ +/* MC_CMD_TESTASSERT + */ #define MC_CMD_TESTASSERT 0x49 -#define MC_CMD_TESTASSERT_IN_LEN 0 -#define MC_CMD_TESTASSERT_OUT_LEN 0 -/* MC_CMD_WORKAROUND 0x4a - * - * Enable/Disable a given workaround. The mcfw will return EINVAL if it - * doesn't understand the given workaround number - which should not - * be treated as a hard error by client code. - * - * This op does not imply any semantics about each workaround, that's between - * the driver and the mcfw on a per-workaround basis. - * - * Locks required: None - * Returns: 0, EINVAL +/* MC_CMD_TESTASSERT_IN msgrequest */ +#define MC_CMD_TESTASSERT_IN_LEN 0 + +/* MC_CMD_TESTASSERT_OUT msgresponse */ +#define MC_CMD_TESTASSERT_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_WORKAROUND + * Enable/Disable a given workaround. */ #define MC_CMD_WORKAROUND 0x4a -#define MC_CMD_WORKAROUND_IN_LEN 8 -#define MC_CMD_WORKAROUND_IN_TYPE_OFST 0 -#define MC_CMD_WORKAROUND_BUG17230 1 -#define MC_CMD_WORKAROUND_IN_ENABLED_OFST 4 -#define MC_CMD_WORKAROUND_OUT_LEN 0 - -/* MC_CMD_GET_PHY_MEDIA_INFO: - * Read media-specific data from PHY (e.g. SFP/SFP+ module ID information for - * SFP+ PHYs). - * - * The "media type" can be found via GET_PHY_CFG (GET_PHY_CFG_OUT_MEDIA_TYPE); - * the valid "page number" input values, and the output data, are interpreted - * on a per-type basis. - * - * For SFP+: PAGE=0 or 1 returns a 128-byte block read from module I2C address - * 0xA0 offset 0 or 0x80. - * Anything else: currently undefined. - * - * Locks required: None - * Return code: 0 + +/* MC_CMD_WORKAROUND_IN msgrequest */ +#define MC_CMD_WORKAROUND_IN_LEN 8 +#define MC_CMD_WORKAROUND_IN_TYPE_OFST 0 +#define MC_CMD_WORKAROUND_BUG17230 0x1 /* enum */ +#define MC_CMD_WORKAROUND_IN_ENABLED_OFST 4 + +/* MC_CMD_WORKAROUND_OUT msgresponse */ +#define MC_CMD_WORKAROUND_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_PHY_MEDIA_INFO + * Read media-specific data from PHY. */ #define MC_CMD_GET_PHY_MEDIA_INFO 0x4b -#define MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN 4 -#define MC_CMD_GET_PHY_MEDIA_INFO_IN_PAGE_OFST 0 -#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(_num_bytes) (4 + (_num_bytes)) -#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATALEN_OFST 0 -#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST 4 - -/* MC_CMD_NVRAM_TEST: - * Test a particular NVRAM partition for valid contents (where "valid" - * depends on the type of partition). - * - * Locks required: None - * Return code: 0 + +/* MC_CMD_GET_PHY_MEDIA_INFO_IN msgrequest */ +#define MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN 4 +#define MC_CMD_GET_PHY_MEDIA_INFO_IN_PAGE_OFST 0 + +/* MC_CMD_GET_PHY_MEDIA_INFO_OUT msgresponse */ +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMIN 5 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX 255 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(num) (4+1*(num)) +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATALEN_OFST 0 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST 4 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_LEN 1 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MINNUM 1 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MAXNUM 251 + + +/***********************************/ +/* MC_CMD_NVRAM_TEST + * Test a particular NVRAM partition. */ #define MC_CMD_NVRAM_TEST 0x4c -#define MC_CMD_NVRAM_TEST_IN_LEN 4 -#define MC_CMD_NVRAM_TEST_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_TEST_OUT_LEN 4 -#define MC_CMD_NVRAM_TEST_OUT_RESULT_OFST 0 -#define MC_CMD_NVRAM_TEST_PASS 0 -#define MC_CMD_NVRAM_TEST_FAIL 1 -#define MC_CMD_NVRAM_TEST_NOTSUPP 2 - -/* MC_CMD_MRSFP_TWEAK: (debug) - * Read status and/or set parameters for the "mrsfp" driver in mr_rusty builds. - * I2C I/O expander bits are always read; if equaliser parameters are supplied, - * they are configured first. - * - * Locks required: None - * Return code: 0, EINVAL + +/* MC_CMD_NVRAM_TEST_IN msgrequest */ +#define MC_CMD_NVRAM_TEST_IN_LEN 4 +#define MC_CMD_NVRAM_TEST_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ + +/* MC_CMD_NVRAM_TEST_OUT msgresponse */ +#define MC_CMD_NVRAM_TEST_OUT_LEN 4 +#define MC_CMD_NVRAM_TEST_OUT_RESULT_OFST 0 +#define MC_CMD_NVRAM_TEST_PASS 0x0 /* enum */ +#define MC_CMD_NVRAM_TEST_FAIL 0x1 /* enum */ +#define MC_CMD_NVRAM_TEST_NOTSUPP 0x2 /* enum */ + + +/***********************************/ +/* MC_CMD_MRSFP_TWEAK + * Read status and/or set parameters for the 'mrsfp' driver. */ #define MC_CMD_MRSFP_TWEAK 0x4d -#define MC_CMD_MRSFP_TWEAK_IN_LEN_READ_ONLY 0 -#define MC_CMD_MRSFP_TWEAK_IN_LEN_EQ_CONFIG 16 -#define MC_CMD_MRSFP_TWEAK_IN_TXEQ_LEVEL_OFST 0 /* 0-6 low->high de-emph. */ -#define MC_CMD_MRSFP_TWEAK_IN_TXEQ_DT_CFG_OFST 4 /* 0-8 low->high ref.V */ -#define MC_CMD_MRSFP_TWEAK_IN_RXEQ_BOOST_OFST 8 /* 0-8 low->high boost */ -#define MC_CMD_MRSFP_TWEAK_IN_RXEQ_DT_CFG_OFST 12 /* 0-8 low->high ref.V */ -#define MC_CMD_MRSFP_TWEAK_OUT_LEN 12 -#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_INPUTS_OFST 0 /* input bits */ -#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_OUTPUTS_OFST 4 /* output bits */ -#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OFST 8 /* dirs: 0=out, 1=in */ - -/* MC_CMD_TEST_HACK: (debug (unsurprisingly)) - * Change bits of network port state for test purposes in ways that would never be - * useful in normal operation and so need a special command to change. */ -#define MC_CMD_TEST_HACK 0x2f -#define MC_CMD_TEST_HACK_IN_LEN 8 -#define MC_CMD_TEST_HACK_IN_TXPAD_OFST 0 -#define MC_CMD_TEST_HACK_IN_TXPAD_AUTO 0 /* Let the MC manage things */ -#define MC_CMD_TEST_HACK_IN_TXPAD_ON 1 /* Force on */ -#define MC_CMD_TEST_HACK_IN_TXPAD_OFF 2 /* Force on */ -#define MC_CMD_TEST_HACK_IN_IPG_OFST 4 /* Takes a value in bits */ -#define MC_CMD_TEST_HACK_IN_IPG_AUTO 0 /* The MC picks the value */ -#define MC_CMD_TEST_HACK_OUT_LEN 0 - -/* MC_CMD_SENSOR_SET_LIMS: (debug) (mostly) adjust the sensor limits. This - * is a warranty-voiding operation. - * - * IN: sensor identifier (one of the enumeration starting with MC_CMD_SENSOR_CONTROLLER_TEMP - * followed by 4 32-bit values: min(warning) max(warning), min(fatal), max(fatal). Which - * of these limits are meaningful and what their interpretation is is sensor-specific. - * - * OUT: nothing - * - * Returns: ENOENT if the sensor specified does not exist, EINVAL if the limits are - * out of range. + +/* MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG msgrequest */ +#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_LEN 16 +#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_TXEQ_LEVEL_OFST 0 +#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_TXEQ_DT_CFG_OFST 4 +#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_RXEQ_BOOST_OFST 8 +#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_RXEQ_DT_CFG_OFST 12 + +/* MC_CMD_MRSFP_TWEAK_IN_READ_ONLY msgrequest */ +#define MC_CMD_MRSFP_TWEAK_IN_READ_ONLY_LEN 0 + +/* MC_CMD_MRSFP_TWEAK_OUT msgresponse */ +#define MC_CMD_MRSFP_TWEAK_OUT_LEN 12 +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_INPUTS_OFST 0 +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_OUTPUTS_OFST 4 +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OFST 8 +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OUT 0x0 /* enum */ +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_IN 0x1 /* enum */ + + +/***********************************/ +/* MC_CMD_SENSOR_SET_LIMS + * Adjusts the sensor limits. */ #define MC_CMD_SENSOR_SET_LIMS 0x4e -#define MC_CMD_SENSOR_SET_LIMS_IN_LEN 20 -#define MC_CMD_SENSOR_SET_LIMS_IN_SENSOR_OFST 0 -#define MC_CMD_SENSOR_SET_LIMS_IN_LOW0_OFST 4 -#define MC_CMD_SENSOR_SET_LIMS_IN_HI0_OFST 8 -#define MC_CMD_SENSOR_SET_LIMS_IN_LOW1_OFST 12 -#define MC_CMD_SENSOR_SET_LIMS_IN_HI1_OFST 16 - -/* Do NOT add new commands beyond 0x4f as part of 3.0 : 0x50 - 0x7f will be - * used for post-3.0 extensions. If you run out of space, look for gaps or - * commands that are unused in the existing range. */ + +/* MC_CMD_SENSOR_SET_LIMS_IN msgrequest */ +#define MC_CMD_SENSOR_SET_LIMS_IN_LEN 20 +#define MC_CMD_SENSOR_SET_LIMS_IN_SENSOR_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_SENSOR_INFO/MC_CMD_SENSOR_INFO_OUT/MASK */ +#define MC_CMD_SENSOR_SET_LIMS_IN_LOW0_OFST 4 +#define MC_CMD_SENSOR_SET_LIMS_IN_HI0_OFST 8 +#define MC_CMD_SENSOR_SET_LIMS_IN_LOW1_OFST 12 +#define MC_CMD_SENSOR_SET_LIMS_IN_HI1_OFST 16 + +/* MC_CMD_SENSOR_SET_LIMS_OUT msgresponse */ +#define MC_CMD_SENSOR_SET_LIMS_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_RESOURCE_LIMITS + */ +#define MC_CMD_GET_RESOURCE_LIMITS 0x4f + +/* MC_CMD_GET_RESOURCE_LIMITS_IN msgrequest */ +#define MC_CMD_GET_RESOURCE_LIMITS_IN_LEN 0 + +/* MC_CMD_GET_RESOURCE_LIMITS_OUT msgresponse */ +#define MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN 16 +#define MC_CMD_GET_RESOURCE_LIMITS_OUT_BUFTBL_OFST 0 +#define MC_CMD_GET_RESOURCE_LIMITS_OUT_EVQ_OFST 4 +#define MC_CMD_GET_RESOURCE_LIMITS_OUT_RXQ_OFST 8 +#define MC_CMD_GET_RESOURCE_LIMITS_OUT_TXQ_OFST 12 + +/* MC_CMD_RESOURCE_SPECIFIER enum */ +#define MC_CMD_RESOURCE_INSTANCE_ANY 0xffffffff /* enum */ +#define MC_CMD_RESOURCE_INSTANCE_NONE 0xfffffffe /* enum */ + #endif /* MCDI_PCOL_H */ diff --git a/drivers/net/ethernet/sfc/mcdi_phy.c b/drivers/net/ethernet/sfc/mcdi_phy.c index 6c63ab0710af..7bcad899a936 100644 --- a/drivers/net/ethernet/sfc/mcdi_phy.c +++ b/drivers/net/ethernet/sfc/mcdi_phy.c @@ -116,7 +116,7 @@ static int efx_mcdi_loopback_modes(struct efx_nic *efx, u64 *loopback_modes) goto fail; } - *loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_SUGGESTED); + *loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_OUT_SUGGESTED); return 0; @@ -264,22 +264,22 @@ static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx) /* TODO: Advertise the capabilities supported by this PHY */ supported = 0; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_TXDIS_LBN)) + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_TXDIS_LBN)) supported |= PHY_MODE_TX_DISABLED; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_LOWPOWER_LBN)) + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_LBN)) supported |= PHY_MODE_LOW_POWER; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_POWEROFF_LBN)) + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_POWEROFF_LBN)) supported |= PHY_MODE_OFF; mode = efx->phy_mode & supported; flags = 0; if (mode & PHY_MODE_TX_DISABLED) - flags |= (1 << MC_CMD_SET_LINK_TXDIS_LBN); + flags |= (1 << MC_CMD_SET_LINK_IN_TXDIS_LBN); if (mode & PHY_MODE_LOW_POWER) - flags |= (1 << MC_CMD_SET_LINK_LOWPOWER_LBN); + flags |= (1 << MC_CMD_SET_LINK_IN_LOWPOWER_LBN); if (mode & PHY_MODE_OFF) - flags |= (1 << MC_CMD_SET_LINK_POWEROFF_LBN); + flags |= (1 << MC_CMD_SET_LINK_IN_POWEROFF_LBN); return flags; } @@ -436,8 +436,8 @@ void efx_mcdi_phy_decode_link(struct efx_nic *efx, break; } - link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_LINK_UP_LBN)); - link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_FULL_DUPLEX_LBN)); + link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN)); + link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN)); link_state->speed = speed; } @@ -592,7 +592,7 @@ static int efx_mcdi_phy_test_alive(struct efx_nic *efx) if (outlen < MC_CMD_GET_PHY_STATE_OUT_LEN) return -EIO; - if (MCDI_DWORD(outbuf, GET_PHY_STATE_STATE) != MC_CMD_PHY_STATE_OK) + if (MCDI_DWORD(outbuf, GET_PHY_STATE_OUT_STATE) != MC_CMD_PHY_STATE_OK) return -EINVAL; return 0; @@ -680,7 +680,7 @@ static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results, u32 mode; int rc; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_LBN)) { + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) { rc = efx_mcdi_bist(efx, MC_CMD_PHY_BIST, results); if (rc < 0) return rc; @@ -691,15 +691,15 @@ static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results, /* If we support both LONG and SHORT, then run each in response to * break or not. Otherwise, run the one we support */ mode = 0; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_LBN)) { + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN)) { if ((flags & ETH_TEST_FL_OFFLINE) && (phy_cfg->flags & - (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN))) + (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))) mode = MC_CMD_PHY_BIST_CABLE_LONG; else mode = MC_CMD_PHY_BIST_CABLE_SHORT; } else if (phy_cfg->flags & - (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN)) + (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN)) mode = MC_CMD_PHY_BIST_CABLE_LONG; if (mode != 0) { @@ -717,14 +717,14 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic *efx, { struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_LBN)) { + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) { if (index == 0) return "bist"; --index; } - if (phy_cfg->flags & ((1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_LBN) | - (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN))) { + if (phy_cfg->flags & ((1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN) | + (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))) { if (index == 0) return "cable"; --index; @@ -741,7 +741,7 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic *efx, const struct efx_phy_operations efx_mcdi_phy_ops = { .probe = efx_mcdi_phy_probe, - .init = efx_port_dummy_op_int, + .init = efx_port_dummy_op_int, .reconfigure = efx_mcdi_phy_reconfigure, .poll = efx_mcdi_phy_poll, .fini = efx_port_dummy_op_void, diff --git a/drivers/net/ethernet/sfc/mdio_10g.c b/drivers/net/ethernet/sfc/mdio_10g.c index 7ab385c8136d..9acfd6696ffb 100644 --- a/drivers/net/ethernet/sfc/mdio_10g.c +++ b/drivers/net/ethernet/sfc/mdio_10g.c @@ -228,7 +228,7 @@ void efx_mdio_set_mmds_lpower(struct efx_nic *efx, /** * efx_mdio_set_settings - Set (some of) the PHY settings over MDIO. * @efx: Efx NIC - * @ecmd: New settings + * @ecmd: New settings */ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { diff --git a/drivers/net/ethernet/sfc/mtd.c b/drivers/net/ethernet/sfc/mtd.c index bc9dcd6b30d7..79c192272047 100644 --- a/drivers/net/ethernet/sfc/mtd.c +++ b/drivers/net/ethernet/sfc/mtd.c @@ -382,7 +382,7 @@ static int falcon_mtd_sync(struct mtd_info *mtd) return rc; } -static struct efx_mtd_ops falcon_mtd_ops = { +static const struct efx_mtd_ops falcon_mtd_ops = { .read = falcon_mtd_read, .erase = falcon_mtd_erase, .write = falcon_mtd_write, @@ -560,7 +560,7 @@ static int siena_mtd_sync(struct mtd_info *mtd) return rc; } -static struct efx_mtd_ops siena_mtd_ops = { +static const struct efx_mtd_ops siena_mtd_ops = { .read = siena_mtd_read, .erase = siena_mtd_erase, .write = siena_mtd_write, @@ -572,7 +572,7 @@ struct siena_nvram_type_info { const char *name; }; -static struct siena_nvram_type_info siena_nvram_types[] = { +static const struct siena_nvram_type_info siena_nvram_types[] = { [MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO] = { 0, "sfc_dummy_phy" }, [MC_CMD_NVRAM_TYPE_MC_FW] = { 0, "sfc_mcfw" }, [MC_CMD_NVRAM_TYPE_MC_FW_BACKUP] = { 0, "sfc_mcfw_backup" }, @@ -593,7 +593,7 @@ static int siena_mtd_probe_partition(struct efx_nic *efx, unsigned int type) { struct efx_mtd_partition *part = &efx_mtd->part[part_id]; - struct siena_nvram_type_info *info; + const struct siena_nvram_type_info *info; size_t size, erase_size; bool protected; int rc; @@ -627,11 +627,10 @@ static int siena_mtd_get_fw_subtypes(struct efx_nic *efx, struct efx_mtd *efx_mtd) { struct efx_mtd_partition *part; - uint16_t fw_subtype_list[MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN / - sizeof(uint16_t)]; + uint16_t fw_subtype_list[MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM]; int rc; - rc = efx_mcdi_get_board_cfg(efx, NULL, fw_subtype_list); + rc = efx_mcdi_get_board_cfg(efx, NULL, fw_subtype_list, NULL); if (rc) return rc; diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index c49502bab6a3..53864014c2b4 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -13,10 +13,6 @@ #ifndef EFX_NET_DRIVER_H #define EFX_NET_DRIVER_H -#if defined(EFX_ENABLE_DEBUG) && !defined(DEBUG) -#define DEBUG -#endif - #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> @@ -42,7 +38,7 @@ #define EFX_DRIVER_VERSION "3.1" -#ifdef EFX_ENABLE_DEBUG +#ifdef DEBUG #define EFX_BUG_ON_PARANOID(x) BUG_ON(x) #define EFX_WARN_ON_PARANOID(x) WARN_ON(x) #else @@ -209,12 +205,12 @@ struct efx_tx_queue { /** * struct efx_rx_buffer - An Efx RX data buffer * @dma_addr: DMA base address of the buffer - * @skb: The associated socket buffer, if any. - * If both this and page are %NULL, the buffer slot is currently free. - * @page: The associated page buffer, if any. - * If both this and skb are %NULL, the buffer slot is currently free. + * @skb: The associated socket buffer. Valid iff !(@flags & %EFX_RX_BUF_PAGE). + * Will be %NULL if the buffer slot is currently free. + * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE. + * Will be %NULL if the buffer slot is currently free. * @len: Buffer length, in bytes. - * @is_page: Indicates if @page is valid. If false, @skb is valid. + * @flags: Flags for buffer and packet state. */ struct efx_rx_buffer { dma_addr_t dma_addr; @@ -223,8 +219,11 @@ struct efx_rx_buffer { struct page *page; } u; unsigned int len; - bool is_page; + u16 flags; }; +#define EFX_RX_BUF_PAGE 0x0001 +#define EFX_RX_PKT_CSUMMED 0x0002 +#define EFX_RX_PKT_DISCARD 0x0004 /** * struct efx_rx_page_state - Page-based rx buffer state @@ -329,6 +328,7 @@ enum efx_rx_alloc_method { * @eventq_mask: Event queue pointer mask * @eventq_read_ptr: Event queue read pointer * @last_eventq_read_ptr: Last event queue read pointer value. + * @last_irq_cpu: Last CPU to handle interrupt for this channel * @irq_count: Number of IRQs since last adaptive moderation decision * @irq_mod_score: IRQ moderation score * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors @@ -359,6 +359,7 @@ struct efx_channel { unsigned int eventq_read_ptr; unsigned int last_eventq_read_ptr; + int last_irq_cpu; unsigned int irq_count; unsigned int irq_mod_score; #ifdef CONFIG_RFS_ACCEL @@ -380,7 +381,6 @@ struct efx_channel { * access with prefetches. */ struct efx_rx_buffer *rx_pkt; - bool rx_pkt_csummed; struct efx_rx_queue rx_queue; struct efx_tx_queue tx_queue[EFX_TXQ_TYPES]; @@ -395,12 +395,12 @@ enum efx_led_mode { #define STRING_TABLE_LOOKUP(val, member) \ ((val) < member ## _max) ? member ## _names[val] : "(invalid)" -extern const char *efx_loopback_mode_names[]; +extern const char *const efx_loopback_mode_names[]; extern const unsigned int efx_loopback_mode_max; #define LOOPBACK_MODE(efx) \ STRING_TABLE_LOOKUP((efx)->loopback_mode, efx_loopback_mode) -extern const char *efx_reset_type_names[]; +extern const char *const efx_reset_type_names[]; extern const unsigned int efx_reset_type_max; #define RESET_TYPE(type) \ STRING_TABLE_LOOKUP(type, efx_reset_type) @@ -474,18 +474,6 @@ static inline bool efx_link_state_equal(const struct efx_link_state *left, } /** - * struct efx_mac_operations - Efx MAC operations table - * @reconfigure: Reconfigure MAC. Serialised by the mac_lock - * @update_stats: Update statistics - * @check_fault: Check fault state. True if fault present. - */ -struct efx_mac_operations { - int (*reconfigure) (struct efx_nic *efx); - void (*update_stats) (struct efx_nic *efx); - bool (*check_fault)(struct efx_nic *efx); -}; - -/** * struct efx_phy_operations - Efx PHY operations table * @probe: Probe PHY and initialise efx->mdio.mode_support, efx->mdio.mmds, * efx->loopback_modes. @@ -552,64 +540,64 @@ struct efx_mac_stats { u64 tx_bytes; u64 tx_good_bytes; u64 tx_bad_bytes; - unsigned long tx_packets; - unsigned long tx_bad; - unsigned long tx_pause; - unsigned long tx_control; - unsigned long tx_unicast; - unsigned long tx_multicast; - unsigned long tx_broadcast; - unsigned long tx_lt64; - unsigned long tx_64; - unsigned long tx_65_to_127; - unsigned long tx_128_to_255; - unsigned long tx_256_to_511; - unsigned long tx_512_to_1023; - unsigned long tx_1024_to_15xx; - unsigned long tx_15xx_to_jumbo; - unsigned long tx_gtjumbo; - unsigned long tx_collision; - unsigned long tx_single_collision; - unsigned long tx_multiple_collision; - unsigned long tx_excessive_collision; - unsigned long tx_deferred; - unsigned long tx_late_collision; - unsigned long tx_excessive_deferred; - unsigned long tx_non_tcpudp; - unsigned long tx_mac_src_error; - unsigned long tx_ip_src_error; + u64 tx_packets; + u64 tx_bad; + u64 tx_pause; + u64 tx_control; + u64 tx_unicast; + u64 tx_multicast; + u64 tx_broadcast; + u64 tx_lt64; + u64 tx_64; + u64 tx_65_to_127; + u64 tx_128_to_255; + u64 tx_256_to_511; + u64 tx_512_to_1023; + u64 tx_1024_to_15xx; + u64 tx_15xx_to_jumbo; + u64 tx_gtjumbo; + u64 tx_collision; + u64 tx_single_collision; + u64 tx_multiple_collision; + u64 tx_excessive_collision; + u64 tx_deferred; + u64 tx_late_collision; + u64 tx_excessive_deferred; + u64 tx_non_tcpudp; + u64 tx_mac_src_error; + u64 tx_ip_src_error; u64 rx_bytes; u64 rx_good_bytes; u64 rx_bad_bytes; - unsigned long rx_packets; - unsigned long rx_good; - unsigned long rx_bad; - unsigned long rx_pause; - unsigned long rx_control; - unsigned long rx_unicast; - unsigned long rx_multicast; - unsigned long rx_broadcast; - unsigned long rx_lt64; - unsigned long rx_64; - unsigned long rx_65_to_127; - unsigned long rx_128_to_255; - unsigned long rx_256_to_511; - unsigned long rx_512_to_1023; - unsigned long rx_1024_to_15xx; - unsigned long rx_15xx_to_jumbo; - unsigned long rx_gtjumbo; - unsigned long rx_bad_lt64; - unsigned long rx_bad_64_to_15xx; - unsigned long rx_bad_15xx_to_jumbo; - unsigned long rx_bad_gtjumbo; - unsigned long rx_overflow; - unsigned long rx_missed; - unsigned long rx_false_carrier; - unsigned long rx_symbol_error; - unsigned long rx_align_error; - unsigned long rx_length_error; - unsigned long rx_internal_error; - unsigned long rx_good_lt64; + u64 rx_packets; + u64 rx_good; + u64 rx_bad; + u64 rx_pause; + u64 rx_control; + u64 rx_unicast; + u64 rx_multicast; + u64 rx_broadcast; + u64 rx_lt64; + u64 rx_64; + u64 rx_65_to_127; + u64 rx_128_to_255; + u64 rx_256_to_511; + u64 rx_512_to_1023; + u64 rx_1024_to_15xx; + u64 rx_15xx_to_jumbo; + u64 rx_gtjumbo; + u64 rx_bad_lt64; + u64 rx_bad_64_to_15xx; + u64 rx_bad_15xx_to_jumbo; + u64 rx_bad_gtjumbo; + u64 rx_overflow; + u64 rx_missed; + u64 rx_false_carrier; + u64 rx_symbol_error; + u64 rx_align_error; + u64 rx_length_error; + u64 rx_internal_error; + u64 rx_good_lt64; }; /* Number of bits used in a multicast filter hash address */ @@ -640,6 +628,7 @@ struct efx_filter_state; * @membase_phys: Memory BAR value as physical address * @membase: Memory BAR value * @interrupt_mode: Interrupt mode + * @timer_quantum_ns: Interrupt timer quantum, in nanoseconds * @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues * @irq_rx_moderation: IRQ moderation time for RX event queues * @msg_enable: Log message enable flags @@ -663,7 +652,7 @@ struct efx_filter_state; * @int_error_expire: Time at which error count will be expired * @irq_status: Interrupt status buffer * @irq_zero_count: Number of legacy IRQs seen with queue flags == 0 - * @fatal_irq_level: IRQ level (bit number) used for serious errors + * @irq_level: IRQ level/index for IRQs not triggered by an event queue * @mtd_list: List of MTDs attached to the NIC * @nic_data: Hardware dependent state * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode, @@ -676,7 +665,6 @@ struct efx_filter_state; * @port_initialized: Port initialized? * @net_dev: Operating system network device. Consider holding the rtnl lock * @stats_buffer: DMA buffer for statistics - * @mac_op: MAC interface * @phy_type: PHY type * @phy_op: PHY interface * @phy_data: PHY private data (including PHY-specific stats) @@ -695,15 +683,15 @@ struct efx_filter_state; * @loopback_selftest: Offline self-test private state * @monitor_work: Hardware monitor workitem * @biu_lock: BIU (bus interface unit) lock - * @last_irq_cpu: Last CPU to handle interrupt. - * This register is written with the SMP processor ID whenever an - * interrupt is handled. It is used by efx_nic_test_interrupt() - * to verify that an interrupt has occurred. + * @last_irq_cpu: Last CPU to handle a possible test interrupt. This + * field is used by efx_test_interrupts() to verify that an + * interrupt has occurred. * @n_rx_nodesc_drop_cnt: RX no descriptor drop count * @mac_stats: MAC statistics. These include all statistics the MACs * can provide. Generic code converts these into a standard * &struct net_device_stats. * @stats_lock: Statistics update lock. Serialises statistics fetches + * and access to @mac_stats. * * This is stored in the private area of the &struct net_device. */ @@ -722,6 +710,7 @@ struct efx_nic { void __iomem *membase; enum efx_int_mode interrupt_mode; + unsigned int timer_quantum_ns; bool irq_rx_adaptive; unsigned int irq_rx_moderation; u32 msg_enable; @@ -749,7 +738,7 @@ struct efx_nic { struct efx_buffer irq_status; unsigned irq_zero_count; - unsigned fatal_irq_level; + unsigned irq_level; #ifdef CONFIG_SFC_MTD struct list_head mtd_list; @@ -766,8 +755,6 @@ struct efx_nic { struct efx_buffer stats_buffer; - const struct efx_mac_operations *mac_op; - unsigned int phy_type; const struct efx_phy_operations *phy_op; void *phy_data; @@ -795,7 +782,7 @@ struct efx_nic { struct delayed_work monitor_work ____cacheline_aligned_in_smp; spinlock_t biu_lock; - volatile signed int last_irq_cpu; + int last_irq_cpu; unsigned n_rx_nodesc_drop_cnt; struct efx_mac_stats mac_stats; spinlock_t stats_lock; @@ -806,15 +793,6 @@ static inline int efx_dev_registered(struct efx_nic *efx) return efx->net_dev->reg_state == NETREG_REGISTERED; } -/* Net device name, for inclusion in log messages if it has been registered. - * Use efx->name not efx->net_dev->name so that races with (un)registration - * are harmless. - */ -static inline const char *efx_dev_name(struct efx_nic *efx) -{ - return efx_dev_registered(efx) ? efx->name : ""; -} - static inline unsigned int efx_port_num(struct efx_nic *efx) { return efx->net_dev->dev_id; @@ -840,14 +818,15 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * @stop_stats: Stop the regular fetching of statistics * @set_id_led: Set state of identifying LED or revert to automatic function * @push_irq_moderation: Apply interrupt moderation value - * @push_multicast_hash: Apply multicast hash table * @reconfigure_port: Push loopback/power/txdis changes to the MAC and PHY + * @reconfigure_mac: Push MAC address, MTU, flow control and filter settings + * to the hardware. Serialised by the mac_lock. + * @check_mac_fault: Check MAC fault state. True if fault present. * @get_wol: Get WoL configuration from driver state * @set_wol: Push WoL configuration to the NIC * @resume_wol: Synchronise WoL state between driver and MC (e.g. after resume) * @test_registers: Test read/write functionality of control registers * @test_nvram: Test validity of NVRAM contents - * @default_mac_ops: efx_mac_operations to set at startup * @revision: Hardware architecture revision * @mem_map_size: Memory BAR mapped size * @txd_ptr_tbl_base: TX descriptor ring base address @@ -862,6 +841,7 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * from &enum efx_init_mode. * @phys_addr_channels: Number of channels with physically addressed * descriptors + * @timer_period_max: Maximum period of interrupt timer (in ticks) * @tx_dc_base: Base address in SRAM of TX queue descriptor caches * @rx_dc_base: Base address in SRAM of RX queue descriptor caches * @offload_features: net_device feature flags for protocol offload @@ -885,14 +865,14 @@ struct efx_nic_type { void (*stop_stats)(struct efx_nic *efx); void (*set_id_led)(struct efx_nic *efx, enum efx_led_mode mode); void (*push_irq_moderation)(struct efx_channel *channel); - void (*push_multicast_hash)(struct efx_nic *efx); int (*reconfigure_port)(struct efx_nic *efx); + int (*reconfigure_mac)(struct efx_nic *efx); + bool (*check_mac_fault)(struct efx_nic *efx); void (*get_wol)(struct efx_nic *efx, struct ethtool_wolinfo *wol); int (*set_wol)(struct efx_nic *efx, u32 type); void (*resume_wol)(struct efx_nic *efx); int (*test_registers)(struct efx_nic *efx); int (*test_nvram)(struct efx_nic *efx); - const struct efx_mac_operations *default_mac_ops; int revision; unsigned int mem_map_size; @@ -906,6 +886,7 @@ struct efx_nic_type { unsigned int rx_buffer_padding; unsigned int max_interrupt_mode; unsigned int phys_addr_channels; + unsigned int timer_period_max; unsigned int tx_dc_base; unsigned int rx_dc_base; netdev_features_t offload_features; diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 3edfbaf5f022..a43d1ca270c0 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -726,11 +726,9 @@ efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event) tx_queue = efx_channel_get_tx_queue( channel, tx_ev_q_label % EFX_TXQ_TYPES); - if (efx_dev_registered(efx)) - netif_tx_lock(efx->net_dev); + netif_tx_lock(efx->net_dev); efx_notify_tx_desc(tx_queue); - if (efx_dev_registered(efx)) - netif_tx_unlock(efx->net_dev); + netif_tx_unlock(efx->net_dev); } else if (EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_PKT_ERR) && EFX_WORKAROUND_10727(efx)) { efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH); @@ -745,10 +743,8 @@ efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event) } /* Detect errors included in the rx_evt_pkt_ok bit. */ -static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue, - const efx_qword_t *event, - bool *rx_ev_pkt_ok, - bool *discard) +static u16 efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue, + const efx_qword_t *event) { struct efx_channel *channel = efx_rx_queue_channel(rx_queue); struct efx_nic *efx = rx_queue->efx; @@ -793,15 +789,11 @@ static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue, ++channel->n_rx_tcp_udp_chksum_err; } - /* The frame must be discarded if any of these are true. */ - *discard = (rx_ev_eth_crc_err | rx_ev_frm_trunc | rx_ev_drib_nib | - rx_ev_tobe_disc | rx_ev_pause_frm); - /* TOBE_DISC is expected on unicast mismatches; don't print out an * error message. FRM_TRUNC indicates RXDP dropped the packet due * to a FIFO overflow. */ -#ifdef EFX_ENABLE_DEBUG +#ifdef DEBUG if (rx_ev_other_err && net_ratelimit()) { netif_dbg(efx, rx_err, efx->net_dev, " RX queue %d unexpected RX event " @@ -819,6 +811,11 @@ static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue, rx_ev_pause_frm ? " [PAUSE]" : ""); } #endif + + /* The frame must be discarded if any of these are true. */ + return (rx_ev_eth_crc_err | rx_ev_frm_trunc | rx_ev_drib_nib | + rx_ev_tobe_disc | rx_ev_pause_frm) ? + EFX_RX_PKT_DISCARD : 0; } /* Handle receive events that are not in-order. */ @@ -851,7 +848,8 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event) unsigned int rx_ev_desc_ptr, rx_ev_byte_cnt; unsigned int rx_ev_hdr_type, rx_ev_mcast_pkt; unsigned expected_ptr; - bool rx_ev_pkt_ok, discard = false, checksummed; + bool rx_ev_pkt_ok; + u16 flags; struct efx_rx_queue *rx_queue; /* Basic packet information */ @@ -874,12 +872,11 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event) /* If packet is marked as OK and packet type is TCP/IP or * UDP/IP, then we can rely on the hardware checksum. */ - checksummed = - rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP || - rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP; + flags = (rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP || + rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP) ? + EFX_RX_PKT_CSUMMED : 0; } else { - efx_handle_rx_not_ok(rx_queue, event, &rx_ev_pkt_ok, &discard); - checksummed = false; + flags = efx_handle_rx_not_ok(rx_queue, event); } /* Detect multicast packets that didn't match the filter */ @@ -890,15 +887,14 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event) if (unlikely(!rx_ev_mcast_hash_match)) { ++channel->n_rx_mcast_mismatch; - discard = true; + flags |= EFX_RX_PKT_DISCARD; } } channel->irq_mod_score += 2; /* Handle received packet */ - efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt, - checksummed, discard); + efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt, flags); } static void @@ -1311,7 +1307,7 @@ static inline void efx_nic_interrupts(struct efx_nic *efx, efx_oword_t int_en_reg_ker; EFX_POPULATE_OWORD_3(int_en_reg_ker, - FRF_AZ_KER_INT_LEVE_SEL, efx->fatal_irq_level, + FRF_AZ_KER_INT_LEVE_SEL, efx->irq_level, FRF_AZ_KER_INT_KER, force, FRF_AZ_DRV_INT_EN_KER, enabled); efx_writeo(efx, &int_en_reg_ker, FR_AZ_INT_EN_KER); @@ -1427,11 +1423,12 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) efx_readd(efx, ®, FR_BZ_INT_ISR0); queues = EFX_EXTRACT_DWORD(reg, 0, 31); - /* Check to see if we have a serious error condition */ - if (queues & (1U << efx->fatal_irq_level)) { + /* Handle non-event-queue sources */ + if (queues & (1U << efx->irq_level)) { syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); if (unlikely(syserr)) return efx_nic_fatal_interrupt(efx); + efx->last_irq_cpu = raw_smp_processor_id(); } if (queues != 0) { @@ -1441,7 +1438,7 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) /* Schedule processing of any interrupting queues */ efx_for_each_channel(channel, efx) { if (queues & 1) - efx_schedule_channel(channel); + efx_schedule_channel_irq(channel); queues >>= 1; } result = IRQ_HANDLED; @@ -1458,18 +1455,16 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) efx_for_each_channel(channel, efx) { event = efx_event(channel, channel->eventq_read_ptr); if (efx_event_present(event)) - efx_schedule_channel(channel); + efx_schedule_channel_irq(channel); else efx_nic_eventq_read_ack(channel); } } - if (result == IRQ_HANDLED) { - efx->last_irq_cpu = raw_smp_processor_id(); + if (result == IRQ_HANDLED) netif_vdbg(efx, intr, efx->net_dev, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n", irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg)); - } return result; } @@ -1488,20 +1483,20 @@ static irqreturn_t efx_msi_interrupt(int irq, void *dev_id) efx_oword_t *int_ker = efx->irq_status.addr; int syserr; - efx->last_irq_cpu = raw_smp_processor_id(); netif_vdbg(efx, intr, efx->net_dev, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n", irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker)); - /* Check to see if we have a serious error condition */ - if (channel->channel == efx->fatal_irq_level) { + /* Handle non-event-queue sources */ + if (channel->channel == efx->irq_level) { syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); if (unlikely(syserr)) return efx_nic_fatal_interrupt(efx); + efx->last_irq_cpu = raw_smp_processor_id(); } /* Schedule processing of the channel */ - efx_schedule_channel(channel); + efx_schedule_channel_irq(channel); return IRQ_HANDLED; } @@ -1640,10 +1635,10 @@ void efx_nic_init_common(struct efx_nic *efx) if (EFX_WORKAROUND_17213(efx) && !EFX_INT_MODE_USE_MSI(efx)) /* Use an interrupt level unused by event queues */ - efx->fatal_irq_level = 0x1f; + efx->irq_level = 0x1f; else /* Use a valid MSI-X vector */ - efx->fatal_irq_level = 0; + efx->irq_level = 0; /* Enable all the genuinely fatal interrupts. (They are still * masked by the overall interrupt mask, controlled by @@ -1837,7 +1832,7 @@ struct efx_nic_reg_table { REGISTER_REVISION_ ## min_rev, REGISTER_REVISION_ ## max_rev, \ step, rows \ } -#define REGISTER_TABLE(name, min_rev, max_rev) \ +#define REGISTER_TABLE(name, min_rev, max_rev) \ REGISTER_TABLE_DIMENSIONS( \ name, FR_ ## min_rev ## max_rev ## _ ## name, \ min_rev, max_rev, \ diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 5fb24d3aa3ca..905a1877d603 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -144,12 +144,26 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx) * struct siena_nic_data - Siena NIC state * @mcdi: Management-Controller-to-Driver Interface * @wol_filter_id: Wake-on-LAN packet filter id + * @hwmon: Hardware monitor state */ struct siena_nic_data { struct efx_mcdi_iface mcdi; int wol_filter_id; +#ifdef CONFIG_SFC_MCDI_MON + struct efx_mcdi_mon hwmon; +#endif }; +#ifdef CONFIG_SFC_MCDI_MON +static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx) +{ + struct siena_nic_data *nic_data; + EFX_BUG_ON_PARANOID(efx_nic_rev(efx) < EFX_REV_SIENA_A0); + nic_data = efx->nic_data; + return &nic_data->hwmon; +} +#endif + extern const struct efx_nic_type falcon_a1_nic_type; extern const struct efx_nic_type falcon_b0_nic_type; extern const struct efx_nic_type siena_a0_nic_type; @@ -189,6 +203,9 @@ extern bool efx_nic_event_present(struct efx_channel *channel); /* MAC/PHY */ extern void falcon_drain_tx_fifo(struct efx_nic *efx); extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx); +extern bool falcon_xmac_check_fault(struct efx_nic *efx); +extern int falcon_reconfigure_xmac(struct efx_nic *efx); +extern void falcon_update_stats_xmac(struct efx_nic *efx); /* Interrupts and test events */ extern int efx_nic_init_interrupt(struct efx_nic *efx); @@ -202,9 +219,6 @@ extern irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx); extern irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id); extern void falcon_irq_ack_a1(struct efx_nic *efx); -#define EFX_IRQ_MOD_RESOLUTION 5 -#define EFX_IRQ_MOD_MAX 0x1000 - /* Global Resources */ extern int efx_nic_flush_queues(struct efx_nic *efx); extern void falcon_start_nic_stats(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/qt202x_phy.c b/drivers/net/ethernet/sfc/qt202x_phy.c index 7ad97e397406..8a7caf88ffb6 100644 --- a/drivers/net/ethernet/sfc/qt202x_phy.c +++ b/drivers/net/ethernet/sfc/qt202x_phy.c @@ -47,7 +47,7 @@ #define PMA_PMD_FTX_STATIC_LBN 13 #define PMA_PMD_VEND1_REG 0xc001 #define PMA_PMD_VEND1_LBTXD_LBN 15 -#define PCS_VEND1_REG 0xc000 +#define PCS_VEND1_REG 0xc000 #define PCS_VEND1_LBTXD_LBN 5 void falcon_qt202x_set_led(struct efx_nic *p, int led, int mode) @@ -453,9 +453,9 @@ const struct efx_phy_operations falcon_qt202x_phy_ops = { .probe = qt202x_phy_probe, .init = qt202x_phy_init, .reconfigure = qt202x_phy_reconfigure, - .poll = qt202x_phy_poll, + .poll = qt202x_phy_poll, .fini = efx_port_dummy_op_void, - .remove = qt202x_phy_remove, + .remove = qt202x_phy_remove, .get_settings = qt202x_phy_get_settings, .set_settings = efx_mdio_set_settings, .test_alive = efx_mdio_test_alive, diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index aca349861767..1dfda5e27919 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -98,8 +98,8 @@ static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx, /* Offset is always within one page, so we don't need to consider * the page order. */ - return (((__force unsigned long) buf->dma_addr & (PAGE_SIZE - 1)) + - efx->type->rx_buffer_hash_size); + return ((unsigned int) buf->dma_addr & (PAGE_SIZE - 1)) + + efx->type->rx_buffer_hash_size; } static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) { @@ -108,11 +108,10 @@ static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) static u8 *efx_rx_buf_eh(struct efx_nic *efx, struct efx_rx_buffer *buf) { - if (buf->is_page) + if (buf->flags & EFX_RX_BUF_PAGE) return page_address(buf->u.page) + efx_rx_buf_offset(efx, buf); else - return ((u8 *)buf->u.skb->data + - efx->type->rx_buffer_hash_size); + return (u8 *)buf->u.skb->data + efx->type->rx_buffer_hash_size; } static inline u32 efx_rx_buf_hash(const u8 *eh) @@ -122,10 +121,10 @@ static inline u32 efx_rx_buf_hash(const u8 *eh) return __le32_to_cpup((const __le32 *)(eh - 4)); #else const u8 *data = eh - 4; - return ((u32)data[0] | - (u32)data[1] << 8 | - (u32)data[2] << 16 | - (u32)data[3] << 24); + return (u32)data[0] | + (u32)data[1] << 8 | + (u32)data[2] << 16 | + (u32)data[3] << 24; #endif } @@ -159,7 +158,7 @@ static int efx_init_rx_buffers_skb(struct efx_rx_queue *rx_queue) /* Adjust the SKB for padding and checksum */ skb_reserve(skb, NET_IP_ALIGN); rx_buf->len = skb_len - NET_IP_ALIGN; - rx_buf->is_page = false; + rx_buf->flags = 0; skb->ip_summed = CHECKSUM_UNNECESSARY; rx_buf->dma_addr = pci_map_single(efx->pci_dev, @@ -228,7 +227,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN; rx_buf->u.page = page; rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; - rx_buf->is_page = true; + rx_buf->flags = EFX_RX_BUF_PAGE; ++rx_queue->added_count; ++rx_queue->alloc_page_count; ++state->refcnt; @@ -249,7 +248,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) static void efx_unmap_rx_buffer(struct efx_nic *efx, struct efx_rx_buffer *rx_buf) { - if (rx_buf->is_page && rx_buf->u.page) { + if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) { struct efx_rx_page_state *state; state = page_address(rx_buf->u.page); @@ -259,7 +258,7 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx, efx_rx_buf_size(efx), PCI_DMA_FROMDEVICE); } - } else if (!rx_buf->is_page && rx_buf->u.skb) { + } else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) { pci_unmap_single(efx->pci_dev, rx_buf->dma_addr, rx_buf->len, PCI_DMA_FROMDEVICE); } @@ -268,10 +267,10 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx, static void efx_free_rx_buffer(struct efx_nic *efx, struct efx_rx_buffer *rx_buf) { - if (rx_buf->is_page && rx_buf->u.page) { + if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) { __free_pages(rx_buf->u.page, efx->rx_buffer_order); rx_buf->u.page = NULL; - } else if (!rx_buf->is_page && rx_buf->u.skb) { + } else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) { dev_kfree_skb_any(rx_buf->u.skb); rx_buf->u.skb = NULL; } @@ -311,7 +310,7 @@ static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue, new_buf->dma_addr = rx_buf->dma_addr ^ (PAGE_SIZE >> 1); new_buf->u.page = rx_buf->u.page; new_buf->len = rx_buf->len; - new_buf->is_page = true; + new_buf->flags = EFX_RX_BUF_PAGE; ++rx_queue->added_count; } @@ -325,7 +324,10 @@ static void efx_recycle_rx_buffer(struct efx_channel *channel, struct efx_rx_buffer *new_buf; unsigned index; - if (rx_buf->is_page && efx->rx_buffer_len <= EFX_RX_HALF_PAGE && + rx_buf->flags &= EFX_RX_BUF_PAGE; + + if ((rx_buf->flags & EFX_RX_BUF_PAGE) && + efx->rx_buffer_len <= EFX_RX_HALF_PAGE && page_count(rx_buf->u.page) == 1) efx_resurrect_rx_buffer(rx_queue, rx_buf); @@ -412,8 +414,7 @@ void efx_rx_slow_fill(unsigned long context) static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue, struct efx_rx_buffer *rx_buf, - int len, bool *discard, - bool *leak_packet) + int len, bool *leak_packet) { struct efx_nic *efx = rx_queue->efx; unsigned max_len = rx_buf->len - efx->type->rx_buffer_padding; @@ -424,7 +425,7 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue, /* The packet must be discarded, but this is only a fatal error * if the caller indicated it was */ - *discard = true; + rx_buf->flags |= EFX_RX_PKT_DISCARD; if ((len > rx_buf->len) && EFX_WORKAROUND_8071(efx)) { if (net_ratelimit()) @@ -437,7 +438,7 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue, * data at the end of the skb will be trashed. So * we have no choice but to leak the fragment. */ - *leak_packet = !rx_buf->is_page; + *leak_packet = !(rx_buf->flags & EFX_RX_BUF_PAGE); efx_schedule_reset(efx, RESET_TYPE_RX_RECOVERY); } else { if (net_ratelimit()) @@ -457,13 +458,13 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue, */ static void efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf, - const u8 *eh, bool checksummed) + const u8 *eh) { struct napi_struct *napi = &channel->napi_str; gro_result_t gro_result; /* Pass the skb/page into the GRO engine */ - if (rx_buf->is_page) { + if (rx_buf->flags & EFX_RX_BUF_PAGE) { struct efx_nic *efx = channel->efx; struct page *page = rx_buf->u.page; struct sk_buff *skb; @@ -485,8 +486,8 @@ static void efx_rx_packet_gro(struct efx_channel *channel, skb->len = rx_buf->len; skb->data_len = rx_buf->len; skb->truesize += rx_buf->len; - skb->ip_summed = - checksummed ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE; + skb->ip_summed = ((rx_buf->flags & EFX_RX_PKT_CSUMMED) ? + CHECKSUM_UNNECESSARY : CHECKSUM_NONE); skb_record_rx_queue(skb, channel->channel); @@ -494,7 +495,7 @@ static void efx_rx_packet_gro(struct efx_channel *channel, } else { struct sk_buff *skb = rx_buf->u.skb; - EFX_BUG_ON_PARANOID(!checksummed); + EFX_BUG_ON_PARANOID(!(rx_buf->flags & EFX_RX_PKT_CSUMMED)); rx_buf->u.skb = NULL; gro_result = napi_gro_receive(napi, skb); @@ -509,7 +510,7 @@ static void efx_rx_packet_gro(struct efx_channel *channel, } void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, - unsigned int len, bool checksummed, bool discard) + unsigned int len, u16 flags) { struct efx_nic *efx = rx_queue->efx; struct efx_channel *channel = efx_rx_queue_channel(rx_queue); @@ -517,6 +518,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, bool leak_packet = false; rx_buf = efx_rx_buffer(rx_queue, index); + rx_buf->flags |= flags; /* This allows the refill path to post another buffer. * EFX_RXD_HEAD_ROOM ensures that the slot we are using @@ -525,18 +527,17 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, rx_queue->removed_count++; /* Validate the length encoded in the event vs the descriptor pushed */ - efx_rx_packet__check_len(rx_queue, rx_buf, len, - &discard, &leak_packet); + efx_rx_packet__check_len(rx_queue, rx_buf, len, &leak_packet); netif_vdbg(efx, rx_status, efx->net_dev, "RX queue %d received id %x at %llx+%x %s%s\n", efx_rx_queue_index(rx_queue), index, (unsigned long long)rx_buf->dma_addr, len, - (checksummed ? " [SUMMED]" : ""), - (discard ? " [DISCARD]" : "")); + (rx_buf->flags & EFX_RX_PKT_CSUMMED) ? " [SUMMED]" : "", + (rx_buf->flags & EFX_RX_PKT_DISCARD) ? " [DISCARD]" : ""); /* Discard packet, if instructed to do so */ - if (unlikely(discard)) { + if (unlikely(rx_buf->flags & EFX_RX_PKT_DISCARD)) { if (unlikely(leak_packet)) channel->n_skbuff_leaks++; else @@ -563,18 +564,33 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, rx_buf->len = len - efx->type->rx_buffer_hash_size; out: if (channel->rx_pkt) - __efx_rx_packet(channel, - channel->rx_pkt, channel->rx_pkt_csummed); + __efx_rx_packet(channel, channel->rx_pkt); channel->rx_pkt = rx_buf; - channel->rx_pkt_csummed = checksummed; +} + +static void efx_rx_deliver(struct efx_channel *channel, + struct efx_rx_buffer *rx_buf) +{ + struct sk_buff *skb; + + /* We now own the SKB */ + skb = rx_buf->u.skb; + rx_buf->u.skb = NULL; + + /* Set the SKB flags */ + skb_checksum_none_assert(skb); + + /* Pass the packet up */ + netif_receive_skb(skb); + + /* Update allocation strategy method */ + channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; } /* Handle a received packet. Second half: Touches packet payload. */ -void __efx_rx_packet(struct efx_channel *channel, - struct efx_rx_buffer *rx_buf, bool checksummed) +void __efx_rx_packet(struct efx_channel *channel, struct efx_rx_buffer *rx_buf) { struct efx_nic *efx = channel->efx; - struct sk_buff *skb; u8 *eh = efx_rx_buf_eh(efx, rx_buf); /* If we're in loopback test, then pass the packet directly to the @@ -586,8 +602,8 @@ void __efx_rx_packet(struct efx_channel *channel, return; } - if (!rx_buf->is_page) { - skb = rx_buf->u.skb; + if (!(rx_buf->flags & EFX_RX_BUF_PAGE)) { + struct sk_buff *skb = rx_buf->u.skb; prefetch(skb_shinfo(skb)); @@ -605,25 +621,12 @@ void __efx_rx_packet(struct efx_channel *channel, } if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM))) - checksummed = false; - - if (likely(checksummed || rx_buf->is_page)) { - efx_rx_packet_gro(channel, rx_buf, eh, checksummed); - return; - } - - /* We now own the SKB */ - skb = rx_buf->u.skb; - rx_buf->u.skb = NULL; + rx_buf->flags &= ~EFX_RX_PKT_CSUMMED; - /* Set the SKB flags */ - skb_checksum_none_assert(skb); - - /* Pass the packet up */ - netif_receive_skb(skb); - - /* Update allocation strategy method */ - channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; + if (likely(rx_buf->flags & (EFX_RX_BUF_PAGE | EFX_RX_PKT_CSUMMED))) + efx_rx_packet_gro(channel, rx_buf, eh); + else + efx_rx_deliver(channel, rx_buf); } void efx_rx_strategy(struct efx_channel *channel) diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 52edd24fcde3..febe2a9e6211 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -19,7 +19,6 @@ #include <linux/udp.h> #include <linux/rtnetlink.h> #include <linux/slab.h> -#include <asm/io.h> #include "net_driver.h" #include "efx.h" #include "nic.h" @@ -50,7 +49,7 @@ static const char payload_msg[] = /* Interrupt mode names */ static const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX; -static const char *efx_interrupt_mode_names[] = { +static const char *const efx_interrupt_mode_names[] = { [EFX_INT_MODE_MSIX] = "MSI-X", [EFX_INT_MODE_MSI] = "MSI", [EFX_INT_MODE_LEGACY] = "legacy", @@ -131,6 +130,8 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) static int efx_test_interrupts(struct efx_nic *efx, struct efx_self_tests *tests) { + int cpu; + netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n"); tests->interrupt = -1; @@ -143,7 +144,8 @@ static int efx_test_interrupts(struct efx_nic *efx, /* Wait for arrival of test interrupt. */ netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n"); schedule_timeout_uninterruptible(HZ / 10); - if (efx->last_irq_cpu >= 0) + cpu = ACCESS_ONCE(efx->last_irq_cpu); + if (cpu >= 0) goto success; netif_err(efx, drv, efx->net_dev, "timed out waiting for interrupt\n"); @@ -151,8 +153,7 @@ static int efx_test_interrupts(struct efx_nic *efx, success: netif_dbg(efx, drv, efx->net_dev, "%s test interrupt seen on CPU%d\n", - INT_MODE(efx), - efx->last_irq_cpu); + INT_MODE(efx), cpu); tests->interrupt = 1; return 0; } @@ -162,56 +163,57 @@ static int efx_test_eventq_irq(struct efx_channel *channel, struct efx_self_tests *tests) { struct efx_nic *efx = channel->efx; - unsigned int read_ptr, count; - - tests->eventq_dma[channel->channel] = -1; - tests->eventq_int[channel->channel] = -1; - tests->eventq_poll[channel->channel] = -1; + unsigned int read_ptr; + bool napi_ran, dma_seen, int_seen; read_ptr = channel->eventq_read_ptr; - channel->efx->last_irq_cpu = -1; + channel->last_irq_cpu = -1; smp_wmb(); efx_nic_generate_test_event(channel); - /* Wait for arrival of interrupt */ - count = 0; - do { - schedule_timeout_uninterruptible(HZ / 100); - - if (ACCESS_ONCE(channel->eventq_read_ptr) != read_ptr) - goto eventq_ok; - } while (++count < 2); - - netif_err(efx, drv, efx->net_dev, - "channel %d timed out waiting for event queue\n", - channel->channel); - - /* See if interrupt arrived */ - if (channel->efx->last_irq_cpu >= 0) { - netif_err(efx, drv, efx->net_dev, - "channel %d saw interrupt on CPU%d " - "during event queue test\n", channel->channel, - raw_smp_processor_id()); - tests->eventq_int[channel->channel] = 1; + /* Wait for arrival of interrupt. NAPI processing may or may + * not complete in time, but we can cope in any case. + */ + msleep(10); + napi_disable(&channel->napi_str); + if (channel->eventq_read_ptr != read_ptr) { + napi_ran = true; + dma_seen = true; + int_seen = true; + } else { + napi_ran = false; + dma_seen = efx_nic_event_present(channel); + int_seen = ACCESS_ONCE(channel->last_irq_cpu) >= 0; } + napi_enable(&channel->napi_str); + efx_nic_eventq_read_ack(channel); + + tests->eventq_dma[channel->channel] = dma_seen ? 1 : -1; + tests->eventq_int[channel->channel] = int_seen ? 1 : -1; - /* Check to see if event was received even if interrupt wasn't */ - if (efx_nic_event_present(channel)) { + if (dma_seen && int_seen) { + netif_dbg(efx, drv, efx->net_dev, + "channel %d event queue passed (with%s NAPI)\n", + channel->channel, napi_ran ? "" : "out"); + return 0; + } else { + /* Report failure and whether either interrupt or DMA worked */ netif_err(efx, drv, efx->net_dev, - "channel %d event was generated, but " - "failed to trigger an interrupt\n", channel->channel); - tests->eventq_dma[channel->channel] = 1; + "channel %d timed out waiting for event queue\n", + channel->channel); + if (int_seen) + netif_err(efx, drv, efx->net_dev, + "channel %d saw interrupt " + "during event queue test\n", + channel->channel); + if (dma_seen) + netif_err(efx, drv, efx->net_dev, + "channel %d event was generated, but " + "failed to trigger an interrupt\n", + channel->channel); + return -ETIMEDOUT; } - - return -ETIMEDOUT; - eventq_ok: - netif_dbg(efx, drv, efx->net_dev, "channel %d event queue passed\n", - channel->channel); - tests->eventq_dma[channel->channel] = 1; - tests->eventq_int[channel->channel] = 1; - tests->eventq_poll[channel->channel] = 1; - return 0; } static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests, @@ -316,7 +318,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, return; err: -#ifdef EFX_ENABLE_DEBUG +#ifdef DEBUG if (atomic_read(&state->rx_bad) == 0) { netif_err(efx, drv, efx->net_dev, "received packet:\n"); print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, @@ -395,11 +397,9 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) * interrupt handler. */ smp_wmb(); - if (efx_dev_registered(efx)) - netif_tx_lock_bh(efx->net_dev); + netif_tx_lock_bh(efx->net_dev); rc = efx_enqueue_skb(tx_queue, skb); - if (efx_dev_registered(efx)) - netif_tx_unlock_bh(efx->net_dev); + netif_tx_unlock_bh(efx->net_dev); if (rc != NETDEV_TX_OK) { netif_err(efx, drv, efx->net_dev, @@ -440,20 +440,18 @@ static int efx_end_loopback(struct efx_tx_queue *tx_queue, int tx_done = 0, rx_good, rx_bad; int i, rc = 0; - if (efx_dev_registered(efx)) - netif_tx_lock_bh(efx->net_dev); + netif_tx_lock_bh(efx->net_dev); /* Count the number of tx completions, and decrement the refcnt. Any * skbs not already completed will be free'd when the queue is flushed */ - for (i=0; i < state->packet_count; i++) { + for (i = 0; i < state->packet_count; i++) { skb = state->skbs[i]; if (skb && !skb_shared(skb)) ++tx_done; dev_kfree_skb_any(skb); } - if (efx_dev_registered(efx)) - netif_tx_unlock_bh(efx->net_dev); + netif_tx_unlock_bh(efx->net_dev); /* Check TX completion and received packet counts */ rx_good = atomic_read(&state->rx_good); @@ -570,7 +568,7 @@ static int efx_wait_for_link(struct efx_nic *efx) mutex_lock(&efx->mac_lock); link_up = link_state->up; if (link_up) - link_up = !efx->mac_op->check_fault(efx); + link_up = !efx->type->check_mac_fault(efx); mutex_unlock(&efx->mac_lock); if (link_up) { diff --git a/drivers/net/ethernet/sfc/selftest.h b/drivers/net/ethernet/sfc/selftest.h index dba5456e70f3..87abe2a53846 100644 --- a/drivers/net/ethernet/sfc/selftest.h +++ b/drivers/net/ethernet/sfc/selftest.h @@ -37,7 +37,6 @@ struct efx_self_tests { int interrupt; int eventq_dma[EFX_MAX_CHANNELS]; int eventq_int[EFX_MAX_CHANNELS]; - int eventq_poll[EFX_MAX_CHANNELS]; /* offline tests */ int registers; int phy_ext[EFX_MAX_PHY_TESTS]; diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 4d5d619feaa6..d3c4169e2a0b 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -18,7 +18,6 @@ #include "bitfield.h" #include "efx.h" #include "nic.h" -#include "mac.h" #include "spi.h" #include "regs.h" #include "io.h" @@ -36,8 +35,6 @@ static void siena_push_irq_moderation(struct efx_channel *channel) { efx_dword_t timer_cmd; - BUILD_BUG_ON(EFX_IRQ_MOD_MAX > (1 << FRF_CZ_TC_TIMER_VAL_WIDTH)); - if (channel->irq_moderation) EFX_POPULATE_DWORD_2(timer_cmd, FRF_CZ_TC_TIMER_MODE, @@ -53,15 +50,6 @@ static void siena_push_irq_moderation(struct efx_channel *channel) channel->channel); } -static void siena_push_multicast_hash(struct efx_nic *efx) -{ - WARN_ON(!mutex_is_locked(&efx->mac_lock)); - - efx_mcdi_rpc(efx, MC_CMD_SET_MCAST_HASH, - efx->multicast_hash.byte, sizeof(efx->multicast_hash), - NULL, 0, NULL); -} - static int siena_mdio_write(struct net_device *net_dev, int prtad, int devad, u16 addr, u16 value) { @@ -226,7 +214,15 @@ static int siena_reset_hw(struct efx_nic *efx, enum reset_type method) static int siena_probe_nvconfig(struct efx_nic *efx) { - return efx_mcdi_get_board_cfg(efx, efx->net_dev->perm_addr, NULL); + u32 caps = 0; + int rc; + + rc = efx_mcdi_get_board_cfg(efx, efx->net_dev->perm_addr, NULL, &caps); + + efx->timer_quantum_ns = + (caps & (1 << MC_CMD_CAPABILITIES_TURBO_ACTIVE_LBN)) ? + 3072 : 6144; /* 768 cycles */ + return rc; } static int siena_probe_nic(struct efx_nic *efx) @@ -304,6 +300,10 @@ static int siena_probe_nic(struct efx_nic *efx) goto fail5; } + rc = efx_mcdi_mon_probe(efx); + if (rc) + goto fail5; + return 0; fail5: @@ -391,6 +391,8 @@ static int siena_init_nic(struct efx_nic *efx) static void siena_remove_nic(struct efx_nic *efx) { + efx_mcdi_mon_remove(efx); + efx_nic_free_buffer(efx, &efx->irq_status); siena_reset_hw(efx, RESET_TYPE_ALL); @@ -630,14 +632,14 @@ const struct efx_nic_type siena_a0_nic_type = { .stop_stats = siena_stop_nic_stats, .set_id_led = efx_mcdi_set_id_led, .push_irq_moderation = siena_push_irq_moderation, - .push_multicast_hash = siena_push_multicast_hash, + .reconfigure_mac = efx_mcdi_mac_reconfigure, + .check_mac_fault = efx_mcdi_mac_check_fault, .reconfigure_port = efx_mcdi_phy_reconfigure, .get_wol = siena_get_wol, .set_wol = siena_set_wol, .resume_wol = siena_init_wol, .test_registers = siena_test_registers, .test_nvram = efx_mcdi_nvram_test_all, - .default_mac_ops = &efx_mcdi_mac_operations, .revision = EFX_REV_SIENA_A0, .mem_map_size = (FR_CZ_MC_TREG_SMEM + @@ -654,6 +656,7 @@ const struct efx_nic_type siena_a0_nic_type = { .phys_addr_channels = 32, /* Hardware limit is 64, but the legacy * interrupt handler only supports 32 * channels */ + .timer_period_max = 1 << FRF_CZ_TC_TIMER_VAL_WIDTH, .tx_dc_base = 0x88000, .rx_dc_base = 0x68000, .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | diff --git a/drivers/net/ethernet/sfc/spi.h b/drivers/net/ethernet/sfc/spi.h index 71f2e3ebe1c7..5431a1bbff5c 100644 --- a/drivers/net/ethernet/sfc/spi.h +++ b/drivers/net/ethernet/sfc/spi.h @@ -68,7 +68,7 @@ static inline bool efx_spi_present(const struct efx_spi_device *spi) int falcon_spi_cmd(struct efx_nic *efx, const struct efx_spi_device *spi, unsigned int command, - int address, const void* in, void *out, size_t len); + int address, const void *in, void *out, size_t len); int falcon_spi_wait_write(struct efx_nic *efx, const struct efx_spi_device *spi); int falcon_spi_read(struct efx_nic *efx, diff --git a/drivers/net/ethernet/sfc/tenxpress.c b/drivers/net/ethernet/sfc/tenxpress.c index 7b0fd89e7b85..d37cb5017129 100644 --- a/drivers/net/ethernet/sfc/tenxpress.c +++ b/drivers/net/ethernet/sfc/tenxpress.c @@ -121,7 +121,7 @@ #define GPHY_XCONTROL_REG 49152 #define GPHY_ISOLATE_LBN 10 #define GPHY_ISOLATE_WIDTH 1 -#define GPHY_DUPLEX_LBN 8 +#define GPHY_DUPLEX_LBN 8 #define GPHY_DUPLEX_WIDTH 1 #define GPHY_LOOPBACK_NEAR_LBN 14 #define GPHY_LOOPBACK_NEAR_WIDTH 1 diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 72f0fbc73b1a..5cb81fa3fcbd 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -446,10 +446,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) likely(efx->port_enabled) && likely(netif_device_present(efx->net_dev))) { fill_level = tx_queue->insert_count - tx_queue->read_count; - if (fill_level < EFX_TXQ_THRESHOLD(efx)) { - EFX_BUG_ON_PARANOID(!efx_dev_registered(efx)); + if (fill_level < EFX_TXQ_THRESHOLD(efx)) netif_tx_wake_queue(tx_queue->core_txq); - } } /* Check whether the hardware queue is now empty */ diff --git a/drivers/net/ethernet/sfc/txc43128_phy.c b/drivers/net/ethernet/sfc/txc43128_phy.c index 7c21b334a75b..29bb3f9941c0 100644 --- a/drivers/net/ethernet/sfc/txc43128_phy.c +++ b/drivers/net/ethernet/sfc/txc43128_phy.c @@ -512,7 +512,7 @@ static bool txc43128_phy_poll(struct efx_nic *efx) return efx->link_state.up != was_up; } -static const char *txc43128_test_names[] = { +static const char *const txc43128_test_names[] = { "bist" }; diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c index 5b118cd5bf94..a9deda8eaf63 100644 --- a/drivers/net/ethernet/sis/sis190.c +++ b/drivers/net/ethernet/sis/sis190.c @@ -1462,8 +1462,6 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev) dev = alloc_etherdev(sizeof(*tp)); if (!dev) { - if (netif_msg_drv(&debug)) - pr_err("unable to alloc new ethernet\n"); rc = -ENOMEM; goto err_out_0; } diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index c8efc708c792..f968898c86db 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -619,7 +619,6 @@ static int __devinit sis900_mii_probe(struct net_device * net_dev) } if ((mii_phy = kmalloc(sizeof(struct mii_phy), GFP_KERNEL)) == NULL) { - printk(KERN_WARNING "Cannot allocate mem for struct mii_phy\n"); mii_phy = sis_priv->first_mii; while (mii_phy) { struct mii_phy *phy; @@ -1167,7 +1166,7 @@ sis900_init_rx_ring(struct net_device *net_dev) for (i = 0; i < NUM_RX_DESC; i++) { struct sk_buff *skb; - if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) { + if ((skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE)) == NULL) { /* not enough memory for skbuff, this makes a "hole" on the buffer ring, it is not clear how the hardware will react to this kind of degenerated @@ -1770,7 +1769,7 @@ static int sis900_rx(struct net_device *net_dev) /* refill the Rx buffer, what if there is not enough * memory for new socket buffer ?? */ - if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) { + if ((skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE)) == NULL) { /* * Not enough memory to refill the buffer * so we need to recycle the old one so @@ -1828,7 +1827,7 @@ refill_rx_ring: entry = sis_priv->dirty_rx % NUM_RX_DESC; if (sis_priv->rx_skbuff[entry] == NULL) { - if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) { + if ((skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE)) == NULL) { /* not enough memory for skbuff, this makes a * "hole" on the buffer ring, it is not clear * how the hardware will react to this kind diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c index 2c077ce0b6d6..2a662e6112e9 100644 --- a/drivers/net/ethernet/smsc/epic100.c +++ b/drivers/net/ethernet/smsc/epic100.c @@ -363,10 +363,9 @@ static int __devinit epic_init_one (struct pci_dev *pdev, ret = -ENOMEM; dev = alloc_etherdev(sizeof (*ep)); - if (!dev) { - dev_err(&pdev->dev, "no memory for eth device\n"); + if (!dev) goto err_out_free_res; - } + SET_NETDEV_DEV(dev, &pdev->dev); #ifdef USE_IO_OPS @@ -935,7 +934,7 @@ static void epic_init_ring(struct net_device *dev) /* Fill in the Rx buffers. Handle allocation failure gracefully. */ for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = dev_alloc_skb(ep->rx_buf_sz + 2); + struct sk_buff *skb = netdev_alloc_skb(dev, ep->rx_buf_sz + 2); ep->rx_skbuff[i] = skb; if (skb == NULL) break; @@ -1200,7 +1199,7 @@ static int epic_rx(struct net_device *dev, int budget) /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < rx_copybreak && - (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) { skb_reserve(skb, 2); /* 16 byte align the IP header */ pci_dma_sync_single_for_cpu(ep->pci_dev, ep->rx_ring[entry].bufaddr, @@ -1233,7 +1232,7 @@ static int epic_rx(struct net_device *dev, int budget) entry = ep->dirty_rx % RX_RING_SIZE; if (ep->rx_skbuff[entry] == NULL) { struct sk_buff *skb; - skb = ep->rx_skbuff[entry] = dev_alloc_skb(ep->rx_buf_sz + 2); + skb = ep->rx_skbuff[entry] = netdev_alloc_skb(dev, ep->rx_buf_sz + 2); if (skb == NULL) break; skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c index 313ba3b32ab4..8814b2f5d46f 100644 --- a/drivers/net/ethernet/smsc/smc911x.c +++ b/drivers/net/ethernet/smsc/smc911x.c @@ -401,7 +401,7 @@ static inline void smc911x_rcv(struct net_device *dev) } else { /* Receive a valid packet */ /* Alloc a buffer with extra room for DMA alignment */ - skb=dev_alloc_skb(pkt_len+32); + skb = netdev_alloc_skb(dev, pkt_len+32); if (unlikely(skb == NULL)) { PRINTK( "%s: Low memory, rcvd packet dropped.\n", dev->name); @@ -2065,7 +2065,6 @@ static int __devinit smc911x_drv_probe(struct platform_device *pdev) ndev = alloc_etherdev(sizeof(struct smc911x_local)); if (!ndev) { - printk("%s: could not allocate device.\n", CARDNAME); ret = -ENOMEM; goto release_1; } diff --git a/drivers/net/ethernet/smsc/smc9194.c b/drivers/net/ethernet/smsc/smc9194.c index 4e45094efb18..50823da9dc1e 100644 --- a/drivers/net/ethernet/smsc/smc9194.c +++ b/drivers/net/ethernet/smsc/smc9194.c @@ -1222,7 +1222,7 @@ static void smc_rcv(struct net_device *dev) if ( status & RS_MULTICAST ) dev->stats.multicast++; - skb = dev_alloc_skb( packet_length + 5); + skb = netdev_alloc_skb(dev, packet_length + 5); if ( skb == NULL ) { printk(KERN_NOTICE CARDNAME ": Low memory, packet dropped.\n"); diff --git a/drivers/net/ethernet/smsc/smc91c92_cs.c b/drivers/net/ethernet/smsc/smc91c92_cs.c index ada927aba7a5..d12e48a7861d 100644 --- a/drivers/net/ethernet/smsc/smc91c92_cs.c +++ b/drivers/net/ethernet/smsc/smc91c92_cs.c @@ -1500,7 +1500,7 @@ static void smc_rx(struct net_device *dev) struct sk_buff *skb; /* Note: packet_length adds 5 or 6 extra bytes here! */ - skb = dev_alloc_skb(packet_length+2); + skb = netdev_alloc_skb(dev, packet_length+2); if (skb == NULL) { pr_debug("%s: Low memory, packet dropped.\n", dev->name); diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 64ad3ed74495..1dc4fad593e7 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -463,7 +463,7 @@ static inline void smc_rcv(struct net_device *dev) * multiple of 4 bytes on 32 bit buses. * Hence packet_len - 6 + 2 + 2 + 2. */ - skb = dev_alloc_skb(packet_len); + skb = netdev_alloc_skb(dev, packet_len); if (unlikely(skb == NULL)) { printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", dev->name); @@ -2223,7 +2223,6 @@ static int __devinit smc_drv_probe(struct platform_device *pdev) ndev = alloc_etherdev(sizeof(struct smc_local)); if (!ndev) { - printk("%s: could not allocate device.\n", CARDNAME); ret = -ENOMEM; goto out; } diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 24d2df068d71..6a1cd2360818 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -2374,7 +2374,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) dev = alloc_etherdev(sizeof(struct smsc911x_data)); if (!dev) { - pr_warn("Could not allocate device\n"); retval = -ENOMEM; goto out_release_io_1; } diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c index a9efbdfe5302..ee1a1680b7a8 100644 --- a/drivers/net/ethernet/smsc/smsc9420.c +++ b/drivers/net/ethernet/smsc/smsc9420.c @@ -850,8 +850,6 @@ static int smsc9420_alloc_rx_buffer(struct smsc9420_pdata *pd, int index) return -ENOMEM; } - skb->dev = pd->dev; - mapping = pci_map_single(pd->pdev, skb_tail_pointer(skb), PKT_BUF_SZ, PCI_DMA_FROMDEVICE); if (pci_dma_mapping_error(pd->pdev, mapping)) { @@ -1598,10 +1596,8 @@ smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); dev = alloc_etherdev(sizeof(*pd)); - if (!dev) { - printk(KERN_ERR "ether device alloc failed\n"); + if (!dev) goto out_disable_pci_device_1; - } SET_NETDEV_DEV(dev, &pdev->dev); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 96fa2da30763..166fc95e5baf 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -954,10 +954,9 @@ static int stmmac_open(struct net_device *dev) #ifdef CONFIG_STMMAC_TIMER priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL); - if (unlikely(priv->tm == NULL)) { - pr_err("%s: ERROR: timer memory alloc failed\n", __func__); + if (unlikely(priv->tm == NULL)) return -ENOMEM; - } + priv->tm->freq = tmrate; /* Test if the external timer can be actually used. @@ -1802,10 +1801,8 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, struct stmmac_priv *priv; ndev = alloc_etherdev(sizeof(struct stmmac_priv)); - if (!ndev) { - pr_err("%s: ERROR: allocating the device\n", __func__); + if (!ndev) return NULL; - } SET_NETDEV_DEV(ndev, device); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index c796de9eed72..6ce0706b2d1b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -85,7 +85,7 @@ static int __devinit stmmac_pci_probe(struct pci_dev *pdev, continue; addr = pci_iomap(pdev, i, 0); if (addr == NULL) { - pr_err("%s: ERROR: cannot map regiser memory, aborting", + pr_err("%s: ERROR: cannot map register memory, aborting", __func__); ret = -EIO; goto err_out_map_failed; diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index f10665f594c4..b36edbd625dd 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -835,7 +835,6 @@ static int cas_saturn_firmware_init(struct cas *cp) cp->fw_data = vmalloc(cp->fw_size); if (!cp->fw_data) { err = -ENOMEM; - pr_err("\"%s\" Failed %d\n", fw_name, err); goto out; } memcpy(cp->fw_data, &fw->data[2], cp->fw_size); @@ -1975,7 +1974,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, else alloclen = max(hlen, RX_COPY_MIN); - skb = dev_alloc_skb(alloclen + swivel + cp->crc_size); + skb = netdev_alloc_skb(cp->dev, alloclen + swivel + cp->crc_size); if (skb == NULL) return -1; @@ -4947,7 +4946,6 @@ static int __devinit cas_init_one(struct pci_dev *pdev, dev = alloc_etherdev(sizeof(*cp)); if (!dev) { - dev_err(&pdev->dev, "Etherdev alloc failed, aborting\n"); err = -ENOMEM; goto err_out_disable_pdev; } diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index cf433931304f..d83c50816714 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -9685,10 +9685,8 @@ static struct net_device * __devinit niu_alloc_and_init( struct niu *np; dev = alloc_etherdev_mq(sizeof(struct niu), NIU_NUM_TXCHAN); - if (!dev) { - dev_err(gen_dev, "Etherdev alloc failed, aborting\n"); + if (!dev) return NULL; - } SET_NETDEV_DEV(dev, gen_dev); diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c index 220f724c3377..f359863b5340 100644 --- a/drivers/net/ethernet/sun/sunbmac.c +++ b/drivers/net/ethernet/sun/sunbmac.c @@ -853,7 +853,7 @@ static void bigmac_rx(struct bigmac *bp) /* Trim the original skb for the netif. */ skb_trim(skb, len); } else { - struct sk_buff *copy_skb = dev_alloc_skb(len + 2); + struct sk_buff *copy_skb = netdev_alloc_skb(bp->dev, len + 2); if (copy_skb == NULL) { drops++; diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index 31441a870b0b..ba041596e046 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -2885,7 +2885,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev, dev = alloc_etherdev(sizeof(*gp)); if (!dev) { - pr_err("Etherdev alloc failed, aborting\n"); err = -ENOMEM; goto err_disable_device; } diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c index 09c518655db2..8b627e2f798d 100644 --- a/drivers/net/ethernet/sun/sunhme.c +++ b/drivers/net/ethernet/sun/sunhme.c @@ -2043,7 +2043,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev) /* Trim the original skb for the netif. */ skb_trim(skb, len); } else { - struct sk_buff *copy_skb = dev_alloc_skb(len + 2); + struct sk_buff *copy_skb = netdev_alloc_skb(dev, len + 2); if (copy_skb == NULL) { drops++; diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c index b28f74367ebe..b42d1c5a6ca1 100644 --- a/drivers/net/ethernet/sun/sunqe.c +++ b/drivers/net/ethernet/sun/sunqe.c @@ -435,7 +435,7 @@ static void qe_rx(struct sunqe *qep) dev->stats.rx_length_errors++; dev->stats.rx_dropped++; } else { - skb = dev_alloc_skb(len + 2); + skb = netdev_alloc_skb(dev, len + 2); if (skb == NULL) { drops++; dev->stats.rx_dropped++; diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 8c6c059f3489..92a037a8228a 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -949,10 +949,9 @@ static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port) int map_len = (ETH_FRAME_LEN + 7) & ~7; err = -ENOMEM; - if (!buf) { - pr_err("TX buffer allocation failure\n"); + if (!buf) goto err_out; - } + err = -EFAULT; if ((unsigned long)buf & (8UL - 1)) { pr_err("TX buffer misaligned\n"); @@ -1027,10 +1026,8 @@ static struct vnet * __devinit vnet_new(const u64 *local_mac) int err, i; dev = alloc_etherdev(sizeof(*vp)); - if (!dev) { - pr_err("Etherdev alloc failed, aborting\n"); + if (!dev) return ERR_PTR(-ENOMEM); - } for (i = 0; i < ETH_ALEN; i++) dev->dev_addr[i] = (*local_mac >> (5 - i) * 8) & 0xff; @@ -1165,10 +1162,8 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev, port = kzalloc(sizeof(*port), GFP_KERNEL); err = -ENOMEM; - if (!port) { - pr_err("Cannot allocate vnet_port\n"); + if (!port) goto err_out_put_mdesc; - } for (i = 0; i < ETH_ALEN; i++) port->raddr[i] = (*rmac >> (5 - i) * 8) & 0xff; diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index 4b19e9b0606b..ad973ffc9ff3 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -1089,12 +1089,11 @@ static void bdx_rx_alloc_skbs(struct bdx_priv *priv, struct rxf_fifo *f) ENTER; dno = bdx_rxdb_available(db) - 1; while (dno > 0) { - skb = dev_alloc_skb(f->m.pktsz + NET_IP_ALIGN); + skb = netdev_alloc_skb(priv->ndev, f->m.pktsz + NET_IP_ALIGN); if (!skb) { - pr_err("NO MEM: dev_alloc_skb failed\n"); + pr_err("NO MEM: netdev_alloc_skb failed\n"); break; } - skb->dev = priv->ndev; skb_reserve(skb, NET_IP_ALIGN); idx = bdx_rxdb_alloc_elem(db); @@ -1258,7 +1257,7 @@ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget) skb = dm->skb; if (len < BDX_COPYBREAK && - (skb2 = dev_alloc_skb(len + NET_IP_ALIGN))) { + (skb2 = netdev_alloc_skb(priv->ndev, len + NET_IP_ALIGN))) { skb_reserve(skb2, NET_IP_ALIGN); /*skb_put(skb2, len); */ pci_dma_sync_single_for_cpu(priv->pdev, @@ -1978,7 +1977,6 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ndev = alloc_etherdev(sizeof(struct bdx_priv)); if (!ndev) { err = -ENOMEM; - pr_err("alloc_etherdev failed\n"); goto err_out_iomap; } diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c index 4d9a28ffd3c3..97e1df330a17 100644 --- a/drivers/net/ethernet/ti/cpmac.c +++ b/drivers/net/ethernet/ti/cpmac.c @@ -1143,11 +1143,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev) } dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES); - - if (!dev) { - printk(KERN_ERR "cpmac: Unable to allocate net_device\n"); + if (!dev) return -ENOMEM; - } platform_set_drvdata(pdev, dev); priv = netdev_priv(dev); diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 4fa0bcb25dfc..6b0659c59ddd 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -992,10 +992,9 @@ static irqreturn_t emac_irq(int irq, void *dev_id) static struct sk_buff *emac_rx_alloc(struct emac_priv *priv) { - struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size); + struct sk_buff *skb = netdev_alloc_skb(priv->ndev, priv->rx_buf_size); if (WARN_ON(!skb)) return NULL; - skb->dev = priv->ndev; skb_reserve(skb, NET_IP_ALIGN); return skb; } @@ -1790,7 +1789,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) ndev = alloc_etherdev(sizeof(struct emac_priv)); if (!ndev) { - dev_err(&pdev->dev, "error allocating net_device\n"); rc = -ENOMEM; goto free_clk; } diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c index 9c0dd6b8d6c9..817ad3bc4957 100644 --- a/drivers/net/ethernet/ti/tlan.c +++ b/drivers/net/ethernet/ti/tlan.c @@ -486,7 +486,6 @@ static int __devinit tlan_probe1(struct pci_dev *pdev, dev = alloc_etherdev(sizeof(struct tlan_priv)); if (dev == NULL) { - pr_err("Could not allocate memory for device\n"); rc = -ENOMEM; goto err_out_regions; } diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c index d9951afb9269..a8e5daaef6fa 100644 --- a/drivers/net/ethernet/tile/tilepro.c +++ b/drivers/net/ethernet/tile/tilepro.c @@ -419,7 +419,7 @@ static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info, #endif /* Avoid "false sharing" with last cache line. */ - /* ISSUE: This is already done by "dev_alloc_skb()". */ + /* ISSUE: This is already done by "netdev_alloc_skb()". */ unsigned int len = (((small ? LIPP_SMALL_PACKET_SIZE : large_size) + CHIP_L2_LINE_SIZE() - 1) & -CHIP_L2_LINE_SIZE()); @@ -433,7 +433,7 @@ static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info, struct sk_buff **skb_ptr; /* Request 96 extra bytes for alignment purposes. */ - skb = dev_alloc_skb(len + padding); + skb = netdev_alloc_skb(info->napi->dev, len + padding); if (skb == NULL) return false; diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c index fd4ed7f8cfa1..5c14f82c4954 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c @@ -1621,10 +1621,9 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl) kfree(target->hwinfo); target->hwinfo = kzalloc(be16_to_cpu(scan_info->size), GFP_KERNEL); - if (!target->hwinfo) { - pr_info("%s: kzalloc failed\n", __func__); + if (!target->hwinfo) continue; - } + /* copy hw scan info */ memcpy(target->hwinfo, scan_info, scan_info->size); target->essid_len = strnlen(scan_info->essid, diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c index 71b785cd7563..d117ad475c3e 100644 --- a/drivers/net/ethernet/toshiba/tc35815.c +++ b/drivers/net/ethernet/toshiba/tc35815.c @@ -453,7 +453,7 @@ static struct sk_buff *alloc_rxbuf_skb(struct net_device *dev, dma_addr_t *dma_handle) { struct sk_buff *skb; - skb = dev_alloc_skb(RX_BUF_SIZE); + skb = netdev_alloc_skb(dev, RX_BUF_SIZE); if (!skb) return NULL; *dma_handle = pci_map_single(hwdev, skb->data, RX_BUF_SIZE, @@ -808,10 +808,9 @@ static int __devinit tc35815_init_one(struct pci_dev *pdev, /* dev zeroed in alloc_etherdev */ dev = alloc_etherdev(sizeof(*lp)); - if (dev == NULL) { - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); + if (dev == NULL) return -ENOMEM; - } + SET_NETDEV_DEV(dev, &pdev->dev); lp = netdev_priv(dev); lp->dev = dev; diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c index 164fb775d7b3..fc5521c9c089 100644 --- a/drivers/net/ethernet/tundra/tsi108_eth.c +++ b/drivers/net/ethernet/tundra/tsi108_eth.c @@ -1582,10 +1582,8 @@ tsi108_init_one(struct platform_device *pdev) /* Create an ethernet device instance */ dev = alloc_etherdev(sizeof(struct tsi108_prv_data)); - if (!dev) { - printk("tsi108_eth: Could not allocate a device structure\n"); + if (!dev) return -ENOMEM; - } printk("tsi108_eth%d: probe...\n", pdev->id); data = netdev_priv(dev); diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 10b18eb63d25..cb2ff28a0602 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -927,7 +927,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, dev = alloc_etherdev(sizeof(struct rhine_private)); if (!dev) { rc = -ENOMEM; - dev_err(&pdev->dev, "alloc_etherdev failed\n"); goto err_out; } SET_NETDEV_DEV(dev, &pdev->dev); @@ -1156,7 +1155,6 @@ static void alloc_rbufs(struct net_device *dev) rp->rx_skbuff[i] = skb; if (skb == NULL) break; - skb->dev = dev; /* Mark as being used by this device. */ rp->rx_skbuff_dma[i] = pci_map_single(rp->pdev, skb->data, rp->rx_buf_sz, @@ -1941,7 +1939,6 @@ static int rhine_rx(struct net_device *dev, int limit) rp->rx_skbuff[entry] = skb; if (skb == NULL) break; /* Better luck next round. */ - skb->dev = dev; /* Mark as being used by this device. */ rp->rx_skbuff_dma[entry] = pci_map_single(rp->pdev, skb->data, rp->rx_buf_sz, diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index cb35b14b73bb..8a5d7c100a5e 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -1509,7 +1509,7 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx) struct rx_desc *rd = &(vptr->rx.ring[idx]); struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]); - rd_info->skb = dev_alloc_skb(vptr->rx.buf_sz + 64); + rd_info->skb = netdev_alloc_skb(vptr->dev, vptr->rx.buf_sz + 64); if (rd_info->skb == NULL) return -ENOMEM; @@ -2730,10 +2730,8 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi } dev = alloc_etherdev(sizeof(struct velocity_info)); - if (!dev) { - dev_err(&pdev->dev, "allocate net device failed.\n"); + if (!dev) goto out; - } /* Chain it all together */ diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig index d5a826063a82..5778a4ae1164 100644 --- a/drivers/net/ethernet/xilinx/Kconfig +++ b/drivers/net/ethernet/xilinx/Kconfig @@ -25,6 +25,14 @@ config XILINX_EMACLITE ---help--- This driver supports the 10/100 Ethernet Lite from Xilinx. +config XILINX_AXI_EMAC + tristate "Xilinx 10/100/1000 AXI Ethernet support" + depends on (PPC32 || MICROBLAZE) + select PHYLIB + ---help--- + This driver supports the 10/100/1000 Ethernet from Xilinx for the + AXI bus interface used in Xilinx Virtex FPGAs. + config XILINX_LL_TEMAC tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver" depends on (PPC || MICROBLAZE) diff --git a/drivers/net/ethernet/xilinx/Makefile b/drivers/net/ethernet/xilinx/Makefile index 5feac734ea45..214205e975e3 100644 --- a/drivers/net/ethernet/xilinx/Makefile +++ b/drivers/net/ethernet/xilinx/Makefile @@ -5,3 +5,5 @@ ll_temac-objs := ll_temac_main.o ll_temac_mdio.o obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o +xilinx_emac-objs := xilinx_axienet_main.o xilinx_axienet_mdio.o +obj-$(CONFIG_XILINX_AXI_EMAC) += xilinx_emac.o diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index f21addb1db95..d8eb9c9e3ee2 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -1011,10 +1011,9 @@ static int __devinit temac_of_probe(struct platform_device *op) /* Init network device structure */ ndev = alloc_etherdev(sizeof(*lp)); - if (!ndev) { - dev_err(&op->dev, "could not allocate device.\n"); + if (!ndev) return -ENOMEM; - } + ether_setup(ndev); dev_set_drvdata(&op->dev, ndev); SET_NETDEV_DEV(ndev, &op->dev); diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h new file mode 100644 index 000000000000..cc83af083fd7 --- /dev/null +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -0,0 +1,508 @@ +/* + * Definitions for Xilinx Axi Ethernet device driver. + * + * Copyright (c) 2009 Secret Lab Technologies, Ltd. + * Copyright (c) 2010 Xilinx, Inc. All rights reserved. + * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch> + * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch> + */ + +#ifndef XILINX_AXIENET_H +#define XILINX_AXIENET_H + +#include <linux/netdevice.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> + +/* Packet size info */ +#define XAE_HDR_SIZE 14 /* Size of Ethernet header */ +#define XAE_HDR_VLAN_SIZE 18 /* Size of an Ethernet hdr + VLAN */ +#define XAE_TRL_SIZE 4 /* Size of Ethernet trailer (FCS) */ +#define XAE_MTU 1500 /* Max MTU of an Ethernet frame */ +#define XAE_JUMBO_MTU 9000 /* Max MTU of a jumbo Eth. frame */ + +#define XAE_MAX_FRAME_SIZE (XAE_MTU + XAE_HDR_SIZE + XAE_TRL_SIZE) +#define XAE_MAX_VLAN_FRAME_SIZE (XAE_MTU + XAE_HDR_VLAN_SIZE + XAE_TRL_SIZE) +#define XAE_MAX_JUMBO_FRAME_SIZE (XAE_JUMBO_MTU + XAE_HDR_SIZE + XAE_TRL_SIZE) + +/* Configuration options */ + +/* Accept all incoming packets. Default: disabled (cleared) */ +#define XAE_OPTION_PROMISC (1 << 0) + +/* Jumbo frame support for Tx & Rx. Default: disabled (cleared) */ +#define XAE_OPTION_JUMBO (1 << 1) + +/* VLAN Rx & Tx frame support. Default: disabled (cleared) */ +#define XAE_OPTION_VLAN (1 << 2) + +/* Enable recognition of flow control frames on Rx. Default: enabled (set) */ +#define XAE_OPTION_FLOW_CONTROL (1 << 4) + +/* Strip FCS and PAD from incoming frames. Note: PAD from VLAN frames is not + * stripped. Default: disabled (set) */ +#define XAE_OPTION_FCS_STRIP (1 << 5) + +/* Generate FCS field and add PAD automatically for outgoing frames. + * Default: enabled (set) */ +#define XAE_OPTION_FCS_INSERT (1 << 6) + +/* Enable Length/Type error checking for incoming frames. When this option is + * set, the MAC will filter frames that have a mismatched type/length field + * and if XAE_OPTION_REPORT_RXERR is set, the user is notified when these + * types of frames are encountered. When this option is cleared, the MAC will + * allow these types of frames to be received. Default: enabled (set) */ +#define XAE_OPTION_LENTYPE_ERR (1 << 7) + +/* Enable the transmitter. Default: enabled (set) */ +#define XAE_OPTION_TXEN (1 << 11) + +/* Enable the receiver. Default: enabled (set) */ +#define XAE_OPTION_RXEN (1 << 12) + +/* Default options set when device is initialized or reset */ +#define XAE_OPTION_DEFAULTS \ + (XAE_OPTION_TXEN | \ + XAE_OPTION_FLOW_CONTROL | \ + XAE_OPTION_RXEN) + +/* Axi DMA Register definitions */ + +#define XAXIDMA_TX_CR_OFFSET 0x00000000 /* Channel control */ +#define XAXIDMA_TX_SR_OFFSET 0x00000004 /* Status */ +#define XAXIDMA_TX_CDESC_OFFSET 0x00000008 /* Current descriptor pointer */ +#define XAXIDMA_TX_TDESC_OFFSET 0x00000010 /* Tail descriptor pointer */ + +#define XAXIDMA_RX_CR_OFFSET 0x00000030 /* Channel control */ +#define XAXIDMA_RX_SR_OFFSET 0x00000034 /* Status */ +#define XAXIDMA_RX_CDESC_OFFSET 0x00000038 /* Current descriptor pointer */ +#define XAXIDMA_RX_TDESC_OFFSET 0x00000040 /* Tail descriptor pointer */ + +#define XAXIDMA_CR_RUNSTOP_MASK 0x00000001 /* Start/stop DMA channel */ +#define XAXIDMA_CR_RESET_MASK 0x00000004 /* Reset DMA engine */ + +#define XAXIDMA_BD_NDESC_OFFSET 0x00 /* Next descriptor pointer */ +#define XAXIDMA_BD_BUFA_OFFSET 0x08 /* Buffer address */ +#define XAXIDMA_BD_CTRL_LEN_OFFSET 0x18 /* Control/buffer length */ +#define XAXIDMA_BD_STS_OFFSET 0x1C /* Status */ +#define XAXIDMA_BD_USR0_OFFSET 0x20 /* User IP specific word0 */ +#define XAXIDMA_BD_USR1_OFFSET 0x24 /* User IP specific word1 */ +#define XAXIDMA_BD_USR2_OFFSET 0x28 /* User IP specific word2 */ +#define XAXIDMA_BD_USR3_OFFSET 0x2C /* User IP specific word3 */ +#define XAXIDMA_BD_USR4_OFFSET 0x30 /* User IP specific word4 */ +#define XAXIDMA_BD_ID_OFFSET 0x34 /* Sw ID */ +#define XAXIDMA_BD_HAS_STSCNTRL_OFFSET 0x38 /* Whether has stscntrl strm */ +#define XAXIDMA_BD_HAS_DRE_OFFSET 0x3C /* Whether has DRE */ + +#define XAXIDMA_BD_HAS_DRE_SHIFT 8 /* Whether has DRE shift */ +#define XAXIDMA_BD_HAS_DRE_MASK 0xF00 /* Whether has DRE mask */ +#define XAXIDMA_BD_WORDLEN_MASK 0xFF /* Whether has DRE mask */ + +#define XAXIDMA_BD_CTRL_LENGTH_MASK 0x007FFFFF /* Requested len */ +#define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /* First tx packet */ +#define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /* Last tx packet */ +#define XAXIDMA_BD_CTRL_ALL_MASK 0x0C000000 /* All control bits */ + +#define XAXIDMA_DELAY_MASK 0xFF000000 /* Delay timeout counter */ +#define XAXIDMA_COALESCE_MASK 0x00FF0000 /* Coalesce counter */ + +#define XAXIDMA_DELAY_SHIFT 24 +#define XAXIDMA_COALESCE_SHIFT 16 + +#define XAXIDMA_IRQ_IOC_MASK 0x00001000 /* Completion intr */ +#define XAXIDMA_IRQ_DELAY_MASK 0x00002000 /* Delay interrupt */ +#define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /* Error interrupt */ +#define XAXIDMA_IRQ_ALL_MASK 0x00007000 /* All interrupts */ + +/* Default TX/RX Threshold and waitbound values for SGDMA mode */ +#define XAXIDMA_DFT_TX_THRESHOLD 24 +#define XAXIDMA_DFT_TX_WAITBOUND 254 +#define XAXIDMA_DFT_RX_THRESHOLD 24 +#define XAXIDMA_DFT_RX_WAITBOUND 254 + +#define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /* First tx packet */ +#define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /* Last tx packet */ +#define XAXIDMA_BD_CTRL_ALL_MASK 0x0C000000 /* All control bits */ + +#define XAXIDMA_BD_STS_ACTUAL_LEN_MASK 0x007FFFFF /* Actual len */ +#define XAXIDMA_BD_STS_COMPLETE_MASK 0x80000000 /* Completed */ +#define XAXIDMA_BD_STS_DEC_ERR_MASK 0x40000000 /* Decode error */ +#define XAXIDMA_BD_STS_SLV_ERR_MASK 0x20000000 /* Slave error */ +#define XAXIDMA_BD_STS_INT_ERR_MASK 0x10000000 /* Internal err */ +#define XAXIDMA_BD_STS_ALL_ERR_MASK 0x70000000 /* All errors */ +#define XAXIDMA_BD_STS_RXSOF_MASK 0x08000000 /* First rx pkt */ +#define XAXIDMA_BD_STS_RXEOF_MASK 0x04000000 /* Last rx pkt */ +#define XAXIDMA_BD_STS_ALL_MASK 0xFC000000 /* All status bits */ + +#define XAXIDMA_BD_MINIMUM_ALIGNMENT 0x40 + +/* Axi Ethernet registers definition */ +#define XAE_RAF_OFFSET 0x00000000 /* Reset and Address filter */ +#define XAE_TPF_OFFSET 0x00000004 /* Tx Pause Frame */ +#define XAE_IFGP_OFFSET 0x00000008 /* Tx Inter-frame gap adjustment*/ +#define XAE_IS_OFFSET 0x0000000C /* Interrupt status */ +#define XAE_IP_OFFSET 0x00000010 /* Interrupt pending */ +#define XAE_IE_OFFSET 0x00000014 /* Interrupt enable */ +#define XAE_TTAG_OFFSET 0x00000018 /* Tx VLAN TAG */ +#define XAE_RTAG_OFFSET 0x0000001C /* Rx VLAN TAG */ +#define XAE_UAWL_OFFSET 0x00000020 /* Unicast address word lower */ +#define XAE_UAWU_OFFSET 0x00000024 /* Unicast address word upper */ +#define XAE_TPID0_OFFSET 0x00000028 /* VLAN TPID0 register */ +#define XAE_TPID1_OFFSET 0x0000002C /* VLAN TPID1 register */ +#define XAE_PPST_OFFSET 0x00000030 /* PCS PMA Soft Temac Status Reg */ +#define XAE_RCW0_OFFSET 0x00000400 /* Rx Configuration Word 0 */ +#define XAE_RCW1_OFFSET 0x00000404 /* Rx Configuration Word 1 */ +#define XAE_TC_OFFSET 0x00000408 /* Tx Configuration */ +#define XAE_FCC_OFFSET 0x0000040C /* Flow Control Configuration */ +#define XAE_EMMC_OFFSET 0x00000410 /* EMAC mode configuration */ +#define XAE_PHYC_OFFSET 0x00000414 /* RGMII/SGMII configuration */ +#define XAE_MDIO_MC_OFFSET 0x00000500 /* MII Management Config */ +#define XAE_MDIO_MCR_OFFSET 0x00000504 /* MII Management Control */ +#define XAE_MDIO_MWD_OFFSET 0x00000508 /* MII Management Write Data */ +#define XAE_MDIO_MRD_OFFSET 0x0000050C /* MII Management Read Data */ +#define XAE_MDIO_MIS_OFFSET 0x00000600 /* MII Management Interrupt Status */ +#define XAE_MDIO_MIP_OFFSET 0x00000620 /* MII Mgmt Interrupt Pending + * register offset */ +#define XAE_MDIO_MIE_OFFSET 0x00000640 /* MII Management Interrupt Enable + * register offset */ +#define XAE_MDIO_MIC_OFFSET 0x00000660 /* MII Management Interrupt Clear + * register offset. */ +#define XAE_UAW0_OFFSET 0x00000700 /* Unicast address word 0 */ +#define XAE_UAW1_OFFSET 0x00000704 /* Unicast address word 1 */ +#define XAE_FMI_OFFSET 0x00000708 /* Filter Mask Index */ +#define XAE_AF0_OFFSET 0x00000710 /* Address Filter 0 */ +#define XAE_AF1_OFFSET 0x00000714 /* Address Filter 1 */ + +#define XAE_TX_VLAN_DATA_OFFSET 0x00004000 /* TX VLAN data table address */ +#define XAE_RX_VLAN_DATA_OFFSET 0x00008000 /* RX VLAN data table address */ +#define XAE_MCAST_TABLE_OFFSET 0x00020000 /* Multicast table address */ + +/* Bit Masks for Axi Ethernet RAF register */ +#define XAE_RAF_MCSTREJ_MASK 0x00000002 /* Reject receive multicast + * destination address */ +#define XAE_RAF_BCSTREJ_MASK 0x00000004 /* Reject receive broadcast + * destination address */ +#define XAE_RAF_TXVTAGMODE_MASK 0x00000018 /* Tx VLAN TAG mode */ +#define XAE_RAF_RXVTAGMODE_MASK 0x00000060 /* Rx VLAN TAG mode */ +#define XAE_RAF_TXVSTRPMODE_MASK 0x00000180 /* Tx VLAN STRIP mode */ +#define XAE_RAF_RXVSTRPMODE_MASK 0x00000600 /* Rx VLAN STRIP mode */ +#define XAE_RAF_NEWFNCENBL_MASK 0x00000800 /* New function mode */ +#define XAE_RAF_EMULTIFLTRENBL_MASK 0x00001000 /* Exteneded Multicast + * Filtering mode + */ +#define XAE_RAF_STATSRST_MASK 0x00002000 /* Stats. Counter Reset */ +#define XAE_RAF_RXBADFRMEN_MASK 0x00004000 /* Recv Bad Frame Enable */ +#define XAE_RAF_TXVTAGMODE_SHIFT 3 /* Tx Tag mode shift bits */ +#define XAE_RAF_RXVTAGMODE_SHIFT 5 /* Rx Tag mode shift bits */ +#define XAE_RAF_TXVSTRPMODE_SHIFT 7 /* Tx strip mode shift bits*/ +#define XAE_RAF_RXVSTRPMODE_SHIFT 9 /* Rx Strip mode shift bits*/ + +/* Bit Masks for Axi Ethernet TPF and IFGP registers */ +#define XAE_TPF_TPFV_MASK 0x0000FFFF /* Tx pause frame value */ +#define XAE_IFGP0_IFGP_MASK 0x0000007F /* Transmit inter-frame + * gap adjustment value */ + +/* Bit Masks for Axi Ethernet IS, IE and IP registers, Same masks apply + * for all 3 registers. */ +#define XAE_INT_HARDACSCMPLT_MASK 0x00000001 /* Hard register access + * complete */ +#define XAE_INT_AUTONEG_MASK 0x00000002 /* Auto negotiation + * complete */ +#define XAE_INT_RXCMPIT_MASK 0x00000004 /* Rx complete */ +#define XAE_INT_RXRJECT_MASK 0x00000008 /* Rx frame rejected */ +#define XAE_INT_RXFIFOOVR_MASK 0x00000010 /* Rx fifo overrun */ +#define XAE_INT_TXCMPIT_MASK 0x00000020 /* Tx complete */ +#define XAE_INT_RXDCMLOCK_MASK 0x00000040 /* Rx Dcm Lock */ +#define XAE_INT_MGTRDY_MASK 0x00000080 /* MGT clock Lock */ +#define XAE_INT_PHYRSTCMPLT_MASK 0x00000100 /* Phy Reset complete */ +#define XAE_INT_ALL_MASK 0x0000003F /* All the ints */ + +#define XAE_INT_RECV_ERROR_MASK \ + (XAE_INT_RXRJECT_MASK | XAE_INT_RXFIFOOVR_MASK) /* INT bits that + * indicate receive + * errors */ + +/* Bit masks for Axi Ethernet VLAN TPID Word 0 register */ +#define XAE_TPID_0_MASK 0x0000FFFF /* TPID 0 */ +#define XAE_TPID_1_MASK 0xFFFF0000 /* TPID 1 */ + +/* Bit masks for Axi Ethernet VLAN TPID Word 1 register */ +#define XAE_TPID_2_MASK 0x0000FFFF /* TPID 0 */ +#define XAE_TPID_3_MASK 0xFFFF0000 /* TPID 1 */ + +/* Bit masks for Axi Ethernet RCW1 register */ +#define XAE_RCW1_RST_MASK 0x80000000 /* Reset */ +#define XAE_RCW1_JUM_MASK 0x40000000 /* Jumbo frame enable */ +#define XAE_RCW1_FCS_MASK 0x20000000 /* In-Band FCS enable + * (FCS not stripped) */ +#define XAE_RCW1_RX_MASK 0x10000000 /* Receiver enable */ +#define XAE_RCW1_VLAN_MASK 0x08000000 /* VLAN frame enable */ +#define XAE_RCW1_LT_DIS_MASK 0x02000000 /* Length/type field valid check + * disable */ +#define XAE_RCW1_CL_DIS_MASK 0x01000000 /* Control frame Length check + * disable */ +#define XAE_RCW1_PAUSEADDR_MASK 0x0000FFFF /* Pause frame source address + * bits [47:32]. Bits [31:0] are + * stored in register RCW0 */ + +/* Bit masks for Axi Ethernet TC register */ +#define XAE_TC_RST_MASK 0x80000000 /* Reset */ +#define XAE_TC_JUM_MASK 0x40000000 /* Jumbo frame enable */ +#define XAE_TC_FCS_MASK 0x20000000 /* In-Band FCS enable + * (FCS not generated) */ +#define XAE_TC_TX_MASK 0x10000000 /* Transmitter enable */ +#define XAE_TC_VLAN_MASK 0x08000000 /* VLAN frame enable */ +#define XAE_TC_IFG_MASK 0x02000000 /* Inter-frame gap adjustment + * enable */ + +/* Bit masks for Axi Ethernet FCC register */ +#define XAE_FCC_FCRX_MASK 0x20000000 /* Rx flow control enable */ +#define XAE_FCC_FCTX_MASK 0x40000000 /* Tx flow control enable */ + +/* Bit masks for Axi Ethernet EMMC register */ +#define XAE_EMMC_LINKSPEED_MASK 0xC0000000 /* Link speed */ +#define XAE_EMMC_RGMII_MASK 0x20000000 /* RGMII mode enable */ +#define XAE_EMMC_SGMII_MASK 0x10000000 /* SGMII mode enable */ +#define XAE_EMMC_GPCS_MASK 0x08000000 /* 1000BaseX mode enable */ +#define XAE_EMMC_HOST_MASK 0x04000000 /* Host interface enable */ +#define XAE_EMMC_TX16BIT 0x02000000 /* 16 bit Tx client enable */ +#define XAE_EMMC_RX16BIT 0x01000000 /* 16 bit Rx client enable */ +#define XAE_EMMC_LINKSPD_10 0x00000000 /* Link Speed mask for 10 Mbit */ +#define XAE_EMMC_LINKSPD_100 0x40000000 /* Link Speed mask for 100 Mbit */ +#define XAE_EMMC_LINKSPD_1000 0x80000000 /* Link Speed mask for 1000 Mbit */ + +/* Bit masks for Axi Ethernet PHYC register */ +#define XAE_PHYC_SGMIILINKSPEED_MASK 0xC0000000 /* SGMII link speed mask*/ +#define XAE_PHYC_RGMIILINKSPEED_MASK 0x0000000C /* RGMII link speed */ +#define XAE_PHYC_RGMIIHD_MASK 0x00000002 /* RGMII Half-duplex */ +#define XAE_PHYC_RGMIILINK_MASK 0x00000001 /* RGMII link status */ +#define XAE_PHYC_RGLINKSPD_10 0x00000000 /* RGMII link 10 Mbit */ +#define XAE_PHYC_RGLINKSPD_100 0x00000004 /* RGMII link 100 Mbit */ +#define XAE_PHYC_RGLINKSPD_1000 0x00000008 /* RGMII link 1000 Mbit */ +#define XAE_PHYC_SGLINKSPD_10 0x00000000 /* SGMII link 10 Mbit */ +#define XAE_PHYC_SGLINKSPD_100 0x40000000 /* SGMII link 100 Mbit */ +#define XAE_PHYC_SGLINKSPD_1000 0x80000000 /* SGMII link 1000 Mbit */ + +/* Bit masks for Axi Ethernet MDIO interface MC register */ +#define XAE_MDIO_MC_MDIOEN_MASK 0x00000040 /* MII management enable */ +#define XAE_MDIO_MC_CLOCK_DIVIDE_MAX 0x3F /* Maximum MDIO divisor */ + +/* Bit masks for Axi Ethernet MDIO interface MCR register */ +#define XAE_MDIO_MCR_PHYAD_MASK 0x1F000000 /* Phy Address Mask */ +#define XAE_MDIO_MCR_PHYAD_SHIFT 24 /* Phy Address Shift */ +#define XAE_MDIO_MCR_REGAD_MASK 0x001F0000 /* Reg Address Mask */ +#define XAE_MDIO_MCR_REGAD_SHIFT 16 /* Reg Address Shift */ +#define XAE_MDIO_MCR_OP_MASK 0x0000C000 /* Operation Code Mask */ +#define XAE_MDIO_MCR_OP_SHIFT 13 /* Operation Code Shift */ +#define XAE_MDIO_MCR_OP_READ_MASK 0x00008000 /* Op Code Read Mask */ +#define XAE_MDIO_MCR_OP_WRITE_MASK 0x00004000 /* Op Code Write Mask */ +#define XAE_MDIO_MCR_INITIATE_MASK 0x00000800 /* Ready Mask */ +#define XAE_MDIO_MCR_READY_MASK 0x00000080 /* Ready Mask */ + +/* Bit masks for Axi Ethernet MDIO interface MIS, MIP, MIE, MIC registers */ +#define XAE_MDIO_INT_MIIM_RDY_MASK 0x00000001 /* MIIM Interrupt */ + +/* Bit masks for Axi Ethernet UAW1 register */ +#define XAE_UAW1_UNICASTADDR_MASK 0x0000FFFF /* Station address bits + * [47:32]; Station address + * bits [31:0] are stored in + * register UAW0 */ + +/* Bit masks for Axi Ethernet FMI register */ +#define XAE_FMI_PM_MASK 0x80000000 /* Promis. mode enable */ +#define XAE_FMI_IND_MASK 0x00000003 /* Index Mask */ + +#define XAE_MDIO_DIV_DFT 29 /* Default MDIO clock divisor */ + +/* Defines for different options for C_PHY_TYPE parameter in Axi Ethernet IP */ +#define XAE_PHY_TYPE_MII 0 +#define XAE_PHY_TYPE_GMII 1 +#define XAE_PHY_TYPE_RGMII_1_3 2 +#define XAE_PHY_TYPE_RGMII_2_0 3 +#define XAE_PHY_TYPE_SGMII 4 +#define XAE_PHY_TYPE_1000BASE_X 5 + +#define XAE_MULTICAST_CAM_TABLE_NUM 4 /* Total number of entries in the + * hardware multicast table. */ + +/* Axi Ethernet Synthesis features */ +#define XAE_FEATURE_PARTIAL_RX_CSUM (1 << 0) +#define XAE_FEATURE_PARTIAL_TX_CSUM (1 << 1) +#define XAE_FEATURE_FULL_RX_CSUM (1 << 2) +#define XAE_FEATURE_FULL_TX_CSUM (1 << 3) + +#define XAE_NO_CSUM_OFFLOAD 0 + +#define XAE_FULL_CSUM_STATUS_MASK 0x00000038 +#define XAE_IP_UDP_CSUM_VALIDATED 0x00000003 +#define XAE_IP_TCP_CSUM_VALIDATED 0x00000002 + +#define DELAY_OF_ONE_MILLISEC 1000 + +/** + * struct axidma_bd - Axi Dma buffer descriptor layout + * @next: MM2S/S2MM Next Descriptor Pointer + * @reserved1: Reserved and not used + * @phys: MM2S/S2MM Buffer Address + * @reserved2: Reserved and not used + * @reserved3: Reserved and not used + * @reserved4: Reserved and not used + * @cntrl: MM2S/S2MM Control value + * @status: MM2S/S2MM Status value + * @app0: MM2S/S2MM User Application Field 0. + * @app1: MM2S/S2MM User Application Field 1. + * @app2: MM2S/S2MM User Application Field 2. + * @app3: MM2S/S2MM User Application Field 3. + * @app4: MM2S/S2MM User Application Field 4. + * @sw_id_offset: MM2S/S2MM Sw ID + * @reserved5: Reserved and not used + * @reserved6: Reserved and not used + */ +struct axidma_bd { + u32 next; /* Physical address of next buffer descriptor */ + u32 reserved1; + u32 phys; + u32 reserved2; + u32 reserved3; + u32 reserved4; + u32 cntrl; + u32 status; + u32 app0; + u32 app1; /* TX start << 16 | insert */ + u32 app2; /* TX csum seed */ + u32 app3; + u32 app4; + u32 sw_id_offset; + u32 reserved5; + u32 reserved6; +}; + +/** + * struct axienet_local - axienet private per device data + * @ndev: Pointer for net_device to which it will be attached. + * @dev: Pointer to device structure + * @phy_dev: Pointer to PHY device structure attached to the axienet_local + * @phy_node: Pointer to device node structure + * @mii_bus: Pointer to MII bus structure + * @mdio_irqs: IRQs table for MDIO bus required in mii_bus structure + * @regs: Base address for the axienet_local device address space + * @dma_regs: Base address for the axidma device address space + * @dma_err_tasklet: Tasklet structure to process Axi DMA errors + * @tx_irq: Axidma TX IRQ number + * @rx_irq: Axidma RX IRQ number + * @temac_type: axienet type to identify between soft and hard temac + * @phy_type: Phy type to identify between MII/GMII/RGMII/SGMII/1000 Base-X + * @options: AxiEthernet option word + * @last_link: Phy link state in which the PHY was negotiated earlier + * @features: Stores the extended features supported by the axienet hw + * @tx_bd_v: Virtual address of the TX buffer descriptor ring + * @tx_bd_p: Physical address(start address) of the TX buffer descr. ring + * @rx_bd_v: Virtual address of the RX buffer descriptor ring + * @rx_bd_p: Physical address(start address) of the RX buffer descr. ring + * @tx_bd_ci: Stores the index of the Tx buffer descriptor in the ring being + * accessed currently. Used while alloc. BDs before a TX starts + * @tx_bd_tail: Stores the index of the Tx buffer descriptor in the ring being + * accessed currently. Used while processing BDs after the TX + * completed. + * @rx_bd_ci: Stores the index of the Rx buffer descriptor in the ring being + * accessed currently. + * @max_frm_size: Stores the maximum size of the frame that can be that + * Txed/Rxed in the existing hardware. If jumbo option is + * supported, the maximum frame size would be 9k. Else it is + * 1522 bytes (assuming support for basic VLAN) + * @jumbo_support: Stores hardware configuration for jumbo support. If hardware + * can handle jumbo packets, this entry will be 1, else 0. + */ +struct axienet_local { + struct net_device *ndev; + struct device *dev; + + /* Connection to PHY device */ + struct phy_device *phy_dev; /* Pointer to PHY device */ + struct device_node *phy_node; + + /* MDIO bus data */ + struct mii_bus *mii_bus; /* MII bus reference */ + int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */ + + /* IO registers, dma functions and IRQs */ + void __iomem *regs; + void __iomem *dma_regs; + + struct tasklet_struct dma_err_tasklet; + + int tx_irq; + int rx_irq; + u32 temac_type; + u32 phy_type; + + u32 options; /* Current options word */ + u32 last_link; + u32 features; + + /* Buffer descriptors */ + struct axidma_bd *tx_bd_v; + dma_addr_t tx_bd_p; + struct axidma_bd *rx_bd_v; + dma_addr_t rx_bd_p; + u32 tx_bd_ci; + u32 tx_bd_tail; + u32 rx_bd_ci; + + u32 max_frm_size; + u32 jumbo_support; + + int csum_offload_on_tx_path; + int csum_offload_on_rx_path; + + u32 coalesce_count_rx; + u32 coalesce_count_tx; +}; + +/** + * struct axiethernet_option - Used to set axi ethernet hardware options + * @opt: Option to be set. + * @reg: Register offset to be written for setting the option + * @m_or: Mask to be ORed for setting the option in the register + */ +struct axienet_option { + u32 opt; + u32 reg; + u32 m_or; +}; + +/** + * axienet_ior - Memory mapped Axi Ethernet register read + * @lp: Pointer to axienet local structure + * @offset: Address offset from the base address of Axi Ethernet core + * + * returns: The contents of the Axi Ethernet register + * + * This function returns the contents of the corresponding register. + */ +static inline u32 axienet_ior(struct axienet_local *lp, off_t offset) +{ + return in_be32(lp->regs + offset); +} + +/** + * axienet_iow - Memory mapped Axi Ethernet register write + * @lp: Pointer to axienet local structure + * @offset: Address offset from the base address of Axi Ethernet core + * @value: Value to be written into the Axi Ethernet register + * + * This function writes the desired value into the corresponding Axi Ethernet + * register. + */ +static inline void axienet_iow(struct axienet_local *lp, off_t offset, + u32 value) +{ + out_be32((lp->regs + offset), value); +} + +/* Function prototypes visible in xilinx_axienet_mdio.c for other files */ +int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np); +int axienet_mdio_wait_until_ready(struct axienet_local *lp); +void axienet_mdio_teardown(struct axienet_local *lp); + +#endif /* XILINX_AXI_ENET_H */ diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c new file mode 100644 index 000000000000..a7cf00438a36 --- /dev/null +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -0,0 +1,1680 @@ +/* + * Xilinx Axi Ethernet device driver + * + * Copyright (c) 2008 Nissin Systems Co., Ltd., Yoshio Kashiwagi + * Copyright (c) 2005-2008 DLA Systems, David H. Lynch Jr. <dhlii@dlasys.net> + * Copyright (c) 2008-2009 Secret Lab Technologies Ltd. + * Copyright (c) 2010 Xilinx, Inc. All rights reserved. + * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch> + * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch> + * + * This is a driver for the Xilinx Axi Ethernet which is used in the Virtex6 + * and Spartan6. + * + * TODO: + * - Add Axi Fifo support. + * - Factor out Axi DMA code into separate driver. + * - Test and fix basic multicast filtering. + * - Add support for extended multicast filtering. + * - Test basic VLAN support. + * - Add support for extended VLAN support. + */ + +#include <linux/delay.h> +#include <linux/etherdevice.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/of_mdio.h> +#include <linux/of_platform.h> +#include <linux/of_address.h> +#include <linux/skbuff.h> +#include <linux/spinlock.h> +#include <linux/phy.h> +#include <linux/mii.h> +#include <linux/ethtool.h> + +#include "xilinx_axienet.h" + +/* Descriptors defines for Tx and Rx DMA - 2^n for the best performance */ +#define TX_BD_NUM 64 +#define RX_BD_NUM 128 + +/* Must be shorter than length of ethtool_drvinfo.driver field to fit */ +#define DRIVER_NAME "xaxienet" +#define DRIVER_DESCRIPTION "Xilinx Axi Ethernet driver" +#define DRIVER_VERSION "1.00a" + +#define AXIENET_REGS_N 32 + +/* Match table for of_platform binding */ +static struct of_device_id axienet_of_match[] __devinitdata = { + { .compatible = "xlnx,axi-ethernet-1.00.a", }, + { .compatible = "xlnx,axi-ethernet-1.01.a", }, + { .compatible = "xlnx,axi-ethernet-2.01.a", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, axienet_of_match); + +/* Option table for setting up Axi Ethernet hardware options */ +static struct axienet_option axienet_options[] = { + /* Turn on jumbo packet support for both Rx and Tx */ + { + .opt = XAE_OPTION_JUMBO, + .reg = XAE_TC_OFFSET, + .m_or = XAE_TC_JUM_MASK, + }, { + .opt = XAE_OPTION_JUMBO, + .reg = XAE_RCW1_OFFSET, + .m_or = XAE_RCW1_JUM_MASK, + }, { /* Turn on VLAN packet support for both Rx and Tx */ + .opt = XAE_OPTION_VLAN, + .reg = XAE_TC_OFFSET, + .m_or = XAE_TC_VLAN_MASK, + }, { + .opt = XAE_OPTION_VLAN, + .reg = XAE_RCW1_OFFSET, + .m_or = XAE_RCW1_VLAN_MASK, + }, { /* Turn on FCS stripping on receive packets */ + .opt = XAE_OPTION_FCS_STRIP, + .reg = XAE_RCW1_OFFSET, + .m_or = XAE_RCW1_FCS_MASK, + }, { /* Turn on FCS insertion on transmit packets */ + .opt = XAE_OPTION_FCS_INSERT, + .reg = XAE_TC_OFFSET, + .m_or = XAE_TC_FCS_MASK, + }, { /* Turn off length/type field checking on receive packets */ + .opt = XAE_OPTION_LENTYPE_ERR, + .reg = XAE_RCW1_OFFSET, + .m_or = XAE_RCW1_LT_DIS_MASK, + }, { /* Turn on Rx flow control */ + .opt = XAE_OPTION_FLOW_CONTROL, + .reg = XAE_FCC_OFFSET, + .m_or = XAE_FCC_FCRX_MASK, + }, { /* Turn on Tx flow control */ + .opt = XAE_OPTION_FLOW_CONTROL, + .reg = XAE_FCC_OFFSET, + .m_or = XAE_FCC_FCTX_MASK, + }, { /* Turn on promiscuous frame filtering */ + .opt = XAE_OPTION_PROMISC, + .reg = XAE_FMI_OFFSET, + .m_or = XAE_FMI_PM_MASK, + }, { /* Enable transmitter */ + .opt = XAE_OPTION_TXEN, + .reg = XAE_TC_OFFSET, + .m_or = XAE_TC_TX_MASK, + }, { /* Enable receiver */ + .opt = XAE_OPTION_RXEN, + .reg = XAE_RCW1_OFFSET, + .m_or = XAE_RCW1_RX_MASK, + }, + {} +}; + +/** + * axienet_dma_in32 - Memory mapped Axi DMA register read + * @lp: Pointer to axienet local structure + * @reg: Address offset from the base address of the Axi DMA core + * + * returns: The contents of the Axi DMA register + * + * This function returns the contents of the corresponding Axi DMA register. + */ +static inline u32 axienet_dma_in32(struct axienet_local *lp, off_t reg) +{ + return in_be32(lp->dma_regs + reg); +} + +/** + * axienet_dma_out32 - Memory mapped Axi DMA register write. + * @lp: Pointer to axienet local structure + * @reg: Address offset from the base address of the Axi DMA core + * @value: Value to be written into the Axi DMA register + * + * This function writes the desired value into the corresponding Axi DMA + * register. + */ +static inline void axienet_dma_out32(struct axienet_local *lp, + off_t reg, u32 value) +{ + out_be32((lp->dma_regs + reg), value); +} + +/** + * axienet_dma_bd_release - Release buffer descriptor rings + * @ndev: Pointer to the net_device structure + * + * This function is used to release the descriptors allocated in + * axienet_dma_bd_init. axienet_dma_bd_release is called when Axi Ethernet + * driver stop api is called. + */ +static void axienet_dma_bd_release(struct net_device *ndev) +{ + int i; + struct axienet_local *lp = netdev_priv(ndev); + + for (i = 0; i < RX_BD_NUM; i++) { + dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys, + lp->max_frm_size, DMA_FROM_DEVICE); + dev_kfree_skb((struct sk_buff *) + (lp->rx_bd_v[i].sw_id_offset)); + } + + if (lp->rx_bd_v) { + dma_free_coherent(ndev->dev.parent, + sizeof(*lp->rx_bd_v) * RX_BD_NUM, + lp->rx_bd_v, + lp->rx_bd_p); + } + if (lp->tx_bd_v) { + dma_free_coherent(ndev->dev.parent, + sizeof(*lp->tx_bd_v) * TX_BD_NUM, + lp->tx_bd_v, + lp->tx_bd_p); + } +} + +/** + * axienet_dma_bd_init - Setup buffer descriptor rings for Axi DMA + * @ndev: Pointer to the net_device structure + * + * returns: 0, on success + * -ENOMEM, on failure + * + * This function is called to initialize the Rx and Tx DMA descriptor + * rings. This initializes the descriptors with required default values + * and is called when Axi Ethernet driver reset is called. + */ +static int axienet_dma_bd_init(struct net_device *ndev) +{ + u32 cr; + int i; + struct sk_buff *skb; + struct axienet_local *lp = netdev_priv(ndev); + + /* Reset the indexes which are used for accessing the BDs */ + lp->tx_bd_ci = 0; + lp->tx_bd_tail = 0; + lp->rx_bd_ci = 0; + + /* + * Allocate the Tx and Rx buffer descriptors. + */ + lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*lp->tx_bd_v) * TX_BD_NUM, + &lp->tx_bd_p, + GFP_KERNEL); + if (!lp->tx_bd_v) { + dev_err(&ndev->dev, "unable to allocate DMA Tx buffer " + "descriptors"); + goto out; + } + + lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent, + sizeof(*lp->rx_bd_v) * RX_BD_NUM, + &lp->rx_bd_p, + GFP_KERNEL); + if (!lp->rx_bd_v) { + dev_err(&ndev->dev, "unable to allocate DMA Rx buffer " + "descriptors"); + goto out; + } + + memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM); + for (i = 0; i < TX_BD_NUM; i++) { + lp->tx_bd_v[i].next = lp->tx_bd_p + + sizeof(*lp->tx_bd_v) * + ((i + 1) % TX_BD_NUM); + } + + memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM); + for (i = 0; i < RX_BD_NUM; i++) { + lp->rx_bd_v[i].next = lp->rx_bd_p + + sizeof(*lp->rx_bd_v) * + ((i + 1) % RX_BD_NUM); + + skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size); + if (!skb) { + dev_err(&ndev->dev, "alloc_skb error %d\n", i); + goto out; + } + + lp->rx_bd_v[i].sw_id_offset = (u32) skb; + lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent, + skb->data, + lp->max_frm_size, + DMA_FROM_DEVICE); + lp->rx_bd_v[i].cntrl = lp->max_frm_size; + } + + /* Start updating the Rx channel control register */ + cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); + /* Update the interrupt coalesce count */ + cr = ((cr & ~XAXIDMA_COALESCE_MASK) | + ((lp->coalesce_count_rx) << XAXIDMA_COALESCE_SHIFT)); + /* Update the delay timer count */ + cr = ((cr & ~XAXIDMA_DELAY_MASK) | + (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT)); + /* Enable coalesce, delay timer and error interrupts */ + cr |= XAXIDMA_IRQ_ALL_MASK; + /* Write to the Rx channel control register */ + axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr); + + /* Start updating the Tx channel control register */ + cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); + /* Update the interrupt coalesce count */ + cr = (((cr & ~XAXIDMA_COALESCE_MASK)) | + ((lp->coalesce_count_tx) << XAXIDMA_COALESCE_SHIFT)); + /* Update the delay timer count */ + cr = (((cr & ~XAXIDMA_DELAY_MASK)) | + (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT)); + /* Enable coalesce, delay timer and error interrupts */ + cr |= XAXIDMA_IRQ_ALL_MASK; + /* Write to the Tx channel control register */ + axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr); + + /* Populate the tail pointer and bring the Rx Axi DMA engine out of + * halted state. This will make the Rx side ready for reception.*/ + axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p); + cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); + axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, + cr | XAXIDMA_CR_RUNSTOP_MASK); + axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p + + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); + + /* Write to the RS (Run-stop) bit in the Tx channel control register. + * Tx channel is now ready to run. But only after we write to the + * tail pointer register that the Tx channel will start transmitting */ + axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p); + cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); + axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, + cr | XAXIDMA_CR_RUNSTOP_MASK); + + return 0; +out: + axienet_dma_bd_release(ndev); + return -ENOMEM; +} + +/** + * axienet_set_mac_address - Write the MAC address + * @ndev: Pointer to the net_device structure + * @address: 6 byte Address to be written as MAC address + * + * This function is called to initialize the MAC address of the Axi Ethernet + * core. It writes to the UAW0 and UAW1 registers of the core. + */ +static void axienet_set_mac_address(struct net_device *ndev, void *address) +{ + struct axienet_local *lp = netdev_priv(ndev); + + if (address) + memcpy(ndev->dev_addr, address, ETH_ALEN); + if (!is_valid_ether_addr(ndev->dev_addr)) + random_ether_addr(ndev->dev_addr); + + /* Set up unicast MAC address filter set its mac address */ + axienet_iow(lp, XAE_UAW0_OFFSET, + (ndev->dev_addr[0]) | + (ndev->dev_addr[1] << 8) | + (ndev->dev_addr[2] << 16) | + (ndev->dev_addr[3] << 24)); + axienet_iow(lp, XAE_UAW1_OFFSET, + (((axienet_ior(lp, XAE_UAW1_OFFSET)) & + ~XAE_UAW1_UNICASTADDR_MASK) | + (ndev->dev_addr[4] | + (ndev->dev_addr[5] << 8)))); +} + +/** + * netdev_set_mac_address - Write the MAC address (from outside the driver) + * @ndev: Pointer to the net_device structure + * @p: 6 byte Address to be written as MAC address + * + * returns: 0 for all conditions. Presently, there is no failure case. + * + * This function is called to initialize the MAC address of the Axi Ethernet + * core. It calls the core specific axienet_set_mac_address. This is the + * function that goes into net_device_ops structure entry ndo_set_mac_address. + */ +static int netdev_set_mac_address(struct net_device *ndev, void *p) +{ + struct sockaddr *addr = p; + axienet_set_mac_address(ndev, addr->sa_data); + return 0; +} + +/** + * axienet_set_multicast_list - Prepare the multicast table + * @ndev: Pointer to the net_device structure + * + * This function is called to initialize the multicast table during + * initialization. The Axi Ethernet basic multicast support has a four-entry + * multicast table which is initialized here. Additionally this function + * goes into the net_device_ops structure entry ndo_set_multicast_list. This + * means whenever the multicast table entries need to be updated this + * function gets called. + */ +static void axienet_set_multicast_list(struct net_device *ndev) +{ + int i; + u32 reg, af0reg, af1reg; + struct axienet_local *lp = netdev_priv(ndev); + + if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) || + netdev_mc_count(ndev) > XAE_MULTICAST_CAM_TABLE_NUM) { + /* We must make the kernel realize we had to move into + * promiscuous mode. If it was a promiscuous mode request + * the flag is already set. If not we set it. */ + ndev->flags |= IFF_PROMISC; + reg = axienet_ior(lp, XAE_FMI_OFFSET); + reg |= XAE_FMI_PM_MASK; + axienet_iow(lp, XAE_FMI_OFFSET, reg); + dev_info(&ndev->dev, "Promiscuous mode enabled.\n"); + } else if (!netdev_mc_empty(ndev)) { + struct netdev_hw_addr *ha; + + i = 0; + netdev_for_each_mc_addr(ha, ndev) { + if (i >= XAE_MULTICAST_CAM_TABLE_NUM) + break; + + af0reg = (ha->addr[0]); + af0reg |= (ha->addr[1] << 8); + af0reg |= (ha->addr[2] << 16); + af0reg |= (ha->addr[3] << 24); + + af1reg = (ha->addr[4]); + af1reg |= (ha->addr[5] << 8); + + reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00; + reg |= i; + + axienet_iow(lp, XAE_FMI_OFFSET, reg); + axienet_iow(lp, XAE_AF0_OFFSET, af0reg); + axienet_iow(lp, XAE_AF1_OFFSET, af1reg); + i++; + } + } else { + reg = axienet_ior(lp, XAE_FMI_OFFSET); + reg &= ~XAE_FMI_PM_MASK; + + axienet_iow(lp, XAE_FMI_OFFSET, reg); + + for (i = 0; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) { + reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00; + reg |= i; + + axienet_iow(lp, XAE_FMI_OFFSET, reg); + axienet_iow(lp, XAE_AF0_OFFSET, 0); + axienet_iow(lp, XAE_AF1_OFFSET, 0); + } + + dev_info(&ndev->dev, "Promiscuous mode disabled.\n"); + } +} + +/** + * axienet_setoptions - Set an Axi Ethernet option + * @ndev: Pointer to the net_device structure + * @options: Option to be enabled/disabled + * + * The Axi Ethernet core has multiple features which can be selectively turned + * on or off. The typical options could be jumbo frame option, basic VLAN + * option, promiscuous mode option etc. This function is used to set or clear + * these options in the Axi Ethernet hardware. This is done through + * axienet_option structure . + */ +static void axienet_setoptions(struct net_device *ndev, u32 options) +{ + int reg; + struct axienet_local *lp = netdev_priv(ndev); + struct axienet_option *tp = &axienet_options[0]; + + while (tp->opt) { + reg = ((axienet_ior(lp, tp->reg)) & ~(tp->m_or)); + if (options & tp->opt) + reg |= tp->m_or; + axienet_iow(lp, tp->reg, reg); + tp++; + } + + lp->options |= options; +} + +static void __axienet_device_reset(struct axienet_local *lp, + struct device *dev, off_t offset) +{ + u32 timeout; + /* Reset Axi DMA. This would reset Axi Ethernet core as well. The reset + * process of Axi DMA takes a while to complete as all pending + * commands/transfers will be flushed or completed during this + * reset process. */ + axienet_dma_out32(lp, offset, XAXIDMA_CR_RESET_MASK); + timeout = DELAY_OF_ONE_MILLISEC; + while (axienet_dma_in32(lp, offset) & XAXIDMA_CR_RESET_MASK) { + udelay(1); + if (--timeout == 0) { + dev_err(dev, "axienet_device_reset DMA " + "reset timeout!\n"); + break; + } + } +} + +/** + * axienet_device_reset - Reset and initialize the Axi Ethernet hardware. + * @ndev: Pointer to the net_device structure + * + * This function is called to reset and initialize the Axi Ethernet core. This + * is typically called during initialization. It does a reset of the Axi DMA + * Rx/Tx channels and initializes the Axi DMA BDs. Since Axi DMA reset lines + * areconnected to Axi Ethernet reset lines, this in turn resets the Axi + * Ethernet core. No separate hardware reset is done for the Axi Ethernet + * core. + */ +static void axienet_device_reset(struct net_device *ndev) +{ + u32 axienet_status; + struct axienet_local *lp = netdev_priv(ndev); + + __axienet_device_reset(lp, &ndev->dev, XAXIDMA_TX_CR_OFFSET); + __axienet_device_reset(lp, &ndev->dev, XAXIDMA_RX_CR_OFFSET); + + lp->max_frm_size = XAE_MAX_VLAN_FRAME_SIZE; + lp->options &= (~XAE_OPTION_JUMBO); + + if ((ndev->mtu > XAE_MTU) && + (ndev->mtu <= XAE_JUMBO_MTU) && + (lp->jumbo_support)) { + lp->max_frm_size = ndev->mtu + XAE_HDR_VLAN_SIZE + + XAE_TRL_SIZE; + lp->options |= XAE_OPTION_JUMBO; + } + + if (axienet_dma_bd_init(ndev)) { + dev_err(&ndev->dev, "axienet_device_reset descriptor " + "allocation failed\n"); + } + + axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET); + axienet_status &= ~XAE_RCW1_RX_MASK; + axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status); + + axienet_status = axienet_ior(lp, XAE_IP_OFFSET); + if (axienet_status & XAE_INT_RXRJECT_MASK) + axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK); + + axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK); + + /* Sync default options with HW but leave receiver and + * transmitter disabled.*/ + axienet_setoptions(ndev, lp->options & + ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); + axienet_set_mac_address(ndev, NULL); + axienet_set_multicast_list(ndev); + axienet_setoptions(ndev, lp->options); + + ndev->trans_start = jiffies; +} + +/** + * axienet_adjust_link - Adjust the PHY link speed/duplex. + * @ndev: Pointer to the net_device structure + * + * This function is called to change the speed and duplex setting after + * auto negotiation is done by the PHY. This is the function that gets + * registered with the PHY interface through the "of_phy_connect" call. + */ +static void axienet_adjust_link(struct net_device *ndev) +{ + u32 emmc_reg; + u32 link_state; + u32 setspeed = 1; + struct axienet_local *lp = netdev_priv(ndev); + struct phy_device *phy = lp->phy_dev; + + link_state = phy->speed | (phy->duplex << 1) | phy->link; + if (lp->last_link != link_state) { + if ((phy->speed == SPEED_10) || (phy->speed == SPEED_100)) { + if (lp->phy_type == XAE_PHY_TYPE_1000BASE_X) + setspeed = 0; + } else { + if ((phy->speed == SPEED_1000) && + (lp->phy_type == XAE_PHY_TYPE_MII)) + setspeed = 0; + } + + if (setspeed == 1) { + emmc_reg = axienet_ior(lp, XAE_EMMC_OFFSET); + emmc_reg &= ~XAE_EMMC_LINKSPEED_MASK; + + switch (phy->speed) { + case SPEED_1000: + emmc_reg |= XAE_EMMC_LINKSPD_1000; + break; + case SPEED_100: + emmc_reg |= XAE_EMMC_LINKSPD_100; + break; + case SPEED_10: + emmc_reg |= XAE_EMMC_LINKSPD_10; + break; + default: + dev_err(&ndev->dev, "Speed other than 10, 100 " + "or 1Gbps is not supported\n"); + break; + } + + axienet_iow(lp, XAE_EMMC_OFFSET, emmc_reg); + lp->last_link = link_state; + phy_print_status(phy); + } else { + dev_err(&ndev->dev, "Error setting Axi Ethernet " + "mac speed\n"); + } + } +} + +/** + * axienet_start_xmit_done - Invoked once a transmit is completed by the + * Axi DMA Tx channel. + * @ndev: Pointer to the net_device structure + * + * This function is invoked from the Axi DMA Tx isr to notify the completion + * of transmit operation. It clears fields in the corresponding Tx BDs and + * unmaps the corresponding buffer so that CPU can regain ownership of the + * buffer. It finally invokes "netif_wake_queue" to restart transmission if + * required. + */ +static void axienet_start_xmit_done(struct net_device *ndev) +{ + u32 size = 0; + u32 packets = 0; + struct axienet_local *lp = netdev_priv(ndev); + struct axidma_bd *cur_p; + unsigned int status = 0; + + cur_p = &lp->tx_bd_v[lp->tx_bd_ci]; + status = cur_p->status; + while (status & XAXIDMA_BD_STS_COMPLETE_MASK) { + dma_unmap_single(ndev->dev.parent, cur_p->phys, + (cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK), + DMA_TO_DEVICE); + if (cur_p->app4) + dev_kfree_skb_irq((struct sk_buff *)cur_p->app4); + /*cur_p->phys = 0;*/ + cur_p->app0 = 0; + cur_p->app1 = 0; + cur_p->app2 = 0; + cur_p->app4 = 0; + cur_p->status = 0; + + size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK; + packets++; + + lp->tx_bd_ci = ++lp->tx_bd_ci % TX_BD_NUM; + cur_p = &lp->tx_bd_v[lp->tx_bd_ci]; + status = cur_p->status; + } + + ndev->stats.tx_packets += packets; + ndev->stats.tx_bytes += size; + netif_wake_queue(ndev); +} + +/** + * axienet_check_tx_bd_space - Checks if a BD/group of BDs are currently busy + * @lp: Pointer to the axienet_local structure + * @num_frag: The number of BDs to check for + * + * returns: 0, on success + * NETDEV_TX_BUSY, if any of the descriptors are not free + * + * This function is invoked before BDs are allocated and transmission starts. + * This function returns 0 if a BD or group of BDs can be allocated for + * transmission. If the BD or any of the BDs are not free the function + * returns a busy status. This is invoked from axienet_start_xmit. + */ +static inline int axienet_check_tx_bd_space(struct axienet_local *lp, + int num_frag) +{ + struct axidma_bd *cur_p; + cur_p = &lp->tx_bd_v[(lp->tx_bd_tail + num_frag) % TX_BD_NUM]; + if (cur_p->status & XAXIDMA_BD_STS_ALL_MASK) + return NETDEV_TX_BUSY; + return 0; +} + +/** + * axienet_start_xmit - Starts the transmission. + * @skb: sk_buff pointer that contains data to be Txed. + * @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. The + * function uses the next available free BDs and populates their fields to + * start the transmission. Additionally if checksum offloading is supported, + * it populates AXI Stream Control fields with appropriate values. + */ +static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + u32 ii; + u32 num_frag; + u32 csum_start_off; + u32 csum_index_off; + skb_frag_t *frag; + dma_addr_t tail_p; + struct axienet_local *lp = netdev_priv(ndev); + struct axidma_bd *cur_p; + + num_frag = skb_shinfo(skb)->nr_frags; + cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; + + if (axienet_check_tx_bd_space(lp, num_frag)) { + if (!netif_queue_stopped(ndev)) + netif_stop_queue(ndev); + return NETDEV_TX_BUSY; + } + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (lp->features & XAE_FEATURE_FULL_TX_CSUM) { + /* Tx Full Checksum Offload Enabled */ + cur_p->app0 |= 2; + } else if (lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) { + csum_start_off = skb_transport_offset(skb); + csum_index_off = csum_start_off + skb->csum_offset; + /* Tx Partial Checksum Offload Enabled */ + cur_p->app0 |= 1; + cur_p->app1 = (csum_start_off << 16) | csum_index_off; + } + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + cur_p->app0 |= 2; /* Tx Full Checksum Offload Enabled */ + } + + cur_p->cntrl = skb_headlen(skb) | XAXIDMA_BD_CTRL_TXSOF_MASK; + cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); + + for (ii = 0; ii < num_frag; ii++) { + lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM; + cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; + frag = &skb_shinfo(skb)->frags[ii]; + cur_p->phys = dma_map_single(ndev->dev.parent, + skb_frag_address(frag), + skb_frag_size(frag), + DMA_TO_DEVICE); + cur_p->cntrl = skb_frag_size(frag); + } + + cur_p->cntrl |= XAXIDMA_BD_CTRL_TXEOF_MASK; + cur_p->app4 = (unsigned long)skb; + + tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail; + /* Start the transfer */ + axienet_dma_out32(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p); + lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM; + + return NETDEV_TX_OK; +} + +/** + * axienet_recv - Is called from Axi DMA Rx Isr to complete the received + * BD processing. + * @ndev: Pointer to net_device structure. + * + * This function is invoked from the Axi DMA Rx isr to process the Rx BDs. It + * does minimal processing and invokes "netif_rx" to complete further + * processing. + */ +static void axienet_recv(struct net_device *ndev) +{ + u32 length; + u32 csumstatus; + u32 size = 0; + u32 packets = 0; + dma_addr_t tail_p; + struct axienet_local *lp = netdev_priv(ndev); + struct sk_buff *skb, *new_skb; + struct axidma_bd *cur_p; + + tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci; + cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; + + while ((cur_p->status & XAXIDMA_BD_STS_COMPLETE_MASK)) { + skb = (struct sk_buff *) (cur_p->sw_id_offset); + length = cur_p->app4 & 0x0000FFFF; + + dma_unmap_single(ndev->dev.parent, cur_p->phys, + lp->max_frm_size, + DMA_FROM_DEVICE); + + skb_put(skb, length); + skb->protocol = eth_type_trans(skb, ndev); + /*skb_checksum_none_assert(skb);*/ + skb->ip_summed = CHECKSUM_NONE; + + /* if we're doing Rx csum offload, set it up */ + if (lp->features & XAE_FEATURE_FULL_RX_CSUM) { + csumstatus = (cur_p->app2 & + XAE_FULL_CSUM_STATUS_MASK) >> 3; + if ((csumstatus == XAE_IP_TCP_CSUM_VALIDATED) || + (csumstatus == XAE_IP_UDP_CSUM_VALIDATED)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + } + } else if ((lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) != 0 && + skb->protocol == __constant_htons(ETH_P_IP) && + skb->len > 64) { + skb->csum = be32_to_cpu(cur_p->app3 & 0xFFFF); + skb->ip_summed = CHECKSUM_COMPLETE; + } + + netif_rx(skb); + + size += length; + packets++; + + new_skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size); + if (!new_skb) { + dev_err(&ndev->dev, "no memory for new sk_buff\n"); + return; + } + cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data, + lp->max_frm_size, + DMA_FROM_DEVICE); + cur_p->cntrl = lp->max_frm_size; + cur_p->status = 0; + cur_p->sw_id_offset = (u32) new_skb; + + lp->rx_bd_ci = ++lp->rx_bd_ci % RX_BD_NUM; + cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; + } + + ndev->stats.rx_packets += packets; + ndev->stats.rx_bytes += size; + + axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, tail_p); +} + +/** + * axienet_tx_irq - Tx Done Isr. + * @irq: irq number + * @_ndev: net_device pointer + * + * returns: IRQ_HANDLED for all cases. + * + * This is the Axi DMA Tx done Isr. It invokes "axienet_start_xmit_done" + * to complete the BD processing. + */ +static irqreturn_t axienet_tx_irq(int irq, void *_ndev) +{ + u32 cr; + unsigned int status; + struct net_device *ndev = _ndev; + struct axienet_local *lp = netdev_priv(ndev); + + status = axienet_dma_in32(lp, XAXIDMA_TX_SR_OFFSET); + if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) { + axienet_start_xmit_done(lp->ndev); + goto out; + } + if (!(status & XAXIDMA_IRQ_ALL_MASK)) + dev_err(&ndev->dev, "No interrupts asserted in Tx path"); + if (status & XAXIDMA_IRQ_ERROR_MASK) { + dev_err(&ndev->dev, "DMA Tx error 0x%x\n", status); + dev_err(&ndev->dev, "Current BD is at: 0x%x\n", + (lp->tx_bd_v[lp->tx_bd_ci]).phys); + + cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); + /* Disable coalesce, delay timer and error interrupts */ + cr &= (~XAXIDMA_IRQ_ALL_MASK); + /* Write to the Tx channel control register */ + axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr); + + cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); + /* Disable coalesce, delay timer and error interrupts */ + cr &= (~XAXIDMA_IRQ_ALL_MASK); + /* Write to the Rx channel control register */ + axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr); + + tasklet_schedule(&lp->dma_err_tasklet); + } +out: + axienet_dma_out32(lp, XAXIDMA_TX_SR_OFFSET, status); + return IRQ_HANDLED; +} + +/** + * axienet_rx_irq - Rx Isr. + * @irq: irq number + * @_ndev: net_device pointer + * + * returns: IRQ_HANDLED for all cases. + * + * This is the Axi DMA Rx Isr. It invokes "axienet_recv" to complete the BD + * processing. + */ +static irqreturn_t axienet_rx_irq(int irq, void *_ndev) +{ + u32 cr; + unsigned int status; + struct net_device *ndev = _ndev; + struct axienet_local *lp = netdev_priv(ndev); + + status = axienet_dma_in32(lp, XAXIDMA_RX_SR_OFFSET); + if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) { + axienet_recv(lp->ndev); + goto out; + } + if (!(status & XAXIDMA_IRQ_ALL_MASK)) + dev_err(&ndev->dev, "No interrupts asserted in Rx path"); + if (status & XAXIDMA_IRQ_ERROR_MASK) { + dev_err(&ndev->dev, "DMA Rx error 0x%x\n", status); + dev_err(&ndev->dev, "Current BD is at: 0x%x\n", + (lp->rx_bd_v[lp->rx_bd_ci]).phys); + + cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); + /* Disable coalesce, delay timer and error interrupts */ + cr &= (~XAXIDMA_IRQ_ALL_MASK); + /* Finally write to the Tx channel control register */ + axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr); + + cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); + /* Disable coalesce, delay timer and error interrupts */ + cr &= (~XAXIDMA_IRQ_ALL_MASK); + /* write to the Rx channel control register */ + axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr); + + tasklet_schedule(&lp->dma_err_tasklet); + } +out: + axienet_dma_out32(lp, XAXIDMA_RX_SR_OFFSET, status); + return IRQ_HANDLED; +} + +/** + * axienet_open - Driver open routine. + * @ndev: Pointer to net_device structure + * + * returns: 0, on success. + * -ENODEV, if PHY cannot be connected to + * non-zero error value on failure + * + * This is the driver open routine. It calls phy_start to start the PHY device. + * It also allocates interrupt service routines, enables the interrupt lines + * and ISR handling. Axi Ethernet core is reset through Axi DMA core. Buffer + * descriptors are initialized. + */ +static int axienet_open(struct net_device *ndev) +{ + int ret, mdio_mcreg; + struct axienet_local *lp = netdev_priv(ndev); + + dev_dbg(&ndev->dev, "axienet_open()\n"); + + mdio_mcreg = axienet_ior(lp, XAE_MDIO_MC_OFFSET); + ret = axienet_mdio_wait_until_ready(lp); + if (ret < 0) + return ret; + /* Disable the MDIO interface till Axi Ethernet Reset is completed. + * When we do an Axi Ethernet reset, it resets the complete core + * including the MDIO. If MDIO is not disabled when the reset + * process is started, MDIO will be broken afterwards. */ + axienet_iow(lp, XAE_MDIO_MC_OFFSET, + (mdio_mcreg & (~XAE_MDIO_MC_MDIOEN_MASK))); + axienet_device_reset(ndev); + /* Enable the MDIO */ + axienet_iow(lp, XAE_MDIO_MC_OFFSET, mdio_mcreg); + ret = axienet_mdio_wait_until_ready(lp); + if (ret < 0) + return ret; + + if (lp->phy_node) { + lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node, + axienet_adjust_link, 0, + PHY_INTERFACE_MODE_GMII); + if (!lp->phy_dev) { + dev_err(lp->dev, "of_phy_connect() failed\n"); + return -ENODEV; + } + phy_start(lp->phy_dev); + } + + /* Enable interrupts for Axi DMA Tx */ + ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev); + if (ret) + goto err_tx_irq; + /* Enable interrupts for Axi DMA Rx */ + ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev); + if (ret) + goto err_rx_irq; + /* Enable tasklets for Axi DMA error handling */ + tasklet_enable(&lp->dma_err_tasklet); + return 0; + +err_rx_irq: + free_irq(lp->tx_irq, ndev); +err_tx_irq: + if (lp->phy_dev) + phy_disconnect(lp->phy_dev); + lp->phy_dev = NULL; + dev_err(lp->dev, "request_irq() failed\n"); + return ret; +} + +/** + * axienet_stop - Driver stop routine. + * @ndev: Pointer to net_device structure + * + * returns: 0, on success. + * + * This is the driver stop routine. It calls phy_disconnect to stop the PHY + * device. It also removes the interrupt handlers and disables the interrupts. + * The Axi DMA Tx/Rx BDs are released. + */ +static int axienet_stop(struct net_device *ndev) +{ + u32 cr; + struct axienet_local *lp = netdev_priv(ndev); + + dev_dbg(&ndev->dev, "axienet_close()\n"); + + cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); + axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, + cr & (~XAXIDMA_CR_RUNSTOP_MASK)); + cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); + axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, + cr & (~XAXIDMA_CR_RUNSTOP_MASK)); + axienet_setoptions(ndev, lp->options & + ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); + + tasklet_disable(&lp->dma_err_tasklet); + + free_irq(lp->tx_irq, ndev); + free_irq(lp->rx_irq, ndev); + + if (lp->phy_dev) + phy_disconnect(lp->phy_dev); + lp->phy_dev = NULL; + + axienet_dma_bd_release(ndev); + return 0; +} + +/** + * axienet_change_mtu - Driver change mtu routine. + * @ndev: Pointer to net_device structure + * @new_mtu: New mtu value to be applied + * + * returns: Always returns 0 (success). + * + * This is the change mtu driver routine. It checks if the Axi Ethernet + * hardware supports jumbo frames before changing the mtu. This can be + * called only when the device is not up. + */ +static int axienet_change_mtu(struct net_device *ndev, int new_mtu) +{ + struct axienet_local *lp = netdev_priv(ndev); + + if (netif_running(ndev)) + return -EBUSY; + if (lp->jumbo_support) { + if ((new_mtu > XAE_JUMBO_MTU) || (new_mtu < 64)) + return -EINVAL; + ndev->mtu = new_mtu; + } else { + if ((new_mtu > XAE_MTU) || (new_mtu < 64)) + return -EINVAL; + ndev->mtu = new_mtu; + } + + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +/** + * axienet_poll_controller - Axi Ethernet poll mechanism. + * @ndev: Pointer to net_device structure + * + * This implements Rx/Tx ISR poll mechanisms. The interrupts are disabled prior + * to polling the ISRs and are enabled back after the polling is done. + */ +static void axienet_poll_controller(struct net_device *ndev) +{ + struct axienet_local *lp = netdev_priv(ndev); + disable_irq(lp->tx_irq); + disable_irq(lp->rx_irq); + axienet_rx_irq(lp->tx_irq, ndev); + axienet_tx_irq(lp->rx_irq, ndev); + enable_irq(lp->tx_irq); + enable_irq(lp->rx_irq); +} +#endif + +static const struct net_device_ops axienet_netdev_ops = { + .ndo_open = axienet_open, + .ndo_stop = axienet_stop, + .ndo_start_xmit = axienet_start_xmit, + .ndo_change_mtu = axienet_change_mtu, + .ndo_set_mac_address = netdev_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_rx_mode = axienet_set_multicast_list, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = axienet_poll_controller, +#endif +}; + +/** + * axienet_ethtools_get_settings - Get Axi Ethernet settings related to PHY. + * @ndev: Pointer to net_device structure + * @ecmd: Pointer to ethtool_cmd structure + * + * This implements ethtool command for getting PHY settings. If PHY could + * not be found, the function returns -ENODEV. This function calls the + * relevant PHY ethtool API to get the PHY settings. + * Issue "ethtool ethX" under linux prompt to execute this function. + */ +static int axienet_ethtools_get_settings(struct net_device *ndev, + struct ethtool_cmd *ecmd) +{ + struct axienet_local *lp = netdev_priv(ndev); + struct phy_device *phydev = lp->phy_dev; + if (!phydev) + return -ENODEV; + return phy_ethtool_gset(phydev, ecmd); +} + +/** + * axienet_ethtools_set_settings - Set PHY settings as passed in the argument. + * @ndev: Pointer to net_device structure + * @ecmd: Pointer to ethtool_cmd structure + * + * This implements ethtool command for setting various PHY settings. If PHY + * could not be found, the function returns -ENODEV. This function calls the + * relevant PHY ethtool API to set the PHY. + * Issue e.g. "ethtool -s ethX speed 1000" under linux prompt to execute this + * function. + */ +static int axienet_ethtools_set_settings(struct net_device *ndev, + struct ethtool_cmd *ecmd) +{ + struct axienet_local *lp = netdev_priv(ndev); + struct phy_device *phydev = lp->phy_dev; + if (!phydev) + return -ENODEV; + return phy_ethtool_sset(phydev, ecmd); +} + +/** + * axienet_ethtools_get_drvinfo - Get various Axi Ethernet driver information. + * @ndev: Pointer to net_device structure + * @ed: Pointer to ethtool_drvinfo structure + * + * This implements ethtool command for getting the driver information. + * Issue "ethtool -i ethX" under linux prompt to execute this function. + */ +static void axienet_ethtools_get_drvinfo(struct net_device *ndev, + struct ethtool_drvinfo *ed) +{ + memset(ed, 0, sizeof(struct ethtool_drvinfo)); + strcpy(ed->driver, DRIVER_NAME); + strcpy(ed->version, DRIVER_VERSION); + ed->regdump_len = sizeof(u32) * AXIENET_REGS_N; +} + +/** + * axienet_ethtools_get_regs_len - Get the total regs length present in the + * AxiEthernet core. + * @ndev: Pointer to net_device structure + * + * This implements ethtool command for getting the total register length + * information. + */ +static int axienet_ethtools_get_regs_len(struct net_device *ndev) +{ + return sizeof(u32) * AXIENET_REGS_N; +} + +/** + * axienet_ethtools_get_regs - Dump the contents of all registers present + * in AxiEthernet core. + * @ndev: Pointer to net_device structure + * @regs: Pointer to ethtool_regs structure + * @ret: Void pointer used to return the contents of the registers. + * + * This implements ethtool command for getting the Axi Ethernet register dump. + * Issue "ethtool -d ethX" to execute this function. + */ +static void axienet_ethtools_get_regs(struct net_device *ndev, + struct ethtool_regs *regs, void *ret) +{ + u32 *data = (u32 *) ret; + size_t len = sizeof(u32) * AXIENET_REGS_N; + struct axienet_local *lp = netdev_priv(ndev); + + regs->version = 0; + regs->len = len; + + memset(data, 0, len); + data[0] = axienet_ior(lp, XAE_RAF_OFFSET); + data[1] = axienet_ior(lp, XAE_TPF_OFFSET); + data[2] = axienet_ior(lp, XAE_IFGP_OFFSET); + data[3] = axienet_ior(lp, XAE_IS_OFFSET); + data[4] = axienet_ior(lp, XAE_IP_OFFSET); + data[5] = axienet_ior(lp, XAE_IE_OFFSET); + data[6] = axienet_ior(lp, XAE_TTAG_OFFSET); + data[7] = axienet_ior(lp, XAE_RTAG_OFFSET); + data[8] = axienet_ior(lp, XAE_UAWL_OFFSET); + data[9] = axienet_ior(lp, XAE_UAWU_OFFSET); + data[10] = axienet_ior(lp, XAE_TPID0_OFFSET); + data[11] = axienet_ior(lp, XAE_TPID1_OFFSET); + data[12] = axienet_ior(lp, XAE_PPST_OFFSET); + data[13] = axienet_ior(lp, XAE_RCW0_OFFSET); + data[14] = axienet_ior(lp, XAE_RCW1_OFFSET); + data[15] = axienet_ior(lp, XAE_TC_OFFSET); + data[16] = axienet_ior(lp, XAE_FCC_OFFSET); + data[17] = axienet_ior(lp, XAE_EMMC_OFFSET); + data[18] = axienet_ior(lp, XAE_PHYC_OFFSET); + data[19] = axienet_ior(lp, XAE_MDIO_MC_OFFSET); + data[20] = axienet_ior(lp, XAE_MDIO_MCR_OFFSET); + data[21] = axienet_ior(lp, XAE_MDIO_MWD_OFFSET); + data[22] = axienet_ior(lp, XAE_MDIO_MRD_OFFSET); + data[23] = axienet_ior(lp, XAE_MDIO_MIS_OFFSET); + data[24] = axienet_ior(lp, XAE_MDIO_MIP_OFFSET); + data[25] = axienet_ior(lp, XAE_MDIO_MIE_OFFSET); + data[26] = axienet_ior(lp, XAE_MDIO_MIC_OFFSET); + data[27] = axienet_ior(lp, XAE_UAW0_OFFSET); + data[28] = axienet_ior(lp, XAE_UAW1_OFFSET); + data[29] = axienet_ior(lp, XAE_FMI_OFFSET); + data[30] = axienet_ior(lp, XAE_AF0_OFFSET); + data[31] = axienet_ior(lp, XAE_AF1_OFFSET); +} + +/** + * axienet_ethtools_get_pauseparam - Get the pause parameter setting for + * Tx and Rx paths. + * @ndev: Pointer to net_device structure + * @epauseparm: Pointer to ethtool_pauseparam structure. + * + * This implements ethtool command for getting axi ethernet pause frame + * setting. Issue "ethtool -a ethX" to execute this function. + */ +static void +axienet_ethtools_get_pauseparam(struct net_device *ndev, + struct ethtool_pauseparam *epauseparm) +{ + u32 regval; + struct axienet_local *lp = netdev_priv(ndev); + epauseparm->autoneg = 0; + regval = axienet_ior(lp, XAE_FCC_OFFSET); + epauseparm->tx_pause = regval & XAE_FCC_FCTX_MASK; + epauseparm->rx_pause = regval & XAE_FCC_FCRX_MASK; +} + +/** + * axienet_ethtools_set_pauseparam - Set device pause parameter(flow control) + * settings. + * @ndev: Pointer to net_device structure + * @epauseparam:Pointer to ethtool_pauseparam structure + * + * This implements ethtool command for enabling flow control on Rx and Tx + * paths. Issue "ethtool -A ethX tx on|off" under linux prompt to execute this + * function. + */ +static int +axienet_ethtools_set_pauseparam(struct net_device *ndev, + struct ethtool_pauseparam *epauseparm) +{ + u32 regval = 0; + struct axienet_local *lp = netdev_priv(ndev); + + if (netif_running(ndev)) { + printk(KERN_ERR "%s: Please stop netif before applying " + "configruation\n", ndev->name); + return -EFAULT; + } + + regval = axienet_ior(lp, XAE_FCC_OFFSET); + if (epauseparm->tx_pause) + regval |= XAE_FCC_FCTX_MASK; + else + regval &= ~XAE_FCC_FCTX_MASK; + if (epauseparm->rx_pause) + regval |= XAE_FCC_FCRX_MASK; + else + regval &= ~XAE_FCC_FCRX_MASK; + axienet_iow(lp, XAE_FCC_OFFSET, regval); + + return 0; +} + +/** + * axienet_ethtools_get_coalesce - Get DMA interrupt coalescing count. + * @ndev: Pointer to net_device structure + * @ecoalesce: Pointer to ethtool_coalesce structure + * + * This implements ethtool command for getting the DMA interrupt coalescing + * count on Tx and Rx paths. Issue "ethtool -c ethX" under linux prompt to + * execute this function. + */ +static int axienet_ethtools_get_coalesce(struct net_device *ndev, + struct ethtool_coalesce *ecoalesce) +{ + u32 regval = 0; + struct axienet_local *lp = netdev_priv(ndev); + regval = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); + ecoalesce->rx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK) + >> XAXIDMA_COALESCE_SHIFT; + regval = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); + ecoalesce->tx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK) + >> XAXIDMA_COALESCE_SHIFT; + return 0; +} + +/** + * axienet_ethtools_set_coalesce - Set DMA interrupt coalescing count. + * @ndev: Pointer to net_device structure + * @ecoalesce: Pointer to ethtool_coalesce structure + * + * This implements ethtool command for setting the DMA interrupt coalescing + * count on Tx and Rx paths. Issue "ethtool -C ethX rx-frames 5" under linux + * prompt to execute this function. + */ +static int axienet_ethtools_set_coalesce(struct net_device *ndev, + struct ethtool_coalesce *ecoalesce) +{ + struct axienet_local *lp = netdev_priv(ndev); + + if (netif_running(ndev)) { + printk(KERN_ERR "%s: Please stop netif before applying " + "configruation\n", ndev->name); + return -EFAULT; + } + + if ((ecoalesce->rx_coalesce_usecs) || + (ecoalesce->rx_coalesce_usecs_irq) || + (ecoalesce->rx_max_coalesced_frames_irq) || + (ecoalesce->tx_coalesce_usecs) || + (ecoalesce->tx_coalesce_usecs_irq) || + (ecoalesce->tx_max_coalesced_frames_irq) || + (ecoalesce->stats_block_coalesce_usecs) || + (ecoalesce->use_adaptive_rx_coalesce) || + (ecoalesce->use_adaptive_tx_coalesce) || + (ecoalesce->pkt_rate_low) || + (ecoalesce->rx_coalesce_usecs_low) || + (ecoalesce->rx_max_coalesced_frames_low) || + (ecoalesce->tx_coalesce_usecs_low) || + (ecoalesce->tx_max_coalesced_frames_low) || + (ecoalesce->pkt_rate_high) || + (ecoalesce->rx_coalesce_usecs_high) || + (ecoalesce->rx_max_coalesced_frames_high) || + (ecoalesce->tx_coalesce_usecs_high) || + (ecoalesce->tx_max_coalesced_frames_high) || + (ecoalesce->rate_sample_interval)) + return -EOPNOTSUPP; + if (ecoalesce->rx_max_coalesced_frames) + lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames; + if (ecoalesce->tx_max_coalesced_frames) + lp->coalesce_count_tx = ecoalesce->tx_max_coalesced_frames; + + return 0; +} + +static struct ethtool_ops axienet_ethtool_ops = { + .get_settings = axienet_ethtools_get_settings, + .set_settings = axienet_ethtools_set_settings, + .get_drvinfo = axienet_ethtools_get_drvinfo, + .get_regs_len = axienet_ethtools_get_regs_len, + .get_regs = axienet_ethtools_get_regs, + .get_link = ethtool_op_get_link, + .get_pauseparam = axienet_ethtools_get_pauseparam, + .set_pauseparam = axienet_ethtools_set_pauseparam, + .get_coalesce = axienet_ethtools_get_coalesce, + .set_coalesce = axienet_ethtools_set_coalesce, +}; + +/** + * axienet_dma_err_handler - Tasklet handler for Axi DMA Error + * @data: Data passed + * + * Resets the Axi DMA and Axi Ethernet devices, and reconfigures the + * Tx/Rx BDs. + */ +static void axienet_dma_err_handler(unsigned long data) +{ + u32 axienet_status; + u32 cr, i; + int mdio_mcreg; + struct axienet_local *lp = (struct axienet_local *) data; + struct net_device *ndev = lp->ndev; + struct axidma_bd *cur_p; + + axienet_setoptions(ndev, lp->options & + ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); + mdio_mcreg = axienet_ior(lp, XAE_MDIO_MC_OFFSET); + axienet_mdio_wait_until_ready(lp); + /* Disable the MDIO interface till Axi Ethernet Reset is completed. + * When we do an Axi Ethernet reset, it resets the complete core + * including the MDIO. So if MDIO is not disabled when the reset + * process is started, MDIO will be broken afterwards. */ + axienet_iow(lp, XAE_MDIO_MC_OFFSET, (mdio_mcreg & + ~XAE_MDIO_MC_MDIOEN_MASK)); + + __axienet_device_reset(lp, &ndev->dev, XAXIDMA_TX_CR_OFFSET); + __axienet_device_reset(lp, &ndev->dev, XAXIDMA_RX_CR_OFFSET); + + axienet_iow(lp, XAE_MDIO_MC_OFFSET, mdio_mcreg); + axienet_mdio_wait_until_ready(lp); + + for (i = 0; i < TX_BD_NUM; i++) { + cur_p = &lp->tx_bd_v[i]; + if (cur_p->phys) + dma_unmap_single(ndev->dev.parent, cur_p->phys, + (cur_p->cntrl & + XAXIDMA_BD_CTRL_LENGTH_MASK), + DMA_TO_DEVICE); + if (cur_p->app4) + dev_kfree_skb_irq((struct sk_buff *) cur_p->app4); + cur_p->phys = 0; + cur_p->cntrl = 0; + cur_p->status = 0; + cur_p->app0 = 0; + cur_p->app1 = 0; + cur_p->app2 = 0; + cur_p->app3 = 0; + cur_p->app4 = 0; + cur_p->sw_id_offset = 0; + } + + for (i = 0; i < RX_BD_NUM; i++) { + cur_p = &lp->rx_bd_v[i]; + cur_p->status = 0; + cur_p->app0 = 0; + cur_p->app1 = 0; + cur_p->app2 = 0; + cur_p->app3 = 0; + cur_p->app4 = 0; + } + + lp->tx_bd_ci = 0; + lp->tx_bd_tail = 0; + lp->rx_bd_ci = 0; + + /* Start updating the Rx channel control register */ + cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); + /* Update the interrupt coalesce count */ + cr = ((cr & ~XAXIDMA_COALESCE_MASK) | + (XAXIDMA_DFT_RX_THRESHOLD << XAXIDMA_COALESCE_SHIFT)); + /* Update the delay timer count */ + cr = ((cr & ~XAXIDMA_DELAY_MASK) | + (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT)); + /* Enable coalesce, delay timer and error interrupts */ + cr |= XAXIDMA_IRQ_ALL_MASK; + /* Finally write to the Rx channel control register */ + axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr); + + /* Start updating the Tx channel control register */ + cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); + /* Update the interrupt coalesce count */ + cr = (((cr & ~XAXIDMA_COALESCE_MASK)) | + (XAXIDMA_DFT_TX_THRESHOLD << XAXIDMA_COALESCE_SHIFT)); + /* Update the delay timer count */ + cr = (((cr & ~XAXIDMA_DELAY_MASK)) | + (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT)); + /* Enable coalesce, delay timer and error interrupts */ + cr |= XAXIDMA_IRQ_ALL_MASK; + /* Finally write to the Tx channel control register */ + axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr); + + /* Populate the tail pointer and bring the Rx Axi DMA engine out of + * halted state. This will make the Rx side ready for reception.*/ + axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p); + cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); + axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, + cr | XAXIDMA_CR_RUNSTOP_MASK); + axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p + + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); + + /* Write to the RS (Run-stop) bit in the Tx channel control register. + * Tx channel is now ready to run. But only after we write to the + * tail pointer register that the Tx channel will start transmitting */ + axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p); + cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); + axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, + cr | XAXIDMA_CR_RUNSTOP_MASK); + + axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET); + axienet_status &= ~XAE_RCW1_RX_MASK; + axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status); + + axienet_status = axienet_ior(lp, XAE_IP_OFFSET); + if (axienet_status & XAE_INT_RXRJECT_MASK) + axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK); + axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK); + + /* Sync default options with HW but leave receiver and + * transmitter disabled.*/ + axienet_setoptions(ndev, lp->options & + ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); + axienet_set_mac_address(ndev, NULL); + axienet_set_multicast_list(ndev); + axienet_setoptions(ndev, lp->options); +} + +/** + * axienet_of_probe - Axi Ethernet probe function. + * @op: Pointer to platform device structure. + * @match: Pointer to device id structure + * + * returns: 0, on success + * Non-zero error value on failure. + * + * This is the probe routine for Axi Ethernet driver. This is called before + * any other driver routines are invoked. It allocates and sets up the Ethernet + * device. Parses through device tree and populates fields of + * axienet_local. It registers the Ethernet device. + */ +static int __devinit axienet_of_probe(struct platform_device *op) +{ + __be32 *p; + int size, ret = 0; + struct device_node *np; + struct axienet_local *lp; + struct net_device *ndev; + const void *addr; + + ndev = alloc_etherdev(sizeof(*lp)); + if (!ndev) + return -ENOMEM; + + ether_setup(ndev); + dev_set_drvdata(&op->dev, ndev); + + SET_NETDEV_DEV(ndev, &op->dev); + ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ + ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST; + ndev->netdev_ops = &axienet_netdev_ops; + ndev->ethtool_ops = &axienet_ethtool_ops; + + lp = netdev_priv(ndev); + lp->ndev = ndev; + lp->dev = &op->dev; + lp->options = XAE_OPTION_DEFAULTS; + /* Map device registers */ + lp->regs = of_iomap(op->dev.of_node, 0); + if (!lp->regs) { + dev_err(&op->dev, "could not map Axi Ethernet regs.\n"); + goto nodev; + } + /* Setup checksum offload, but default to off if not specified */ + lp->features = 0; + + p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,txcsum", NULL); + if (p) { + switch (be32_to_cpup(p)) { + case 1: + lp->csum_offload_on_tx_path = + XAE_FEATURE_PARTIAL_TX_CSUM; + lp->features |= XAE_FEATURE_PARTIAL_TX_CSUM; + /* Can checksum TCP/UDP over IPv4. */ + ndev->features |= NETIF_F_IP_CSUM; + break; + case 2: + lp->csum_offload_on_tx_path = + XAE_FEATURE_FULL_TX_CSUM; + lp->features |= XAE_FEATURE_FULL_TX_CSUM; + /* Can checksum TCP/UDP over IPv4. */ + ndev->features |= NETIF_F_IP_CSUM; + break; + default: + lp->csum_offload_on_tx_path = XAE_NO_CSUM_OFFLOAD; + } + } + p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL); + if (p) { + switch (be32_to_cpup(p)) { + case 1: + lp->csum_offload_on_rx_path = + XAE_FEATURE_PARTIAL_RX_CSUM; + lp->features |= XAE_FEATURE_PARTIAL_RX_CSUM; + break; + case 2: + lp->csum_offload_on_rx_path = + XAE_FEATURE_FULL_RX_CSUM; + lp->features |= XAE_FEATURE_FULL_RX_CSUM; + break; + default: + lp->csum_offload_on_rx_path = XAE_NO_CSUM_OFFLOAD; + } + } + /* For supporting jumbo frames, the Axi Ethernet hardware must have + * a larger Rx/Tx Memory. Typically, the size must be more than or + * equal to 16384 bytes, so that we can enable jumbo option and start + * supporting jumbo frames. Here we check for memory allocated for + * Rx/Tx in the hardware from the device-tree and accordingly set + * flags. */ + p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,rxmem", NULL); + if (p) { + if ((be32_to_cpup(p)) >= 0x4000) + lp->jumbo_support = 1; + } + p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,temac-type", + NULL); + if (p) + lp->temac_type = be32_to_cpup(p); + p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,phy-type", NULL); + if (p) + lp->phy_type = be32_to_cpup(p); + + /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ + np = of_parse_phandle(op->dev.of_node, "axistream-connected", 0); + if (!np) { + dev_err(&op->dev, "could not find DMA node\n"); + goto err_iounmap; + } + lp->dma_regs = of_iomap(np, 0); + if (lp->dma_regs) { + dev_dbg(&op->dev, "MEM base: %p\n", lp->dma_regs); + } else { + dev_err(&op->dev, "unable to map DMA registers\n"); + of_node_put(np); + } + lp->rx_irq = irq_of_parse_and_map(np, 1); + lp->tx_irq = irq_of_parse_and_map(np, 0); + of_node_put(np); + if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) { + dev_err(&op->dev, "could not determine irqs\n"); + ret = -ENOMEM; + goto err_iounmap_2; + } + + /* Retrieve the MAC address */ + addr = of_get_property(op->dev.of_node, "local-mac-address", &size); + if ((!addr) || (size != 6)) { + dev_err(&op->dev, "could not find MAC address\n"); + ret = -ENODEV; + goto err_iounmap_2; + } + axienet_set_mac_address(ndev, (void *) addr); + + lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD; + lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD; + + lp->phy_node = of_parse_phandle(op->dev.of_node, "phy-handle", 0); + ret = axienet_mdio_setup(lp, op->dev.of_node); + if (ret) + dev_warn(&op->dev, "error registering MDIO bus\n"); + + ret = register_netdev(lp->ndev); + if (ret) { + dev_err(lp->dev, "register_netdev() error (%i)\n", ret); + goto err_iounmap_2; + } + + tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler, + (unsigned long) lp); + tasklet_disable(&lp->dma_err_tasklet); + + return 0; + +err_iounmap_2: + if (lp->dma_regs) + iounmap(lp->dma_regs); +err_iounmap: + iounmap(lp->regs); +nodev: + free_netdev(ndev); + ndev = NULL; + return ret; +} + +static int __devexit axienet_of_remove(struct platform_device *op) +{ + struct net_device *ndev = dev_get_drvdata(&op->dev); + struct axienet_local *lp = netdev_priv(ndev); + + axienet_mdio_teardown(lp); + unregister_netdev(ndev); + + if (lp->phy_node) + of_node_put(lp->phy_node); + lp->phy_node = NULL; + + dev_set_drvdata(&op->dev, NULL); + + iounmap(lp->regs); + if (lp->dma_regs) + iounmap(lp->dma_regs); + free_netdev(ndev); + + return 0; +} + +static struct platform_driver axienet_of_driver = { + .probe = axienet_of_probe, + .remove = __devexit_p(axienet_of_remove), + .driver = { + .owner = THIS_MODULE, + .name = "xilinx_axienet", + .of_match_table = axienet_of_match, + }, +}; + +static int __init axienet_init(void) +{ + return platform_driver_register(&axienet_of_driver); +} + +static void __exit axienet_exit(void) +{ + platform_driver_unregister(&axienet_of_driver); +} + +module_init(axienet_init); +module_exit(axienet_exit); + +MODULE_DESCRIPTION("Xilinx Axi Ethernet driver"); +MODULE_AUTHOR("Xilinx"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c new file mode 100644 index 000000000000..d70b6e79f6c0 --- /dev/null +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c @@ -0,0 +1,238 @@ +/* + * MDIO bus driver for the Xilinx Axi Ethernet device + * + * Copyright (c) 2009 Secret Lab Technologies, Ltd. + * Copyright (c) 2010 Xilinx, Inc. All rights reserved. + * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch> + * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch> + */ + +#include <linux/of_address.h> +#include <linux/of_mdio.h> +#include <linux/jiffies.h> + +#include "xilinx_axienet.h" + +#define MAX_MDIO_FREQ 2500000 /* 2.5 MHz */ +#define DEFAULT_CLOCK_DIVISOR XAE_MDIO_DIV_DFT + +/* Wait till MDIO interface is ready to accept a new transaction.*/ +int axienet_mdio_wait_until_ready(struct axienet_local *lp) +{ + long end = jiffies + 2; + while (!(axienet_ior(lp, XAE_MDIO_MCR_OFFSET) & + XAE_MDIO_MCR_READY_MASK)) { + if (end - jiffies <= 0) { + WARN_ON(1); + return -ETIMEDOUT; + } + udelay(1); + } + return 0; +} + +/** + * axienet_mdio_read - MDIO interface read function + * @bus: Pointer to mii bus structure + * @phy_id: Address of the PHY device + * @reg: PHY register to read + * + * returns: The register contents on success, -ETIMEDOUT on a timeout + * + * Reads the contents of the requested register from the requested PHY + * address by first writing the details into MCR register. After a while + * the register MRD is read to obtain the PHY register content. + */ +static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg) +{ + u32 rc; + int ret; + struct axienet_local *lp = bus->priv; + + ret = axienet_mdio_wait_until_ready(lp); + if (ret < 0) + return ret; + + axienet_iow(lp, XAE_MDIO_MCR_OFFSET, + (((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) & + XAE_MDIO_MCR_PHYAD_MASK) | + ((reg << XAE_MDIO_MCR_REGAD_SHIFT) & + XAE_MDIO_MCR_REGAD_MASK) | + XAE_MDIO_MCR_INITIATE_MASK | + XAE_MDIO_MCR_OP_READ_MASK)); + + ret = axienet_mdio_wait_until_ready(lp); + if (ret < 0) + return ret; + + rc = axienet_ior(lp, XAE_MDIO_MRD_OFFSET) & 0x0000FFFF; + + dev_dbg(lp->dev, "axienet_mdio_read(phy_id=%i, reg=%x) == %x\n", + phy_id, reg, rc); + + return rc; +} + +/** + * axienet_mdio_write - MDIO interface write function + * @bus: Pointer to mii bus structure + * @phy_id: Address of the PHY device + * @reg: PHY register to write to + * @val: Value to be written into the register + * + * returns: 0 on success, -ETIMEDOUT on a timeout + * + * Writes the value to the requested register by first writing the value + * into MWD register. The the MCR register is then appropriately setup + * to finish the write operation. + */ +static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg, + u16 val) +{ + int ret; + struct axienet_local *lp = bus->priv; + + dev_dbg(lp->dev, "axienet_mdio_write(phy_id=%i, reg=%x, val=%x)\n", + phy_id, reg, val); + + ret = axienet_mdio_wait_until_ready(lp); + if (ret < 0) + return ret; + + axienet_iow(lp, XAE_MDIO_MWD_OFFSET, (u32) val); + axienet_iow(lp, XAE_MDIO_MCR_OFFSET, + (((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) & + XAE_MDIO_MCR_PHYAD_MASK) | + ((reg << XAE_MDIO_MCR_REGAD_SHIFT) & + XAE_MDIO_MCR_REGAD_MASK) | + XAE_MDIO_MCR_INITIATE_MASK | + XAE_MDIO_MCR_OP_WRITE_MASK)); + + ret = axienet_mdio_wait_until_ready(lp); + if (ret < 0) + return ret; + return 0; +} + +/** + * axienet_mdio_setup - MDIO setup function + * @lp: Pointer to axienet local data structure. + * @np: Pointer to device node + * + * returns: 0 on success, -ETIMEDOUT on a timeout, -ENOMEM when + * mdiobus_alloc (to allocate memory for mii bus structure) fails. + * + * Sets up the MDIO interface by initializing the MDIO clock and enabling the + * MDIO interface in hardware. Register the MDIO interface. + **/ +int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np) +{ + int ret; + u32 clk_div, host_clock; + u32 *property_p; + struct mii_bus *bus; + struct resource res; + struct device_node *np1; + + /* clk_div can be calculated by deriving it from the equation: + * fMDIO = fHOST / ((1 + clk_div) * 2) + * + * Where fMDIO <= 2500000, so we get: + * fHOST / ((1 + clk_div) * 2) <= 2500000 + * + * Then we get: + * 1 / ((1 + clk_div) * 2) <= (2500000 / fHOST) + * + * Then we get: + * 1 / (1 + clk_div) <= ((2500000 * 2) / fHOST) + * + * Then we get: + * 1 / (1 + clk_div) <= (5000000 / fHOST) + * + * So: + * (1 + clk_div) >= (fHOST / 5000000) + * + * And finally: + * clk_div >= (fHOST / 5000000) - 1 + * + * fHOST can be read from the flattened device tree as property + * "clock-frequency" from the CPU + */ + + np1 = of_find_node_by_name(NULL, "cpu"); + if (!np1) { + printk(KERN_WARNING "%s(): Could not find CPU device node.", + __func__); + printk(KERN_WARNING "Setting MDIO clock divisor to " + "default %d\n", DEFAULT_CLOCK_DIVISOR); + clk_div = DEFAULT_CLOCK_DIVISOR; + goto issue; + } + property_p = (u32 *) of_get_property(np1, "clock-frequency", NULL); + if (!property_p) { + printk(KERN_WARNING "%s(): Could not find CPU property: " + "clock-frequency.", __func__); + printk(KERN_WARNING "Setting MDIO clock divisor to " + "default %d\n", DEFAULT_CLOCK_DIVISOR); + clk_div = DEFAULT_CLOCK_DIVISOR; + goto issue; + } + + host_clock = be32_to_cpup(property_p); + clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1; + /* If there is any remainder from the division of + * fHOST / (MAX_MDIO_FREQ * 2), then we need to add + * 1 to the clock divisor or we will surely be above 2.5 MHz */ + if (host_clock % (MAX_MDIO_FREQ * 2)) + clk_div++; + + printk(KERN_DEBUG "%s(): Setting MDIO clock divisor to %u based " + "on %u Hz host clock.\n", __func__, clk_div, host_clock); + + of_node_put(np1); +issue: + axienet_iow(lp, XAE_MDIO_MC_OFFSET, + (((u32) clk_div) | XAE_MDIO_MC_MDIOEN_MASK)); + + ret = axienet_mdio_wait_until_ready(lp); + if (ret < 0) + return ret; + + bus = mdiobus_alloc(); + if (!bus) + return -ENOMEM; + + np1 = of_get_parent(lp->phy_node); + of_address_to_resource(np1, 0, &res); + snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx", + (unsigned long long) res.start); + + bus->priv = lp; + bus->name = "Xilinx Axi Ethernet MDIO"; + bus->read = axienet_mdio_read; + bus->write = axienet_mdio_write; + bus->parent = lp->dev; + bus->irq = lp->mdio_irqs; /* preallocated IRQ table */ + lp->mii_bus = bus; + + ret = of_mdiobus_register(bus, np1); + if (ret) { + mdiobus_free(bus); + return ret; + } + return 0; +} + +/** + * axienet_mdio_teardown - MDIO remove function + * @lp: Pointer to axienet local data structure. + * + * Unregisters the MDIO and frees any associate memory for mii bus. + */ +void axienet_mdio_teardown(struct axienet_local *lp) +{ + mdiobus_unregister(lp->mii_bus); + kfree(lp->mii_bus->irq); + mdiobus_free(lp->mii_bus); + lp->mii_bus = NULL; +} diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 79013e5731a5..77cfe5110318 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -613,7 +613,7 @@ static void xemaclite_rx_handler(struct net_device *dev) u32 len; len = ETH_FRAME_LEN + ETH_FCS_LEN; - skb = dev_alloc_skb(len + ALIGNMENT); + skb = netdev_alloc_skb(dev, len + ALIGNMENT); if (!skb) { /* Couldn't get memory. */ dev->stats.rx_dropped++; @@ -1136,10 +1136,8 @@ static int __devinit xemaclite_of_probe(struct platform_device *ofdev) /* Create an ethernet device instance */ ndev = alloc_etherdev(sizeof(struct net_local)); - if (!ndev) { - dev_err(dev, "Could not allocate network device\n"); + if (!ndev) return -ENOMEM; - } dev_set_drvdata(dev, ndev); SET_NETDEV_DEV(ndev, &ofdev->dev); diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c index 33979c3ac943..5c69c6f93fb8 100644 --- a/drivers/net/ethernet/xircom/xirc2ps_cs.c +++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c @@ -1039,7 +1039,8 @@ xirc2ps_interrupt(int irq, void *dev_id) pr_debug("rsr=%#02x packet_length=%u\n", rsr, pktlen); - skb = dev_alloc_skb(pktlen+3); /* 1 extra so we can use insw */ + /* 1 extra so we can use insw */ + skb = netdev_alloc_skb(dev, pktlen + 3); if (!skb) { pr_notice("low memory, packet dropped (size=%u)\n", pktlen); dev->stats.rx_dropped++; |