diff options
author | Jiri Kosina <jkosina@suse.cz> | 2013-01-29 10:48:30 +0100 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-01-29 10:48:30 +0100 |
commit | 617677295b53a40d0e54aac4cbbc216ffbc755dd (patch) | |
tree | 51b9e87213243ed5efff252c8e8d8fec4eebc588 /drivers/net/ethernet | |
parent | time: x86: report_lost_ticks doesn't exist any more (diff) | |
parent | Merge tag 'regulator-3.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff) | |
download | linux-617677295b53a40d0e54aac4cbbc216ffbc755dd.tar.xz linux-617677295b53a40d0e54aac4cbbc216ffbc755dd.zip |
Merge branch 'master' into for-next
Conflicts:
drivers/devfreq/exynos4_bus.c
Sync with Linus' tree to be able to apply patches that are
against newer code (mvneta).
Diffstat (limited to 'drivers/net/ethernet')
374 files changed, 22466 insertions, 13162 deletions
diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c index 1a8eef2c3d58..633c709b9d99 100644 --- a/drivers/net/ethernet/3com/3c509.c +++ b/drivers/net/ethernet/3com/3c509.c @@ -92,7 +92,7 @@ #include <asm/io.h> #include <asm/irq.h> -static char version[] __devinitdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; +static char version[] = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; #ifdef EL3_DEBUG static int el3_debug = EL3_DEBUG; @@ -184,7 +184,7 @@ static int max_interrupt_work = 10; static int nopnp; #endif -static int __devinit el3_common_init(struct net_device *dev); +static int el3_common_init(struct net_device *dev); static void el3_common_remove(struct net_device *dev); static ushort id_read_eeprom(int index); static ushort read_eeprom(int ioaddr, int index); @@ -270,9 +270,8 @@ static int el3_isa_id_sequence(__be16 *phys_addr) } -static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr, - int ioaddr, int irq, int if_port, - enum el3_cardtype type) +static void el3_dev_fill(struct net_device *dev, __be16 *phys_addr, int ioaddr, + int irq, int if_port, enum el3_cardtype type) { struct el3_private *lp = netdev_priv(dev); @@ -283,8 +282,7 @@ static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr, lp->type = type; } -static int __devinit el3_isa_match(struct device *pdev, - unsigned int ndev) +static int el3_isa_match(struct device *pdev, unsigned int ndev) { struct net_device *dev; int ioaddr, isa_irq, if_port, err; @@ -341,7 +339,7 @@ static int __devinit el3_isa_match(struct device *pdev, return 1; } -static int __devexit el3_isa_remove(struct device *pdev, +static int el3_isa_remove(struct device *pdev, unsigned int ndev) { el3_device_remove(pdev); @@ -382,7 +380,7 @@ static int el3_isa_resume(struct device *dev, unsigned int n) static struct isa_driver el3_isa_driver = { .match = el3_isa_match, - .remove = __devexit_p(el3_isa_remove), + .remove = el3_isa_remove, #ifdef CONFIG_PM .suspend = el3_isa_suspend, .resume = el3_isa_resume, @@ -406,8 +404,7 @@ static struct pnp_device_id el3_pnp_ids[] = { }; MODULE_DEVICE_TABLE(pnp, el3_pnp_ids); -static int __devinit el3_pnp_probe(struct pnp_dev *pdev, - const struct pnp_device_id *id) +static int el3_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id) { short i; int ioaddr, irq, if_port; @@ -445,7 +442,7 @@ static int __devinit el3_pnp_probe(struct pnp_dev *pdev, return 0; } -static void __devexit el3_pnp_remove(struct pnp_dev *pdev) +static void el3_pnp_remove(struct pnp_dev *pdev) { el3_common_remove(pnp_get_drvdata(pdev)); pnp_set_drvdata(pdev, NULL); @@ -467,7 +464,7 @@ static struct pnp_driver el3_pnp_driver = { .name = "3c509", .id_table = el3_pnp_ids, .probe = el3_pnp_probe, - .remove = __devexit_p(el3_pnp_remove), + .remove = el3_pnp_remove, #ifdef CONFIG_PM .suspend = el3_pnp_suspend, .resume = el3_pnp_resume, @@ -496,7 +493,7 @@ static struct eisa_driver el3_eisa_driver = { .driver = { .name = "3c579", .probe = el3_eisa_probe, - .remove = __devexit_p (el3_device_remove), + .remove = el3_device_remove, .suspend = el3_suspend, .resume = el3_resume, } @@ -519,7 +516,7 @@ static const struct net_device_ops netdev_ops = { #endif }; -static int __devinit el3_common_init(struct net_device *dev) +static int el3_common_init(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); int err; @@ -618,7 +615,7 @@ static int __init el3_eisa_probe (struct device *device) /* This remove works for all device types. * * The net dev must be stored in the driver data field */ -static int __devexit el3_device_remove (struct device *device) +static int el3_device_remove(struct device *device) { struct net_device *dev; diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c index 66df93638085..ffd8de28a76a 100644 --- a/drivers/net/ethernet/3com/3c574_cs.c +++ b/drivers/net/ethernet/3com/3c574_cs.c @@ -432,7 +432,7 @@ static int tc574_config(struct pcmcia_device *link) netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n", cardname, dev->base_addr, dev->irq, dev->dev_addr); netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n", - 8 << config & Ram_size, + 8 << (config & Ram_size), ram_split[(config & Ram_split) >> Ram_split_shift], config & Autoselect ? "autoselect " : ""); diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index e463d1036829..ed0feb3cc6fa 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -102,7 +102,7 @@ static int vortex_debug = 1; #include <linux/delay.h> -static const char version[] __devinitconst = +static const char version[] = DRV_NAME ": Donald Becker and others.\n"; MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); @@ -277,7 +277,7 @@ static struct vortex_chip_info { int flags; int drv_flags; int io_size; -} vortex_info_tbl[] __devinitdata = { +} vortex_info_tbl[] = { {"3c590 Vortex 10Mbps", PCI_USES_MASTER, IS_VORTEX, 32, }, {"3c592 EISA 10Mbps Demon/Vortex", /* AKPM: from Don's 3c59x_cb.c 0.49H */ @@ -931,7 +931,7 @@ static int __init vortex_eisa_probe(struct device *device) return 0; } -static int __devexit vortex_eisa_remove(struct device *device) +static int vortex_eisa_remove(struct device *device) { struct eisa_device *edev; struct net_device *dev; @@ -962,7 +962,7 @@ static struct eisa_driver vortex_eisa_driver = { .driver = { .name = "3c59x", .probe = vortex_eisa_probe, - .remove = __devexit_p(vortex_eisa_remove) + .remove = vortex_eisa_remove } }; @@ -1000,8 +1000,8 @@ static int __init vortex_eisa_init(void) } /* returns count (>= 0), or negative on error */ -static int __devinit vortex_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int vortex_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { int rc, unit, pci_bar; struct vortex_chip_info *vci; @@ -1088,9 +1088,8 @@ static const struct net_device_ops vortex_netdev_ops = { * * NOTE: pdev can be NULL, for the case of a Compaq device */ -static int __devinit vortex_probe1(struct device *gendev, - void __iomem *ioaddr, int irq, - int chip_idx, int card_idx) +static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq, + int chip_idx, int card_idx) { struct vortex_private *vp; int option; @@ -3222,7 +3221,7 @@ static void acpi_set_WOL(struct net_device *dev) } -static void __devexit vortex_remove_one(struct pci_dev *pdev) +static void vortex_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct vortex_private *vp; @@ -3265,7 +3264,7 @@ static void __devexit vortex_remove_one(struct pci_dev *pdev) static struct pci_driver vortex_driver = { .name = "3c59x", .probe = vortex_init_one, - .remove = __devexit_p(vortex_remove_one), + .remove = vortex_remove_one, .id_table = vortex_pci_tbl, .driver.pm = VORTEX_PM_OPS, }; diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig index bad4fa6815c5..eb56174469a7 100644 --- a/drivers/net/ethernet/3com/Kconfig +++ b/drivers/net/ethernet/3com/Kconfig @@ -80,7 +80,7 @@ config PCMCIA_3C589 config VORTEX tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support" - depends on (PCI || EISA) + depends on (PCI || EISA) && HAS_IOPORT select NET_CORE select MII ---help--- diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c index bb9670f29b59..27aaaf99e73e 100644 --- a/drivers/net/ethernet/3com/typhoon.c +++ b/drivers/net/ethernet/3com/typhoon.c @@ -168,7 +168,7 @@ enum typhoon_cards { }; /* directly indexed by enum typhoon_cards, above */ -static struct typhoon_card_info typhoon_card_info[] __devinitdata = { +static struct typhoon_card_info typhoon_card_info[] = { { "3Com Typhoon (3C990-TX)", TYPHOON_CRYPTO_NONE}, { "3Com Typhoon (3CR990-TX-95)", @@ -2200,7 +2200,7 @@ need_resume: } #endif -static int __devinit +static int typhoon_test_mmio(struct pci_dev *pdev) { void __iomem *ioaddr = pci_iomap(pdev, 1, 128); @@ -2258,7 +2258,7 @@ static const struct net_device_ops typhoon_netdev_ops = { .ndo_change_mtu = eth_change_mtu, }; -static int __devinit +static int typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; @@ -2509,7 +2509,7 @@ error_out: return err; } -static void __devexit +static void typhoon_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -2533,7 +2533,7 @@ static struct pci_driver typhoon_driver = { .name = KBUILD_MODNAME, .id_table = typhoon_pci_tbl, .probe = typhoon_init_one, - .remove = __devexit_p(typhoon_remove_one), + .remove = typhoon_remove_one, #ifdef CONFIG_PM .suspend = typhoon_suspend, .resume = typhoon_resume, diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c index 846381c31185..70dba5d01ad3 100644 --- a/drivers/net/ethernet/8390/ax88796.c +++ b/drivers/net/ethernet/8390/ax88796.c @@ -191,11 +191,11 @@ static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); if (ei_local->word16) - readsw(nic_base + NE_DATAPORT, hdr, - sizeof(struct e8390_pkt_hdr) >> 1); + ioread16_rep(nic_base + NE_DATAPORT, hdr, + sizeof(struct e8390_pkt_hdr) >> 1); else - readsb(nic_base + NE_DATAPORT, hdr, - sizeof(struct e8390_pkt_hdr)); + ioread8_rep(nic_base + NE_DATAPORT, hdr, + sizeof(struct e8390_pkt_hdr)); ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ ei_local->dmaing &= ~0x01; @@ -237,12 +237,12 @@ static void ax_block_input(struct net_device *dev, int count, ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); if (ei_local->word16) { - readsw(nic_base + NE_DATAPORT, buf, count >> 1); + ioread16_rep(nic_base + NE_DATAPORT, buf, count >> 1); if (count & 0x01) buf[count-1] = ei_inb(nic_base + NE_DATAPORT); } else { - readsb(nic_base + NE_DATAPORT, buf, count); + ioread8_rep(nic_base + NE_DATAPORT, buf, count); } ei_local->dmaing &= ~1; @@ -286,9 +286,9 @@ static void ax_block_output(struct net_device *dev, int count, ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD); if (ei_local->word16) - writesw(nic_base + NE_DATAPORT, buf, count >> 1); + iowrite16_rep(nic_base + NE_DATAPORT, buf, count >> 1); else - writesb(nic_base + NE_DATAPORT, buf, count); + iowrite8_rep(nic_base + NE_DATAPORT, buf, count); dma_start = jiffies; diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c index 8322c54972f3..78c6fb4b1143 100644 --- a/drivers/net/ethernet/8390/etherh.c +++ b/drivers/net/ethernet/8390/etherh.c @@ -463,12 +463,6 @@ etherh_open(struct net_device *dev) { struct ei_device *ei_local = netdev_priv(dev); - if (!is_valid_ether_addr(dev->dev_addr)) { - printk(KERN_WARNING "%s: invalid ethernet MAC address\n", - dev->name); - return -EINVAL; - } - if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev)) return -EAGAIN; @@ -527,7 +521,7 @@ static void __init etherh_banner(void) * Read the ethernet address string from the on board rom. * This is an ascii string... */ -static int __devinit etherh_addr(char *addr, struct expansion_card *ec) +static int etherh_addr(char *addr, struct expansion_card *ec) { struct in_chunk_dir cd; char *s; @@ -657,7 +651,7 @@ static const struct net_device_ops etherh_netdev_ops = { static u32 etherh_regoffsets[16]; static u32 etherm_regoffsets[16]; -static int __devinit +static int etherh_probe(struct expansion_card *ec, const struct ecard_id *id) { const struct etherh_data *data = id->data; @@ -775,7 +769,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) return ret; } -static void __devexit etherh_remove(struct expansion_card *ec) +static void etherh_remove(struct expansion_card *ec) { struct net_device *dev = ecard_get_drvdata(ec); @@ -839,7 +833,7 @@ static const struct ecard_id etherh_ids[] = { static struct ecard_driver etherh_driver = { .probe = etherh_probe, - .remove = __devexit_p(etherh_remove), + .remove = etherh_remove, .id_table = etherh_ids, .drv = { .name = DRV_NAME, diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c index 5370c884620b..fb3dd4399cf3 100644 --- a/drivers/net/ethernet/8390/hydra.c +++ b/drivers/net/ethernet/8390/hydra.c @@ -53,9 +53,9 @@ static const char version[] = #define WORDSWAP(a) ((((a)>>8)&0xff) | ((a)<<8)) -static int __devinit hydra_init_one(struct zorro_dev *z, +static int hydra_init_one(struct zorro_dev *z, const struct zorro_device_id *ent); -static int __devinit hydra_init(struct zorro_dev *z); +static int hydra_init(struct zorro_dev *z); static int hydra_open(struct net_device *dev); static int hydra_close(struct net_device *dev); static void hydra_reset_8390(struct net_device *dev); @@ -65,9 +65,9 @@ static void hydra_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset); static void hydra_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page); -static void __devexit hydra_remove_one(struct zorro_dev *z); +static void hydra_remove_one(struct zorro_dev *z); -static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = { +static struct zorro_device_id hydra_zorro_tbl[] = { { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET }, { 0 } }; @@ -77,11 +77,11 @@ static struct zorro_driver hydra_driver = { .name = "hydra", .id_table = hydra_zorro_tbl, .probe = hydra_init_one, - .remove = __devexit_p(hydra_remove_one), + .remove = hydra_remove_one, }; -static int __devinit hydra_init_one(struct zorro_dev *z, - const struct zorro_device_id *ent) +static int hydra_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent) { int err; @@ -110,7 +110,7 @@ static const struct net_device_ops hydra_netdev_ops = { #endif }; -static int __devinit hydra_init(struct zorro_dev *z) +static int hydra_init(struct zorro_dev *z) { struct net_device *dev; unsigned long board = ZTWO_VADDR(z->resource.start); @@ -247,7 +247,7 @@ static void hydra_block_output(struct net_device *dev, int count, z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count); } -static void __devexit hydra_remove_one(struct zorro_dev *z) +static void hydra_remove_one(struct zorro_dev *z) { struct net_device *dev = zorro_get_drvdata(z); diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c index d04911d33b64..47618e505355 100644 --- a/drivers/net/ethernet/8390/ne.c +++ b/drivers/net/ethernet/8390/ne.c @@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct platform_device *pdev) dev->irq = irq[this_dev]; dev->mem_end = bad[this_dev]; } + SET_NETDEV_DEV(dev, &pdev->dev); err = do_ne_probe(dev); if (err) { free_netdev(dev); diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c index 5e8845febfb8..c0c127913dec 100644 --- a/drivers/net/ethernet/8390/ne2k-pci.c +++ b/drivers/net/ethernet/8390/ne2k-pci.c @@ -61,7 +61,7 @@ static int options[MAX_UNITS]; #include "8390.h" /* These identify the driver base version and may not be removed. */ -static const char version[] __devinitconst = +static const char version[] = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " D. Becker/P. Gortmaker\n"; @@ -119,7 +119,7 @@ enum ne2k_pci_chipsets { static struct { char *name; int flags; -} pci_clone_list[] __devinitdata = { +} pci_clone_list[] = { {"RealTek RTL-8029", REALTEK_FDX}, {"Winbond 89C940", 0}, {"Compex RL2000", 0}, @@ -215,8 +215,8 @@ static const struct net_device_ops ne2k_netdev_ops = { #endif }; -static int __devinit ne2k_pci_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int ne2k_pci_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct net_device *dev; int i; @@ -647,7 +647,7 @@ static const struct ethtool_ops ne2k_pci_ethtool_ops = { .get_drvinfo = ne2k_pci_get_drvinfo, }; -static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev) +static void ne2k_pci_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -696,7 +696,7 @@ static int ne2k_pci_resume (struct pci_dev *pdev) static struct pci_driver ne2k_driver = { .name = DRV_NAME, .probe = ne2k_pci_init_one, - .remove = __devexit_p(ne2k_pci_remove_one), + .remove = ne2k_pci_remove_one, .id_table = ne2k_pci_tbl, #ifdef CONFIG_PM .suspend = ne2k_pci_suspend, diff --git a/drivers/net/ethernet/8390/ne3210.c b/drivers/net/ethernet/8390/ne3210.c index e3f57427d5c5..ebcdb52ec739 100644 --- a/drivers/net/ethernet/8390/ne3210.c +++ b/drivers/net/ethernet/8390/ne3210.c @@ -222,7 +222,7 @@ static int __init ne3210_eisa_probe (struct device *device) return retval; } -static int __devexit ne3210_eisa_remove (struct device *device) +static int ne3210_eisa_remove(struct device *device) { struct net_device *dev = dev_get_drvdata(device); unsigned long ioaddr = to_eisa_device (device)->base_addr; @@ -324,7 +324,7 @@ static struct eisa_driver ne3210_eisa_driver = { .driver = { .name = "ne3210", .probe = ne3210_eisa_probe, - .remove = __devexit_p (ne3210_eisa_remove), + .remove = ne3210_eisa_remove, }, }; diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c index 7818e6397e91..85ec4c2d2645 100644 --- a/drivers/net/ethernet/8390/zorro8390.c +++ b/drivers/net/ethernet/8390/zorro8390.c @@ -75,7 +75,7 @@ static struct card_info { zorro_id id; const char *name; unsigned int offset; -} cards[] __devinitdata = { +} cards[] = { { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 }, { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 }, }; @@ -254,7 +254,7 @@ static int zorro8390_close(struct net_device *dev) return 0; } -static void __devexit zorro8390_remove_one(struct zorro_dev *z) +static void zorro8390_remove_one(struct zorro_dev *z) { struct net_device *dev = zorro_get_drvdata(z); @@ -264,7 +264,7 @@ static void __devexit zorro8390_remove_one(struct zorro_dev *z) free_netdev(dev); } -static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = { +static struct zorro_device_id zorro8390_zorro_tbl[] = { { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, }, { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, }, { 0 } @@ -286,9 +286,8 @@ static const struct net_device_ops zorro8390_netdev_ops = { #endif }; -static int __devinit zorro8390_init(struct net_device *dev, - unsigned long board, const char *name, - unsigned long ioaddr) +static int zorro8390_init(struct net_device *dev, unsigned long board, + const char *name, unsigned long ioaddr) { int i; int err; @@ -396,8 +395,8 @@ static int __devinit zorro8390_init(struct net_device *dev, return 0; } -static int __devinit zorro8390_init_one(struct zorro_dev *z, - const struct zorro_device_id *ent) +static int zorro8390_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent) { struct net_device *dev; unsigned long board, ioaddr; @@ -432,7 +431,7 @@ static struct zorro_driver zorro8390_driver = { .name = "zorro8390", .id_table = zorro8390_zorro_tbl, .probe = zorro8390_init_one, - .remove = __devexit_p(zorro8390_remove_one), + .remove = zorro8390_remove_one, }; static int __init zorro8390_init_module(void) diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c index 5b65992c2a0a..549b77500579 100644 --- a/drivers/net/ethernet/adaptec/starfire.c +++ b/drivers/net/ethernet/adaptec/starfire.c @@ -166,7 +166,7 @@ static int rx_copybreak /* = 0 */; #define FIRMWARE_TX "adaptec/starfire_tx.bin" /* These identify the driver base version and may not be removed. */ -static const char version[] __devinitconst = +static const char version[] = KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n" " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; @@ -295,7 +295,7 @@ MODULE_DEVICE_TABLE(pci, starfire_pci_tbl); static const struct chip_info { const char *name; int drv_flags; -} netdrv_tbl[] __devinitconst = { +} netdrv_tbl[] = { { "Adaptec Starfire 6915", CanHaveMII }, }; @@ -641,8 +641,8 @@ static const struct net_device_ops netdev_ops = { #endif }; -static int __devinit starfire_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int starfire_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct device *d = &pdev->dev; struct netdev_private *np; @@ -1990,7 +1990,7 @@ static int starfire_resume(struct pci_dev *pdev) #endif /* CONFIG_PM */ -static void __devexit starfire_remove_one (struct pci_dev *pdev) +static void starfire_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct netdev_private *np = netdev_priv(dev); @@ -2018,7 +2018,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev) static struct pci_driver starfire_driver = { .name = DRV_NAME, .probe = starfire_init_one, - .remove = __devexit_p(starfire_remove_one), + .remove = starfire_remove_one, #ifdef CONFIG_PM .suspend = starfire_suspend, .resume = starfire_resume, diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig index 49a30d37ae4a..a9481606bbcd 100644 --- a/drivers/net/ethernet/adi/Kconfig +++ b/drivers/net/ethernet/adi/Kconfig @@ -62,6 +62,7 @@ config BFIN_RX_DESC_NUM config BFIN_MAC_USE_HWSTAMP bool "Use IEEE 1588 hwstamp" depends on BFIN_MAC && BF518 + select PTP_1588_CLOCK default y ---help--- To support the IEEE 1588 Precision Time Protocol (PTP), select y here diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c index f816426e1085..c1fdb8be8bee 100644 --- a/drivers/net/ethernet/adi/bfin_mac.c +++ b/drivers/net/ethernet/adi/bfin_mac.c @@ -548,14 +548,17 @@ static int bfin_mac_ethtool_setwol(struct net_device *dev, return 0; } +#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP static int bfin_mac_ethtool_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) { + struct bfin_mac_local *lp = netdev_priv(dev); + info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | - SOF_TIMESTAMPING_SYS_HARDWARE; - info->phc_index = -1; + SOF_TIMESTAMPING_RAW_HARDWARE; + info->phc_index = lp->phc_index; info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); @@ -566,6 +569,7 @@ static int bfin_mac_ethtool_get_ts_info(struct net_device *dev, (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT); return 0; } +#endif static const struct ethtool_ops bfin_mac_ethtool_ops = { .get_settings = bfin_mac_ethtool_getsettings, @@ -574,7 +578,9 @@ static const struct ethtool_ops bfin_mac_ethtool_ops = { .get_drvinfo = bfin_mac_ethtool_getdrvinfo, .get_wol = bfin_mac_ethtool_getwol, .set_wol = bfin_mac_ethtool_setwol, +#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP .get_ts_info = bfin_mac_ethtool_get_ts_info, +#endif }; /**************************************************************************/ @@ -649,6 +655,20 @@ static int bfin_mac_set_mac_address(struct net_device *dev, void *p) #ifdef CONFIG_BFIN_MAC_USE_HWSTAMP #define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE) +static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result) +{ + u32 ipn = 1000000000UL / input_clk; + u32 ppn = 1; + unsigned int shift = 0; + + while (ppn <= ipn) { + ppn <<= 1; + shift++; + } + *shift_result = shift; + return 1000000000UL / ppn; +} + static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { @@ -798,19 +818,7 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, bfin_read_EMAC_PTP_TXSNAPLO(); bfin_read_EMAC_PTP_TXSNAPHI(); - /* - * Set registers so that rollover occurs soon to test this. - */ - bfin_write_EMAC_PTP_TIMELO(0x00000000); - bfin_write_EMAC_PTP_TIMEHI(0xFF800000); - SSYNC(); - - lp->compare.last_update = 0; - timecounter_init(&lp->clock, - &lp->cycles, - ktime_to_ns(ktime_get_real())); - timecompare_update(&lp->compare, 0); } lp->stamp_cfg = config; @@ -818,15 +826,6 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev, -EFAULT : 0; } -static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompare *cmp) -{ - ktime_t sys = ktime_get_real(); - - pr_debug("%s %s hardware:%d,%d transform system:%d,%d system:%d,%d, cmp:%lld, %lld\n", - __func__, s, hw->tv.sec, hw->tv.nsec, ts->tv.sec, ts->tv.nsec, sys.tv.sec, - sys.tv.nsec, cmp->offset, cmp->skew); -} - static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) { struct bfin_mac_local *lp = netdev_priv(netdev); @@ -857,15 +856,9 @@ static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) regval = bfin_read_EMAC_PTP_TXSNAPLO(); regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32; memset(&shhwtstamps, 0, sizeof(shhwtstamps)); - ns = timecounter_cyc2time(&lp->clock, - regval); - timecompare_update(&lp->compare, ns); + ns = regval << lp->shift; shhwtstamps.hwtstamp = ns_to_ktime(ns); - shhwtstamps.syststamp = - timecompare_transform(&lp->compare, ns); skb_tstamp_tx(skb, &shhwtstamps); - - bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare); } } } @@ -888,55 +881,184 @@ static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) regval = bfin_read_EMAC_PTP_RXSNAPLO(); regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32; - ns = timecounter_cyc2time(&lp->clock, regval); - timecompare_update(&lp->compare, ns); + ns = regval << lp->shift; memset(shhwtstamps, 0, sizeof(*shhwtstamps)); shhwtstamps->hwtstamp = ns_to_ktime(ns); - shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns); +} + +static void bfin_mac_hwtstamp_init(struct net_device *netdev) +{ + struct bfin_mac_local *lp = netdev_priv(netdev); + u64 addend, ppb; + u32 input_clk, phc_clk; + + /* Initialize hardware timer */ + input_clk = get_sclk(); + phc_clk = bfin_select_phc_clock(input_clk, &lp->shift); + addend = phc_clk * (1ULL << 32); + do_div(addend, input_clk); + bfin_write_EMAC_PTP_ADDEND((u32)addend); + + lp->addend = addend; + ppb = 1000000000ULL * input_clk; + do_div(ppb, phc_clk); + lp->max_ppb = ppb - 1000000000ULL - 1ULL; - bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare); + /* Initialize hwstamp config */ + lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE; + lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF; } -/* - * bfin_read_clock - read raw cycle counter (to be used by time counter) - */ -static cycle_t bfin_read_clock(const struct cyclecounter *tc) +static u64 bfin_ptp_time_read(struct bfin_mac_local *lp) { - u64 stamp; + u64 ns; + u32 lo, hi; + + lo = bfin_read_EMAC_PTP_TIMELO(); + hi = bfin_read_EMAC_PTP_TIMEHI(); - stamp = bfin_read_EMAC_PTP_TIMELO(); - stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL; + ns = ((u64) hi) << 32; + ns |= lo; + ns <<= lp->shift; - return stamp; + return ns; } -#define PTP_CLK 25000000 +static void bfin_ptp_time_write(struct bfin_mac_local *lp, u64 ns) +{ + u32 hi, lo; -static void bfin_mac_hwtstamp_init(struct net_device *netdev) + ns >>= lp->shift; + hi = ns >> 32; + lo = ns & 0xffffffff; + + bfin_write_EMAC_PTP_TIMELO(lo); + bfin_write_EMAC_PTP_TIMEHI(hi); +} + +/* PTP Hardware Clock operations */ + +static int bfin_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) +{ + u64 adj; + u32 diff, addend; + int neg_adj = 0; + struct bfin_mac_local *lp = + container_of(ptp, struct bfin_mac_local, caps); + + if (ppb < 0) { + neg_adj = 1; + ppb = -ppb; + } + addend = lp->addend; + adj = addend; + adj *= ppb; + diff = div_u64(adj, 1000000000ULL); + + addend = neg_adj ? addend - diff : addend + diff; + + bfin_write_EMAC_PTP_ADDEND(addend); + + return 0; +} + +static int bfin_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + s64 now; + unsigned long flags; + struct bfin_mac_local *lp = + container_of(ptp, struct bfin_mac_local, caps); + + spin_lock_irqsave(&lp->phc_lock, flags); + + now = bfin_ptp_time_read(lp); + now += delta; + bfin_ptp_time_write(lp, now); + + spin_unlock_irqrestore(&lp->phc_lock, flags); + + return 0; +} + +static int bfin_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts) +{ + u64 ns; + u32 remainder; + unsigned long flags; + struct bfin_mac_local *lp = + container_of(ptp, struct bfin_mac_local, caps); + + spin_lock_irqsave(&lp->phc_lock, flags); + + ns = bfin_ptp_time_read(lp); + + spin_unlock_irqrestore(&lp->phc_lock, flags); + + ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); + ts->tv_nsec = remainder; + return 0; +} + +static int bfin_ptp_settime(struct ptp_clock_info *ptp, + const struct timespec *ts) +{ + u64 ns; + unsigned long flags; + struct bfin_mac_local *lp = + container_of(ptp, struct bfin_mac_local, caps); + + ns = ts->tv_sec * 1000000000ULL; + ns += ts->tv_nsec; + + spin_lock_irqsave(&lp->phc_lock, flags); + + bfin_ptp_time_write(lp, ns); + + spin_unlock_irqrestore(&lp->phc_lock, flags); + + return 0; +} + +static int bfin_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + return -EOPNOTSUPP; +} + +static struct ptp_clock_info bfin_ptp_caps = { + .owner = THIS_MODULE, + .name = "BF518 clock", + .max_adj = 0, + .n_alarm = 0, + .n_ext_ts = 0, + .n_per_out = 0, + .pps = 0, + .adjfreq = bfin_ptp_adjfreq, + .adjtime = bfin_ptp_adjtime, + .gettime = bfin_ptp_gettime, + .settime = bfin_ptp_settime, + .enable = bfin_ptp_enable, +}; + +static int bfin_phc_init(struct net_device *netdev, struct device *dev) { struct bfin_mac_local *lp = netdev_priv(netdev); - u64 append; - /* Initialize hardware timer */ - append = PTP_CLK * (1ULL << 32); - do_div(append, get_sclk()); - bfin_write_EMAC_PTP_ADDEND((u32)append); - - memset(&lp->cycles, 0, sizeof(lp->cycles)); - lp->cycles.read = bfin_read_clock; - lp->cycles.mask = CLOCKSOURCE_MASK(64); - lp->cycles.mult = 1000000000 / PTP_CLK; - lp->cycles.shift = 0; - - /* Synchronize our NIC clock against system wall clock */ - memset(&lp->compare, 0, sizeof(lp->compare)); - lp->compare.source = &lp->clock; - lp->compare.target = ktime_get_real; - lp->compare.num_samples = 10; + lp->caps = bfin_ptp_caps; + lp->caps.max_adj = lp->max_ppb; + lp->clock = ptp_clock_register(&lp->caps, dev); + if (IS_ERR(lp->clock)) + return PTR_ERR(lp->clock); - /* Initialize hwstamp config */ - lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE; - lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF; + lp->phc_index = ptp_clock_index(lp->clock); + spin_lock_init(&lp->phc_lock); + + return 0; +} + +static void bfin_phc_release(struct bfin_mac_local *lp) +{ + ptp_clock_unregister(lp->clock); } #else @@ -945,6 +1067,8 @@ static void bfin_mac_hwtstamp_init(struct net_device *netdev) # define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP) # define bfin_rx_hwtstamp(dev, skb) # define bfin_tx_hwtstamp(dev, skb) +# define bfin_phc_init(netdev, dev) 0 +# define bfin_phc_release(lp) #endif static inline void _tx_reclaim_skb(void) @@ -1479,7 +1603,7 @@ static const struct net_device_ops bfin_mac_netdev_ops = { #endif }; -static int __devinit bfin_mac_probe(struct platform_device *pdev) +static int bfin_mac_probe(struct platform_device *pdev) { struct net_device *ndev; struct bfin_mac_local *lp; @@ -1579,12 +1703,17 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) } bfin_mac_hwtstamp_init(ndev); + if (bfin_phc_init(ndev, &pdev->dev)) { + dev_err(&pdev->dev, "Cannot register PHC device!\n"); + goto out_err_phc; + } /* now, print out the card info, in a short format.. */ netdev_info(ndev, "%s, Version %s\n", DRV_DESC, DRV_VERSION); return 0; +out_err_phc: out_err_reg_ndev: free_irq(IRQ_MAC_RX, ndev); out_err_request_irq: @@ -1598,11 +1727,13 @@ out_err_probe_mac: return rc; } -static int __devexit bfin_mac_remove(struct platform_device *pdev) +static int bfin_mac_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct bfin_mac_local *lp = netdev_priv(ndev); + bfin_phc_release(lp); + platform_set_drvdata(pdev, NULL); lp->mii_bus->priv = NULL; @@ -1655,7 +1786,7 @@ static int bfin_mac_resume(struct platform_device *pdev) #define bfin_mac_resume NULL #endif /* CONFIG_PM */ -static int __devinit bfin_mii_bus_probe(struct platform_device *pdev) +static int bfin_mii_bus_probe(struct platform_device *pdev) { struct mii_bus *miibus; struct bfin_mii_bus_platform_data *mii_bus_pd; @@ -1733,7 +1864,7 @@ out_err_alloc: return rc; } -static int __devexit bfin_mii_bus_remove(struct platform_device *pdev) +static int bfin_mii_bus_remove(struct platform_device *pdev) { struct mii_bus *miibus = platform_get_drvdata(pdev); struct bfin_mii_bus_platform_data *mii_bus_pd = @@ -1750,7 +1881,7 @@ static int __devexit bfin_mii_bus_remove(struct platform_device *pdev) static struct platform_driver bfin_mii_bus_driver = { .probe = bfin_mii_bus_probe, - .remove = __devexit_p(bfin_mii_bus_remove), + .remove = bfin_mii_bus_remove, .driver = { .name = "bfin_mii_bus", .owner = THIS_MODULE, @@ -1759,7 +1890,7 @@ static struct platform_driver bfin_mii_bus_driver = { static struct platform_driver bfin_mac_driver = { .probe = bfin_mac_probe, - .remove = __devexit_p(bfin_mac_remove), + .remove = bfin_mac_remove, .resume = bfin_mac_resume, .suspend = bfin_mac_suspend, .driver = { diff --git a/drivers/net/ethernet/adi/bfin_mac.h b/drivers/net/ethernet/adi/bfin_mac.h index 960905c08223..7a07ee07906b 100644 --- a/drivers/net/ethernet/adi/bfin_mac.h +++ b/drivers/net/ethernet/adi/bfin_mac.h @@ -11,8 +11,7 @@ #define _BFIN_MAC_H_ #include <linux/net_tstamp.h> -#include <linux/clocksource.h> -#include <linux/timecompare.h> +#include <linux/ptp_clock_kernel.h> #include <linux/timer.h> #include <linux/etherdevice.h> #include <linux/bfin_mac.h> @@ -94,10 +93,14 @@ struct bfin_mac_local { struct mii_bus *mii_bus; #if defined(CONFIG_BFIN_MAC_USE_HWSTAMP) - struct cyclecounter cycles; - struct timecounter clock; - struct timecompare compare; + u32 addend; + unsigned int shift; + s32 max_ppb; struct hwtstamp_config stamp_cfg; + struct ptp_clock_info caps; + struct ptp_clock *clock; + int phc_index; + spinlock_t phc_lock; /* protects time lo/hi registers */ #endif }; diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c index 9c77c736f171..aa53115bb38b 100644 --- a/drivers/net/ethernet/aeroflex/greth.c +++ b/drivers/net/ethernet/aeroflex/greth.c @@ -1376,7 +1376,7 @@ error: } /* Initialize the GRETH MAC */ -static int __devinit greth_of_probe(struct platform_device *ofdev) +static int greth_of_probe(struct platform_device *ofdev) { struct net_device *dev; struct greth_private *greth; @@ -1576,7 +1576,7 @@ error1: return err; } -static int __devexit greth_of_remove(struct platform_device *of_dev) +static int greth_of_remove(struct platform_device *of_dev) { struct net_device *ndev = dev_get_drvdata(&of_dev->dev); struct greth_private *greth = netdev_priv(ndev); @@ -1619,7 +1619,7 @@ static struct platform_driver greth_of_driver = { .of_match_table = greth_of_match, }, .probe = greth_of_probe, - .remove = __devexit_p(greth_of_remove), + .remove = greth_of_remove, }; module_platform_driver(greth_of_driver); diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c index 7219123fa0a4..c0bc41a784ca 100644 --- a/drivers/net/ethernet/alteon/acenic.c +++ b/drivers/net/ethernet/alteon/acenic.c @@ -426,7 +426,7 @@ MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descript MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)"); -static const char version[] __devinitconst = +static const char version[] = "acenic.c: v0.92 08/05/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n"; @@ -454,8 +454,8 @@ static const struct net_device_ops ace_netdev_ops = { .ndo_change_mtu = ace_change_mtu, }; -static int __devinit acenic_probe_one(struct pci_dev *pdev, - const struct pci_device_id *id) +static int acenic_probe_one(struct pci_dev *pdev, + const struct pci_device_id *id) { struct net_device *dev; struct ace_private *ap; @@ -603,7 +603,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev, return -ENODEV; } -static void __devexit acenic_remove_one(struct pci_dev *pdev) +static void acenic_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct ace_private *ap = netdev_priv(dev); @@ -699,7 +699,7 @@ static struct pci_driver acenic_pci_driver = { .name = "acenic", .id_table = acenic_pci_tbl, .probe = acenic_probe_one, - .remove = __devexit_p(acenic_remove_one), + .remove = acenic_remove_one, }; static int __init acenic_init(void) @@ -871,7 +871,7 @@ static inline void ace_issue_cmd(struct ace_regs __iomem *regs, struct cmd *cmd) } -static int __devinit ace_init(struct net_device *dev) +static int ace_init(struct net_device *dev) { struct ace_private *ap; struct ace_regs __iomem *regs; @@ -2824,8 +2824,8 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev) } -static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src, - u32 dest, int size) +static void ace_copy(struct ace_regs __iomem *regs, const __be32 *src, + u32 dest, int size) { void __iomem *tdest; short tsize, i; @@ -2851,7 +2851,7 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src, } -static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int size) +static void ace_clear(struct ace_regs __iomem *regs, u32 dest, int size) { void __iomem *tdest; short tsize = 0, i; @@ -2882,7 +2882,7 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz * This operation requires the NIC to be halted and is performed with * interrupts disabled and with the spinlock hold. */ -static int __devinit ace_load_firmware(struct net_device *dev) +static int ace_load_firmware(struct net_device *dev) { const struct firmware *fw; const char *fw_name = "acenic/tg2.bin"; @@ -2962,7 +2962,7 @@ static int __devinit ace_load_firmware(struct net_device *dev) * Thanks to Stevarino Webinski for helping tracking down the bugs in the * code i2c readout code by beta testing all my hacks. */ -static void __devinit eeprom_start(struct ace_regs __iomem *regs) +static void eeprom_start(struct ace_regs __iomem *regs) { u32 local; @@ -2991,7 +2991,7 @@ static void __devinit eeprom_start(struct ace_regs __iomem *regs) } -static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic) +static void eeprom_prep(struct ace_regs __iomem *regs, u8 magic) { short i; u32 local; @@ -3028,7 +3028,7 @@ static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic) } -static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs) +static int eeprom_check_ack(struct ace_regs __iomem *regs) { int state; u32 local; @@ -3056,7 +3056,7 @@ static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs) } -static void __devinit eeprom_stop(struct ace_regs __iomem *regs) +static void eeprom_stop(struct ace_regs __iomem *regs) { u32 local; @@ -3091,8 +3091,7 @@ static void __devinit eeprom_stop(struct ace_regs __iomem *regs) /* * Read a whole byte from the EEPROM. */ -static int __devinit read_eeprom_byte(struct net_device *dev, - unsigned long offset) +static int read_eeprom_byte(struct net_device *dev, unsigned long offset) { struct ace_private *ap = netdev_priv(dev); struct ace_regs __iomem *regs = ap->regs; diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c index 689dfcafc6d4..3789affbc0e5 100644 --- a/drivers/net/ethernet/amd/a2065.c +++ b/drivers/net/ethernet/amd/a2065.c @@ -639,12 +639,12 @@ static void lance_set_multicast(struct net_device *dev) netif_wake_queue(dev); } -static int __devinit a2065_init_one(struct zorro_dev *z, - const struct zorro_device_id *ent); -static void __devexit a2065_remove_one(struct zorro_dev *z); +static int a2065_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent); +static void a2065_remove_one(struct zorro_dev *z); -static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = { +static struct zorro_device_id a2065_zorro_tbl[] = { { ZORRO_PROD_CBM_A2065_1 }, { ZORRO_PROD_CBM_A2065_2 }, { ZORRO_PROD_AMERISTAR_A2065 }, @@ -656,7 +656,7 @@ static struct zorro_driver a2065_driver = { .name = "a2065", .id_table = a2065_zorro_tbl, .probe = a2065_init_one, - .remove = __devexit_p(a2065_remove_one), + .remove = a2065_remove_one, }; static const struct net_device_ops lance_netdev_ops = { @@ -670,8 +670,8 @@ static const struct net_device_ops lance_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, }; -static int __devinit a2065_init_one(struct zorro_dev *z, - const struct zorro_device_id *ent) +static int a2065_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent) { struct net_device *dev; struct lance_private *priv; @@ -754,7 +754,7 @@ static int __devinit a2065_init_one(struct zorro_dev *z, } -static void __devexit a2065_remove_one(struct zorro_dev *z) +static void a2065_remove_one(struct zorro_dev *z) { struct net_device *dev = zorro_get_drvdata(z); diff --git a/drivers/net/ethernet/amd/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c index e10ffad525a7..60e2b701afe7 100644 --- a/drivers/net/ethernet/amd/am79c961a.c +++ b/drivers/net/ethernet/amd/am79c961a.c @@ -671,7 +671,7 @@ static const struct net_device_ops am79c961_netdev_ops = { #endif }; -static int __devinit am79c961_probe(struct platform_device *pdev) +static int am79c961_probe(struct platform_device *pdev) { struct resource *res; struct net_device *dev; diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index 3491d4312fc9..42d4e6ad58a5 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c @@ -1702,7 +1702,7 @@ static int amd8111e_resume(struct pci_dev *pci_dev) } -static void __devexit amd8111e_remove_one(struct pci_dev *pdev) +static void amd8111e_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); if (dev) { @@ -1774,7 +1774,7 @@ static void amd8111e_config_ipg(struct net_device* dev) } -static void __devinit amd8111e_probe_ext_phy(struct net_device* dev) +static void amd8111e_probe_ext_phy(struct net_device *dev) { struct amd8111e_priv *lp = netdev_priv(dev); int i; @@ -1810,7 +1810,7 @@ static const struct net_device_ops amd8111e_netdev_ops = { #endif }; -static int __devinit amd8111e_probe_one(struct pci_dev *pdev, +static int amd8111e_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int err,i,pm_cap; @@ -1976,7 +1976,7 @@ static struct pci_driver amd8111e_driver = { .name = MODULE_NAME, .id_table = amd8111e_pci_tbl, .probe = amd8111e_probe_one, - .remove = __devexit_p(amd8111e_remove_one), + .remove = amd8111e_remove_one, .suspend = amd8111e_suspend, .resume = amd8111e_resume }; diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c index f2958df9a1e4..98f4522fd17b 100644 --- a/drivers/net/ethernet/amd/ariadne.c +++ b/drivers/net/ethernet/amd/ariadne.c @@ -682,7 +682,7 @@ static void set_multicast_list(struct net_device *dev) } -static void __devexit ariadne_remove_one(struct zorro_dev *z) +static void ariadne_remove_one(struct zorro_dev *z) { struct net_device *dev = zorro_get_drvdata(z); @@ -692,7 +692,7 @@ static void __devexit ariadne_remove_one(struct zorro_dev *z) free_netdev(dev); } -static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = { +static struct zorro_device_id ariadne_zorro_tbl[] = { { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE }, { 0 } }; @@ -710,8 +710,8 @@ static const struct net_device_ops ariadne_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, }; -static int __devinit ariadne_init_one(struct zorro_dev *z, - const struct zorro_device_id *ent) +static int ariadne_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent) { unsigned long board = z->resource.start; unsigned long base_addr = board + ARIADNE_LANCE; @@ -774,7 +774,7 @@ static struct zorro_driver ariadne_driver = { .name = "ariadne", .id_table = ariadne_zorro_tbl, .probe = ariadne_init_one, - .remove = __devexit_p(ariadne_remove_one), + .remove = ariadne_remove_one, }; static int __init ariadne_init_module(void) diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index f195acfa2df7..2ea221ed4777 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -1016,7 +1016,7 @@ static const struct net_device_ops au1000_netdev_ops = { .ndo_change_mtu = eth_change_mtu, }; -static int __devinit au1000_probe(struct platform_device *pdev) +static int au1000_probe(struct platform_device *pdev) { static unsigned version_printed; struct au1000_private *aup = NULL; @@ -1295,7 +1295,7 @@ out: return err; } -static int __devexit au1000_remove(struct platform_device *pdev) +static int au1000_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct au1000_private *aup = netdev_priv(dev); @@ -1340,7 +1340,7 @@ static int __devexit au1000_remove(struct platform_device *pdev) static struct platform_driver au1000_eth_driver = { .probe = au1000_probe, - .remove = __devexit_p(au1000_remove), + .remove = au1000_remove, .driver = { .name = "au1000-eth", .owner = THIS_MODULE, diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c index 7203b522f234..baca0bd1b393 100644 --- a/drivers/net/ethernet/amd/declance.c +++ b/drivers/net/ethernet/amd/declance.c @@ -72,7 +72,7 @@ #include <asm/dec/machtype.h> #include <asm/dec/system.h> -static char version[] __devinitdata = +static char version[] = "declance.c: v0.011 by Linux MIPS DECstation task force\n"; MODULE_AUTHOR("Linux MIPS DECstation task force"); @@ -1020,7 +1020,7 @@ static const struct net_device_ops lance_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, }; -static int __devinit dec_lance_probe(struct device *bdev, const int type) +static int dec_lance_probe(struct device *bdev, const int type) { static unsigned version_printed; static const char fmt[] = "declance%d"; @@ -1322,7 +1322,7 @@ static void __exit dec_lance_platform_remove(void) } #ifdef CONFIG_TC -static int __devinit dec_lance_tc_probe(struct device *dev); +static int dec_lance_tc_probe(struct device *dev); static int __exit dec_lance_tc_remove(struct device *dev); static const struct tc_device_id dec_lance_tc_table[] = { @@ -1341,7 +1341,7 @@ static struct tc_driver dec_lance_tc_driver = { }, }; -static int __devinit dec_lance_tc_probe(struct device *dev) +static int dec_lance_tc_probe(struct device *dev) { int status = dec_lance_probe(dev, PMAD_LANCE); if (!status) diff --git a/drivers/net/ethernet/amd/depca.c b/drivers/net/ethernet/amd/depca.c index c771de71612a..34a485363d5b 100644 --- a/drivers/net/ethernet/amd/depca.c +++ b/drivers/net/ethernet/amd/depca.c @@ -338,21 +338,21 @@ static struct eisa_driver depca_eisa_driver = { .driver = { .name = depca_string, .probe = depca_eisa_probe, - .remove = __devexit_p (depca_device_remove) + .remove = depca_device_remove } }; #endif static int depca_isa_probe (struct platform_device *); -static int __devexit depca_isa_remove(struct platform_device *pdev) +static int depca_isa_remove(struct platform_device *pdev) { return depca_device_remove(&pdev->dev); } static struct platform_driver depca_isa_driver = { .probe = depca_isa_probe, - .remove = __devexit_p(depca_isa_remove), + .remove = depca_isa_remove, .driver = { .name = depca_string, }, @@ -1320,7 +1320,7 @@ static enum depca_type __init depca_shmem_probe (ulong *mem_start) return adapter; } -static int __devinit depca_isa_probe (struct platform_device *device) +static int depca_isa_probe(struct platform_device *device) { struct net_device *dev; struct depca_private *lp; @@ -1412,7 +1412,7 @@ static int __init depca_eisa_probe (struct device *device) } #endif -static int __devexit depca_device_remove (struct device *device) +static int depca_device_remove(struct device *device) { struct net_device *dev; struct depca_private *lp; diff --git a/drivers/net/ethernet/amd/hplance.c b/drivers/net/ethernet/amd/hplance.c index 8baff4e5d964..0c61fd50d882 100644 --- a/drivers/net/ethernet/amd/hplance.c +++ b/drivers/net/ethernet/amd/hplance.c @@ -46,11 +46,9 @@ struct hplance_private { * plus board-specific init, open and close actions. * Oh, and we need to tell the generic code how to read and write LANCE registers... */ -static int __devinit hplance_init_one(struct dio_dev *d, - const struct dio_device_id *ent); -static void __devinit hplance_init(struct net_device *dev, - struct dio_dev *d); -static void __devexit hplance_remove_one(struct dio_dev *d); +static int hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent); +static void hplance_init(struct net_device *dev, struct dio_dev *d); +static void hplance_remove_one(struct dio_dev *d); static void hplance_writerap(void *priv, unsigned short value); static void hplance_writerdp(void *priv, unsigned short value); static unsigned short hplance_readrdp(void *priv); @@ -66,7 +64,7 @@ static struct dio_driver hplance_driver = { .name = "hplance", .id_table = hplance_dio_tbl, .probe = hplance_init_one, - .remove = __devexit_p(hplance_remove_one), + .remove = hplance_remove_one, }; static const struct net_device_ops hplance_netdev_ops = { @@ -83,8 +81,7 @@ static const struct net_device_ops hplance_netdev_ops = { }; /* Find all the HP Lance boards and initialise them... */ -static int __devinit hplance_init_one(struct dio_dev *d, - const struct dio_device_id *ent) +static int hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent) { struct net_device *dev; int err = -ENOMEM; @@ -118,7 +115,7 @@ static int __devinit hplance_init_one(struct dio_dev *d, return err; } -static void __devexit hplance_remove_one(struct dio_dev *d) +static void hplance_remove_one(struct dio_dev *d) { struct net_device *dev = dio_get_drvdata(d); @@ -128,7 +125,7 @@ static void __devexit hplance_remove_one(struct dio_dev *d) } /* Initialise a single lance board at the given DIO device */ -static void __devinit hplance_init(struct net_device *dev, struct dio_dev *d) +static void hplance_init(struct net_device *dev, struct dio_dev *d) { unsigned long va = (d->resource.start + DIO_VIRADDRBASE); struct hplance_private *lp; diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index 86b6d8e4e6cd..a227ccdcb9b5 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c @@ -1443,7 +1443,7 @@ static const struct ethtool_ops pcnet32_ethtool_ops = { /* only probes for non-PCI devices, the rest are handled by * pci_register_driver via pcnet32_probe_pci */ -static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist) +static void pcnet32_probe_vlbus(unsigned int *pcnet32_portlist) { unsigned int *port, ioaddr; @@ -1462,7 +1462,7 @@ static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist) } } -static int __devinit +static int pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) { unsigned long ioaddr; @@ -1521,7 +1521,7 @@ static const struct net_device_ops pcnet32_netdev_ops = { * Called from both pcnet32_probe_vlbus and pcnet_probe_pci. * pdev will be NULL when called from pcnet32_probe_vlbus. */ -static int __devinit +static int pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) { struct pcnet32_private *lp; @@ -2823,7 +2823,7 @@ static int pcnet32_pm_resume(struct pci_dev *pdev) return 0; } -static void __devexit pcnet32_remove_one(struct pci_dev *pdev) +static void pcnet32_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -2844,7 +2844,7 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev) static struct pci_driver pcnet32_driver = { .name = DRV_NAME, .probe = pcnet32_probe_pci, - .remove = __devexit_p(pcnet32_remove_one), + .remove = pcnet32_remove_one, .id_table = pcnet32_pci_tbl, .suspend = pcnet32_pm_suspend, .resume = pcnet32_pm_resume, diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c index d7a3533d990b..c2d696c88e46 100644 --- a/drivers/net/ethernet/amd/sunlance.c +++ b/drivers/net/ethernet/amd/sunlance.c @@ -1304,9 +1304,9 @@ static const struct net_device_ops sparc_lance_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit sparc_lance_probe_one(struct platform_device *op, - struct platform_device *ledma, - struct platform_device *lebuffer) +static int sparc_lance_probe_one(struct platform_device *op, + struct platform_device *ledma, + struct platform_device *lebuffer) { struct device_node *dp = op->dev.of_node; static unsigned version_printed; @@ -1488,7 +1488,7 @@ fail: return -ENODEV; } -static int __devinit sunlance_sbus_probe(struct platform_device *op) +static int sunlance_sbus_probe(struct platform_device *op) { struct platform_device *parent = to_platform_device(op->dev.parent); struct device_node *parent_dp = parent->dev.of_node; @@ -1504,7 +1504,7 @@ static int __devinit sunlance_sbus_probe(struct platform_device *op) return err; } -static int __devexit sunlance_sbus_remove(struct platform_device *op) +static int sunlance_sbus_remove(struct platform_device *op) { struct lance_private *lp = dev_get_drvdata(&op->dev); struct net_device *net_dev = lp->dev; @@ -1536,7 +1536,7 @@ static struct platform_driver sunlance_sbus_driver = { .of_match_table = sunlance_sbus_match, }, .probe = sunlance_sbus_probe, - .remove = __devexit_p(sunlance_sbus_remove), + .remove = sunlance_sbus_remove, }; module_platform_driver(sunlance_sbus_driver); diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c index 855bdafb1a87..f36bbd6d5085 100644 --- a/drivers/net/ethernet/apple/bmac.c +++ b/drivers/net/ethernet/apple/bmac.c @@ -1244,7 +1244,7 @@ static const struct net_device_ops bmac_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_id *match) +static int bmac_probe(struct macio_dev *mdev, const struct of_device_id *match) { int j, rev, ret; struct bmac_data *bp; @@ -1602,7 +1602,7 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length) } #endif -static int __devexit bmac_remove(struct macio_dev *mdev) +static int bmac_remove(struct macio_dev *mdev) { struct net_device *dev = macio_get_drvdata(mdev); struct bmac_data *bp = netdev_priv(dev); diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c index e1df4b76c885..842fe7684904 100644 --- a/drivers/net/ethernet/apple/mace.c +++ b/drivers/net/ethernet/apple/mace.c @@ -106,7 +106,7 @@ static const struct net_device_ops mace_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_id *match) +static int mace_probe(struct macio_dev *mdev, const struct of_device_id *match) { struct device_node *mace = macio_get_of_node(mdev); struct net_device *dev; @@ -271,7 +271,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i return rc; } -static int __devexit mace_remove(struct macio_dev *mdev) +static int mace_remove(struct macio_dev *mdev) { struct net_device *dev = macio_get_drvdata(mdev); struct mace_data *mp; diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c index a92ddee7f665..a206779c68cf 100644 --- a/drivers/net/ethernet/apple/macmace.c +++ b/drivers/net/ethernet/apple/macmace.c @@ -195,7 +195,7 @@ static const struct net_device_ops mace_netdev_ops = { * model of Macintrash has a MACE (AV macintoshes) */ -static int __devinit mace_probe(struct platform_device *pdev) +static int mace_probe(struct platform_device *pdev) { int j; struct mace_data *mp; @@ -746,7 +746,7 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Macintosh MACE ethernet driver"); MODULE_ALIAS("platform:macmace"); -static int __devexit mac_mace_device_remove (struct platform_device *pdev) +static int mac_mace_device_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct mace_data *mp = netdev_priv(dev); @@ -768,7 +768,7 @@ static int __devexit mac_mace_device_remove (struct platform_device *pdev) static struct platform_driver mac_mace_driver = { .probe = mace_probe, - .remove = __devexit_p(mac_mace_device_remove), + .remove = mac_mace_device_remove, .driver = { .name = mac_mace_string, .owner = THIS_MODULE, diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index d19f82f7597a..56d3f697e0c7 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -643,7 +643,7 @@ static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) * @adapter: board private structure to initialize * */ -static int __devinit atl1c_alloc_queues(struct atl1c_adapter *adapter) +static int atl1c_alloc_queues(struct atl1c_adapter *adapter) { return 0; } @@ -702,7 +702,7 @@ struct atl1c_platform_patch { u32 patch_flag; #define ATL1C_LINK_PATCH 0x1 }; -static const struct atl1c_platform_patch plats[] __devinitconst = { +static const struct atl1c_platform_patch plats[] = { {0x2060, 0xC1, 0x1019, 0x8152, 0x1}, {0x2060, 0xC1, 0x1019, 0x2060, 0x1}, {0x2060, 0xC1, 0x1019, 0xE000, 0x1}, @@ -725,7 +725,7 @@ static const struct atl1c_platform_patch plats[] __devinitconst = { {0}, }; -static void __devinit atl1c_patch_assign(struct atl1c_hw *hw) +static void atl1c_patch_assign(struct atl1c_hw *hw) { struct pci_dev *pdev = hw->adapter->pdev; u32 misc_ctrl; @@ -764,7 +764,7 @@ static void __devinit atl1c_patch_assign(struct atl1c_hw *hw) * Fields are initialized based on PCI device information and * OS network device settings (MTU size). */ -static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) +static int atl1c_sw_init(struct atl1c_adapter *adapter) { struct atl1c_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; @@ -2442,8 +2442,7 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev) * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. */ -static int __devinit atl1c_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct atl1c_adapter *adapter; @@ -2587,7 +2586,7 @@ err_dma: * Hot-Plug event, or because the driver is going to be removed from * memory. */ -static void __devexit atl1c_remove(struct pci_dev *pdev) +static void atl1c_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct atl1c_adapter *adapter = netdev_priv(netdev); @@ -2697,7 +2696,7 @@ static struct pci_driver atl1c_driver = { .name = atl1c_driver_name, .id_table = atl1c_pci_tbl, .probe = atl1c_probe, - .remove = __devexit_p(atl1c_remove), + .remove = atl1c_remove, .shutdown = atl1c_shutdown, .err_handler = &atl1c_err_handler, .driver.pm = &atl1c_pm_ops, diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index e213da29e73d..e4466a36d106 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -534,7 +534,7 @@ static void atl1e_setup_pcicmd(struct pci_dev *pdev) * @adapter: board private structure to initialize * */ -static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter) +static int atl1e_alloc_queues(struct atl1e_adapter *adapter) { return 0; } @@ -547,7 +547,7 @@ static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter) * Fields are initialized based on PCI device information and * OS network device settings (MTU size). */ -static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter) +static int atl1e_sw_init(struct atl1e_adapter *adapter) { struct atl1e_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; @@ -2235,8 +2235,7 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev) * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. */ -static int __devinit atl1e_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int atl1e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct atl1e_adapter *adapter = NULL; @@ -2387,7 +2386,7 @@ err_dma: * Hot-Plug event, or because the driver is going to be removed from * memory. */ -static void __devexit atl1e_remove(struct pci_dev *pdev) +static void atl1e_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct atl1e_adapter *adapter = netdev_priv(netdev); @@ -2499,7 +2498,7 @@ static struct pci_driver atl1e_driver = { .name = atl1e_driver_name, .id_table = atl1e_pci_tbl, .probe = atl1e_probe, - .remove = __devexit_p(atl1e_remove), + .remove = atl1e_remove, /* Power Management Hooks */ #ifdef CONFIG_PM .suspend = atl1e_suspend, diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_param.c b/drivers/net/ethernet/atheros/atl1e/atl1e_param.c index b5086f1e637f..fa314282c9ad 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_param.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_param.c @@ -40,7 +40,7 @@ #define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET } #define ATL1E_PARAM(x, desc) \ - static int __devinitdata x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \ + static int x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \ static unsigned int num_##x; \ module_param_array_named(x, x, int, &num_##x, 0); \ MODULE_PARM_DESC(x, desc); @@ -116,7 +116,8 @@ struct atl1e_option { } arg; }; -static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, struct atl1e_adapter *adapter) +static int atl1e_validate_option(int *value, struct atl1e_option *opt, + struct atl1e_adapter *adapter) { if (*value == OPTION_UNSET) { *value = opt->def; @@ -177,7 +178,7 @@ static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, * value exists, a default value is used. The final value is stored * in a variable in the adapter structure. */ -void __devinit atl1e_check_options(struct atl1e_adapter *adapter) +void atl1e_check_options(struct atl1e_adapter *adapter) { int bd = adapter->bd_number; diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index 7bae2ad7a7c0..71b3d7daa21d 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c @@ -113,7 +113,7 @@ static const struct ethtool_ops atl1_ethtool_ops; * * Default Value: 100 (200us) */ -static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT; +static int int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT; static unsigned int num_int_mod_timer; module_param_array_named(int_mod_timer, int_mod_timer, int, &num_int_mod_timer, 0); @@ -143,8 +143,8 @@ struct atl1_option { } arg; }; -static int __devinit atl1_validate_option(int *value, struct atl1_option *opt, - struct pci_dev *pdev) +static int atl1_validate_option(int *value, struct atl1_option *opt, + struct pci_dev *pdev) { if (*value == OPTION_UNSET) { *value = opt->def; @@ -204,7 +204,7 @@ static int __devinit atl1_validate_option(int *value, struct atl1_option *opt, * value exists, a default value is used. The final value is stored * in a variable in the adapter structure. */ -static void __devinit atl1_check_options(struct atl1_adapter *adapter) +static void atl1_check_options(struct atl1_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; int bd = adapter->bd_number; @@ -945,7 +945,7 @@ static void atl1_set_mac_addr(struct atl1_hw *hw) * Fields are initialized based on PCI device information and * OS network device settings (MTU size). */ -static int __devinit atl1_sw_init(struct atl1_adapter *adapter) +static int atl1_sw_init(struct atl1_adapter *adapter) { struct atl1_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; @@ -2934,8 +2934,7 @@ static const struct net_device_ops atl1_netdev_ops = { * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. */ -static int __devinit atl1_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int atl1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct atl1_adapter *adapter; @@ -3113,7 +3112,7 @@ err_request_regions: * Hot-Plug event, or because the driver is going to be removed from * memory. */ -static void __devexit atl1_remove(struct pci_dev *pdev) +static void atl1_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct atl1_adapter *adapter; @@ -3146,7 +3145,7 @@ static struct pci_driver atl1_driver = { .name = ATLX_DRIVER_NAME, .id_table = atl1_pci_tbl, .probe = atl1_probe, - .remove = __devexit_p(atl1_remove), + .remove = atl1_remove, .shutdown = atl1_shutdown, .driver.pm = ATL1_PM_OPS, }; diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index 623dd8635c46..aab83a2d4e07 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -83,7 +83,7 @@ static void atl2_check_options(struct atl2_adapter *adapter); * Fields are initialized based on PCI device information and * OS network device settings (MTU size). */ -static int __devinit atl2_sw_init(struct atl2_adapter *adapter) +static int atl2_sw_init(struct atl2_adapter *adapter) { struct atl2_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; @@ -1338,8 +1338,7 @@ static const struct net_device_ops atl2_netdev_ops = { * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. */ -static int __devinit atl2_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct atl2_adapter *adapter; @@ -1498,7 +1497,7 @@ err_dma: */ /* FIXME: write the original MAC address back in case it was changed from a * BIOS-set value, as in atl1 -- CHS */ -static void __devexit atl2_remove(struct pci_dev *pdev) +static void atl2_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct atl2_adapter *adapter = netdev_priv(netdev); @@ -1705,7 +1704,7 @@ static struct pci_driver atl2_driver = { .name = atl2_driver_name, .id_table = atl2_pci_tbl, .probe = atl2_probe, - .remove = __devexit_p(atl2_remove), + .remove = atl2_remove, /* Power Management Hooks */ .suspend = atl2_suspend, #ifdef CONFIG_PM @@ -2845,12 +2844,12 @@ static void atl2_force_ps(struct atl2_hw *hw) */ #define ATL2_PARAM(X, desc) \ - static const int __devinitconst X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \ + static const int X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \ MODULE_PARM(X, "1-" __MODULE_STRING(ATL2_MAX_NIC) "i"); \ MODULE_PARM_DESC(X, desc); #else #define ATL2_PARAM(X, desc) \ - static int __devinitdata X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \ + static int X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \ static unsigned int num_##X; \ module_param_array_named(X, X, int, &num_##X, 0); \ MODULE_PARM_DESC(X, desc); @@ -2934,7 +2933,7 @@ struct atl2_option { } arg; }; -static int __devinit atl2_validate_option(int *value, struct atl2_option *opt) +static int atl2_validate_option(int *value, struct atl2_option *opt) { int i; struct atl2_opt_list *ent; @@ -2992,7 +2991,7 @@ static int __devinit atl2_validate_option(int *value, struct atl2_option *opt) * value exists, a default value is used. The final value is stored * in a variable in the adapter structure. */ -static void __devinit atl2_check_options(struct atl2_adapter *adapter) +static void atl2_check_options(struct atl2_adapter *adapter) { int val; struct atl2_option opt; diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index 4bd416b72e65..f55267363f35 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -102,6 +102,7 @@ config TIGON3 depends on PCI select PHYLIB select HWMON + select PTP_1588_CLOCK ---help--- This driver supports Broadcom Tigon3 based gigabit Ethernet cards. diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 9786c0e9890e..219f6226fcb1 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -2083,7 +2083,7 @@ out: return err; } -static int __devinit b44_get_invariants(struct b44 *bp) +static int b44_get_invariants(struct b44 *bp) { struct ssb_device *sdev = bp->sdev; int err = 0; @@ -2141,8 +2141,8 @@ static const struct net_device_ops b44_netdev_ops = { #endif }; -static int __devinit b44_init_one(struct ssb_device *sdev, - const struct ssb_device_id *ent) +static int b44_init_one(struct ssb_device *sdev, + const struct ssb_device_id *ent) { struct net_device *dev; struct b44 *bp; @@ -2249,7 +2249,7 @@ out: return err; } -static void __devexit b44_remove_one(struct ssb_device *sdev) +static void b44_remove_one(struct ssb_device *sdev) { struct net_device *dev = ssb_get_drvdata(sdev); @@ -2340,7 +2340,7 @@ static struct ssb_driver b44_ssb_driver = { .name = DRV_MODULE_NAME, .id_table = b44_ssb_tbl, .probe = b44_init_one, - .remove = __devexit_p(b44_remove_one), + .remove = b44_remove_one, .suspend = b44_suspend, .resume = b44_resume, }; diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index c7ca7ec065ee..39387d67b722 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -1612,7 +1612,7 @@ static const struct net_device_ops bcm_enet_ops = { /* * allocate netdevice, request register memory and register device. */ -static int __devinit bcm_enet_probe(struct platform_device *pdev) +static int bcm_enet_probe(struct platform_device *pdev) { struct bcm_enet_priv *priv; struct net_device *dev; @@ -1830,7 +1830,7 @@ out: /* * exit func, stops hardware and unregisters netdevice */ -static int __devexit bcm_enet_remove(struct platform_device *pdev) +static int bcm_enet_remove(struct platform_device *pdev) { struct bcm_enet_priv *priv; struct net_device *dev; @@ -1877,7 +1877,7 @@ static int __devexit bcm_enet_remove(struct platform_device *pdev) struct platform_driver bcm63xx_enet_driver = { .probe = bcm_enet_probe, - .remove = __devexit_p(bcm_enet_remove), + .remove = bcm_enet_remove, .driver = { .name = "bcm63xx_enet", .owner = THIS_MODULE, @@ -1887,7 +1887,7 @@ struct platform_driver bcm63xx_enet_driver = { /* * reserve & remap memory space shared between all macs */ -static int __devinit bcm_enet_shared_probe(struct platform_device *pdev) +static int bcm_enet_shared_probe(struct platform_device *pdev) { struct resource *res; unsigned int iomem_size; @@ -1908,7 +1908,7 @@ static int __devinit bcm_enet_shared_probe(struct platform_device *pdev) return 0; } -static int __devexit bcm_enet_shared_remove(struct platform_device *pdev) +static int bcm_enet_shared_remove(struct platform_device *pdev) { struct resource *res; @@ -1924,7 +1924,7 @@ static int __devexit bcm_enet_shared_remove(struct platform_device *pdev) */ struct platform_driver bcm63xx_enet_shared_driver = { .probe = bcm_enet_shared_probe, - .remove = __devexit_p(bcm_enet_shared_remove), + .remove = bcm_enet_shared_remove, .driver = { .name = "bcm63xx_enet_shared", .owner = THIS_MODULE, diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index d4310700c7a7..a1adfaf87f49 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -71,7 +71,7 @@ /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (5*HZ) -static char version[] __devinitdata = +static char version[] = "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>"); @@ -106,7 +106,7 @@ typedef enum { /* indexed by board_t, above */ static struct { char *name; -} board_info[] __devinitdata = { +} board_info[] = { { "Broadcom NetXtreme II BCM5706 1000Base-T" }, { "HP NC370T Multifunction Gigabit Server Adapter" }, { "HP NC370i Multifunction Gigabit Server Adapter" }, @@ -260,10 +260,10 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr) * needs to be skipped. */ diff = txr->tx_prod - txr->tx_cons; - if (unlikely(diff >= TX_DESC_CNT)) { + if (unlikely(diff >= BNX2_TX_DESC_CNT)) { diff &= 0xffff; - if (diff == TX_DESC_CNT) - diff = MAX_TX_DESC_CNT; + if (diff == BNX2_TX_DESC_CNT) + diff = BNX2_MAX_TX_DESC_CNT; } return bp->tx_ring_size - diff; } @@ -274,8 +274,8 @@ bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset) u32 val; spin_lock_bh(&bp->indirect_lock); - REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); - val = REG_RD(bp, BNX2_PCICFG_REG_WINDOW); + BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); + val = BNX2_RD(bp, BNX2_PCICFG_REG_WINDOW); spin_unlock_bh(&bp->indirect_lock); return val; } @@ -284,8 +284,8 @@ static void bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val) { spin_lock_bh(&bp->indirect_lock); - REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); - REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val); + BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset); + BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW, val); spin_unlock_bh(&bp->indirect_lock); } @@ -306,21 +306,21 @@ bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val) { offset += cid_addr; spin_lock_bh(&bp->indirect_lock); - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { int i; - REG_WR(bp, BNX2_CTX_CTX_DATA, val); - REG_WR(bp, BNX2_CTX_CTX_CTRL, - offset | BNX2_CTX_CTX_CTRL_WRITE_REQ); + BNX2_WR(bp, BNX2_CTX_CTX_DATA, val); + BNX2_WR(bp, BNX2_CTX_CTX_CTRL, + offset | BNX2_CTX_CTX_CTRL_WRITE_REQ); for (i = 0; i < 5; i++) { - val = REG_RD(bp, BNX2_CTX_CTX_CTRL); + val = BNX2_RD(bp, BNX2_CTX_CTX_CTRL); if ((val & BNX2_CTX_CTX_CTRL_WRITE_REQ) == 0) break; udelay(5); } } else { - REG_WR(bp, BNX2_CTX_DATA_ADR, offset); - REG_WR(bp, BNX2_CTX_DATA, val); + BNX2_WR(bp, BNX2_CTX_DATA_ADR, offset); + BNX2_WR(bp, BNX2_CTX_DATA, val); } spin_unlock_bh(&bp->indirect_lock); } @@ -434,7 +434,6 @@ struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev) return cp; } -EXPORT_SYMBOL(bnx2_cnic_probe); static void bnx2_cnic_stop(struct bnx2 *bp) @@ -494,11 +493,11 @@ bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val) int i, ret; if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) { - val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); + val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE); val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL; - REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); - REG_RD(bp, BNX2_EMAC_MDIO_MODE); + BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1); + BNX2_RD(bp, BNX2_EMAC_MDIO_MODE); udelay(40); } @@ -506,16 +505,16 @@ bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val) val1 = (bp->phy_addr << 21) | (reg << 16) | BNX2_EMAC_MDIO_COMM_COMMAND_READ | BNX2_EMAC_MDIO_COMM_DISEXT | BNX2_EMAC_MDIO_COMM_START_BUSY; - REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1); + BNX2_WR(bp, BNX2_EMAC_MDIO_COMM, val1); for (i = 0; i < 50; i++) { udelay(10); - val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM); + val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_COMM); if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) { udelay(5); - val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM); + val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_COMM); val1 &= BNX2_EMAC_MDIO_COMM_DATA; break; @@ -532,11 +531,11 @@ bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val) } if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) { - val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); + val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE); val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL; - REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); - REG_RD(bp, BNX2_EMAC_MDIO_MODE); + BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1); + BNX2_RD(bp, BNX2_EMAC_MDIO_MODE); udelay(40); } @@ -551,11 +550,11 @@ bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val) int i, ret; if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) { - val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); + val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE); val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL; - REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); - REG_RD(bp, BNX2_EMAC_MDIO_MODE); + BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1); + BNX2_RD(bp, BNX2_EMAC_MDIO_MODE); udelay(40); } @@ -563,12 +562,12 @@ bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val) val1 = (bp->phy_addr << 21) | (reg << 16) | val | BNX2_EMAC_MDIO_COMM_COMMAND_WRITE | BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT; - REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1); + BNX2_WR(bp, BNX2_EMAC_MDIO_COMM, val1); for (i = 0; i < 50; i++) { udelay(10); - val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM); + val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_COMM); if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) { udelay(5); break; @@ -581,11 +580,11 @@ bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val) ret = 0; if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) { - val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE); + val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE); val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL; - REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1); - REG_RD(bp, BNX2_EMAC_MDIO_MODE); + BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1); + BNX2_RD(bp, BNX2_EMAC_MDIO_MODE); udelay(40); } @@ -601,10 +600,10 @@ bnx2_disable_int(struct bnx2 *bp) for (i = 0; i < bp->irq_nvecs; i++) { bnapi = &bp->bnx2_napi[i]; - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | + BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | BNX2_PCICFG_INT_ACK_CMD_MASK_INT); } - REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD); + BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD); } static void @@ -616,16 +615,16 @@ bnx2_enable_int(struct bnx2 *bp) for (i = 0; i < bp->irq_nvecs; i++) { bnapi = &bp->bnx2_napi[i]; - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | - BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | - BNX2_PCICFG_INT_ACK_CMD_MASK_INT | - bnapi->last_status_idx); + BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | + BNX2_PCICFG_INT_ACK_CMD_MASK_INT | + bnapi->last_status_idx); - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | - BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | - bnapi->last_status_idx); + BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | + bnapi->last_status_idx); } - REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); + BNX2_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); } static void @@ -824,7 +823,7 @@ bnx2_free_mem(struct bnx2 *bp) for (i = 0; i < bp->ctx_pages; i++) { if (bp->ctx_blk[i]) { - dma_free_coherent(&bp->pdev->dev, BCM_PAGE_SIZE, + dma_free_coherent(&bp->pdev->dev, BNX2_PAGE_SIZE, bp->ctx_blk[i], bp->ctx_blk_mapping[i]); bp->ctx_blk[i] = NULL; @@ -887,13 +886,13 @@ bnx2_alloc_mem(struct bnx2 *bp) bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size; - if (CHIP_NUM(bp) == CHIP_NUM_5709) { - bp->ctx_pages = 0x2000 / BCM_PAGE_SIZE; + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { + bp->ctx_pages = 0x2000 / BNX2_PAGE_SIZE; if (bp->ctx_pages == 0) bp->ctx_pages = 1; for (i = 0; i < bp->ctx_pages; i++) { bp->ctx_blk[i] = dma_alloc_coherent(&bp->pdev->dev, - BCM_PAGE_SIZE, + BNX2_PAGE_SIZE, &bp->ctx_blk_mapping[i], GFP_KERNEL); if (bp->ctx_blk[i] == NULL) @@ -1034,7 +1033,7 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp) } if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && - (CHIP_NUM(bp) == CHIP_NUM_5708)) { + (BNX2_CHIP(bp) == BNX2_CHIP_5708)) { u32 val; bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val); @@ -1294,14 +1293,14 @@ bnx2_set_mac_link(struct bnx2 *bp) { u32 val; - REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620); + BNX2_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620); if (bp->link_up && (bp->line_speed == SPEED_1000) && (bp->duplex == DUPLEX_HALF)) { - REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff); + BNX2_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff); } /* Configure the EMAC mode register. */ - val = REG_RD(bp, BNX2_EMAC_MODE); + val = BNX2_RD(bp, BNX2_EMAC_MODE); val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX | BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK | @@ -1310,7 +1309,7 @@ bnx2_set_mac_link(struct bnx2 *bp) if (bp->link_up) { switch (bp->line_speed) { case SPEED_10: - if (CHIP_NUM(bp) != CHIP_NUM_5706) { + if (BNX2_CHIP(bp) != BNX2_CHIP_5706) { val |= BNX2_EMAC_MODE_PORT_MII_10M; break; } @@ -1333,25 +1332,25 @@ bnx2_set_mac_link(struct bnx2 *bp) /* Set the MAC to operate in the appropriate duplex mode. */ if (bp->duplex == DUPLEX_HALF) val |= BNX2_EMAC_MODE_HALF_DUPLEX; - REG_WR(bp, BNX2_EMAC_MODE, val); + BNX2_WR(bp, BNX2_EMAC_MODE, val); /* Enable/disable rx PAUSE. */ bp->rx_mode &= ~BNX2_EMAC_RX_MODE_FLOW_EN; if (bp->flow_ctrl & FLOW_CTRL_RX) bp->rx_mode |= BNX2_EMAC_RX_MODE_FLOW_EN; - REG_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode); + BNX2_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode); /* Enable/disable tx PAUSE. */ - val = REG_RD(bp, BNX2_EMAC_TX_MODE); + val = BNX2_RD(bp, BNX2_EMAC_TX_MODE); val &= ~BNX2_EMAC_TX_MODE_FLOW_EN; if (bp->flow_ctrl & FLOW_CTRL_TX) val |= BNX2_EMAC_TX_MODE_FLOW_EN; - REG_WR(bp, BNX2_EMAC_TX_MODE, val); + BNX2_WR(bp, BNX2_EMAC_TX_MODE, val); /* Acknowledge the interrupt. */ - REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE); + BNX2_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE); bnx2_init_all_rx_contexts(bp); } @@ -1360,7 +1359,7 @@ static void bnx2_enable_bmsr1(struct bnx2 *bp) { if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && - (CHIP_NUM(bp) == CHIP_NUM_5709)) + (BNX2_CHIP(bp) == BNX2_CHIP_5709)) bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_GP_STATUS); } @@ -1369,7 +1368,7 @@ static void bnx2_disable_bmsr1(struct bnx2 *bp) { if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && - (CHIP_NUM(bp) == CHIP_NUM_5709)) + (BNX2_CHIP(bp) == BNX2_CHIP_5709)) bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0); } @@ -1386,7 +1385,7 @@ bnx2_test_and_enable_2g5(struct bnx2 *bp) if (bp->autoneg & AUTONEG_SPEED) bp->advertising |= ADVERTISED_2500baseX_Full; - if (CHIP_NUM(bp) == CHIP_NUM_5709) + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G); bnx2_read_phy(bp, bp->mii_up1, &up1); @@ -1396,7 +1395,7 @@ bnx2_test_and_enable_2g5(struct bnx2 *bp) ret = 0; } - if (CHIP_NUM(bp) == CHIP_NUM_5709) + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0); @@ -1412,7 +1411,7 @@ bnx2_test_and_disable_2g5(struct bnx2 *bp) if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) return 0; - if (CHIP_NUM(bp) == CHIP_NUM_5709) + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G); bnx2_read_phy(bp, bp->mii_up1, &up1); @@ -1422,7 +1421,7 @@ bnx2_test_and_disable_2g5(struct bnx2 *bp) ret = 1; } - if (CHIP_NUM(bp) == CHIP_NUM_5709) + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0); @@ -1438,7 +1437,7 @@ bnx2_enable_forced_2g5(struct bnx2 *bp) if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) return; - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { u32 val; bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, @@ -1454,7 +1453,7 @@ bnx2_enable_forced_2g5(struct bnx2 *bp) MII_BNX2_BLK_ADDR_COMBO_IEEEB0); err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); - } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { + } else if (BNX2_CHIP(bp) == BNX2_CHIP_5708) { err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); if (!err) bmcr |= BCM5708S_BMCR_FORCE_2500; @@ -1482,7 +1481,7 @@ bnx2_disable_forced_2g5(struct bnx2 *bp) if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) return; - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { u32 val; bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, @@ -1496,7 +1495,7 @@ bnx2_disable_forced_2g5(struct bnx2 *bp) MII_BNX2_BLK_ADDR_COMBO_IEEEB0); err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); - } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { + } else if (BNX2_CHIP(bp) == BNX2_CHIP_5708) { err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr); if (!err) bmcr &= ~BCM5708S_BMCR_FORCE_2500; @@ -1547,14 +1546,14 @@ bnx2_set_link(struct bnx2 *bp) bnx2_disable_bmsr1(bp); if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) && - (CHIP_NUM(bp) == CHIP_NUM_5706)) { + (BNX2_CHIP(bp) == BNX2_CHIP_5706)) { u32 val, an_dbg; if (bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN) { bnx2_5706s_force_link_dn(bp, 0); bp->phy_flags &= ~BNX2_PHY_FLAG_FORCED_DOWN; } - val = REG_RD(bp, BNX2_EMAC_STATUS); + val = BNX2_RD(bp, BNX2_EMAC_STATUS); bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG); bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg); @@ -1571,11 +1570,11 @@ bnx2_set_link(struct bnx2 *bp) bp->link_up = 1; if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { - if (CHIP_NUM(bp) == CHIP_NUM_5706) + if (BNX2_CHIP(bp) == BNX2_CHIP_5706) bnx2_5706s_linkup(bp); - else if (CHIP_NUM(bp) == CHIP_NUM_5708) + else if (BNX2_CHIP(bp) == BNX2_CHIP_5708) bnx2_5708s_linkup(bp); - else if (CHIP_NUM(bp) == CHIP_NUM_5709) + else if (BNX2_CHIP(bp) == BNX2_CHIP_5709) bnx2_5709s_linkup(bp); } else { @@ -1757,7 +1756,7 @@ __acquires(&bp->phy_lock) new_bmcr = bmcr & ~BMCR_ANENABLE; new_bmcr |= BMCR_SPEED1000; - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { if (bp->req_line_speed == SPEED_2500) bnx2_enable_forced_2g5(bp); else if (bp->req_line_speed == SPEED_1000) { @@ -1765,7 +1764,7 @@ __acquires(&bp->phy_lock) new_bmcr &= ~0x2000; } - } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { + } else if (BNX2_CHIP(bp) == BNX2_CHIP_5708) { if (bp->req_line_speed == SPEED_2500) new_bmcr |= BCM5708S_BMCR_FORCE_2500; else @@ -1942,8 +1941,8 @@ bnx2_send_heart_beat(struct bnx2 *bp) spin_lock(&bp->indirect_lock); msg = (u32) (++bp->fw_drv_pulse_wr_seq & BNX2_DRV_PULSE_SEQ_MASK); addr = bp->shmem_base + BNX2_DRV_PULSE_MB; - REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr); - REG_WR(bp, BNX2_PCICFG_REG_WINDOW, msg); + BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr); + BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW, msg); spin_unlock(&bp->indirect_lock); } @@ -2230,9 +2229,9 @@ bnx2_init_5708s_phy(struct bnx2 *bp, int reset_phy) bnx2_write_phy(bp, BCM5708S_UP1, val); } - if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || - (CHIP_ID(bp) == CHIP_ID_5708_B0) || - (CHIP_ID(bp) == CHIP_ID_5708_B1)) { + if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0) || + (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B0) || + (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B1)) { /* increase tx signal amplitude */ bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_TX_MISC); @@ -2268,8 +2267,8 @@ bnx2_init_5706s_phy(struct bnx2 *bp, int reset_phy) bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT; - if (CHIP_NUM(bp) == CHIP_NUM_5706) - REG_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300); + if (BNX2_CHIP(bp) == BNX2_CHIP_5706) + BNX2_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300); if (bp->dev->mtu > 1500) { u32 val; @@ -2368,7 +2367,7 @@ __acquires(&bp->phy_lock) bp->mii_adv = MII_ADVERTISE; bp->mii_lpa = MII_LPA; - REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); + BNX2_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) goto setup_phy; @@ -2379,11 +2378,11 @@ __acquires(&bp->phy_lock) bp->phy_id |= val & 0xffff; if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { - if (CHIP_NUM(bp) == CHIP_NUM_5706) + if (BNX2_CHIP(bp) == BNX2_CHIP_5706) rc = bnx2_init_5706s_phy(bp, reset_phy); - else if (CHIP_NUM(bp) == CHIP_NUM_5708) + else if (BNX2_CHIP(bp) == BNX2_CHIP_5708) rc = bnx2_init_5708s_phy(bp, reset_phy); - else if (CHIP_NUM(bp) == CHIP_NUM_5709) + else if (BNX2_CHIP(bp) == BNX2_CHIP_5709) rc = bnx2_init_5709s_phy(bp, reset_phy); } else { @@ -2402,10 +2401,10 @@ bnx2_set_mac_loopback(struct bnx2 *bp) { u32 mac_mode; - mac_mode = REG_RD(bp, BNX2_EMAC_MODE); + mac_mode = BNX2_RD(bp, BNX2_EMAC_MODE); mac_mode &= ~BNX2_EMAC_MODE_PORT; mac_mode |= BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK; - REG_WR(bp, BNX2_EMAC_MODE, mac_mode); + BNX2_WR(bp, BNX2_EMAC_MODE, mac_mode); bp->link_up = 1; return 0; } @@ -2431,13 +2430,13 @@ bnx2_set_phy_loopback(struct bnx2 *bp) msleep(100); } - mac_mode = REG_RD(bp, BNX2_EMAC_MODE); + mac_mode = BNX2_RD(bp, BNX2_EMAC_MODE); mac_mode &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX | BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK | BNX2_EMAC_MODE_25G_MODE); mac_mode |= BNX2_EMAC_MODE_PORT_GMII; - REG_WR(bp, BNX2_EMAC_MODE, mac_mode); + BNX2_WR(bp, BNX2_EMAC_MODE, mac_mode); bp->link_up = 1; return 0; } @@ -2449,7 +2448,7 @@ bnx2_dump_mcp_state(struct bnx2 *bp) u32 mcp_p0, mcp_p1; netdev_err(dev, "<--- start MCP states dump --->\n"); - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { mcp_p0 = BNX2_MCP_STATE_P0; mcp_p1 = BNX2_MCP_STATE_P1; } else { @@ -2538,10 +2537,10 @@ bnx2_init_5709_context(struct bnx2 *bp) u32 val; val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12); - val |= (BCM_PAGE_BITS - 8) << 16; - REG_WR(bp, BNX2_CTX_COMMAND, val); + val |= (BNX2_PAGE_BITS - 8) << 16; + BNX2_WR(bp, BNX2_CTX_COMMAND, val); for (i = 0; i < 10; i++) { - val = REG_RD(bp, BNX2_CTX_COMMAND); + val = BNX2_RD(bp, BNX2_CTX_COMMAND); if (!(val & BNX2_CTX_COMMAND_MEM_INIT)) break; udelay(2); @@ -2553,20 +2552,20 @@ bnx2_init_5709_context(struct bnx2 *bp) int j; if (bp->ctx_blk[i]) - memset(bp->ctx_blk[i], 0, BCM_PAGE_SIZE); + memset(bp->ctx_blk[i], 0, BNX2_PAGE_SIZE); else return -ENOMEM; - REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA0, - (bp->ctx_blk_mapping[i] & 0xffffffff) | - BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID); - REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA1, - (u64) bp->ctx_blk_mapping[i] >> 32); - REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL, i | - BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ); + BNX2_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA0, + (bp->ctx_blk_mapping[i] & 0xffffffff) | + BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID); + BNX2_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA1, + (u64) bp->ctx_blk_mapping[i] >> 32); + BNX2_WR(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL, i | + BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ); for (j = 0; j < 10; j++) { - val = REG_RD(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL); + val = BNX2_RD(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL); if (!(val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ)) break; udelay(5); @@ -2591,7 +2590,7 @@ bnx2_init_context(struct bnx2 *bp) vcid--; - if (CHIP_ID(bp) == CHIP_ID_5706_A0) { + if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) { u32 new_vcid; vcid_addr = GET_PCID_ADDR(vcid); @@ -2612,8 +2611,8 @@ bnx2_init_context(struct bnx2 *bp) vcid_addr += (i << PHY_CTX_SHIFT); pcid_addr += (i << PHY_CTX_SHIFT); - REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr); - REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr); + BNX2_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr); + BNX2_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr); /* Zero out the context. */ for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) @@ -2633,7 +2632,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp) if (good_mbuf == NULL) return -ENOMEM; - REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, + BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE); good_mbuf_cnt = 0; @@ -2678,21 +2677,21 @@ bnx2_set_mac_addr(struct bnx2 *bp, u8 *mac_addr, u32 pos) val = (mac_addr[0] << 8) | mac_addr[1]; - REG_WR(bp, BNX2_EMAC_MAC_MATCH0 + (pos * 8), val); + BNX2_WR(bp, BNX2_EMAC_MAC_MATCH0 + (pos * 8), val); val = (mac_addr[2] << 24) | (mac_addr[3] << 16) | (mac_addr[4] << 8) | mac_addr[5]; - REG_WR(bp, BNX2_EMAC_MAC_MATCH1 + (pos * 8), val); + BNX2_WR(bp, BNX2_EMAC_MAC_MATCH1 + (pos * 8), val); } static inline int bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp) { dma_addr_t mapping; - struct sw_pg *rx_pg = &rxr->rx_pg_ring[index]; - struct rx_bd *rxbd = - &rxr->rx_pg_desc_ring[RX_RING(index)][RX_IDX(index)]; + struct bnx2_sw_pg *rx_pg = &rxr->rx_pg_ring[index]; + struct bnx2_rx_bd *rxbd = + &rxr->rx_pg_desc_ring[BNX2_RX_RING(index)][BNX2_RX_IDX(index)]; struct page *page = alloc_page(gfp); if (!page) @@ -2714,7 +2713,7 @@ bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gf static void bnx2_free_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index) { - struct sw_pg *rx_pg = &rxr->rx_pg_ring[index]; + struct bnx2_sw_pg *rx_pg = &rxr->rx_pg_ring[index]; struct page *page = rx_pg->page; if (!page) @@ -2731,9 +2730,10 @@ static inline int bnx2_alloc_rx_data(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp) { u8 *data; - struct sw_bd *rx_buf = &rxr->rx_buf_ring[index]; + struct bnx2_sw_bd *rx_buf = &rxr->rx_buf_ring[index]; dma_addr_t mapping; - struct rx_bd *rxbd = &rxr->rx_desc_ring[RX_RING(index)][RX_IDX(index)]; + struct bnx2_rx_bd *rxbd = + &rxr->rx_desc_ring[BNX2_RX_RING(index)][BNX2_RX_IDX(index)]; data = kmalloc(bp->rx_buf_size, gfp); if (!data) @@ -2770,9 +2770,9 @@ bnx2_phy_event_is_set(struct bnx2 *bp, struct bnx2_napi *bnapi, u32 event) old_link_state = sblk->status_attn_bits_ack & event; if (new_link_state != old_link_state) { if (new_link_state) - REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event); + BNX2_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event); else - REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event); + BNX2_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event); } else is_set = 0; @@ -2802,7 +2802,7 @@ bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi) barrier(); cons = *bnapi->hw_tx_cons_ptr; barrier(); - if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT)) + if (unlikely((cons & BNX2_MAX_TX_DESC_CNT) == BNX2_MAX_TX_DESC_CNT)) cons++; return cons; } @@ -2823,11 +2823,11 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) sw_cons = txr->tx_cons; while (sw_cons != hw_cons) { - struct sw_tx_bd *tx_buf; + struct bnx2_sw_tx_bd *tx_buf; struct sk_buff *skb; int i, last; - sw_ring_cons = TX_RING_IDX(sw_cons); + sw_ring_cons = BNX2_TX_RING_IDX(sw_cons); tx_buf = &txr->tx_buf_ring[sw_ring_cons]; skb = tx_buf->skb; @@ -2841,7 +2841,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) last_idx = sw_cons + tx_buf->nr_frags + 1; last_ring_idx = sw_ring_cons + tx_buf->nr_frags + 1; - if (unlikely(last_ring_idx >= MAX_TX_DESC_CNT)) { + if (unlikely(last_ring_idx >= BNX2_MAX_TX_DESC_CNT)) { last_idx++; } if (((s16) ((s16) last_idx - (s16) hw_cons)) > 0) { @@ -2856,17 +2856,18 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) last = tx_buf->nr_frags; for (i = 0; i < last; i++) { - sw_cons = NEXT_TX_BD(sw_cons); + struct bnx2_sw_tx_bd *tx_buf; + sw_cons = BNX2_NEXT_TX_BD(sw_cons); + + tx_buf = &txr->tx_buf_ring[BNX2_TX_RING_IDX(sw_cons)]; dma_unmap_page(&bp->pdev->dev, - dma_unmap_addr( - &txr->tx_buf_ring[TX_RING_IDX(sw_cons)], - mapping), + dma_unmap_addr(tx_buf, mapping), skb_frag_size(&skb_shinfo(skb)->frags[i]), PCI_DMA_TODEVICE); } - sw_cons = NEXT_TX_BD(sw_cons); + sw_cons = BNX2_NEXT_TX_BD(sw_cons); tx_bytes += skb->len; dev_kfree_skb(skb); @@ -2905,8 +2906,8 @@ static void bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb, int count) { - struct sw_pg *cons_rx_pg, *prod_rx_pg; - struct rx_bd *cons_bd, *prod_bd; + struct bnx2_sw_pg *cons_rx_pg, *prod_rx_pg; + struct bnx2_rx_bd *cons_bd, *prod_bd; int i; u16 hw_prod, prod; u16 cons = rxr->rx_pg_cons; @@ -2933,12 +2934,14 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, hw_prod = rxr->rx_pg_prod; for (i = 0; i < count; i++) { - prod = RX_PG_RING_IDX(hw_prod); + prod = BNX2_RX_PG_RING_IDX(hw_prod); prod_rx_pg = &rxr->rx_pg_ring[prod]; cons_rx_pg = &rxr->rx_pg_ring[cons]; - cons_bd = &rxr->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)]; - prod_bd = &rxr->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)]; + cons_bd = &rxr->rx_pg_desc_ring[BNX2_RX_RING(cons)] + [BNX2_RX_IDX(cons)]; + prod_bd = &rxr->rx_pg_desc_ring[BNX2_RX_RING(prod)] + [BNX2_RX_IDX(prod)]; if (prod != cons) { prod_rx_pg->page = cons_rx_pg->page; @@ -2950,8 +2953,8 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo; } - cons = RX_PG_RING_IDX(NEXT_RX_BD(cons)); - hw_prod = NEXT_RX_BD(hw_prod); + cons = BNX2_RX_PG_RING_IDX(BNX2_NEXT_RX_BD(cons)); + hw_prod = BNX2_NEXT_RX_BD(hw_prod); } rxr->rx_pg_prod = hw_prod; rxr->rx_pg_cons = cons; @@ -2961,8 +2964,8 @@ static inline void bnx2_reuse_rx_data(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u8 *data, u16 cons, u16 prod) { - struct sw_bd *cons_rx_buf, *prod_rx_buf; - struct rx_bd *cons_bd, *prod_bd; + struct bnx2_sw_bd *cons_rx_buf, *prod_rx_buf; + struct bnx2_rx_bd *cons_bd, *prod_bd; cons_rx_buf = &rxr->rx_buf_ring[cons]; prod_rx_buf = &rxr->rx_buf_ring[prod]; @@ -2981,8 +2984,8 @@ bnx2_reuse_rx_data(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, dma_unmap_addr_set(prod_rx_buf, mapping, dma_unmap_addr(cons_rx_buf, mapping)); - cons_bd = &rxr->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)]; - prod_bd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)]; + cons_bd = &rxr->rx_desc_ring[BNX2_RX_RING(cons)][BNX2_RX_IDX(cons)]; + prod_bd = &rxr->rx_desc_ring[BNX2_RX_RING(prod)][BNX2_RX_IDX(prod)]; prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi; prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo; } @@ -3022,7 +3025,7 @@ error: return skb; } else { unsigned int i, frag_len, frag_size, pages; - struct sw_pg *rx_pg; + struct bnx2_sw_pg *rx_pg; u16 pg_cons = rxr->rx_pg_cons; u16 pg_prod = rxr->rx_pg_prod; @@ -3065,7 +3068,7 @@ error: rx_pg->page = NULL; err = bnx2_alloc_rx_page(bp, rxr, - RX_PG_RING_IDX(pg_prod), + BNX2_RX_PG_RING_IDX(pg_prod), GFP_ATOMIC); if (unlikely(err)) { rxr->rx_pg_cons = pg_cons; @@ -3083,8 +3086,8 @@ error: skb->truesize += PAGE_SIZE; skb->len += frag_len; - pg_prod = NEXT_RX_BD(pg_prod); - pg_cons = RX_PG_RING_IDX(NEXT_RX_BD(pg_cons)); + pg_prod = BNX2_NEXT_RX_BD(pg_prod); + pg_cons = BNX2_RX_PG_RING_IDX(BNX2_NEXT_RX_BD(pg_cons)); } rxr->rx_pg_prod = pg_prod; rxr->rx_pg_cons = pg_cons; @@ -3101,7 +3104,7 @@ bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi) barrier(); cons = *bnapi->hw_rx_cons_ptr; barrier(); - if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT)) + if (unlikely((cons & BNX2_MAX_RX_DESC_CNT) == BNX2_MAX_RX_DESC_CNT)) cons++; return cons; } @@ -3125,13 +3128,14 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) while (sw_cons != hw_cons) { unsigned int len, hdr_len; u32 status; - struct sw_bd *rx_buf, *next_rx_buf; + struct bnx2_sw_bd *rx_buf, *next_rx_buf; struct sk_buff *skb; dma_addr_t dma_addr; u8 *data; + u16 next_ring_idx; - sw_ring_cons = RX_RING_IDX(sw_cons); - sw_ring_prod = RX_RING_IDX(sw_prod); + sw_ring_cons = BNX2_RX_RING_IDX(sw_cons); + sw_ring_prod = BNX2_RX_RING_IDX(sw_prod); rx_buf = &rxr->rx_buf_ring[sw_ring_cons]; data = rx_buf->data; @@ -3146,8 +3150,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH, PCI_DMA_FROMDEVICE); - next_rx_buf = - &rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))]; + next_ring_idx = BNX2_RX_RING_IDX(BNX2_NEXT_RX_BD(sw_cons)); + next_rx_buf = &rxr->rx_buf_ring[next_ring_idx]; prefetch(get_l2_fhdr(next_rx_buf->data)); len = rx_hdr->l2_fhdr_pkt_len; @@ -3239,8 +3243,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) rx_pkt++; next_rx: - sw_cons = NEXT_RX_BD(sw_cons); - sw_prod = NEXT_RX_BD(sw_prod); + sw_cons = BNX2_NEXT_RX_BD(sw_cons); + sw_prod = BNX2_NEXT_RX_BD(sw_prod); if ((rx_pkt == budget)) break; @@ -3255,11 +3259,11 @@ next_rx: rxr->rx_prod = sw_prod; if (pg_ring_used) - REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod); + BNX2_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod); - REG_WR16(bp, rxr->rx_bidx_addr, sw_prod); + BNX2_WR16(bp, rxr->rx_bidx_addr, sw_prod); - REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq); + BNX2_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq); mmiowb(); @@ -3277,7 +3281,7 @@ bnx2_msi(int irq, void *dev_instance) struct bnx2 *bp = bnapi->bp; prefetch(bnapi->status_blk.msi); - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | BNX2_PCICFG_INT_ACK_CMD_MASK_INT); @@ -3321,18 +3325,18 @@ bnx2_interrupt(int irq, void *dev_instance) * the status block write. */ if ((sblk->status_idx == bnapi->last_status_idx) && - (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) & + (BNX2_RD(bp, BNX2_PCICFG_MISC_STATUS) & BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) return IRQ_NONE; - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | BNX2_PCICFG_INT_ACK_CMD_MASK_INT); /* Read back to deassert IRQ immediately to avoid too many * spurious interrupts. */ - REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD); + BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD); /* Return here if interrupt is shared and is disabled. */ if (unlikely(atomic_read(&bp->intr_sem) != 0)) @@ -3388,14 +3392,14 @@ bnx2_chk_missed_msi(struct bnx2 *bp) u32 msi_ctrl; if (bnx2_has_work(bnapi)) { - msi_ctrl = REG_RD(bp, BNX2_PCICFG_MSI_CONTROL); + msi_ctrl = BNX2_RD(bp, BNX2_PCICFG_MSI_CONTROL); if (!(msi_ctrl & BNX2_PCICFG_MSI_CONTROL_ENABLE)) return; if (bnapi->last_status_idx == bp->idle_chk_status_idx) { - REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl & - ~BNX2_PCICFG_MSI_CONTROL_ENABLE); - REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl); + BNX2_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl & + ~BNX2_PCICFG_MSI_CONTROL_ENABLE); + BNX2_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl); bnx2_msi(bp->irq_tbl[0].vector, bnapi); } } @@ -3434,9 +3438,9 @@ static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi) /* This is needed to take care of transient status * during link changes. */ - REG_WR(bp, BNX2_HC_COMMAND, - bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); - REG_RD(bp, BNX2_HC_COMMAND); + BNX2_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + BNX2_RD(bp, BNX2_HC_COMMAND); } } @@ -3473,9 +3477,9 @@ static int bnx2_poll_msix(struct napi_struct *napi, int budget) if (likely(!bnx2_has_fast_work(bnapi))) { napi_complete(napi); - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | - BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | - bnapi->last_status_idx); + BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num | + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | + bnapi->last_status_idx); break; } } @@ -3511,19 +3515,19 @@ static int bnx2_poll(struct napi_struct *napi, int budget) if (likely(!bnx2_has_work(bnapi))) { napi_complete(napi); if (likely(bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX)) { - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, - BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | - bnapi->last_status_idx); + BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | + bnapi->last_status_idx); break; } - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, - BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | - BNX2_PCICFG_INT_ACK_CMD_MASK_INT | - bnapi->last_status_idx); - - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, - BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | - bnapi->last_status_idx); + BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | + BNX2_PCICFG_INT_ACK_CMD_MASK_INT | + bnapi->last_status_idx); + + BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, + BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | + bnapi->last_status_idx); break; } } @@ -3561,8 +3565,8 @@ bnx2_set_rx_mode(struct net_device *dev) } else if (dev->flags & IFF_ALLMULTI) { for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { - REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), - 0xffffffff); + BNX2_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), + 0xffffffff); } sort_mode |= BNX2_RPM_SORT_USER0_MC_EN; } @@ -3584,8 +3588,8 @@ bnx2_set_rx_mode(struct net_device *dev) } for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { - REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), - mc_filter[i]); + BNX2_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), + mc_filter[i]); } sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN; @@ -3610,12 +3614,12 @@ bnx2_set_rx_mode(struct net_device *dev) if (rx_mode != bp->rx_mode) { bp->rx_mode = rx_mode; - REG_WR(bp, BNX2_EMAC_RX_MODE, rx_mode); + BNX2_WR(bp, BNX2_EMAC_RX_MODE, rx_mode); } - REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0); - REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode); - REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA); + BNX2_WR(bp, BNX2_RPM_SORT_USER0, 0x0); + BNX2_WR(bp, BNX2_RPM_SORT_USER0, sort_mode); + BNX2_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA); spin_unlock_bh(&bp->phy_lock); } @@ -3663,10 +3667,10 @@ static int bnx2_request_uncached_firmware(struct bnx2 *bp) const struct bnx2_rv2p_fw_file *rv2p_fw; int rc; - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { mips_fw_file = FW_MIPS_FILE_09; - if ((CHIP_ID(bp) == CHIP_ID_5709_A0) || - (CHIP_ID(bp) == CHIP_ID_5709_A1)) + if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5709_A0) || + (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5709_A1)) rv2p_fw_file = FW_RV2P_FILE_09_Ax; else rv2p_fw_file = FW_RV2P_FILE_09; @@ -3756,13 +3760,13 @@ load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc, } for (i = 0; i < rv2p_code_len; i += 8) { - REG_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(*rv2p_code)); + BNX2_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(*rv2p_code)); rv2p_code++; - REG_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(*rv2p_code)); + BNX2_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(*rv2p_code)); rv2p_code++; val = (i / 8) | cmd; - REG_WR(bp, addr, val); + BNX2_WR(bp, addr, val); } rv2p_code = (__be32 *)(bp->rv2p_firmware->data + file_offset); @@ -3772,22 +3776,22 @@ load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc, loc = be32_to_cpu(fw_entry->fixup[i]); if (loc && ((loc * 4) < rv2p_code_len)) { code = be32_to_cpu(*(rv2p_code + loc - 1)); - REG_WR(bp, BNX2_RV2P_INSTR_HIGH, code); + BNX2_WR(bp, BNX2_RV2P_INSTR_HIGH, code); code = be32_to_cpu(*(rv2p_code + loc)); code = rv2p_fw_fixup(rv2p_proc, i, loc, code); - REG_WR(bp, BNX2_RV2P_INSTR_LOW, code); + BNX2_WR(bp, BNX2_RV2P_INSTR_LOW, code); val = (loc / 2) | cmd; - REG_WR(bp, addr, val); + BNX2_WR(bp, addr, val); } } /* Reset the processor, un-stall is done later. */ if (rv2p_proc == RV2P_PROC1) { - REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET); + BNX2_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET); } else { - REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET); + BNX2_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET); } return 0; @@ -3924,14 +3928,14 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state) /* delay required during transition out of D3hot */ msleep(20); - val = REG_RD(bp, BNX2_EMAC_MODE); + val = BNX2_RD(bp, BNX2_EMAC_MODE); val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD; val &= ~BNX2_EMAC_MODE_MPKT; - REG_WR(bp, BNX2_EMAC_MODE, val); + BNX2_WR(bp, BNX2_EMAC_MODE, val); - val = REG_RD(bp, BNX2_RPM_CONFIG); + val = BNX2_RD(bp, BNX2_RPM_CONFIG); val &= ~BNX2_RPM_CONFIG_ACPI_ENA; - REG_WR(bp, BNX2_RPM_CONFIG, val); + BNX2_WR(bp, BNX2_RPM_CONFIG, val); break; } case PCI_D3hot: { @@ -3963,7 +3967,7 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state) bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0); - val = REG_RD(bp, BNX2_EMAC_MODE); + val = BNX2_RD(bp, BNX2_EMAC_MODE); /* Enable port mode. */ val &= ~BNX2_EMAC_MODE_PORT; @@ -3978,32 +3982,32 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state) val |= BNX2_EMAC_MODE_25G_MODE; } - REG_WR(bp, BNX2_EMAC_MODE, val); + BNX2_WR(bp, BNX2_EMAC_MODE, val); /* receive all multicast */ for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { - REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), - 0xffffffff); + BNX2_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4), + 0xffffffff); } - REG_WR(bp, BNX2_EMAC_RX_MODE, - BNX2_EMAC_RX_MODE_SORT_MODE); + BNX2_WR(bp, BNX2_EMAC_RX_MODE, + BNX2_EMAC_RX_MODE_SORT_MODE); val = 1 | BNX2_RPM_SORT_USER0_BC_EN | BNX2_RPM_SORT_USER0_MC_EN; - REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0); - REG_WR(bp, BNX2_RPM_SORT_USER0, val); - REG_WR(bp, BNX2_RPM_SORT_USER0, val | - BNX2_RPM_SORT_USER0_ENA); + BNX2_WR(bp, BNX2_RPM_SORT_USER0, 0x0); + BNX2_WR(bp, BNX2_RPM_SORT_USER0, val); + BNX2_WR(bp, BNX2_RPM_SORT_USER0, val | + BNX2_RPM_SORT_USER0_ENA); /* Need to enable EMAC and RPM for WOL. */ - REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, - BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE | - BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE | - BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE); + BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS, + BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE | + BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE | + BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE); - val = REG_RD(bp, BNX2_RPM_CONFIG); + val = BNX2_RD(bp, BNX2_RPM_CONFIG); val &= ~BNX2_RPM_CONFIG_ACPI_ENA; - REG_WR(bp, BNX2_RPM_CONFIG, val); + BNX2_WR(bp, BNX2_RPM_CONFIG, val); wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_WOL; } @@ -4016,8 +4020,8 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state) 1, 0); pmcsr &= ~PCI_PM_CTRL_STATE_MASK; - if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || - (CHIP_ID(bp) == CHIP_ID_5706_A1)) { + if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) || + (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1)) { if (bp->wol) pmcsr |= 3; @@ -4050,9 +4054,9 @@ bnx2_acquire_nvram_lock(struct bnx2 *bp) int j; /* Request access to the flash interface. */ - REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_SET2); + BNX2_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_SET2); for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { - val = REG_RD(bp, BNX2_NVM_SW_ARB); + val = BNX2_RD(bp, BNX2_NVM_SW_ARB); if (val & BNX2_NVM_SW_ARB_ARB_ARB2) break; @@ -4072,10 +4076,10 @@ bnx2_release_nvram_lock(struct bnx2 *bp) u32 val; /* Relinquish nvram interface. */ - REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_CLR2); + BNX2_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_CLR2); for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { - val = REG_RD(bp, BNX2_NVM_SW_ARB); + val = BNX2_RD(bp, BNX2_NVM_SW_ARB); if (!(val & BNX2_NVM_SW_ARB_ARB_ARB2)) break; @@ -4094,20 +4098,20 @@ bnx2_enable_nvram_write(struct bnx2 *bp) { u32 val; - val = REG_RD(bp, BNX2_MISC_CFG); - REG_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI); + val = BNX2_RD(bp, BNX2_MISC_CFG); + BNX2_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI); if (bp->flash_info->flags & BNX2_NV_WREN) { int j; - REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); - REG_WR(bp, BNX2_NVM_COMMAND, - BNX2_NVM_COMMAND_WREN | BNX2_NVM_COMMAND_DOIT); + BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); + BNX2_WR(bp, BNX2_NVM_COMMAND, + BNX2_NVM_COMMAND_WREN | BNX2_NVM_COMMAND_DOIT); for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { udelay(5); - val = REG_RD(bp, BNX2_NVM_COMMAND); + val = BNX2_RD(bp, BNX2_NVM_COMMAND); if (val & BNX2_NVM_COMMAND_DONE) break; } @@ -4123,8 +4127,8 @@ bnx2_disable_nvram_write(struct bnx2 *bp) { u32 val; - val = REG_RD(bp, BNX2_MISC_CFG); - REG_WR(bp, BNX2_MISC_CFG, val & ~BNX2_MISC_CFG_NVM_WR_EN); + val = BNX2_RD(bp, BNX2_MISC_CFG); + BNX2_WR(bp, BNX2_MISC_CFG, val & ~BNX2_MISC_CFG_NVM_WR_EN); } @@ -4133,10 +4137,10 @@ bnx2_enable_nvram_access(struct bnx2 *bp) { u32 val; - val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE); + val = BNX2_RD(bp, BNX2_NVM_ACCESS_ENABLE); /* Enable both bits, even on read. */ - REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, - val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN); + BNX2_WR(bp, BNX2_NVM_ACCESS_ENABLE, + val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN); } static void @@ -4144,9 +4148,9 @@ bnx2_disable_nvram_access(struct bnx2 *bp) { u32 val; - val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE); + val = BNX2_RD(bp, BNX2_NVM_ACCESS_ENABLE); /* Disable both bits, even after read. */ - REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, + BNX2_WR(bp, BNX2_NVM_ACCESS_ENABLE, val & ~(BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN)); } @@ -4166,13 +4170,13 @@ bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset) BNX2_NVM_COMMAND_DOIT; /* Need to clear DONE bit separately. */ - REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); + BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); /* Address of the NVRAM to read from. */ - REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); + BNX2_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); /* Issue an erase command. */ - REG_WR(bp, BNX2_NVM_COMMAND, cmd); + BNX2_WR(bp, BNX2_NVM_COMMAND, cmd); /* Wait for completion. */ for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { @@ -4180,7 +4184,7 @@ bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset) udelay(5); - val = REG_RD(bp, BNX2_NVM_COMMAND); + val = BNX2_RD(bp, BNX2_NVM_COMMAND); if (val & BNX2_NVM_COMMAND_DONE) break; } @@ -4208,13 +4212,13 @@ bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags) } /* Need to clear DONE bit separately. */ - REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); + BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); /* Address of the NVRAM to read from. */ - REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); + BNX2_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); /* Issue a read command. */ - REG_WR(bp, BNX2_NVM_COMMAND, cmd); + BNX2_WR(bp, BNX2_NVM_COMMAND, cmd); /* Wait for completion. */ for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { @@ -4222,9 +4226,9 @@ bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags) udelay(5); - val = REG_RD(bp, BNX2_NVM_COMMAND); + val = BNX2_RD(bp, BNX2_NVM_COMMAND); if (val & BNX2_NVM_COMMAND_DONE) { - __be32 v = cpu_to_be32(REG_RD(bp, BNX2_NVM_READ)); + __be32 v = cpu_to_be32(BNX2_RD(bp, BNX2_NVM_READ)); memcpy(ret_val, &v, 4); break; } @@ -4254,24 +4258,24 @@ bnx2_nvram_write_dword(struct bnx2 *bp, u32 offset, u8 *val, u32 cmd_flags) } /* Need to clear DONE bit separately. */ - REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); + BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE); memcpy(&val32, val, 4); /* Write the data. */ - REG_WR(bp, BNX2_NVM_WRITE, be32_to_cpu(val32)); + BNX2_WR(bp, BNX2_NVM_WRITE, be32_to_cpu(val32)); /* Address of the NVRAM to write to. */ - REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); + BNX2_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE); /* Issue the write command. */ - REG_WR(bp, BNX2_NVM_COMMAND, cmd); + BNX2_WR(bp, BNX2_NVM_COMMAND, cmd); /* Wait for completion. */ for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { udelay(5); - if (REG_RD(bp, BNX2_NVM_COMMAND) & BNX2_NVM_COMMAND_DONE) + if (BNX2_RD(bp, BNX2_NVM_COMMAND) & BNX2_NVM_COMMAND_DONE) break; } if (j >= NVRAM_TIMEOUT_COUNT) @@ -4287,13 +4291,13 @@ bnx2_init_nvram(struct bnx2 *bp) int j, entry_count, rc = 0; const struct flash_spec *flash; - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { bp->flash_info = &flash_5709; goto get_flash_size; } /* Determine the selected interface. */ - val = REG_RD(bp, BNX2_NVM_CFG1); + val = BNX2_RD(bp, BNX2_NVM_CFG1); entry_count = ARRAY_SIZE(flash_table); @@ -4332,10 +4336,10 @@ bnx2_init_nvram(struct bnx2 *bp) bnx2_enable_nvram_access(bp); /* Reconfigure the flash interface */ - REG_WR(bp, BNX2_NVM_CFG1, flash->config1); - REG_WR(bp, BNX2_NVM_CFG2, flash->config2); - REG_WR(bp, BNX2_NVM_CFG3, flash->config3); - REG_WR(bp, BNX2_NVM_WRITE1, flash->write1); + BNX2_WR(bp, BNX2_NVM_CFG1, flash->config1); + BNX2_WR(bp, BNX2_NVM_CFG2, flash->config2); + BNX2_WR(bp, BNX2_NVM_CFG3, flash->config3); + BNX2_WR(bp, BNX2_NVM_WRITE1, flash->write1); /* Disable access to flash interface */ bnx2_disable_nvram_access(bp); @@ -4696,10 +4700,10 @@ bnx2_init_fw_cap(struct bnx2 *bp) static void bnx2_setup_msix_tbl(struct bnx2 *bp) { - REG_WR(bp, BNX2_PCI_GRC_WINDOW_ADDR, BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN); + BNX2_WR(bp, BNX2_PCI_GRC_WINDOW_ADDR, BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN); - REG_WR(bp, BNX2_PCI_GRC_WINDOW2_ADDR, BNX2_MSIX_TABLE_ADDR); - REG_WR(bp, BNX2_PCI_GRC_WINDOW3_ADDR, BNX2_MSIX_PBA_ADDR); + BNX2_WR(bp, BNX2_PCI_GRC_WINDOW2_ADDR, BNX2_MSIX_TABLE_ADDR); + BNX2_WR(bp, BNX2_PCI_GRC_WINDOW3_ADDR, BNX2_MSIX_PBA_ADDR); } static int @@ -4711,24 +4715,24 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) /* Wait for the current PCI transaction to complete before * issuing a reset. */ - if ((CHIP_NUM(bp) == CHIP_NUM_5706) || - (CHIP_NUM(bp) == CHIP_NUM_5708)) { - REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS, - BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE | - BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE | - BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE | - BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE); - val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS); + if ((BNX2_CHIP(bp) == BNX2_CHIP_5706) || + (BNX2_CHIP(bp) == BNX2_CHIP_5708)) { + BNX2_WR(bp, BNX2_MISC_ENABLE_CLR_BITS, + BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE | + BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE | + BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE | + BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE); + val = BNX2_RD(bp, BNX2_MISC_ENABLE_CLR_BITS); udelay(5); } else { /* 5709 */ - val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL); + val = BNX2_RD(bp, BNX2_MISC_NEW_CORE_CTL); val &= ~BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE; - REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val); - val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL); + BNX2_WR(bp, BNX2_MISC_NEW_CORE_CTL, val); + val = BNX2_RD(bp, BNX2_MISC_NEW_CORE_CTL); for (i = 0; i < 100; i++) { msleep(1); - val = REG_RD(bp, BNX2_PCICFG_DEVICE_CONTROL); + val = BNX2_RD(bp, BNX2_PCICFG_DEVICE_CONTROL); if (!(val & BNX2_PCICFG_DEVICE_STATUS_NO_PEND)) break; } @@ -4744,17 +4748,17 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) /* Do a dummy read to force the chip to complete all current transaction * before we issue a reset. */ - val = REG_RD(bp, BNX2_MISC_ID); + val = BNX2_RD(bp, BNX2_MISC_ID); - if (CHIP_NUM(bp) == CHIP_NUM_5709) { - REG_WR(bp, BNX2_MISC_COMMAND, BNX2_MISC_COMMAND_SW_RESET); - REG_RD(bp, BNX2_MISC_COMMAND); + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { + BNX2_WR(bp, BNX2_MISC_COMMAND, BNX2_MISC_COMMAND_SW_RESET); + BNX2_RD(bp, BNX2_MISC_COMMAND); udelay(5); val = BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; - REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val); + BNX2_WR(bp, BNX2_PCICFG_MISC_CONFIG, val); } else { val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | @@ -4762,19 +4766,19 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; /* Chip reset. */ - REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val); + BNX2_WR(bp, BNX2_PCICFG_MISC_CONFIG, val); /* Reading back any register after chip reset will hang the * bus on 5706 A0 and A1. The msleep below provides plenty * of margin for write posting. */ - if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || - (CHIP_ID(bp) == CHIP_ID_5706_A1)) + if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) || + (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1)) msleep(20); /* Reset takes approximate 30 usec */ for (i = 0; i < 10; i++) { - val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG); + val = BNX2_RD(bp, BNX2_PCICFG_MISC_CONFIG); if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) break; @@ -4789,7 +4793,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) } /* Make sure byte swapping is properly configured. */ - val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0); + val = BNX2_RD(bp, BNX2_PCI_SWAP_DIAG0); if (val != 0x01020304) { pr_err("Chip not in correct endian mode\n"); return -ENODEV; @@ -4808,10 +4812,10 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) bnx2_set_default_remote_link(bp); spin_unlock_bh(&bp->phy_lock); - if (CHIP_ID(bp) == CHIP_ID_5706_A0) { + if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) { /* Adjust the voltage regular to two steps lower. The default * of this register is 0x0000000e. */ - REG_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa); + BNX2_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa); /* Remove bad rbuf memory from the free pool. */ rc = bnx2_alloc_bad_rbuf(bp); @@ -4820,7 +4824,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) if (bp->flags & BNX2_FLAG_USING_MSIX) { bnx2_setup_msix_tbl(bp); /* Prevent MSIX table reads and write from timing out */ - REG_WR(bp, BNX2_MISC_ECO_HW_CTL, + BNX2_WR(bp, BNX2_MISC_ECO_HW_CTL, BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN); } @@ -4834,7 +4838,7 @@ bnx2_init_chip(struct bnx2 *bp) int rc, i; /* Make sure the interrupt is not active. */ - REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT); + BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT); val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP | BNX2_DMA_CONFIG_DATA_WORD_SWAP | @@ -4850,16 +4854,17 @@ bnx2_init_chip(struct bnx2 *bp) if ((bp->flags & BNX2_FLAG_PCIX) && (bp->bus_speed_mhz == 133)) val |= (1 << 23); - if ((CHIP_NUM(bp) == CHIP_NUM_5706) && - (CHIP_ID(bp) != CHIP_ID_5706_A0) && !(bp->flags & BNX2_FLAG_PCIX)) + if ((BNX2_CHIP(bp) == BNX2_CHIP_5706) && + (BNX2_CHIP_ID(bp) != BNX2_CHIP_ID_5706_A0) && + !(bp->flags & BNX2_FLAG_PCIX)) val |= BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA; - REG_WR(bp, BNX2_DMA_CONFIG, val); + BNX2_WR(bp, BNX2_DMA_CONFIG, val); - if (CHIP_ID(bp) == CHIP_ID_5706_A0) { - val = REG_RD(bp, BNX2_TDMA_CONFIG); + if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) { + val = BNX2_RD(bp, BNX2_TDMA_CONFIG); val |= BNX2_TDMA_CONFIG_ONE_DMA; - REG_WR(bp, BNX2_TDMA_CONFIG, val); + BNX2_WR(bp, BNX2_TDMA_CONFIG, val); } if (bp->flags & BNX2_FLAG_PCIX) { @@ -4871,14 +4876,14 @@ bnx2_init_chip(struct bnx2 *bp) val16 & ~PCI_X_CMD_ERO); } - REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, - BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE | - BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE | - BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE); + BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS, + BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE | + BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE | + BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE); /* Initialize context mapping and zero out the quick contexts. The * context block must have already been enabled. */ - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { rc = bnx2_init_5709_context(bp); if (rc) return rc; @@ -4892,29 +4897,29 @@ bnx2_init_chip(struct bnx2 *bp) bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0); - val = REG_RD(bp, BNX2_MQ_CONFIG); + val = BNX2_RD(bp, BNX2_MQ_CONFIG); val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE; val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256; - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { val |= BNX2_MQ_CONFIG_BIN_MQ_MODE; - if (CHIP_REV(bp) == CHIP_REV_Ax) + if (BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Ax) val |= BNX2_MQ_CONFIG_HALT_DIS; } - REG_WR(bp, BNX2_MQ_CONFIG, val); + BNX2_WR(bp, BNX2_MQ_CONFIG, val); val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE); - REG_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val); - REG_WR(bp, BNX2_MQ_KNL_WIND_END, val); + BNX2_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val); + BNX2_WR(bp, BNX2_MQ_KNL_WIND_END, val); - val = (BCM_PAGE_BITS - 8) << 24; - REG_WR(bp, BNX2_RV2P_CONFIG, val); + val = (BNX2_PAGE_BITS - 8) << 24; + BNX2_WR(bp, BNX2_RV2P_CONFIG, val); /* Configure page size. */ - val = REG_RD(bp, BNX2_TBDR_CONFIG); + val = BNX2_RD(bp, BNX2_TBDR_CONFIG); val &= ~BNX2_TBDR_CONFIG_PAGE_SIZE; - val |= (BCM_PAGE_BITS - 8) << 24 | 0x40; - REG_WR(bp, BNX2_TBDR_CONFIG, val); + val |= (BNX2_PAGE_BITS - 8) << 24 | 0x40; + BNX2_WR(bp, BNX2_TBDR_CONFIG, val); val = bp->mac_addr[0] + (bp->mac_addr[1] << 8) + @@ -4922,14 +4927,14 @@ bnx2_init_chip(struct bnx2 *bp) bp->mac_addr[3] + (bp->mac_addr[4] << 8) + (bp->mac_addr[5] << 16); - REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val); + BNX2_WR(bp, BNX2_EMAC_BACKOFF_SEED, val); /* Program the MTU. Also include 4 bytes for CRC32. */ mtu = bp->dev->mtu; val = mtu + ETH_HLEN + ETH_FCS_LEN; if (val > (MAX_ETHERNET_PACKET_SIZE + 4)) val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA; - REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val); + BNX2_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val); if (mtu < 1500) mtu = 1500; @@ -4947,43 +4952,43 @@ bnx2_init_chip(struct bnx2 *bp) bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE; /* Set up how to generate a link change interrupt. */ - REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); + BNX2_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK); - REG_WR(bp, BNX2_HC_STATUS_ADDR_L, - (u64) bp->status_blk_mapping & 0xffffffff); - REG_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32); + BNX2_WR(bp, BNX2_HC_STATUS_ADDR_L, + (u64) bp->status_blk_mapping & 0xffffffff); + BNX2_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32); - REG_WR(bp, BNX2_HC_STATISTICS_ADDR_L, - (u64) bp->stats_blk_mapping & 0xffffffff); - REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H, - (u64) bp->stats_blk_mapping >> 32); + BNX2_WR(bp, BNX2_HC_STATISTICS_ADDR_L, + (u64) bp->stats_blk_mapping & 0xffffffff); + BNX2_WR(bp, BNX2_HC_STATISTICS_ADDR_H, + (u64) bp->stats_blk_mapping >> 32); - REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP, - (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip); + BNX2_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP, + (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip); - REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP, - (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip); + BNX2_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP, + (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip); - REG_WR(bp, BNX2_HC_COMP_PROD_TRIP, - (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip); + BNX2_WR(bp, BNX2_HC_COMP_PROD_TRIP, + (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip); - REG_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks); + BNX2_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks); - REG_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks); + BNX2_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks); - REG_WR(bp, BNX2_HC_COM_TICKS, - (bp->com_ticks_int << 16) | bp->com_ticks); + BNX2_WR(bp, BNX2_HC_COM_TICKS, + (bp->com_ticks_int << 16) | bp->com_ticks); - REG_WR(bp, BNX2_HC_CMD_TICKS, - (bp->cmd_ticks_int << 16) | bp->cmd_ticks); + BNX2_WR(bp, BNX2_HC_CMD_TICKS, + (bp->cmd_ticks_int << 16) | bp->cmd_ticks); if (bp->flags & BNX2_FLAG_BROKEN_STATS) - REG_WR(bp, BNX2_HC_STATS_TICKS, 0); + BNX2_WR(bp, BNX2_HC_STATS_TICKS, 0); else - REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks); - REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ + BNX2_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks); + BNX2_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ - if (CHIP_ID(bp) == CHIP_ID_5706_A1) + if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1) val = BNX2_HC_CONFIG_COLLECT_STATS; else { val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE | @@ -4991,8 +4996,8 @@ bnx2_init_chip(struct bnx2 *bp) } if (bp->flags & BNX2_FLAG_USING_MSIX) { - REG_WR(bp, BNX2_HC_MSIX_BIT_VECTOR, - BNX2_HC_MSIX_BIT_VECTOR_VAL); + BNX2_WR(bp, BNX2_HC_MSIX_BIT_VECTOR, + BNX2_HC_MSIX_BIT_VECTOR_VAL); val |= BNX2_HC_CONFIG_SB_ADDR_INC_128B; } @@ -5000,7 +5005,7 @@ bnx2_init_chip(struct bnx2 *bp) if (bp->flags & BNX2_FLAG_ONE_SHOT_MSI) val |= BNX2_HC_CONFIG_ONE_SHOT | BNX2_HC_CONFIG_USE_INT_PARAM; - REG_WR(bp, BNX2_HC_CONFIG, val); + BNX2_WR(bp, BNX2_HC_CONFIG, val); if (bp->rx_ticks < 25) bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 1); @@ -5011,48 +5016,48 @@ bnx2_init_chip(struct bnx2 *bp) u32 base = ((i - 1) * BNX2_HC_SB_CONFIG_SIZE) + BNX2_HC_SB_CONFIG_1; - REG_WR(bp, base, + BNX2_WR(bp, base, BNX2_HC_SB_CONFIG_1_TX_TMR_MODE | BNX2_HC_SB_CONFIG_1_RX_TMR_MODE | BNX2_HC_SB_CONFIG_1_ONE_SHOT); - REG_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF, + BNX2_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF, (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip); - REG_WR(bp, base + BNX2_HC_TX_TICKS_OFF, + BNX2_WR(bp, base + BNX2_HC_TX_TICKS_OFF, (bp->tx_ticks_int << 16) | bp->tx_ticks); - REG_WR(bp, base + BNX2_HC_RX_QUICK_CONS_TRIP_OFF, - (bp->rx_quick_cons_trip_int << 16) | + BNX2_WR(bp, base + BNX2_HC_RX_QUICK_CONS_TRIP_OFF, + (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip); - REG_WR(bp, base + BNX2_HC_RX_TICKS_OFF, + BNX2_WR(bp, base + BNX2_HC_RX_TICKS_OFF, (bp->rx_ticks_int << 16) | bp->rx_ticks); } /* Clear internal stats counters. */ - REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW); + BNX2_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW); - REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS); + BNX2_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS); /* Initialize the receive filter. */ bnx2_set_rx_mode(bp->dev); - if (CHIP_NUM(bp) == CHIP_NUM_5709) { - val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL); + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { + val = BNX2_RD(bp, BNX2_MISC_NEW_CORE_CTL); val |= BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE; - REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val); + BNX2_WR(bp, BNX2_MISC_NEW_CORE_CTL, val); } rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET, 1, 0); - REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT); - REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS); + BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT); + BNX2_RD(bp, BNX2_MISC_ENABLE_SET_BITS); udelay(20); - bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND); + bp->hc_cmd = BNX2_RD(bp, BNX2_HC_COMMAND); return rc; } @@ -5086,7 +5091,7 @@ bnx2_init_tx_context(struct bnx2 *bp, u32 cid, struct bnx2_tx_ring_info *txr) u32 val, offset0, offset1, offset2, offset3; u32 cid_addr = GET_CID_ADDR(cid); - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { offset0 = BNX2_L2CTX_TYPE_XI; offset1 = BNX2_L2CTX_CMD_TYPE_XI; offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI; @@ -5113,7 +5118,7 @@ bnx2_init_tx_context(struct bnx2 *bp, u32 cid, struct bnx2_tx_ring_info *txr) static void bnx2_init_tx_ring(struct bnx2 *bp, int ring_num) { - struct tx_bd *txbd; + struct bnx2_tx_bd *txbd; u32 cid = TX_CID; struct bnx2_napi *bnapi; struct bnx2_tx_ring_info *txr; @@ -5128,7 +5133,7 @@ bnx2_init_tx_ring(struct bnx2 *bp, int ring_num) bp->tx_wake_thresh = bp->tx_ring_size / 2; - txbd = &txr->tx_desc_ring[MAX_TX_DESC_CNT]; + txbd = &txr->tx_desc_ring[BNX2_MAX_TX_DESC_CNT]; txbd->tx_bd_haddr_hi = (u64) txr->tx_desc_mapping >> 32; txbd->tx_bd_haddr_lo = (u64) txr->tx_desc_mapping & 0xffffffff; @@ -5143,17 +5148,17 @@ bnx2_init_tx_ring(struct bnx2 *bp, int ring_num) } static void -bnx2_init_rxbd_rings(struct rx_bd *rx_ring[], dma_addr_t dma[], u32 buf_size, - int num_rings) +bnx2_init_rxbd_rings(struct bnx2_rx_bd *rx_ring[], dma_addr_t dma[], + u32 buf_size, int num_rings) { int i; - struct rx_bd *rxbd; + struct bnx2_rx_bd *rxbd; for (i = 0; i < num_rings; i++) { int j; rxbd = &rx_ring[i][0]; - for (j = 0; j < MAX_RX_DESC_CNT; j++, rxbd++) { + for (j = 0; j < BNX2_MAX_RX_DESC_CNT; j++, rxbd++) { rxbd->rx_bd_len = buf_size; rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END; } @@ -5187,9 +5192,9 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num) bnx2_init_rx_context(bp, cid); - if (CHIP_NUM(bp) == CHIP_NUM_5709) { - val = REG_RD(bp, BNX2_MQ_MAP_L2_5); - REG_WR(bp, BNX2_MQ_MAP_L2_5, val | BNX2_MQ_MAP_L2_5_ARM); + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { + val = BNX2_RD(bp, BNX2_MQ_MAP_L2_5); + BNX2_WR(bp, BNX2_MQ_MAP_L2_5, val | BNX2_MQ_MAP_L2_5_ARM); } bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0); @@ -5208,8 +5213,8 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num) val = (u64) rxr->rx_pg_desc_mapping[0] & 0xffffffff; bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val); - if (CHIP_NUM(bp) == CHIP_NUM_5709) - REG_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT); + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) + BNX2_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT); } val = (u64) rxr->rx_desc_mapping[0] >> 32; @@ -5225,8 +5230,8 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num) ring_num, i, bp->rx_pg_ring_size); break; } - prod = NEXT_RX_BD(prod); - ring_prod = RX_PG_RING_IDX(prod); + prod = BNX2_NEXT_RX_BD(prod); + ring_prod = BNX2_RX_PG_RING_IDX(prod); } rxr->rx_pg_prod = prod; @@ -5237,8 +5242,8 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num) ring_num, i, bp->rx_ring_size); break; } - prod = NEXT_RX_BD(prod); - ring_prod = RX_RING_IDX(prod); + prod = BNX2_NEXT_RX_BD(prod); + ring_prod = BNX2_RX_RING_IDX(prod); } rxr->rx_prod = prod; @@ -5246,10 +5251,10 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num) rxr->rx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_BSEQ; rxr->rx_pg_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_PG_BDIDX; - REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod); - REG_WR16(bp, rxr->rx_bidx_addr, prod); + BNX2_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod); + BNX2_WR16(bp, rxr->rx_bidx_addr, prod); - REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq); + BNX2_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq); } static void @@ -5260,15 +5265,15 @@ bnx2_init_all_rings(struct bnx2 *bp) bnx2_clear_ring_states(bp); - REG_WR(bp, BNX2_TSCH_TSS_CFG, 0); + BNX2_WR(bp, BNX2_TSCH_TSS_CFG, 0); for (i = 0; i < bp->num_tx_rings; i++) bnx2_init_tx_ring(bp, i); if (bp->num_tx_rings > 1) - REG_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) | - (TX_TSS_CID << 7)); + BNX2_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) | + (TX_TSS_CID << 7)); - REG_WR(bp, BNX2_RLUP_RSS_CONFIG, 0); + BNX2_WR(bp, BNX2_RLUP_RSS_CONFIG, 0); bnx2_reg_wr_ind(bp, BNX2_RXP_SCRATCH_RSS_TBL_SZ, 0); for (i = 0; i < bp->num_rx_rings; i++) @@ -5282,8 +5287,8 @@ bnx2_init_all_rings(struct bnx2 *bp) tbl_32 |= (i % (bp->num_rx_rings - 1)) << shift; if ((i % 8) == 7) { - REG_WR(bp, BNX2_RLUP_RSS_DATA, tbl_32); - REG_WR(bp, BNX2_RLUP_RSS_COMMAND, (i >> 3) | + BNX2_WR(bp, BNX2_RLUP_RSS_DATA, tbl_32); + BNX2_WR(bp, BNX2_RLUP_RSS_COMMAND, (i >> 3) | BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK | BNX2_RLUP_RSS_COMMAND_WRITE | BNX2_RLUP_RSS_COMMAND_HASH_MASK); @@ -5294,7 +5299,7 @@ bnx2_init_all_rings(struct bnx2 *bp) val = BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI | BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_ALL_XI; - REG_WR(bp, BNX2_RLUP_RSS_CONFIG, val); + BNX2_WR(bp, BNX2_RLUP_RSS_CONFIG, val); } } @@ -5303,8 +5308,8 @@ static u32 bnx2_find_max_ring(u32 ring_size, u32 max_size) { u32 max, num_rings = 1; - while (ring_size > MAX_RX_DESC_CNT) { - ring_size -= MAX_RX_DESC_CNT; + while (ring_size > BNX2_MAX_RX_DESC_CNT) { + ring_size -= BNX2_MAX_RX_DESC_CNT; num_rings++; } /* round to next power of 2 */ @@ -5337,13 +5342,14 @@ bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size) int pages = PAGE_ALIGN(bp->dev->mtu - 40) >> PAGE_SHIFT; jumbo_size = size * pages; - if (jumbo_size > MAX_TOTAL_RX_PG_DESC_CNT) - jumbo_size = MAX_TOTAL_RX_PG_DESC_CNT; + if (jumbo_size > BNX2_MAX_TOTAL_RX_PG_DESC_CNT) + jumbo_size = BNX2_MAX_TOTAL_RX_PG_DESC_CNT; bp->rx_pg_ring_size = jumbo_size; bp->rx_max_pg_ring = bnx2_find_max_ring(jumbo_size, - MAX_RX_PG_RINGS); - bp->rx_max_pg_ring_idx = (bp->rx_max_pg_ring * RX_DESC_CNT) - 1; + BNX2_MAX_RX_PG_RINGS); + bp->rx_max_pg_ring_idx = + (bp->rx_max_pg_ring * BNX2_RX_DESC_CNT) - 1; rx_size = BNX2_RX_COPY_THRESH + BNX2_RX_OFFSET; bp->rx_copy_thresh = 0; } @@ -5354,8 +5360,8 @@ bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size) NET_SKB_PAD + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); bp->rx_jumbo_thresh = rx_size - BNX2_RX_OFFSET; bp->rx_ring_size = size; - bp->rx_max_ring = bnx2_find_max_ring(size, MAX_RX_RINGS); - bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1; + bp->rx_max_ring = bnx2_find_max_ring(size, BNX2_MAX_RX_RINGS); + bp->rx_max_ring_idx = (bp->rx_max_ring * BNX2_RX_DESC_CNT) - 1; } static void @@ -5371,13 +5377,13 @@ bnx2_free_tx_skbs(struct bnx2 *bp) if (txr->tx_buf_ring == NULL) continue; - for (j = 0; j < TX_DESC_CNT; ) { - struct sw_tx_bd *tx_buf = &txr->tx_buf_ring[j]; + for (j = 0; j < BNX2_TX_DESC_CNT; ) { + struct bnx2_sw_tx_bd *tx_buf = &txr->tx_buf_ring[j]; struct sk_buff *skb = tx_buf->skb; int k, last; if (skb == NULL) { - j = NEXT_TX_BD(j); + j = BNX2_NEXT_TX_BD(j); continue; } @@ -5389,9 +5395,9 @@ bnx2_free_tx_skbs(struct bnx2 *bp) tx_buf->skb = NULL; last = tx_buf->nr_frags; - j = NEXT_TX_BD(j); - for (k = 0; k < last; k++, j = NEXT_TX_BD(j)) { - tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)]; + j = BNX2_NEXT_TX_BD(j); + for (k = 0; k < last; k++, j = BNX2_NEXT_TX_BD(j)) { + tx_buf = &txr->tx_buf_ring[BNX2_TX_RING_IDX(j)]; dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping), skb_frag_size(&skb_shinfo(skb)->frags[k]), @@ -5417,7 +5423,7 @@ bnx2_free_rx_skbs(struct bnx2 *bp) return; for (j = 0; j < bp->rx_max_ring_idx; j++) { - struct sw_bd *rx_buf = &rxr->rx_buf_ring[j]; + struct bnx2_sw_bd *rx_buf = &rxr->rx_buf_ring[j]; u8 *data = rx_buf->data; if (data == NULL) @@ -5615,7 +5621,7 @@ bnx2_test_registers(struct bnx2 *bp) ret = 0; is_5709 = 0; - if (CHIP_NUM(bp) == CHIP_NUM_5709) + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) is_5709 = 1; for (i = 0; reg_tbl[i].offset != 0xffff; i++) { @@ -5714,7 +5720,7 @@ bnx2_test_memory(struct bnx2 *bp) }; struct mem_entry *mem_tbl; - if (CHIP_NUM(bp) == CHIP_NUM_5709) + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) mem_tbl = mem_tbl_5709; else mem_tbl = mem_tbl_5706; @@ -5741,8 +5747,8 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) unsigned char *packet; u16 rx_start_idx, rx_idx; dma_addr_t map; - struct tx_bd *txbd; - struct sw_bd *rx_buf; + struct bnx2_tx_bd *txbd; + struct bnx2_sw_bd *rx_buf; struct l2_fhdr *rx_hdr; int ret = -ENODEV; struct bnx2_napi *bnapi = &bp->bnx2_napi[0], *tx_napi; @@ -5784,17 +5790,17 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) return -EIO; } - REG_WR(bp, BNX2_HC_COMMAND, - bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + BNX2_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); - REG_RD(bp, BNX2_HC_COMMAND); + BNX2_RD(bp, BNX2_HC_COMMAND); udelay(5); rx_start_idx = bnx2_get_hw_rx_cons(bnapi); num_pkts = 0; - txbd = &txr->tx_desc_ring[TX_RING_IDX(txr->tx_prod)]; + txbd = &txr->tx_desc_ring[BNX2_TX_RING_IDX(txr->tx_prod)]; txbd->tx_bd_haddr_hi = (u64) map >> 32; txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff; @@ -5802,18 +5808,18 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END; num_pkts++; - txr->tx_prod = NEXT_TX_BD(txr->tx_prod); + txr->tx_prod = BNX2_NEXT_TX_BD(txr->tx_prod); txr->tx_prod_bseq += pkt_size; - REG_WR16(bp, txr->tx_bidx_addr, txr->tx_prod); - REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq); + BNX2_WR16(bp, txr->tx_bidx_addr, txr->tx_prod); + BNX2_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq); udelay(100); - REG_WR(bp, BNX2_HC_COMMAND, - bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); + BNX2_WR(bp, BNX2_HC_COMMAND, + bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT); - REG_RD(bp, BNX2_HC_COMMAND); + BNX2_RD(bp, BNX2_HC_COMMAND); udelay(5); @@ -5962,14 +5968,14 @@ bnx2_test_intr(struct bnx2 *bp) if (!netif_running(bp->dev)) return -ENODEV; - status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff; + status_idx = BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff; /* This register is not touched during run-time. */ - REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); - REG_RD(bp, BNX2_HC_COMMAND); + BNX2_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW); + BNX2_RD(bp, BNX2_HC_COMMAND); for (i = 0; i < 10; i++) { - if ((REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff) != + if ((BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff) != status_idx) { break; @@ -6132,11 +6138,11 @@ bnx2_timer(unsigned long data) /* workaround occasional corrupted counters */ if ((bp->flags & BNX2_FLAG_BROKEN_STATS) && bp->stats_ticks) - REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | - BNX2_HC_COMMAND_STATS_NOW); + BNX2_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | + BNX2_HC_COMMAND_STATS_NOW); if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) { - if (CHIP_NUM(bp) == CHIP_NUM_5706) + if (BNX2_CHIP(bp) == BNX2_CHIP_5706) bnx2_5706_serdes_timer(bp); else bnx2_5708_serdes_timer(bp); @@ -6205,13 +6211,13 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs) const int len = sizeof(bp->irq_tbl[0].name); bnx2_setup_msix_tbl(bp); - REG_WR(bp, BNX2_PCI_MSIX_CONTROL, BNX2_MAX_MSIX_HW_VEC - 1); - REG_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE); - REG_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE); + BNX2_WR(bp, BNX2_PCI_MSIX_CONTROL, BNX2_MAX_MSIX_HW_VEC - 1); + BNX2_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE); + BNX2_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE); /* Need to flush the previous three writes to ensure MSI-X * is setup properly */ - REG_RD(bp, BNX2_PCI_MSIX_CONTROL); + BNX2_RD(bp, BNX2_PCI_MSIX_CONTROL); for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { msix_ent[i].entry = i; @@ -6274,7 +6280,7 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi) !(bp->flags & BNX2_FLAG_USING_MSIX)) { if (pci_enable_msi(bp->pdev) == 0) { bp->flags |= BNX2_FLAG_USING_MSI; - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { bp->flags |= BNX2_FLAG_ONE_SHOT_MSI; bp->irq_tbl[0].handler = bnx2_msi_1shot; } else @@ -6464,22 +6470,22 @@ bnx2_dump_ftq(struct bnx2 *bp) netdev_err(dev, "<--- end FTQ dump --->\n"); netdev_err(dev, "<--- start TBDC dump --->\n"); netdev_err(dev, "TBDC free cnt: %ld\n", - REG_RD(bp, BNX2_TBDC_STATUS) & BNX2_TBDC_STATUS_FREE_CNT); + BNX2_RD(bp, BNX2_TBDC_STATUS) & BNX2_TBDC_STATUS_FREE_CNT); netdev_err(dev, "LINE CID BIDX CMD VALIDS\n"); for (i = 0; i < 0x20; i++) { int j = 0; - REG_WR(bp, BNX2_TBDC_BD_ADDR, i); - REG_WR(bp, BNX2_TBDC_CAM_OPCODE, - BNX2_TBDC_CAM_OPCODE_OPCODE_CAM_READ); - REG_WR(bp, BNX2_TBDC_COMMAND, BNX2_TBDC_COMMAND_CMD_REG_ARB); - while ((REG_RD(bp, BNX2_TBDC_COMMAND) & + BNX2_WR(bp, BNX2_TBDC_BD_ADDR, i); + BNX2_WR(bp, BNX2_TBDC_CAM_OPCODE, + BNX2_TBDC_CAM_OPCODE_OPCODE_CAM_READ); + BNX2_WR(bp, BNX2_TBDC_COMMAND, BNX2_TBDC_COMMAND_CMD_REG_ARB); + while ((BNX2_RD(bp, BNX2_TBDC_COMMAND) & BNX2_TBDC_COMMAND_CMD_REG_ARB) && j < 100) j++; - cid = REG_RD(bp, BNX2_TBDC_CID); - bdidx = REG_RD(bp, BNX2_TBDC_BIDX); - valid = REG_RD(bp, BNX2_TBDC_CAM_OPCODE); + cid = BNX2_RD(bp, BNX2_TBDC_CID); + bdidx = BNX2_RD(bp, BNX2_TBDC_BIDX); + valid = BNX2_RD(bp, BNX2_TBDC_CAM_OPCODE); netdev_err(dev, "%02x %06x %04lx %02x [%x]\n", i, cid, bdidx & BNX2_TBDC_BDIDX_BDIDX, bdidx >> 24, (valid >> 8) & 0x0ff); @@ -6500,15 +6506,15 @@ bnx2_dump_state(struct bnx2 *bp) pci_read_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, &val2); netdev_err(dev, "DEBUG: PCI_PM[%08x] PCI_MISC_CFG[%08x]\n", val1, val2); netdev_err(dev, "DEBUG: EMAC_TX_STATUS[%08x] EMAC_RX_STATUS[%08x]\n", - REG_RD(bp, BNX2_EMAC_TX_STATUS), - REG_RD(bp, BNX2_EMAC_RX_STATUS)); + BNX2_RD(bp, BNX2_EMAC_TX_STATUS), + BNX2_RD(bp, BNX2_EMAC_RX_STATUS)); netdev_err(dev, "DEBUG: RPM_MGMT_PKT_CTRL[%08x]\n", - REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL)); + BNX2_RD(bp, BNX2_RPM_MGMT_PKT_CTRL)); netdev_err(dev, "DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n", - REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS)); + BNX2_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS)); if (bp->flags & BNX2_FLAG_USING_MSIX) netdev_err(dev, "DEBUG: PBA[%08x]\n", - REG_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE)); + BNX2_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE)); } static void @@ -6533,8 +6539,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct bnx2 *bp = netdev_priv(dev); dma_addr_t mapping; - struct tx_bd *txbd; - struct sw_tx_bd *tx_buf; + struct bnx2_tx_bd *txbd; + struct bnx2_sw_tx_bd *tx_buf; u32 len, vlan_tag_flags, last_frag, mss; u16 prod, ring_prod; int i; @@ -6557,7 +6563,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) } len = skb_headlen(skb); prod = txr->tx_prod; - ring_prod = TX_RING_IDX(prod); + ring_prod = BNX2_TX_RING_IDX(prod); vlan_tag_flags = 0; if (skb->ip_summed == CHECKSUM_PARTIAL) { @@ -6627,8 +6633,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) for (i = 0; i < last_frag; i++) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - prod = NEXT_TX_BD(prod); - ring_prod = TX_RING_IDX(prod); + prod = BNX2_NEXT_TX_BD(prod); + ring_prod = BNX2_TX_RING_IDX(prod); txbd = &txr->tx_desc_ring[ring_prod]; len = skb_frag_size(frag); @@ -6652,11 +6658,11 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) netdev_tx_sent_queue(txq, skb->len); - prod = NEXT_TX_BD(prod); + prod = BNX2_NEXT_TX_BD(prod); txr->tx_prod_bseq += skb->len; - REG_WR16(bp, txr->tx_bidx_addr, prod); - REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq); + BNX2_WR16(bp, txr->tx_bidx_addr, prod); + BNX2_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq); mmiowb(); @@ -6682,7 +6688,7 @@ dma_error: /* start back at beginning and unmap skb */ prod = txr->tx_prod; - ring_prod = TX_RING_IDX(prod); + ring_prod = BNX2_TX_RING_IDX(prod); tx_buf = &txr->tx_buf_ring[ring_prod]; tx_buf->skb = NULL; dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping), @@ -6690,8 +6696,8 @@ dma_error: /* unmap remaining mapped pages */ for (i = 0; i < last_frag; i++) { - prod = NEXT_TX_BD(prod); - ring_prod = TX_RING_IDX(prod); + prod = BNX2_NEXT_TX_BD(prod); + ring_prod = BNX2_TX_RING_IDX(prod); tx_buf = &txr->tx_buf_ring[ring_prod]; dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping), skb_frag_size(&skb_shinfo(skb)->frags[i]), @@ -6810,8 +6816,8 @@ bnx2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats) GET_32BIT_NET_STATS(stat_Dot3StatsExcessiveCollisions) + GET_32BIT_NET_STATS(stat_Dot3StatsLateCollisions); - if ((CHIP_NUM(bp) == CHIP_NUM_5706) || - (CHIP_ID(bp) == CHIP_ID_5708_A0)) + if ((BNX2_CHIP(bp) == BNX2_CHIP_5706) || + (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0)) net_stats->tx_carrier_errors = 0; else { net_stats->tx_carrier_errors = @@ -7030,7 +7036,7 @@ bnx2_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p) offset = reg_boundaries[0]; p += offset; while (offset < BNX2_REGDUMP_LEN) { - *p++ = REG_RD(bp, offset); + *p++ = BNX2_RD(bp, offset); offset += 4; if (offset == reg_boundaries[i + 1]) { offset = reg_boundaries[i + 2]; @@ -7254,13 +7260,13 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { struct bnx2 *bp = netdev_priv(dev); - ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT; - ering->rx_jumbo_max_pending = MAX_TOTAL_RX_PG_DESC_CNT; + ering->rx_max_pending = BNX2_MAX_TOTAL_RX_DESC_CNT; + ering->rx_jumbo_max_pending = BNX2_MAX_TOTAL_RX_PG_DESC_CNT; ering->rx_pending = bp->rx_ring_size; ering->rx_jumbo_pending = bp->rx_pg_ring_size; - ering->tx_max_pending = MAX_TX_DESC_CNT; + ering->tx_max_pending = BNX2_MAX_TX_DESC_CNT; ering->tx_pending = bp->tx_ring_size; } @@ -7326,8 +7332,8 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) struct bnx2 *bp = netdev_priv(dev); int rc; - if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) || - (ering->tx_pending > MAX_TX_DESC_CNT) || + if ((ering->rx_pending > BNX2_MAX_TOTAL_RX_DESC_CNT) || + (ering->tx_pending > BNX2_MAX_TX_DESC_CNT) || (ering->tx_pending <= MAX_SKB_FRAGS)) { return -EINVAL; @@ -7614,10 +7620,10 @@ bnx2_get_ethtool_stats(struct net_device *dev, return; } - if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || - (CHIP_ID(bp) == CHIP_ID_5706_A1) || - (CHIP_ID(bp) == CHIP_ID_5706_A2) || - (CHIP_ID(bp) == CHIP_ID_5708_A0)) + if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) || + (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1) || + (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A2) || + (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0)) stats_len_arr = bnx2_5706_stats_len_arr; else stats_len_arr = bnx2_5708_stats_len_arr; @@ -7655,26 +7661,26 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state) case ETHTOOL_ID_ACTIVE: bnx2_set_power_state(bp, PCI_D0); - bp->leds_save = REG_RD(bp, BNX2_MISC_CFG); - REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC); + bp->leds_save = BNX2_RD(bp, BNX2_MISC_CFG); + BNX2_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC); return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: - REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE | - BNX2_EMAC_LED_1000MB_OVERRIDE | - BNX2_EMAC_LED_100MB_OVERRIDE | - BNX2_EMAC_LED_10MB_OVERRIDE | - BNX2_EMAC_LED_TRAFFIC_OVERRIDE | - BNX2_EMAC_LED_TRAFFIC); + BNX2_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE | + BNX2_EMAC_LED_1000MB_OVERRIDE | + BNX2_EMAC_LED_100MB_OVERRIDE | + BNX2_EMAC_LED_10MB_OVERRIDE | + BNX2_EMAC_LED_TRAFFIC_OVERRIDE | + BNX2_EMAC_LED_TRAFFIC); break; case ETHTOOL_ID_OFF: - REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE); + BNX2_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE); break; case ETHTOOL_ID_INACTIVE: - REG_WR(bp, BNX2_EMAC_LED, 0); - REG_WR(bp, BNX2_MISC_CFG, bp->leds_save); + BNX2_WR(bp, BNX2_EMAC_LED, 0); + BNX2_WR(bp, BNX2_MISC_CFG, bp->leds_save); if (!netif_running(dev)) bnx2_set_power_state(bp, PCI_D3hot); @@ -7896,10 +7902,10 @@ poll_bnx2(struct net_device *dev) } #endif -static void __devinit +static void bnx2_get_5709_media(struct bnx2 *bp) { - u32 val = REG_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL); + u32 val = BNX2_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL); u32 bond_id = val & BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID; u32 strap; @@ -7934,18 +7940,18 @@ bnx2_get_5709_media(struct bnx2 *bp) } } -static void __devinit +static void bnx2_get_pci_speed(struct bnx2 *bp) { u32 reg; - reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS); + reg = BNX2_RD(bp, BNX2_PCICFG_MISC_STATUS); if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) { u32 clkreg; bp->flags |= BNX2_FLAG_PCIX; - clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS); + clkreg = BNX2_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS); clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET; switch (clkreg) { @@ -7986,7 +7992,7 @@ bnx2_get_pci_speed(struct bnx2 *bp) } -static void __devinit +static void bnx2_read_vpd_fw_ver(struct bnx2 *bp) { int rc, i, j; @@ -8054,7 +8060,7 @@ vpd_done: kfree(data); } -static int __devinit +static int bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) { struct bnx2 *bp; @@ -8131,20 +8137,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) * Rely on CPU to do target byte swapping on big endian systems * The chip's target access swapping will not swap all accesses */ - REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, - BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | - BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP); + BNX2_WR(bp, BNX2_PCICFG_MISC_CONFIG, + BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | + BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP); - bp->chip_id = REG_RD(bp, BNX2_MISC_ID); + bp->chip_id = BNX2_RD(bp, BNX2_MISC_ID); - if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { if (!pci_is_pcie(pdev)) { dev_err(&pdev->dev, "Not PCIE, aborting\n"); rc = -EIO; goto err_out_unmap; } bp->flags |= BNX2_FLAG_PCIE; - if (CHIP_REV(bp) == CHIP_REV_Ax) + if (BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Ax) bp->flags |= BNX2_FLAG_JUMBO_BROKEN; /* AER (Advanced Error Reporting) hooks */ @@ -8163,18 +8169,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->flags |= BNX2_FLAG_BROKEN_STATS; } - if (CHIP_NUM(bp) == CHIP_NUM_5709 && CHIP_REV(bp) != CHIP_REV_Ax) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5709 && + BNX2_CHIP_REV(bp) != BNX2_CHIP_REV_Ax) { if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) bp->flags |= BNX2_FLAG_MSIX_CAP; } - if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) { + if (BNX2_CHIP_ID(bp) != BNX2_CHIP_ID_5706_A0 && + BNX2_CHIP_ID(bp) != BNX2_CHIP_ID_5706_A1) { if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) bp->flags |= BNX2_FLAG_MSI_CAP; } /* 5708 cannot support DMA addresses > 40-bit. */ - if (CHIP_NUM(bp) == CHIP_NUM_5708) + if (BNX2_CHIP(bp) == BNX2_CHIP_5708) persist_dma_mask = dma_mask = DMA_BIT_MASK(40); else persist_dma_mask = dma_mask = DMA_BIT_MASK(64); @@ -8197,12 +8205,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bnx2_get_pci_speed(bp); /* 5706A0 may falsely detect SERR and PERR. */ - if (CHIP_ID(bp) == CHIP_ID_5706_A0) { - reg = REG_RD(bp, PCI_COMMAND); + if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) { + reg = BNX2_RD(bp, PCI_COMMAND); reg &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY); - REG_WR(bp, PCI_COMMAND, reg); - } - else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) && + BNX2_WR(bp, PCI_COMMAND, reg); + } else if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1) && !(bp->flags & BNX2_FLAG_PCIX)) { dev_err(&pdev->dev, @@ -8299,7 +8306,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->mac_addr[4] = (u8) (reg >> 8); bp->mac_addr[5] = (u8) reg; - bp->tx_ring_size = MAX_TX_DESC_CNT; + bp->tx_ring_size = BNX2_MAX_TX_DESC_CNT; bnx2_set_rx_ring_size(bp, 255); bp->tx_quick_cons_trip_int = 2; @@ -8319,9 +8326,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->phy_addr = 1; /* Disable WOL support if we are running on a SERDES chip. */ - if (CHIP_NUM(bp) == CHIP_NUM_5709) + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) bnx2_get_5709_media(bp); - else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) + else if (BNX2_CHIP_BOND(bp) & BNX2_CHIP_BOND_SERDES_BIT) bp->phy_flags |= BNX2_PHY_FLAG_SERDES; bp->phy_port = PORT_TP; @@ -8332,7 +8339,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->flags |= BNX2_FLAG_NO_WOL; bp->wol = 0; } - if (CHIP_NUM(bp) == CHIP_NUM_5706) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5706) { /* Don't do parallel detect on this board because of * some board problems. The link will not go down * if we do parallel detect. @@ -8345,25 +8352,25 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) bp->phy_flags |= BNX2_PHY_FLAG_2_5G_CAPABLE; } - } else if (CHIP_NUM(bp) == CHIP_NUM_5706 || - CHIP_NUM(bp) == CHIP_NUM_5708) + } else if (BNX2_CHIP(bp) == BNX2_CHIP_5706 || + BNX2_CHIP(bp) == BNX2_CHIP_5708) bp->phy_flags |= BNX2_PHY_FLAG_CRC_FIX; - else if (CHIP_NUM(bp) == CHIP_NUM_5709 && - (CHIP_REV(bp) == CHIP_REV_Ax || - CHIP_REV(bp) == CHIP_REV_Bx)) + else if (BNX2_CHIP(bp) == BNX2_CHIP_5709 && + (BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Ax || + BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Bx)) bp->phy_flags |= BNX2_PHY_FLAG_DIS_EARLY_DAC; bnx2_init_fw_cap(bp); - if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || - (CHIP_ID(bp) == CHIP_ID_5708_B0) || - (CHIP_ID(bp) == CHIP_ID_5708_B1) || - !(REG_RD(bp, BNX2_PCI_CONFIG_3) & BNX2_PCI_CONFIG_3_VAUX_PRESET)) { + if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0) || + (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B0) || + (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B1) || + !(BNX2_RD(bp, BNX2_PCI_CONFIG_3) & BNX2_PCI_CONFIG_3_VAUX_PRESET)) { bp->flags |= BNX2_FLAG_NO_WOL; bp->wol = 0; } - if (CHIP_ID(bp) == CHIP_ID_5706_A0) { + if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) { bp->tx_quick_cons_trip_int = bp->tx_quick_cons_trip; bp->tx_ticks_int = bp->tx_ticks; @@ -8385,7 +8392,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) * AMD believes this incompatibility is unique to the 5706, and * prefers to locally disable MSI rather than globally disabling it. */ - if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) { + if (BNX2_CHIP(bp) == BNX2_CHIP_5706 && disable_msi == 0) { struct pci_dev *amd_8132 = NULL; while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD, @@ -8414,6 +8421,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->cnic_eth_dev.max_iscsi_conn = (bnx2_shmem_rd(bp, BNX2_ISCSI_MAX_CONN) & BNX2_ISCSI_MAX_CONN_MASK) >> BNX2_ISCSI_MAX_CONN_SHIFT; + bp->cnic_probe = bnx2_cnic_probe; #endif pci_save_state(pdev); @@ -8439,7 +8447,7 @@ err_out: return rc; } -static char * __devinit +static char * bnx2_bus_string(struct bnx2 *bp, char *str) { char *s = str; @@ -8505,7 +8513,7 @@ static const struct net_device_ops bnx2_netdev_ops = { #endif }; -static int __devinit +static int bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int version_printed = 0; @@ -8541,7 +8549,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_RXHASH | NETIF_F_RXCSUM; - if (CHIP_NUM(bp) == CHIP_NUM_5709) + if (BNX2_CHIP(bp) == BNX2_CHIP_5709) dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; dev->vlan_features = dev->hw_features; @@ -8556,8 +8564,8 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netdev_info(dev, "%s (%c%d) %s found at mem %lx, IRQ %d, " "node addr %pM\n", board_info[ent->driver_data].name, - ((CHIP_ID(bp) & 0xf000) >> 12) + 'A', - ((CHIP_ID(bp) & 0x0ff0) >> 4), + ((BNX2_CHIP_ID(bp) & 0xf000) >> 12) + 'A', + ((BNX2_CHIP_ID(bp) & 0x0ff0) >> 4), bnx2_bus_string(bp, str), (long)pci_resource_start(pdev, 0), pdev->irq, dev->dev_addr); @@ -8573,7 +8581,7 @@ err_free: return rc; } -static void __devexit +static void bnx2_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -8752,7 +8760,7 @@ static struct pci_driver bnx2_pci_driver = { .name = DRV_MODULE_NAME, .id_table = bnx2_pci_tbl, .probe = bnx2_init_one, - .remove = __devexit_p(bnx2_remove_one), + .remove = bnx2_remove_one, .suspend = bnx2_suspend, .resume = bnx2_resume, .err_handler = &bnx2_err_handler, diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h index af6451dec295..172efbecfea2 100644 --- a/drivers/net/ethernet/broadcom/bnx2.h +++ b/drivers/net/ethernet/broadcom/bnx2.h @@ -20,7 +20,7 @@ /* * tx_bd definition */ -struct tx_bd { +struct bnx2_tx_bd { u32 tx_bd_haddr_hi; u32 tx_bd_haddr_lo; u32 tx_bd_mss_nbytes; @@ -48,7 +48,7 @@ struct tx_bd { /* * rx_bd definition */ -struct rx_bd { +struct bnx2_rx_bd { u32 rx_bd_haddr_hi; u32 rx_bd_haddr_lo; u32 rx_bd_len; @@ -6538,37 +6538,38 @@ struct l2_fhdr { /* Use CPU native page size up to 16K for the ring sizes. */ #if (PAGE_SHIFT > 14) -#define BCM_PAGE_BITS 14 +#define BNX2_PAGE_BITS 14 #else -#define BCM_PAGE_BITS PAGE_SHIFT +#define BNX2_PAGE_BITS PAGE_SHIFT #endif -#define BCM_PAGE_SIZE (1 << BCM_PAGE_BITS) +#define BNX2_PAGE_SIZE (1 << BNX2_PAGE_BITS) -#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd)) -#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1) +#define BNX2_TX_DESC_CNT (BNX2_PAGE_SIZE / sizeof(struct bnx2_tx_bd)) +#define BNX2_MAX_TX_DESC_CNT (BNX2_TX_DESC_CNT - 1) -#define MAX_RX_RINGS 8 -#define MAX_RX_PG_RINGS 32 -#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd)) -#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1) -#define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS) -#define MAX_TOTAL_RX_PG_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_PG_RINGS) +#define BNX2_MAX_RX_RINGS 8 +#define BNX2_MAX_RX_PG_RINGS 32 +#define BNX2_RX_DESC_CNT (BNX2_PAGE_SIZE / sizeof(struct bnx2_rx_bd)) +#define BNX2_MAX_RX_DESC_CNT (BNX2_RX_DESC_CNT - 1) +#define BNX2_MAX_TOTAL_RX_DESC_CNT (BNX2_MAX_RX_DESC_CNT * BNX2_MAX_RX_RINGS) +#define BNX2_MAX_TOTAL_RX_PG_DESC_CNT \ + (BNX2_MAX_RX_DESC_CNT * BNX2_MAX_RX_PG_RINGS) -#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \ - (MAX_TX_DESC_CNT - 1)) ? \ +#define BNX2_NEXT_TX_BD(x) (((x) & (BNX2_MAX_TX_DESC_CNT - 1)) == \ + (BNX2_MAX_TX_DESC_CNT - 1)) ? \ (x) + 2 : (x) + 1 -#define TX_RING_IDX(x) ((x) & MAX_TX_DESC_CNT) +#define BNX2_TX_RING_IDX(x) ((x) & BNX2_MAX_TX_DESC_CNT) -#define NEXT_RX_BD(x) (((x) & (MAX_RX_DESC_CNT - 1)) == \ - (MAX_RX_DESC_CNT - 1)) ? \ +#define BNX2_NEXT_RX_BD(x) (((x) & (BNX2_MAX_RX_DESC_CNT - 1)) == \ + (BNX2_MAX_RX_DESC_CNT - 1)) ? \ (x) + 2 : (x) + 1 -#define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx) -#define RX_PG_RING_IDX(x) ((x) & bp->rx_max_pg_ring_idx) +#define BNX2_RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx) +#define BNX2_RX_PG_RING_IDX(x) ((x) & bp->rx_max_pg_ring_idx) -#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4)) -#define RX_IDX(x) ((x) & MAX_RX_DESC_CNT) +#define BNX2_RX_RING(x) (((x) & ~BNX2_MAX_RX_DESC_CNT) >> (BNX2_PAGE_BITS - 4)) +#define BNX2_RX_IDX(x) ((x) & BNX2_MAX_RX_DESC_CNT) /* Context size. */ #define CTX_SHIFT 7 @@ -6609,7 +6610,7 @@ struct l2_fhdr { * RX ring buffer contains pointer to kmalloc() data only, * skb are built only after Hardware filled the frame. */ -struct sw_bd { +struct bnx2_sw_bd { u8 *data; DEFINE_DMA_UNMAP_ADDR(mapping); }; @@ -6623,23 +6624,23 @@ static inline struct l2_fhdr *get_l2_fhdr(u8 *data) } -struct sw_pg { +struct bnx2_sw_pg { struct page *page; DEFINE_DMA_UNMAP_ADDR(mapping); }; -struct sw_tx_bd { +struct bnx2_sw_tx_bd { struct sk_buff *skb; DEFINE_DMA_UNMAP_ADDR(mapping); unsigned short is_gso; unsigned short nr_frags; }; -#define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT) -#define SW_RXPG_RING_SIZE (sizeof(struct sw_pg) * RX_DESC_CNT) -#define RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT) -#define SW_TXBD_RING_SIZE (sizeof(struct sw_tx_bd) * TX_DESC_CNT) -#define TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT) +#define SW_RXBD_RING_SIZE (sizeof(struct bnx2_sw_bd) * BNX2_RX_DESC_CNT) +#define SW_RXPG_RING_SIZE (sizeof(struct bnx2_sw_pg) * BNX2_RX_DESC_CNT) +#define RXBD_RING_SIZE (sizeof(struct bnx2_rx_bd) * BNX2_RX_DESC_CNT) +#define SW_TXBD_RING_SIZE (sizeof(struct bnx2_sw_tx_bd) * BNX2_TX_DESC_CNT) +#define TXBD_RING_SIZE (sizeof(struct bnx2_tx_bd) * BNX2_TX_DESC_CNT) /* Buffered flash (Atmel: AT45DB011B) specific information */ #define SEEPROM_PAGE_BITS 2 @@ -6720,8 +6721,8 @@ struct bnx2_tx_ring_info { u32 tx_bidx_addr; u32 tx_bseq_addr; - struct tx_bd *tx_desc_ring; - struct sw_tx_bd *tx_buf_ring; + struct bnx2_tx_bd *tx_desc_ring; + struct bnx2_sw_tx_bd *tx_buf_ring; u16 tx_cons; u16 hw_tx_cons; @@ -6741,13 +6742,13 @@ struct bnx2_rx_ring_info { u16 rx_pg_prod; u16 rx_pg_cons; - struct sw_bd *rx_buf_ring; - struct rx_bd *rx_desc_ring[MAX_RX_RINGS]; - struct sw_pg *rx_pg_ring; - struct rx_bd *rx_pg_desc_ring[MAX_RX_PG_RINGS]; + struct bnx2_sw_bd *rx_buf_ring; + struct bnx2_rx_bd *rx_desc_ring[BNX2_MAX_RX_RINGS]; + struct bnx2_sw_pg *rx_pg_ring; + struct bnx2_rx_bd *rx_pg_desc_ring[BNX2_MAX_RX_PG_RINGS]; - dma_addr_t rx_desc_mapping[MAX_RX_RINGS]; - dma_addr_t rx_pg_desc_mapping[MAX_RX_PG_RINGS]; + dma_addr_t rx_desc_mapping[BNX2_MAX_RX_RINGS]; + dma_addr_t rx_pg_desc_mapping[BNX2_MAX_RX_PG_RINGS]; }; struct bnx2_napi { @@ -6853,33 +6854,31 @@ struct bnx2 { u32 chip_id; /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */ -#define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000) -#define CHIP_NUM_5706 0x57060000 -#define CHIP_NUM_5708 0x57080000 -#define CHIP_NUM_5709 0x57090000 - -#define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000) -#define CHIP_REV_Ax 0x00000000 -#define CHIP_REV_Bx 0x00001000 -#define CHIP_REV_Cx 0x00002000 - -#define CHIP_METAL(bp) (((bp)->chip_id) & 0x00000ff0) -#define CHIP_BONDING(bp) (((bp)->chip_id) & 0x0000000f) - -#define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0) -#define CHIP_ID_5706_A0 0x57060000 -#define CHIP_ID_5706_A1 0x57060010 -#define CHIP_ID_5706_A2 0x57060020 -#define CHIP_ID_5708_A0 0x57080000 -#define CHIP_ID_5708_B0 0x57081000 -#define CHIP_ID_5708_B1 0x57081010 -#define CHIP_ID_5709_A0 0x57090000 -#define CHIP_ID_5709_A1 0x57090010 - -#define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf) +#define BNX2_CHIP(bp) (((bp)->chip_id) & 0xffff0000) +#define BNX2_CHIP_5706 0x57060000 +#define BNX2_CHIP_5708 0x57080000 +#define BNX2_CHIP_5709 0x57090000 + +#define BNX2_CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000) +#define BNX2_CHIP_REV_Ax 0x00000000 +#define BNX2_CHIP_REV_Bx 0x00001000 +#define BNX2_CHIP_REV_Cx 0x00002000 + +#define BNX2_CHIP_METAL(bp) (((bp)->chip_id) & 0x00000ff0) +#define BNX2_CHIP_BOND(bp) (((bp)->chip_id) & 0x0000000f) + +#define BNX2_CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0) +#define BNX2_CHIP_ID_5706_A0 0x57060000 +#define BNX2_CHIP_ID_5706_A1 0x57060010 +#define BNX2_CHIP_ID_5706_A2 0x57060020 +#define BNX2_CHIP_ID_5708_A0 0x57080000 +#define BNX2_CHIP_ID_5708_B0 0x57081000 +#define BNX2_CHIP_ID_5708_B1 0x57081010 +#define BNX2_CHIP_ID_5709_A0 0x57090000 +#define BNX2_CHIP_ID_5709_A1 0x57090010 /* A serdes chip will have the first bit of the bond id set. */ -#define CHIP_BOND_ID_SERDES_BIT 0x01 +#define BNX2_CHIP_BOND_SERDES_BIT 0x01 u32 phy_addr; u32 phy_id; @@ -6985,19 +6984,20 @@ struct bnx2 { #ifdef BCM_CNIC struct mutex cnic_lock; struct cnic_eth_dev cnic_eth_dev; + struct cnic_eth_dev *(*cnic_probe)(struct net_device *); #endif const struct firmware *mips_firmware; const struct firmware *rv2p_firmware; }; -#define REG_RD(bp, offset) \ +#define BNX2_RD(bp, offset) \ readl(bp->regview + offset) -#define REG_WR(bp, offset, val) \ +#define BNX2_WR(bp, offset, val) \ writel(val, bp->regview + offset) -#define REG_WR16(bp, offset, val) \ +#define BNX2_WR16(bp, offset, val) \ writew(val, bp->regview + offset) struct cpu_reg { @@ -7052,7 +7052,7 @@ struct bnx2_rv2p_fw_file { #define RV2P_P1_FIXUP_PAGE_SIZE_IDX 0 #define RV2P_BD_PAGE_SIZE_MSK 0xffff -#define RV2P_BD_PAGE_SIZE ((BCM_PAGE_SIZE / 16) - 1) +#define RV2P_BD_PAGE_SIZE ((BNX2_PAGE_SIZE / 16) - 1) #define RV2P_PROC1 0 #define RV2P_PROC2 1 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 72897c47b8c8..e8d4db10c8f3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -34,25 +34,16 @@ #include "bnx2x_hsi.h" -#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE) -#define BCM_CNIC 1 #include "../cnic_if.h" -#endif -#ifdef BCM_CNIC -#define BNX2X_MIN_MSIX_VEC_CNT 3 -#define BNX2X_MSIX_VEC_FP_START 2 -#else -#define BNX2X_MIN_MSIX_VEC_CNT 2 -#define BNX2X_MSIX_VEC_FP_START 1 -#endif + +#define BNX2X_MIN_MSIX_VEC_CNT(bp) ((bp)->min_msix_vec_cnt) #include <linux/mdio.h> #include "bnx2x_reg.h" #include "bnx2x_fw_defs.h" #include "bnx2x_mfw_req.h" -#include "bnx2x_hsi.h" #include "bnx2x_link.h" #include "bnx2x_sp.h" #include "bnx2x_dcb.h" @@ -256,15 +247,10 @@ enum { /* FCoE L2 */ #define BNX2X_FCOE_ETH_CID(bp) (BNX2X_CNIC_START_ETH_CID(bp) + 1) -/** Additional rings budgeting */ -#ifdef BCM_CNIC -#define CNIC_PRESENT 1 -#define FCOE_PRESENT 1 -#else -#define CNIC_PRESENT 0 -#define FCOE_PRESENT 0 -#endif /* BCM_CNIC */ -#define NON_ETH_CONTEXT_USE (FCOE_PRESENT) +#define CNIC_SUPPORT(bp) ((bp)->cnic_support) +#define CNIC_ENABLED(bp) ((bp)->cnic_enabled) +#define CNIC_LOADED(bp) ((bp)->cnic_loaded) +#define FCOE_INIT(bp) ((bp)->fcoe_init) #define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \ AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR @@ -297,9 +283,7 @@ enum { OOO_TXQ_IDX_OFFSET, }; #define MAX_ETH_TXQ_IDX(bp) (BNX2X_NUM_NON_CNIC_QUEUES(bp) * (bp)->max_cos) -#ifdef BCM_CNIC #define FCOE_TXQ_IDX(bp) (MAX_ETH_TXQ_IDX(bp) + FCOE_TXQ_IDX_OFFSET) -#endif /* fast path */ /* @@ -505,7 +489,7 @@ struct bnx2x_fastpath { u32 ustorm_rx_prods_offset; u32 rx_buf_size; - + u32 rx_frag_size; /* 0 if kmalloced(), or rx_buf_size + NET_SKB_PAD */ dma_addr_t status_blk_mapping; enum bnx2x_tpa_mode_t mode; @@ -585,15 +569,9 @@ struct bnx2x_fastpath { ->var) -#define IS_ETH_FP(fp) (fp->index < \ - BNX2X_NUM_ETH_QUEUES(fp->bp)) -#ifdef BCM_CNIC -#define IS_FCOE_FP(fp) (fp->index == FCOE_IDX(fp->bp)) -#define IS_FCOE_IDX(idx) ((idx) == FCOE_IDX(bp)) -#else -#define IS_FCOE_FP(fp) false -#define IS_FCOE_IDX(idx) false -#endif +#define IS_ETH_FP(fp) ((fp)->index < BNX2X_NUM_ETH_QUEUES((fp)->bp)) +#define IS_FCOE_FP(fp) ((fp)->index == FCOE_IDX((fp)->bp)) +#define IS_FCOE_IDX(idx) ((idx) == FCOE_IDX(bp)) /* MC hsi */ @@ -886,6 +864,18 @@ struct bnx2x_common { (CHIP_REV(bp) == CHIP_REV_Bx)) #define CHIP_IS_E3A0(bp) (CHIP_IS_E3(bp) && \ (CHIP_REV(bp) == CHIP_REV_Ax)) +/* This define is used in two main places: + * 1. In the early stages of nic_load, to know if to configrue Parser / Searcher + * to nic-only mode or to offload mode. Offload mode is configured if either the + * chip is E1x (where MIC_MODE register is not applicable), or if cnic already + * registered for this port (which means that the user wants storage services). + * 2. During cnic-related load, to know if offload mode is already configured in + * the HW or needs to be configrued. + * Since the transition from nic-mode to offload-mode in HW causes traffic + * coruption, nic-mode is configured only in ports on which storage services + * where never requested. + */ +#define CONFIGURE_NIC_MODE(bp) (!CHIP_IS_E1x(bp) && !CNIC_ENABLED(bp)) int flash_size; #define BNX2X_NVRAM_1MB_SIZE 0x20000 /* 1M bit in bytes */ @@ -925,6 +915,7 @@ struct bnx2x_common { #define BNX2X_IGU_STAS_MSG_VF_CNT 64 #define BNX2X_IGU_STAS_MSG_PF_CNT 4 +#define MAX_IGU_ATTN_ACK_TO 100 /* end of common */ /* port */ @@ -946,7 +937,6 @@ struct bnx2x_port { /* used to synchronize phy accesses */ struct mutex phy_mutex; - int need_hw_lock; u32 port_stx; @@ -1003,18 +993,15 @@ union cdu_context { #define CDU_ILT_PAGE_SZ (8192 << CDU_ILT_PAGE_SZ_HW) /* 32K */ #define ILT_PAGE_CIDS (CDU_ILT_PAGE_SZ / sizeof(union cdu_context)) -#ifdef BCM_CNIC #define CNIC_ISCSI_CID_MAX 256 #define CNIC_FCOE_CID_MAX 2048 #define CNIC_CID_MAX (CNIC_ISCSI_CID_MAX + CNIC_FCOE_CID_MAX) #define CNIC_ILT_LINES DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS) -#endif #define QM_ILT_PAGE_SZ_HW 0 #define QM_ILT_PAGE_SZ (4096 << QM_ILT_PAGE_SZ_HW) /* 4K */ #define QM_CID_ROUND 1024 -#ifdef BCM_CNIC /* TM (timers) host DB constants */ #define TM_ILT_PAGE_SZ_HW 0 #define TM_ILT_PAGE_SZ (4096 << TM_ILT_PAGE_SZ_HW) /* 4K */ @@ -1032,8 +1019,6 @@ union cdu_context { #define SRC_T2_SZ SRC_ILT_SZ #define SRC_ILT_LINES DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ) -#endif - #define MAX_DMAE_C 8 /* DMA memory not used in fastpath */ @@ -1201,6 +1186,7 @@ struct bnx2x_prev_path_list { u8 slot; u8 path; struct list_head list; + u8 undi; }; struct bnx2x_sp_objs { @@ -1227,7 +1213,6 @@ struct bnx2x { struct bnx2x_sp_objs *sp_objs; struct bnx2x_fp_stats *fp_stats; struct bnx2x_fp_txdata *bnx2x_txq; - int bnx2x_txq_size; void __iomem *regview; void __iomem *doorbells; u16 db_size; @@ -1350,6 +1335,16 @@ struct bnx2x { #define NO_ISCSI_OOO(bp) ((bp)->flags & NO_ISCSI_OOO_FLAG) #define NO_FCOE(bp) ((bp)->flags & NO_FCOE_FLAG) + u8 cnic_support; + bool cnic_enabled; + bool cnic_loaded; + struct cnic_eth_dev *(*cnic_probe)(struct net_device *); + + /* Flag that indicates that we can start looking for FCoE L2 queue + * completions in the default status block. + */ + bool fcoe_init; + int pm_cap; int mrrs; @@ -1420,6 +1415,8 @@ struct bnx2x { #define BNX2X_MAX_COS 3 #define BNX2X_MAX_TX_COS 2 int num_queues; + uint num_ethernet_queues; + uint num_cnic_queues; int num_napi_queues; int disable_tpa; @@ -1433,6 +1430,7 @@ struct bnx2x { u8 igu_dsb_id; u8 igu_base_sb; u8 igu_sb_cnt; + u8 min_msix_vec_cnt; dma_addr_t def_status_blk_mapping; @@ -1478,26 +1476,23 @@ struct bnx2x { * Maximum supported number of RSS queues: number of IGU SBs minus one that goes * to CNIC. */ -#define BNX2X_MAX_RSS_COUNT(bp) ((bp)->igu_sb_cnt - CNIC_PRESENT) +#define BNX2X_MAX_RSS_COUNT(bp) ((bp)->igu_sb_cnt - CNIC_SUPPORT(bp)) /* * Maximum CID count that might be required by the bnx2x: * Max RSS * Max_Tx_Multi_Cos + FCoE + iSCSI */ #define BNX2X_L2_CID_COUNT(bp) (BNX2X_NUM_ETH_QUEUES(bp) * BNX2X_MULTI_TX_COS \ - + NON_ETH_CONTEXT_USE + CNIC_PRESENT) + + 2 * CNIC_SUPPORT(bp)) #define BNX2X_L2_MAX_CID(bp) (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS \ - + NON_ETH_CONTEXT_USE + CNIC_PRESENT) + + 2 * CNIC_SUPPORT(bp)) #define L2_ILT_LINES(bp) (DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\ ILT_PAGE_CIDS)) int qm_cid_count; - int dropless_fc; + bool dropless_fc; -#ifdef BCM_CNIC - u32 cnic_flags; -#define BNX2X_CNIC_FLAG_MAC_SET 1 void *t2; dma_addr_t t2_mapping; struct cnic_ops __rcu *cnic_ops; @@ -1518,7 +1513,6 @@ struct bnx2x { /* Start index of the "special" (CNIC related) L2 cleints */ u8 cnic_base_cl_id; -#endif int dmae_ready; /* used to synchronize dmae accesses */ @@ -1647,9 +1641,9 @@ struct bnx2x { /* Tx queues may be less or equal to Rx queues */ extern int num_queues; #define BNX2X_NUM_QUEUES(bp) (bp->num_queues) -#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE) +#define BNX2X_NUM_ETH_QUEUES(bp) ((bp)->num_ethernet_queues) #define BNX2X_NUM_NON_CNIC_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - \ - NON_ETH_CONTEXT_USE) + (bp)->num_cnic_queues) #define BNX2X_NUM_RX_QUEUES(bp) BNX2X_NUM_QUEUES(bp) #define is_multi(bp) (BNX2X_NUM_QUEUES(bp) > 1) @@ -1689,6 +1683,13 @@ struct bnx2x_func_init_params { u16 spq_prod; /* valid iff FUNC_FLG_SPQ */ }; +#define for_each_cnic_queue(bp, var) \ + for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \ + (var)++) \ + if (skip_queue(bp, var)) \ + continue; \ + else + #define for_each_eth_queue(bp, var) \ for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++) @@ -1702,6 +1703,22 @@ struct bnx2x_func_init_params { else /* Skip forwarding FP */ +#define for_each_valid_rx_queue(bp, var) \ + for ((var) = 0; \ + (var) < (CNIC_LOADED(bp) ? BNX2X_NUM_QUEUES(bp) : \ + BNX2X_NUM_ETH_QUEUES(bp)); \ + (var)++) \ + if (skip_rx_queue(bp, var)) \ + continue; \ + else + +#define for_each_rx_queue_cnic(bp, var) \ + for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \ + (var)++) \ + if (skip_rx_queue(bp, var)) \ + continue; \ + else + #define for_each_rx_queue(bp, var) \ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \ if (skip_rx_queue(bp, var)) \ @@ -1709,6 +1726,22 @@ struct bnx2x_func_init_params { else /* Skip OOO FP */ +#define for_each_valid_tx_queue(bp, var) \ + for ((var) = 0; \ + (var) < (CNIC_LOADED(bp) ? BNX2X_NUM_QUEUES(bp) : \ + BNX2X_NUM_ETH_QUEUES(bp)); \ + (var)++) \ + if (skip_tx_queue(bp, var)) \ + continue; \ + else + +#define for_each_tx_queue_cnic(bp, var) \ + for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \ + (var)++) \ + if (skip_tx_queue(bp, var)) \ + continue; \ + else + #define for_each_tx_queue(bp, var) \ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \ if (skip_tx_queue(bp, var)) \ @@ -2179,7 +2212,6 @@ void bnx2x_notify_link_changed(struct bnx2x *bp); #define BNX2X_MF_SD_PROTOCOL(bp) \ ((bp)->mf_config[BP_VN(bp)] & FUNC_MF_CFG_PROTOCOL_MASK) -#ifdef BCM_CNIC #define BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) \ (BNX2X_MF_SD_PROTOCOL(bp) == FUNC_MF_CFG_PROTOCOL_ISCSI) @@ -2196,9 +2228,12 @@ void bnx2x_notify_link_changed(struct bnx2x *bp); #define IS_MF_STORAGE_SD(bp) (IS_MF_SD(bp) && \ (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) || \ BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp))) -#else -#define IS_MF_FCOE_AFEX(bp) false -#endif +enum { + SWITCH_UPDATE, + AFEX_UPDATE, +}; + +#define NUM_MACS 8 #endif /* bnx2x.h */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 4833b6a9031c..f771ddfba646 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -80,12 +80,37 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to) new_txdata_index = new_max_eth_txqs + FCOE_TXQ_IDX_OFFSET; } - memcpy(&bp->bnx2x_txq[old_txdata_index], - &bp->bnx2x_txq[new_txdata_index], + memcpy(&bp->bnx2x_txq[new_txdata_index], + &bp->bnx2x_txq[old_txdata_index], sizeof(struct bnx2x_fp_txdata)); to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index]; } +/** + * bnx2x_shrink_eth_fp - guarantees fastpath structures stay intact + * + * @bp: driver handle + * @delta: number of eth queues which were not allocated + */ +static void bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta) +{ + int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp); + + /* Queue pointer cannot be re-set on an fp-basis, as moving pointer + * backward along the array could cause memory to be overriden + */ + for (cos = 1; cos < bp->max_cos; cos++) { + for (i = 0; i < old_eth_num - delta; i++) { + struct bnx2x_fastpath *fp = &bp->fp[i]; + int new_idx = cos * (old_eth_num - delta) + i; + + memcpy(&bp->bnx2x_txq[new_idx], fp->txdata_ptr[cos], + sizeof(struct bnx2x_fp_txdata)); + fp->txdata_ptr[cos] = &bp->bnx2x_txq[new_idx]; + } + } +} + int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */ /* free skb in the packet ring at pos idx @@ -552,6 +577,23 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, return 0; } +static void bnx2x_frag_free(const struct bnx2x_fastpath *fp, void *data) +{ + if (fp->rx_frag_size) + put_page(virt_to_head_page(data)); + else + kfree(data); +} + +static void *bnx2x_frag_alloc(const struct bnx2x_fastpath *fp) +{ + if (fp->rx_frag_size) + return netdev_alloc_frag(fp->rx_frag_size); + + return kmalloc(fp->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC); +} + + static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, struct bnx2x_agg_info *tpa_info, u16 pages, @@ -574,15 +616,14 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, goto drop; /* Try to allocate the new data */ - new_data = kmalloc(fp->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC); - + new_data = bnx2x_frag_alloc(fp); /* Unmap skb in the pool anyway, as we are going to change pool entry status to BNX2X_TPA_STOP even if new skb allocation fails. */ dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(rx_buf, mapping), fp->rx_buf_size, DMA_FROM_DEVICE); if (likely(new_data)) - skb = build_skb(data, 0); + skb = build_skb(data, fp->rx_frag_size); if (likely(skb)) { #ifdef BNX2X_STOP_ON_ERROR @@ -619,7 +660,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, return; } - kfree(new_data); + bnx2x_frag_free(fp, new_data); drop: /* drop the packet and keep the buffer in the bin */ DP(NETIF_MSG_RX_STATUS, @@ -635,7 +676,7 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp, struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index]; dma_addr_t mapping; - data = kmalloc(fp->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC); + data = bnx2x_frag_alloc(fp); if (unlikely(data == NULL)) return -ENOMEM; @@ -643,7 +684,7 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp, fp->rx_buf_size, DMA_FROM_DEVICE); if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) { - kfree(data); + bnx2x_frag_free(fp, data); BNX2X_ERR("Can't map rx data\n"); return -ENOMEM; } @@ -845,9 +886,9 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) dma_unmap_addr(rx_buf, mapping), fp->rx_buf_size, DMA_FROM_DEVICE); - skb = build_skb(data, 0); + skb = build_skb(data, fp->rx_frag_size); if (unlikely(!skb)) { - kfree(data); + bnx2x_frag_free(fp, data); bnx2x_fp_qstats(bp, fp)-> rx_skb_alloc_failed++; goto next_rx; @@ -948,14 +989,12 @@ void bnx2x_acquire_phy_lock(struct bnx2x *bp) { mutex_lock(&bp->port.phy_mutex); - if (bp->port.need_hw_lock) - bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_MDIO); + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_MDIO); } void bnx2x_release_phy_lock(struct bnx2x *bp) { - if (bp->port.need_hw_lock) - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_MDIO); + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_MDIO); mutex_unlock(&bp->port.phy_mutex); } @@ -1147,11 +1186,30 @@ static void bnx2x_free_tpa_pool(struct bnx2x *bp, dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(first_buf, mapping), fp->rx_buf_size, DMA_FROM_DEVICE); - kfree(data); + bnx2x_frag_free(fp, data); first_buf->data = NULL; } } +void bnx2x_init_rx_rings_cnic(struct bnx2x *bp) +{ + int j; + + for_each_rx_queue_cnic(bp, j) { + struct bnx2x_fastpath *fp = &bp->fp[j]; + + fp->rx_bd_cons = 0; + + /* Activate BD ring */ + /* Warning! + * this will generate an interrupt (to the TSTORM) + * must only be done after chip is initialized + */ + bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod, + fp->rx_sge_prod); + } +} + void bnx2x_init_rx_rings(struct bnx2x *bp) { int func = BP_FUNC(bp); @@ -1159,7 +1217,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) int i, j; /* Allocate TPA resources */ - for_each_rx_queue(bp, j) { + for_each_eth_queue(bp, j) { struct bnx2x_fastpath *fp = &bp->fp[j]; DP(NETIF_MSG_IFUP, @@ -1173,8 +1231,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) struct sw_rx_bd *first_buf = &tpa_info->first_buf; - first_buf->data = kmalloc(fp->rx_buf_size + NET_SKB_PAD, - GFP_ATOMIC); + first_buf->data = bnx2x_frag_alloc(fp); if (!first_buf->data) { BNX2X_ERR("Failed to allocate TPA skb pool for queue[%d] - disabling TPA on this queue!\n", j); @@ -1217,7 +1274,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) } } - for_each_rx_queue(bp, j) { + for_each_eth_queue(bp, j) { struct bnx2x_fastpath *fp = &bp->fp[j]; fp->rx_bd_cons = 0; @@ -1244,29 +1301,45 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) } } -static void bnx2x_free_tx_skbs(struct bnx2x *bp) +static void bnx2x_free_tx_skbs_queue(struct bnx2x_fastpath *fp) { - int i; u8 cos; + struct bnx2x *bp = fp->bp; - for_each_tx_queue(bp, i) { - struct bnx2x_fastpath *fp = &bp->fp[i]; - for_each_cos_in_tx_queue(fp, cos) { - struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos]; - unsigned pkts_compl = 0, bytes_compl = 0; + for_each_cos_in_tx_queue(fp, cos) { + struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos]; + unsigned pkts_compl = 0, bytes_compl = 0; - u16 sw_prod = txdata->tx_pkt_prod; - u16 sw_cons = txdata->tx_pkt_cons; + u16 sw_prod = txdata->tx_pkt_prod; + u16 sw_cons = txdata->tx_pkt_cons; - while (sw_cons != sw_prod) { - bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons), - &pkts_compl, &bytes_compl); - sw_cons++; - } - netdev_tx_reset_queue( - netdev_get_tx_queue(bp->dev, - txdata->txq_index)); + while (sw_cons != sw_prod) { + bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons), + &pkts_compl, &bytes_compl); + sw_cons++; } + + netdev_tx_reset_queue( + netdev_get_tx_queue(bp->dev, + txdata->txq_index)); + } +} + +static void bnx2x_free_tx_skbs_cnic(struct bnx2x *bp) +{ + int i; + + for_each_tx_queue_cnic(bp, i) { + bnx2x_free_tx_skbs_queue(&bp->fp[i]); + } +} + +static void bnx2x_free_tx_skbs(struct bnx2x *bp) +{ + int i; + + for_each_eth_queue(bp, i) { + bnx2x_free_tx_skbs_queue(&bp->fp[i]); } } @@ -1290,7 +1363,16 @@ static void bnx2x_free_rx_bds(struct bnx2x_fastpath *fp) fp->rx_buf_size, DMA_FROM_DEVICE); rx_buf->data = NULL; - kfree(data); + bnx2x_frag_free(fp, data); + } +} + +static void bnx2x_free_rx_skbs_cnic(struct bnx2x *bp) +{ + int j; + + for_each_rx_queue_cnic(bp, j) { + bnx2x_free_rx_bds(&bp->fp[j]); } } @@ -1298,7 +1380,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp) { int j; - for_each_rx_queue(bp, j) { + for_each_eth_queue(bp, j) { struct bnx2x_fastpath *fp = &bp->fp[j]; bnx2x_free_rx_bds(fp); @@ -1308,6 +1390,12 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp) } } +void bnx2x_free_skbs_cnic(struct bnx2x *bp) +{ + bnx2x_free_tx_skbs_cnic(bp); + bnx2x_free_rx_skbs_cnic(bp); +} + void bnx2x_free_skbs(struct bnx2x *bp) { bnx2x_free_tx_skbs(bp); @@ -1347,11 +1435,12 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp, int nvecs) DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n", bp->msix_table[offset].vector); offset++; -#ifdef BCM_CNIC - if (nvecs == offset) - return; - offset++; -#endif + + if (CNIC_SUPPORT(bp)) { + if (nvecs == offset) + return; + offset++; + } for_each_eth_queue(bp, i) { if (nvecs == offset) @@ -1368,7 +1457,7 @@ void bnx2x_free_irq(struct bnx2x *bp) if (bp->flags & USING_MSIX_FLAG && !(bp->flags & USING_SINGLE_MSIX_FLAG)) bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) + - CNIC_PRESENT + 1); + CNIC_SUPPORT(bp) + 1); else free_irq(bp->dev->irq, bp->dev); } @@ -1382,12 +1471,14 @@ int bnx2x_enable_msix(struct bnx2x *bp) bp->msix_table[0].entry); msix_vec++; -#ifdef BCM_CNIC - bp->msix_table[msix_vec].entry = msix_vec; - BNX2X_DEV_INFO("msix_table[%d].entry = %d (CNIC)\n", - bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry); - msix_vec++; -#endif + /* Cnic requires an msix vector for itself */ + if (CNIC_SUPPORT(bp)) { + bp->msix_table[msix_vec].entry = msix_vec; + BNX2X_DEV_INFO("msix_table[%d].entry = %d (CNIC)\n", + msix_vec, bp->msix_table[msix_vec].entry); + msix_vec++; + } + /* We need separate vectors for ETH queues only (not FCoE) */ for_each_eth_queue(bp, i) { bp->msix_table[msix_vec].entry = msix_vec; @@ -1396,7 +1487,7 @@ int bnx2x_enable_msix(struct bnx2x *bp) msix_vec++; } - req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_PRESENT + 1; + req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_SUPPORT(bp) + 1; rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt); @@ -1404,7 +1495,7 @@ int bnx2x_enable_msix(struct bnx2x *bp) * reconfigure number of tx/rx queues according to available * MSI-X vectors */ - if (rc >= BNX2X_MIN_MSIX_VEC_CNT) { + if (rc >= BNX2X_MIN_MSIX_VEC_CNT(bp)) { /* how less vectors we will have? */ int diff = req_cnt - rc; @@ -1419,7 +1510,8 @@ int bnx2x_enable_msix(struct bnx2x *bp) /* * decrease number of queues by number of unallocated entries */ - bp->num_queues -= diff; + bp->num_ethernet_queues -= diff; + bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues; BNX2X_DEV_INFO("New queue configuration set: %d\n", bp->num_queues); @@ -1435,6 +1527,9 @@ int bnx2x_enable_msix(struct bnx2x *bp) BNX2X_DEV_INFO("Using single MSI-X vector\n"); bp->flags |= USING_SINGLE_MSIX_FLAG; + BNX2X_DEV_INFO("set number of queues to 1\n"); + bp->num_ethernet_queues = 1; + bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues; } else if (rc < 0) { BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc); goto no_msix; @@ -1464,9 +1559,9 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) return -EBUSY; } -#ifdef BCM_CNIC - offset++; -#endif + if (CNIC_SUPPORT(bp)) + offset++; + for_each_eth_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; snprintf(fp->name, sizeof(fp->name), "%s-fp-%d", @@ -1485,7 +1580,7 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) } i = BNX2X_NUM_ETH_QUEUES(bp); - offset = 1 + CNIC_PRESENT; + offset = 1 + CNIC_SUPPORT(bp); netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d ... fp[%d] %d\n", bp->msix_table[0].vector, 0, bp->msix_table[offset].vector, @@ -1556,19 +1651,35 @@ static int bnx2x_setup_irqs(struct bnx2x *bp) return 0; } +static void bnx2x_napi_enable_cnic(struct bnx2x *bp) +{ + int i; + + for_each_rx_queue_cnic(bp, i) + napi_enable(&bnx2x_fp(bp, i, napi)); +} + static void bnx2x_napi_enable(struct bnx2x *bp) { int i; - for_each_rx_queue(bp, i) + for_each_eth_queue(bp, i) napi_enable(&bnx2x_fp(bp, i, napi)); } +static void bnx2x_napi_disable_cnic(struct bnx2x *bp) +{ + int i; + + for_each_rx_queue_cnic(bp, i) + napi_disable(&bnx2x_fp(bp, i, napi)); +} + static void bnx2x_napi_disable(struct bnx2x *bp) { int i; - for_each_rx_queue(bp, i) + for_each_eth_queue(bp, i) napi_disable(&bnx2x_fp(bp, i, napi)); } @@ -1576,6 +1687,8 @@ void bnx2x_netif_start(struct bnx2x *bp) { if (netif_running(bp->dev)) { bnx2x_napi_enable(bp); + if (CNIC_LOADED(bp)) + bnx2x_napi_enable_cnic(bp); bnx2x_int_enable(bp); if (bp->state == BNX2X_STATE_OPEN) netif_tx_wake_all_queues(bp->dev); @@ -1586,14 +1699,15 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) { bnx2x_int_disable_sync(bp, disable_hw); bnx2x_napi_disable(bp); + if (CNIC_LOADED(bp)) + bnx2x_napi_disable_cnic(bp); } u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb) { struct bnx2x *bp = netdev_priv(dev); -#ifdef BCM_CNIC - if (!NO_FCOE(bp)) { + if (CNIC_LOADED(bp) && !NO_FCOE(bp)) { struct ethhdr *hdr = (struct ethhdr *)skb->data; u16 ether_type = ntohs(hdr->h_proto); @@ -1609,7 +1723,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb) if ((ether_type == ETH_P_FCOE) || (ether_type == ETH_P_FIP)) return bnx2x_fcoe_tx(bp, txq_index); } -#endif + /* select a non-FCoE queue */ return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp)); } @@ -1618,15 +1732,15 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb) void bnx2x_set_num_queues(struct bnx2x *bp) { /* RSS queues */ - bp->num_queues = bnx2x_calc_num_queues(bp); + bp->num_ethernet_queues = bnx2x_calc_num_queues(bp); -#ifdef BCM_CNIC /* override in STORAGE SD modes */ if (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)) - bp->num_queues = 1; -#endif + bp->num_ethernet_queues = 1; + /* Add special queues */ - bp->num_queues += NON_ETH_CONTEXT_USE; + bp->num_cnic_queues = CNIC_SUPPORT(bp); /* For FCOE */ + bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues; BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues); } @@ -1653,20 +1767,18 @@ void bnx2x_set_num_queues(struct bnx2x *bp) * bnx2x_setup_tc() takes care of the proper TC mappings so that __skb_tx_hash() * will return a proper Tx index if TC is enabled (netdev->num_tc > 0). */ -static int bnx2x_set_real_num_queues(struct bnx2x *bp) +static int bnx2x_set_real_num_queues(struct bnx2x *bp, int include_cnic) { int rc, tx, rx; tx = BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos; - rx = BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE; + rx = BNX2X_NUM_ETH_QUEUES(bp); /* account for fcoe queue */ -#ifdef BCM_CNIC - if (!NO_FCOE(bp)) { - rx += FCOE_PRESENT; - tx += FCOE_PRESENT; + if (include_cnic && !NO_FCOE(bp)) { + rx++; + tx++; } -#endif rc = netif_set_real_num_tx_queues(bp->dev, tx); if (rc) { @@ -1710,6 +1822,10 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp) mtu + BNX2X_FW_RX_ALIGN_END; /* Note : rx_buf_size doesnt take into account NET_SKB_PAD */ + if (fp->rx_buf_size + NET_SKB_PAD <= PAGE_SIZE) + fp->rx_frag_size = fp->rx_buf_size + NET_SKB_PAD; + else + fp->rx_frag_size = 0; } } @@ -1741,7 +1857,6 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, bool config_hash) { struct bnx2x_config_rss_params params = {NULL}; - int i; /* Although RSS is meaningless when there is a single HW queue we * still need it enabled in order to have HW Rx hash generated. @@ -1773,9 +1888,7 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, if (config_hash) { /* RSS keys */ - for (i = 0; i < sizeof(params.rss_key) / 4; i++) - params.rss_key[i] = random32(); - + prandom_bytes(params.rss_key, sizeof(params.rss_key)); __set_bit(BNX2X_RSS_SET_SRCH, ¶ms.rss_flags); } @@ -1859,14 +1972,26 @@ static void bnx2x_squeeze_objects(struct bnx2x *bp) (bp)->state = BNX2X_STATE_ERROR; \ goto label; \ } while (0) -#else + +#define LOAD_ERROR_EXIT_CNIC(bp, label) \ + do { \ + bp->cnic_loaded = false; \ + goto label; \ + } while (0) +#else /*BNX2X_STOP_ON_ERROR*/ #define LOAD_ERROR_EXIT(bp, label) \ do { \ (bp)->state = BNX2X_STATE_ERROR; \ (bp)->panic = 1; \ return -EBUSY; \ } while (0) -#endif +#define LOAD_ERROR_EXIT_CNIC(bp, label) \ + do { \ + bp->cnic_loaded = false; \ + (bp)->panic = 1; \ + return -EBUSY; \ + } while (0) +#endif /*BNX2X_STOP_ON_ERROR*/ bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err) { @@ -1959,10 +2084,8 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index) fp->max_cos = 1; /* Init txdata pointers */ -#ifdef BCM_CNIC if (IS_FCOE_FP(fp)) fp->txdata_ptr[0] = &bp->bnx2x_txq[FCOE_TXQ_IDX(bp)]; -#endif if (IS_ETH_FP(fp)) for_each_cos_in_tx_queue(fp, cos) fp->txdata_ptr[cos] = &bp->bnx2x_txq[cos * @@ -1980,11 +2103,95 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index) else if (bp->flags & GRO_ENABLE_FLAG) fp->mode = TPA_MODE_GRO; -#ifdef BCM_CNIC /* We don't want TPA on an FCoE L2 ring */ if (IS_FCOE_FP(fp)) fp->disable_tpa = 1; -#endif +} + +int bnx2x_load_cnic(struct bnx2x *bp) +{ + int i, rc, port = BP_PORT(bp); + + DP(NETIF_MSG_IFUP, "Starting CNIC-related load\n"); + + mutex_init(&bp->cnic_mutex); + + rc = bnx2x_alloc_mem_cnic(bp); + if (rc) { + BNX2X_ERR("Unable to allocate bp memory for cnic\n"); + LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0); + } + + rc = bnx2x_alloc_fp_mem_cnic(bp); + if (rc) { + BNX2X_ERR("Unable to allocate memory for cnic fps\n"); + LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0); + } + + /* Update the number of queues with the cnic queues */ + rc = bnx2x_set_real_num_queues(bp, 1); + if (rc) { + BNX2X_ERR("Unable to set real_num_queues including cnic\n"); + LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0); + } + + /* Add all CNIC NAPI objects */ + bnx2x_add_all_napi_cnic(bp); + DP(NETIF_MSG_IFUP, "cnic napi added\n"); + bnx2x_napi_enable_cnic(bp); + + rc = bnx2x_init_hw_func_cnic(bp); + if (rc) + LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic1); + + bnx2x_nic_init_cnic(bp); + + /* Enable Timer scan */ + REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1); + + for_each_cnic_queue(bp, i) { + rc = bnx2x_setup_queue(bp, &bp->fp[i], 0); + if (rc) { + BNX2X_ERR("Queue setup failed\n"); + LOAD_ERROR_EXIT(bp, load_error_cnic2); + } + } + + /* Initialize Rx filter. */ + netif_addr_lock_bh(bp->dev); + bnx2x_set_rx_mode(bp->dev); + netif_addr_unlock_bh(bp->dev); + + /* re-read iscsi info */ + bnx2x_get_iscsi_info(bp); + bnx2x_setup_cnic_irq_info(bp); + bnx2x_setup_cnic_info(bp); + bp->cnic_loaded = true; + if (bp->state == BNX2X_STATE_OPEN) + bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD); + + + DP(NETIF_MSG_IFUP, "Ending successfully CNIC-related load\n"); + + return 0; + +#ifndef BNX2X_STOP_ON_ERROR +load_error_cnic2: + /* Disable Timer scan */ + REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0); + +load_error_cnic1: + bnx2x_napi_disable_cnic(bp); + /* Update the number of queues without the cnic queues */ + rc = bnx2x_set_real_num_queues(bp, 0); + if (rc) + BNX2X_ERR("Unable to set real_num_queues not including cnic\n"); +load_error_cnic0: + BNX2X_ERR("CNIC-related load failed\n"); + bnx2x_free_fp_mem_cnic(bp); + bnx2x_free_mem_cnic(bp); + return rc; +#endif /* ! BNX2X_STOP_ON_ERROR */ } @@ -1995,6 +2202,10 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) u32 load_code; int i, rc; + DP(NETIF_MSG_IFUP, "Starting NIC load\n"); + DP(NETIF_MSG_IFUP, + "CNIC is %s\n", CNIC_ENABLED(bp) ? "enabled" : "disabled"); + #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) { BNX2X_ERR("Can't load NIC when there is panic\n"); @@ -2022,9 +2233,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) DP(NETIF_MSG_IFUP, "num queues: %d", bp->num_queues); for_each_queue(bp, i) bnx2x_bz_fp(bp, i); - memset(bp->bnx2x_txq, 0, bp->bnx2x_txq_size * - sizeof(struct bnx2x_fp_txdata)); + memset(bp->bnx2x_txq, 0, (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS + + bp->num_cnic_queues) * + sizeof(struct bnx2x_fp_txdata)); + bp->fcoe_init = false; /* Set the receive queues buffer size */ bnx2x_set_rx_buf_size(bp); @@ -2034,9 +2247,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) /* As long as bnx2x_alloc_mem() may possibly update * bp->num_queues, bnx2x_set_real_num_queues() should always - * come after it. + * come after it. At this stage cnic queues are not counted. */ - rc = bnx2x_set_real_num_queues(bp); + rc = bnx2x_set_real_num_queues(bp, 0); if (rc) { BNX2X_ERR("Unable to set real_num_queues\n"); LOAD_ERROR_EXIT(bp, load_error0); @@ -2050,6 +2263,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) /* Add all NAPI objects */ bnx2x_add_all_napi(bp); + DP(NETIF_MSG_IFUP, "napi added\n"); bnx2x_napi_enable(bp); /* set pf load just before approaching the MCP */ @@ -2073,7 +2287,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) 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); + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, + DRV_MSG_CODE_LOAD_REQ_WITH_LFA); if (!load_code) { BNX2X_ERR("MCP response failure, aborting\n"); rc = -EBUSY; @@ -2191,23 +2406,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) LOAD_ERROR_EXIT(bp, load_error3); } -#ifdef BCM_CNIC - /* Enable Timer scan */ - REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1); -#endif - - for_each_nondefault_queue(bp, i) { + for_each_nondefault_eth_queue(bp, i) { rc = bnx2x_setup_queue(bp, &bp->fp[i], 0); if (rc) { BNX2X_ERR("Queue setup failed\n"); - LOAD_ERROR_EXIT(bp, load_error4); + LOAD_ERROR_EXIT(bp, load_error3); } } rc = bnx2x_init_rss_pf(bp); if (rc) { BNX2X_ERR("PF RSS init failed\n"); - LOAD_ERROR_EXIT(bp, load_error4); + LOAD_ERROR_EXIT(bp, load_error3); } /* Now when Clients are configured we are ready to work */ @@ -2217,7 +2427,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) rc = bnx2x_set_eth_mac(bp, true); if (rc) { BNX2X_ERR("Setting Ethernet MAC failed\n"); - LOAD_ERROR_EXIT(bp, load_error4); + LOAD_ERROR_EXIT(bp, load_error3); } if (bp->pending_max) { @@ -2227,6 +2437,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) if (bp->port.pmf) bnx2x_initial_phy_init(bp, load_mode); + bp->link_params.feature_config_flags &= ~FEATURE_CONFIG_BOOT_FROM_SAN; /* Start fast path */ @@ -2257,21 +2468,15 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) } if (bp->port.pmf) - bnx2x_update_drv_flags(bp, 1 << DRV_FLAGS_DCB_CONFIGURED, 0); + bnx2x_update_drv_flags(bp, 1 << DRV_FLAGS_PORT_MASK, 0); else bnx2x__link_status_update(bp); /* start the timer */ mod_timer(&bp->timer, jiffies + bp->current_interval); -#ifdef BCM_CNIC - /* re-read iscsi info */ - bnx2x_get_iscsi_info(bp); - bnx2x_setup_cnic_irq_info(bp); - bnx2x_setup_cnic_info(bp); - if (bp->state == BNX2X_STATE_OPEN) - bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD); -#endif + if (CNIC_ENABLED(bp)) + bnx2x_load_cnic(bp); /* mark driver is loaded in shmem2 */ if (SHMEM2_HAS(bp, drv_capabilities_flag)) { @@ -2293,14 +2498,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) if (bp->port.pmf && (bp->state != BNX2X_STATE_DIAG)) bnx2x_dcbx_init(bp, false); + DP(NETIF_MSG_IFUP, "Ending successfully NIC load\n"); + return 0; #ifndef BNX2X_STOP_ON_ERROR -load_error4: -#ifdef BCM_CNIC - /* Disable Timer scan */ - REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0); -#endif load_error3: bnx2x_int_disable_sync(bp, 1); @@ -2338,6 +2540,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) int i; bool global = false; + DP(NETIF_MSG_IFUP, "Starting NIC unload\n"); + /* mark driver is unloaded in shmem2 */ if (SHMEM2_HAS(bp, drv_capabilities_flag)) { u32 val; @@ -2373,14 +2577,13 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; smp_mb(); + if (CNIC_LOADED(bp)) + bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD); + /* Stop Tx */ bnx2x_tx_disable(bp); netdev_reset_tc(bp->dev); -#ifdef BCM_CNIC - bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD); -#endif - bp->rx_mode = BNX2X_RX_MODE_NONE; del_timer_sync(&bp->timer); @@ -2414,7 +2617,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) bnx2x_netif_stop(bp, 1); /* Delete all NAPI objects */ bnx2x_del_all_napi(bp); - + if (CNIC_LOADED(bp)) + bnx2x_del_all_napi_cnic(bp); /* Release IRQs */ bnx2x_free_irq(bp); @@ -2435,12 +2639,19 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) /* Free SKBs, SGEs, TPA pool and driver internals */ bnx2x_free_skbs(bp); + if (CNIC_LOADED(bp)) + bnx2x_free_skbs_cnic(bp); for_each_rx_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); + if (CNIC_LOADED(bp)) { + bnx2x_free_fp_mem_cnic(bp); + bnx2x_free_mem_cnic(bp); + } bnx2x_free_mem(bp); bp->state = BNX2X_STATE_CLOSED; + bp->cnic_loaded = false; /* Check if there are pending parity attentions. If there are - set * RECOVERY_IN_PROGRESS. @@ -2460,6 +2671,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) if (!bnx2x_clear_pf_load(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp))) bnx2x_disable_close_the_gate(bp); + DP(NETIF_MSG_IFUP, "Ending NIC unload\n"); + return 0; } @@ -2550,7 +2763,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget) /* Fall out from the NAPI loop if needed */ if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { -#ifdef BCM_CNIC + /* No need to update SB for FCoE L2 ring as long as * it's connected to the default SB and the SB * has been updated when NAPI was scheduled. @@ -2559,8 +2772,6 @@ int bnx2x_poll(struct napi_struct *napi, int budget) napi_complete(napi); break; } -#endif - bnx2x_update_fpsb_idx(fp); /* bnx2x_has_rx_work() reads the status block, * thus we need to ensure that status block indices @@ -2940,7 +3151,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) txq_index = skb_get_queue_mapping(skb); txq = netdev_get_tx_queue(dev, txq_index); - BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + FCOE_PRESENT); + BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + (CNIC_LOADED(bp) ? 1 : 0)); txdata = &bp->bnx2x_txq[txq_index]; @@ -2958,11 +3169,16 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) BDS_PER_TX_PKT + NEXT_CNT_PER_TX_PKT(MAX_BDS_PER_TX_PKT))) { /* Handle special storage cases separately */ - if (txdata->tx_ring_size != 0) { - BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); + if (txdata->tx_ring_size == 0) { + struct bnx2x_eth_q_stats *q_stats = + bnx2x_fp_qstats(bp, txdata->parent_fp); + q_stats->driver_filtered_tx_pkt++; + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++; netif_tx_stop_queue(txq); - } + BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); return NETDEV_TX_BUSY; } @@ -3339,13 +3555,11 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p) return -EINVAL; } -#ifdef BCM_CNIC if ((IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)) && !is_zero_ether_addr(addr->sa_data)) { BNX2X_ERR("Can't configure non-zero address on iSCSI or FCoE functions in MF-SD mode\n"); return -EINVAL; } -#endif if (netif_running(dev)) { rc = bnx2x_set_eth_mac(bp, false); @@ -3369,13 +3583,11 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index) u8 cos; /* Common */ -#ifdef BCM_CNIC + if (IS_FCOE_IDX(fp_index)) { memset(sb, 0, sizeof(union host_hc_status_block)); fp->status_blk_mapping = 0; - } else { -#endif /* status blocks */ if (!CHIP_IS_E1x(bp)) BNX2X_PCI_FREE(sb->e2_sb, @@ -3387,9 +3599,8 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index) bnx2x_fp(bp, fp_index, status_blk_mapping), sizeof(struct host_hc_status_block_e1x)); -#ifdef BCM_CNIC } -#endif + /* Rx */ if (!skip_rx_queue(bp, fp_index)) { bnx2x_free_rx_bds(fp); @@ -3431,10 +3642,17 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index) /* end of fastpath */ } +void bnx2x_free_fp_mem_cnic(struct bnx2x *bp) +{ + int i; + for_each_cnic_queue(bp, i) + bnx2x_free_fp_mem_at(bp, i); +} + void bnx2x_free_fp_mem(struct bnx2x *bp) { int i; - for_each_queue(bp, i) + for_each_eth_queue(bp, i) bnx2x_free_fp_mem_at(bp, i); } @@ -3519,14 +3737,11 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index) u8 cos; int rx_ring_size = 0; -#ifdef BCM_CNIC if (!bp->rx_ring_size && (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) { rx_ring_size = MIN_RX_SIZE_NONTPA; bp->rx_ring_size = rx_ring_size; - } else -#endif - if (!bp->rx_ring_size) { + } else if (!bp->rx_ring_size) { rx_ring_size = MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp); if (CHIP_IS_E3(bp)) { @@ -3550,9 +3765,8 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index) /* Common */ sb = &bnx2x_fp(bp, index, status_blk); -#ifdef BCM_CNIC + if (!IS_FCOE_IDX(index)) { -#endif /* status blocks */ if (!CHIP_IS_E1x(bp)) BNX2X_PCI_ALLOC(sb->e2_sb, @@ -3562,9 +3776,7 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index) BNX2X_PCI_ALLOC(sb->e1x_sb, &bnx2x_fp(bp, index, status_blk_mapping), sizeof(struct host_hc_status_block_e1x)); -#ifdef BCM_CNIC } -#endif /* FCoE Queue uses Default SB and doesn't ACK the SB, thus no need to * set shortcuts for it. @@ -3641,31 +3853,31 @@ alloc_mem_err: return 0; } +int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp) +{ + if (!NO_FCOE(bp)) + /* FCoE */ + if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX(bp))) + /* we will fail load process instead of mark + * NO_FCOE_FLAG + */ + return -ENOMEM; + + return 0; +} + int bnx2x_alloc_fp_mem(struct bnx2x *bp) { int i; - /** - * 1. Allocate FP for leading - fatal if error - * 2. {CNIC} Allocate FCoE FP - fatal if error - * 3. {CNIC} Allocate OOO + FWD - disable OOO if error - * 4. Allocate RSS - fix number of queues if error + /* 1. Allocate FP for leading - fatal if error + * 2. Allocate RSS - fix number of queues if error */ /* leading */ if (bnx2x_alloc_fp_mem_at(bp, 0)) return -ENOMEM; -#ifdef BCM_CNIC - if (!NO_FCOE(bp)) - /* FCoE */ - if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX(bp))) - /* we will fail load process instead of mark - * NO_FCOE_FLAG - */ - return -ENOMEM; -#endif - /* RSS */ for_each_nondefault_eth_queue(bp, i) if (bnx2x_alloc_fp_mem_at(bp, i)) @@ -3676,17 +3888,18 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp) int delta = BNX2X_NUM_ETH_QUEUES(bp) - i; WARN_ON(delta < 0); -#ifdef BCM_CNIC - /** - * move non eth FPs next to last eth FP - * must be done in that order - * FCOE_IDX < FWD_IDX < OOO_IDX - */ + bnx2x_shrink_eth_fp(bp, delta); + if (CNIC_SUPPORT(bp)) + /* move non eth FPs next to last eth FP + * must be done in that order + * FCOE_IDX < FWD_IDX < OOO_IDX + */ - /* move FCoE fp even NO_FCOE_FLAG is on */ - bnx2x_move_fp(bp, FCOE_IDX(bp), FCOE_IDX(bp) - delta); -#endif - bp->num_queues -= delta; + /* move FCoE fp even NO_FCOE_FLAG is on */ + bnx2x_move_fp(bp, FCOE_IDX(bp), FCOE_IDX(bp) - delta); + bp->num_ethernet_queues -= delta; + bp->num_queues = bp->num_ethernet_queues + + bp->num_cnic_queues; BNX2X_ERR("Adjusted num of queues from %d to %d\n", bp->num_queues + delta, bp->num_queues); } @@ -3705,13 +3918,13 @@ void bnx2x_free_mem_bp(struct bnx2x *bp) kfree(bp->ilt); } -int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp) +int bnx2x_alloc_mem_bp(struct bnx2x *bp) { struct bnx2x_fastpath *fp; struct msix_entry *tbl; struct bnx2x_ilt *ilt; int msix_table_size = 0; - int fp_array_size; + int fp_array_size, txq_array_size; int i; /* @@ -3721,7 +3934,7 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp) msix_table_size = bp->igu_sb_cnt + 1; /* fp array: RSS plus CNIC related L2 queues */ - fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + NON_ETH_CONTEXT_USE; + fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + CNIC_SUPPORT(bp); BNX2X_DEV_INFO("fp_array_size %d", fp_array_size); fp = kcalloc(fp_array_size, sizeof(*fp), GFP_KERNEL); @@ -3750,12 +3963,12 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp) goto alloc_err; /* Allocate memory for the transmission queues array */ - bp->bnx2x_txq_size = BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS; -#ifdef BCM_CNIC - bp->bnx2x_txq_size++; -#endif - bp->bnx2x_txq = kcalloc(bp->bnx2x_txq_size, - sizeof(struct bnx2x_fp_txdata), GFP_KERNEL); + txq_array_size = + BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS + CNIC_SUPPORT(bp); + BNX2X_DEV_INFO("txq_array_size %d", txq_array_size); + + bp->bnx2x_txq = kcalloc(txq_array_size, sizeof(struct bnx2x_fp_txdata), + GFP_KERNEL); if (!bp->bnx2x_txq) goto alloc_err; @@ -3838,7 +4051,7 @@ int bnx2x_get_link_cfg_idx(struct bnx2x *bp) return LINK_CONFIG_IDX(sel_phy_idx); } -#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC) +#ifdef NETDEV_FCOE_WWNN int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type) { struct bnx2x *bp = netdev_priv(dev); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 9c5ea6c5b4c7..0991534f61da 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -144,7 +144,7 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param); * @bp: driver handle * @load_mode: current mode */ -u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode); +int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode); /** * bnx2x_link_set - configure hw according to link parameters structure. @@ -238,7 +238,6 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance); * @dev_instance: private instance */ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance); -#ifdef BCM_CNIC /** * bnx2x_cnic_notify - send command to cnic driver @@ -262,8 +261,6 @@ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp); */ void bnx2x_setup_cnic_info(struct bnx2x *bp); -#endif - /** * bnx2x_int_enable - enable HW interrupts. * @@ -283,7 +280,7 @@ void bnx2x_int_enable(struct bnx2x *bp); void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw); /** - * bnx2x_nic_init - init driver internals. + * bnx2x_nic_init_cnic - init driver internals for cnic. * * @bp: driver handle * @load_code: COMMON, PORT or FUNCTION @@ -293,9 +290,26 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw); * - status blocks * - etc. */ -void bnx2x_nic_init(struct bnx2x *bp, u32 load_code); +void bnx2x_nic_init_cnic(struct bnx2x *bp); /** + * bnx2x_nic_init - init driver internals. + * + * @bp: driver handle + * + * Initializes: + * - rings + * - status blocks + * - etc. + */ +void bnx2x_nic_init(struct bnx2x *bp, u32 load_code); +/** + * bnx2x_alloc_mem_cnic - allocate driver's memory for cnic. + * + * @bp: driver handle + */ +int bnx2x_alloc_mem_cnic(struct bnx2x *bp); +/** * bnx2x_alloc_mem - allocate driver's memory. * * @bp: driver handle @@ -303,6 +317,12 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code); int bnx2x_alloc_mem(struct bnx2x *bp); /** + * bnx2x_free_mem_cnic - release driver's memory for cnic. + * + * @bp: driver handle + */ +void bnx2x_free_mem_cnic(struct bnx2x *bp); +/** * bnx2x_free_mem - release driver's memory. * * @bp: driver handle @@ -407,6 +427,7 @@ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine); void bnx2x_set_reset_in_progress(struct bnx2x *bp); void bnx2x_set_reset_global(struct bnx2x *bp); void bnx2x_disable_close_the_gate(struct bnx2x *bp); +int bnx2x_init_hw_func_cnic(struct bnx2x *bp); /** * bnx2x_sp_event - handle ramrods completion. @@ -424,6 +445,14 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe); void bnx2x_ilt_set_info(struct bnx2x *bp); /** + * bnx2x_ilt_set_cnic_info - prepare ILT configurations for SRC + * and TM. + * + * @bp: driver handle + */ +void bnx2x_ilt_set_info_cnic(struct bnx2x *bp); + +/** * bnx2x_dcbx_init - initialize dcbx protocol. * * @bp: driver handle @@ -491,12 +520,17 @@ int bnx2x_resume(struct pci_dev *pdev); /* Release IRQ vectors */ void bnx2x_free_irq(struct bnx2x *bp); +void bnx2x_free_fp_mem_cnic(struct bnx2x *bp); void bnx2x_free_fp_mem(struct bnx2x *bp); +int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp); int bnx2x_alloc_fp_mem(struct bnx2x *bp); void bnx2x_init_rx_rings(struct bnx2x *bp); +void bnx2x_init_rx_rings_cnic(struct bnx2x *bp); +void bnx2x_free_skbs_cnic(struct bnx2x *bp); void bnx2x_free_skbs(struct bnx2x *bp); void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw); void bnx2x_netif_start(struct bnx2x *bp); +int bnx2x_load_cnic(struct bnx2x *bp); /** * bnx2x_enable_msix - set msix configuration. @@ -529,7 +563,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget); * * @bp: driver handle */ -int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp); +int bnx2x_alloc_mem_bp(struct bnx2x *bp); /** * bnx2x_free_mem_bp - release memories outsize main driver structure @@ -547,7 +581,7 @@ void bnx2x_free_mem_bp(struct bnx2x *bp); */ int bnx2x_change_mtu(struct net_device *dev, int new_mtu); -#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC) +#ifdef NETDEV_FCOE_WWNN /** * bnx2x_fcoe_get_wwn - return the requested WWN value for this port * @@ -793,23 +827,39 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp, sge->addr_lo = 0; } -static inline void bnx2x_add_all_napi(struct bnx2x *bp) +static inline void bnx2x_add_all_napi_cnic(struct bnx2x *bp) { int i; - bp->num_napi_queues = bp->num_queues; + /* Add NAPI objects */ + for_each_rx_queue_cnic(bp, i) + netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), + bnx2x_poll, BNX2X_NAPI_WEIGHT); +} + +static inline void bnx2x_add_all_napi(struct bnx2x *bp) +{ + int i; /* Add NAPI objects */ - for_each_rx_queue(bp, i) + for_each_eth_queue(bp, i) netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), bnx2x_poll, BNX2X_NAPI_WEIGHT); } +static inline void bnx2x_del_all_napi_cnic(struct bnx2x *bp) +{ + int i; + + for_each_rx_queue_cnic(bp, i) + netif_napi_del(&bnx2x_fp(bp, i, napi)); +} + static inline void bnx2x_del_all_napi(struct bnx2x *bp) { int i; - for_each_rx_queue(bp, i) + for_each_eth_queue(bp, i) netif_napi_del(&bnx2x_fp(bp, i, napi)); } @@ -979,11 +1029,9 @@ static inline u8 bnx2x_stats_id(struct bnx2x_fastpath *fp) { struct bnx2x *bp = fp->bp; if (!CHIP_IS_E1x(bp)) { -#ifdef BCM_CNIC /* there are special statistics counters for FCoE 136..140 */ if (IS_FCOE_FP(fp)) return bp->cnic_base_cl_id + (bp->pf_num >> 1); -#endif return fp->cl_id; } return fp->cl_id + BP_PORT(bp) * FP_SB_MAX_E1x; @@ -1102,7 +1150,6 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp, txdata->cid, txdata->txq_index); } -#ifdef BCM_CNIC static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx) { return bp->cnic_base_cl_id + cl_idx + @@ -1162,7 +1209,6 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp) fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id, fp->igu_sb_id); } -#endif static inline int bnx2x_clean_tx_queue(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata) @@ -1280,7 +1326,7 @@ static inline bool bnx2x_mtu_allows_gro(int mtu) */ return mtu <= SGE_PAGE_SIZE && (U_ETH_SGL_SIZE * fpp) <= MAX_SKB_FRAGS; } -#ifdef BCM_CNIC + /** * bnx2x_get_iscsi_info - update iSCSI params according to licensing info. * @@ -1288,7 +1334,6 @@ static inline bool bnx2x_mtu_allows_gro(int mtu) * */ void bnx2x_get_iscsi_info(struct bnx2x *bp); -#endif /** * bnx2x_link_sync_notify - send notification to other functions. @@ -1340,13 +1385,11 @@ static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set) static inline bool bnx2x_is_valid_ether_addr(struct bnx2x *bp, u8 *addr) { - if (is_valid_ether_addr(addr)) + if (is_valid_ether_addr(addr) || + (is_zero_ether_addr(addr) && + (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)))) return true; -#ifdef BCM_CNIC - if (is_zero_ether_addr(addr) && - (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) - return true; -#endif + return false; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c index 2245c3895409..10bc093d2ca4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c @@ -413,8 +413,11 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp, static void bnx2x_pfc_set_pfc(struct bnx2x *bp) { + int mfw_configured = SHMEM2_HAS(bp, drv_flags) && + GET_FLAGS(SHMEM2_RD(bp, drv_flags), + 1 << DRV_FLAGS_DCB_MFW_CONFIGURED); if (bp->dcbx_port_params.pfc.enabled && - !(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)) + (!(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) || mfw_configured)) /* * 1. Fills up common PFC structures if required * 2. Configure NIG, MAC and BRB via the elink @@ -552,10 +555,13 @@ static void bnx2x_dcbx_update_ets_config(struct bnx2x *bp) static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp) { + int mfw_configured = SHMEM2_HAS(bp, drv_flags) && + GET_FLAGS(SHMEM2_RD(bp, drv_flags), + 1 << DRV_FLAGS_DCB_MFW_CONFIGURED); bnx2x_ets_disabled(&bp->link_params, &bp->link_vars); if (!bp->dcbx_port_params.ets.enabled || - (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)) + ((bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) && !mfw_configured)) return; if (CHIP_IS_E3B0(bp)) @@ -1802,11 +1808,14 @@ static void bnx2x_dcbx_fw_struct(struct bnx2x *bp, u8 cos = 0, pri = 0; struct priority_cos *tt2cos; u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority; + int mfw_configured = SHMEM2_HAS(bp, drv_flags) && + GET_FLAGS(SHMEM2_RD(bp, drv_flags), + 1 << DRV_FLAGS_DCB_MFW_CONFIGURED); memset(pfc_fw_cfg, 0, sizeof(*pfc_fw_cfg)); /* to disable DCB - the structure must be zeroed */ - if (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) + if ((bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) && !mfw_configured) return; /*shortcut*/ @@ -1895,6 +1904,11 @@ static u8 bnx2x_dcbnl_set_state(struct net_device *netdev, u8 state) struct bnx2x *bp = netdev_priv(netdev); DP(BNX2X_MSG_DCB, "state = %s\n", state ? "on" : "off"); + if (state && ((bp->dcbx_enabled == BNX2X_DCBX_ENABLED_OFF) || + (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_INVALID))) { + DP(BNX2X_MSG_DCB, "Can not set dcbx to enabled while it is disabled in nvm\n"); + return 1; + } bnx2x_dcbx_set_state(bp, (state ? true : false), bp->dcbx_enabled); return 0; } @@ -1908,10 +1922,10 @@ static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev, /* first the HW mac address */ memcpy(perm_addr, netdev->dev_addr, netdev->addr_len); -#ifdef BCM_CNIC - /* second SAN address */ - memcpy(perm_addr+netdev->addr_len, bp->fip_mac, netdev->addr_len); -#endif + if (CNIC_LOADED(bp)) + /* second SAN address */ + memcpy(perm_addr+netdev->addr_len, bp->fip_mac, + netdev->addr_len); } static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio, @@ -2038,10 +2052,13 @@ static void bnx2x_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio, if (!bnx2x_dcbnl_set_valid(bp) || prio >= MAX_PFC_PRIORITIES) return; - bp->dcbx_config_params.admin_pfc_bitmap |= ((setting ? 1 : 0) << prio); - if (setting) + if (setting) { + bp->dcbx_config_params.admin_pfc_bitmap |= (1 << prio); bp->dcbx_config_params.admin_pfc_tx_enable = 1; + } else { + bp->dcbx_config_params.admin_pfc_bitmap &= ~(1 << prio); + } } static void bnx2x_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio, @@ -2073,8 +2090,12 @@ static u8 bnx2x_dcbnl_set_all(struct net_device *netdev) "Handling parity error recovery. Try again later\n"); return 1; } - if (netif_running(bp->dev)) + if (netif_running(bp->dev)) { + bnx2x_update_drv_flags(bp, + 1 << DRV_FLAGS_DCB_MFW_CONFIGURED, + 1); bnx2x_dcbx_init(bp, true); + } DP(BNX2X_MSG_DCB, "set_dcbx_params done (%d)\n", rc); if (rc) return 1; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index c65295dded39..a427b49a886c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -62,7 +62,9 @@ static const struct { 8, "[%s]: tpa_aggregations" }, { Q_STATS_OFFSET32(total_tpa_aggregated_frames_hi), 8, "[%s]: tpa_aggregated_frames"}, - { Q_STATS_OFFSET32(total_tpa_bytes_hi), 8, "[%s]: tpa_bytes"} + { Q_STATS_OFFSET32(total_tpa_bytes_hi), 8, "[%s]: tpa_bytes"}, + { Q_STATS_OFFSET32(driver_filtered_tx_pkt), + 4, "[%s]: driver_filtered_tx_pkt" } }; #define BNX2X_NUM_Q_STATS ARRAY_SIZE(bnx2x_q_stats_arr) @@ -177,6 +179,8 @@ static const struct { 4, STATS_FLAGS_FUNC, "recoverable_errors" }, { STATS_OFFSET32(unrecoverable_error), 4, STATS_FLAGS_FUNC, "unrecoverable_errors" }, + { STATS_OFFSET32(driver_filtered_tx_pkt), + 4, STATS_FLAGS_FUNC, "driver_filtered_tx_pkt" }, { STATS_OFFSET32(eee_tx_lpi), 4, STATS_FLAGS_PORT, "Tx LPI entry count"} }; @@ -227,18 +231,14 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->advertising &= ~(ADVERTISED_10000baseT_Full); } - if ((bp->state == BNX2X_STATE_OPEN) && (bp->link_vars.link_up)) { - if (!(bp->flags & MF_FUNC_DIS)) { - ethtool_cmd_speed_set(cmd, bp->link_vars.line_speed); + if ((bp->state == BNX2X_STATE_OPEN) && bp->link_vars.link_up && + !(bp->flags & MF_FUNC_DIS)) { cmd->duplex = bp->link_vars.duplex; - } else { - ethtool_cmd_speed_set( - cmd, bp->link_params.req_line_speed[cfg_idx]); - cmd->duplex = bp->link_params.req_duplex[cfg_idx]; - } if (IS_MF(bp) && !BP_NOMCP(bp)) ethtool_cmd_speed_set(cmd, bnx2x_get_mf_speed(bp)); + else + ethtool_cmd_speed_set(cmd, bp->link_vars.line_speed); } else { cmd->duplex = DUPLEX_UNKNOWN; ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN); @@ -1702,7 +1702,7 @@ static int bnx2x_set_eee(struct net_device *dev, struct ethtool_eee *edata) SHMEM_EEE_ADV_STATUS_SHIFT); if ((advertised != (eee_cfg & SHMEM_EEE_ADV_STATUS_MASK))) { DP(BNX2X_MSG_ETHTOOL, - "Direct manipulation of EEE advertisment is not supported\n"); + "Direct manipulation of EEE advertisement is not supported\n"); return -EINVAL; } @@ -2660,20 +2660,25 @@ static int bnx2x_set_phys_id(struct net_device *dev, return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: + bnx2x_acquire_phy_lock(bp); bnx2x_set_led(&bp->link_params, &bp->link_vars, LED_MODE_ON, SPEED_1000); + bnx2x_release_phy_lock(bp); break; case ETHTOOL_ID_OFF: + bnx2x_acquire_phy_lock(bp); bnx2x_set_led(&bp->link_params, &bp->link_vars, LED_MODE_FRONT_PANEL_OFF, 0); - + bnx2x_release_phy_lock(bp); break; case ETHTOOL_ID_INACTIVE: + bnx2x_acquire_phy_lock(bp); bnx2x_set_led(&bp->link_params, &bp->link_vars, LED_MODE_OPER, bp->link_vars.line_speed); + bnx2x_release_phy_lock(bp); } return 0; @@ -2772,10 +2777,10 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info) } else if ((info->flow_type == UDP_V6_FLOW) && (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) { bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; - return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); DP(BNX2X_MSG_ETHTOOL, "rss re-configured, UDP 4-tupple %s\n", udp_rss_requested ? "enabled" : "disabled"); + return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); } else { return 0; } @@ -2901,7 +2906,9 @@ static void bnx2x_get_channels(struct net_device *dev, static void bnx2x_change_num_queues(struct bnx2x *bp, int num_rss) { bnx2x_disable_msi(bp); - BNX2X_NUM_QUEUES(bp) = num_rss + NON_ETH_CONTEXT_USE; + bp->num_ethernet_queues = num_rss; + bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues; + BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues); bnx2x_set_int_mode(bp); } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h index 620fe939ecfd..60a83ad10370 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h @@ -23,6 +23,11 @@ (IRO[159].base + ((funcId) * IRO[159].m1)) #define CSTORM_FUNC_EN_OFFSET(funcId) \ (IRO[149].base + ((funcId) * IRO[149].m1)) +#define CSTORM_HC_SYNC_LINE_INDEX_E1X_OFFSET(hcIndex, sbId) \ + (IRO[139].base + ((hcIndex) * IRO[139].m1) + ((sbId) * IRO[139].m2)) +#define CSTORM_HC_SYNC_LINE_INDEX_E2_OFFSET(hcIndex, sbId) \ + (IRO[138].base + (((hcIndex)>>2) * IRO[138].m1) + (((hcIndex)&3) \ + * IRO[138].m2) + ((sbId) * IRO[138].m3)) #define CSTORM_IGU_MODE_OFFSET (IRO[157].base) #define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \ (IRO[316].base + ((pfId) * IRO[316].m1)) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h index 18704929e642..3369a50ac6b4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h @@ -500,7 +500,15 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ u32 e3_cmn_pin_cfg1; /* 0x170 */ #define PORT_HW_CFG_E3_OVER_CURRENT_MASK 0x000000FF #define PORT_HW_CFG_E3_OVER_CURRENT_SHIFT 0 - u32 reserved0[7]; /* 0x174 */ + + /* pause on host ring */ + u32 generic_features; /* 0x174 */ + #define PORT_HW_CFG_PAUSE_ON_HOST_RING_MASK 0x00000001 + #define PORT_HW_CFG_PAUSE_ON_HOST_RING_SHIFT 0 + #define PORT_HW_CFG_PAUSE_ON_HOST_RING_DISABLED 0x00000000 + #define PORT_HW_CFG_PAUSE_ON_HOST_RING_ENABLED 0x00000001 + + u32 reserved0[6]; /* 0x178 */ u32 aeu_int_mask; /* 0x190 */ @@ -695,6 +703,7 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54618SE 0x00000e00 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8722 0x00000f00 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54616 0x00001000 + #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84834 0x00001100 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE 0x0000fd00 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00 @@ -751,6 +760,7 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE 0x00000e00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722 0x00000f00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616 0x00001000 + #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834 0x00001100 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT_WC 0x0000fc00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00 @@ -1246,6 +1256,7 @@ struct drv_func_mb { #define DRV_MSG_CODE_VRFY_AFEX_SUPPORTED 0xa2000000 #define REQ_BC_VER_4_VRFY_AFEX_SUPPORTED 0x00070002 #define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED 0x00070014 + #define REQ_BC_VER_4_MT_SUPPORTED 0x00070201 #define REQ_BC_VER_4_PFC_STATS_SUPPORTED 0x00070201 #define REQ_BC_VER_4_FCOE_FEATURES 0x00070209 @@ -1515,12 +1526,13 @@ enum mf_cfg_afex_vlan_mode { /* This structure is not applicable and should not be accessed on 57711 */ struct func_ext_cfg { u32 func_cfg; - #define MACP_FUNC_CFG_FLAGS_MASK 0x000000FF + #define MACP_FUNC_CFG_FLAGS_MASK 0x0000007F #define MACP_FUNC_CFG_FLAGS_SHIFT 0 #define MACP_FUNC_CFG_FLAGS_ENABLED 0x00000001 #define MACP_FUNC_CFG_FLAGS_ETHERNET 0x00000002 #define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD 0x00000004 #define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD 0x00000008 + #define MACP_FUNC_CFG_PAUSE_ON_HOST_RING 0x00000080 u32 iscsi_mac_addr_upper; u32 iscsi_mac_addr_lower; @@ -2085,8 +2097,13 @@ struct shmem2_region { /* generic flags controlled by the driver */ u32 drv_flags; - #define DRV_FLAGS_DCB_CONFIGURED 0x1 + #define DRV_FLAGS_DCB_CONFIGURED 0x0 + #define DRV_FLAGS_DCB_CONFIGURATION_ABORTED 0x1 + #define DRV_FLAGS_DCB_MFW_CONFIGURED 0x2 + #define DRV_FLAGS_PORT_MASK ((1 << DRV_FLAGS_DCB_CONFIGURED) | \ + (1 << DRV_FLAGS_DCB_CONFIGURATION_ABORTED) | \ + (1 << DRV_FLAGS_DCB_MFW_CONFIGURED)) /* pointer to extended dev_info shared data copied from nvm image */ u32 extended_dev_info_shared_addr; u32 ncsi_oem_data_addr; @@ -2159,6 +2176,16 @@ struct shmem2_region { #define SHMEM_EEE_TIME_OUTPUT_BIT 0x80000000 u32 sizeof_port_stats; + + /* Link Flap Avoidance */ + u32 lfa_host_addr[PORT_MAX]; + u32 reserved1; + + u32 reserved2; /* Offset 0x148 */ + u32 reserved3; /* Offset 0x14C */ + u32 reserved4; /* Offset 0x150 */ + u32 link_attr_sync[PORT_MAX]; /* Offset 0x154 */ + #define LINK_ATTR_SYNC_KR2_ENABLE (1<<0) }; @@ -4845,9 +4872,17 @@ struct vif_list_event_data { __le32 reserved2; }; -/* - * union for all event ring message types - */ +/* function update event data */ +struct function_update_event_data { + u8 echo; + u8 reserved; + __le16 reserved0; + __le32 reserved1; + __le32 reserved2; +}; + + +/* union for all event ring message types */ union event_data { struct vf_pf_event_data vf_pf_event; struct eth_event_data eth_event; @@ -4855,6 +4890,7 @@ union event_data { struct vf_flr_event_data vf_flr_event; struct malicious_vf_event_data malicious_vf_event; struct vif_list_event_data vif_list_event; + struct function_update_event_data function_update_event; }; @@ -4984,8 +5020,10 @@ struct function_update_data { u8 allowed_priorities; u8 network_cos_mode; u8 lb_mode_en; - u8 reserved0; - __le32 reserved1; + u8 tx_switch_suspend_change_flg; + u8 tx_switch_suspend; + u8 echo; + __le16 reserved1; }; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h index fe66d902dc62..d755acfe7a40 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h @@ -648,15 +648,25 @@ static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num, return rc; } +static int bnx2x_ilt_mem_op_cnic(struct bnx2x *bp, u8 memop) +{ + int rc = 0; + + if (CONFIGURE_NIC_MODE(bp)) + rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop); + if (!rc) + rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop); + + return rc; +} + static int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop) { int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop); if (!rc) rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_QM, memop); - if (!rc) + if (!rc && CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp)) rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop); - if (!rc) - rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop); return rc; } @@ -781,12 +791,19 @@ static void bnx2x_ilt_client_id_init_op(struct bnx2x *bp, bnx2x_ilt_client_init_op(bp, ilt_cli, initop); } +static void bnx2x_ilt_init_op_cnic(struct bnx2x *bp, u8 initop) +{ + if (CONFIGURE_NIC_MODE(bp)) + bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop); + bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop); +} + static void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop) { bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop); bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop); - bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop); - bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop); + if (CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp)) + bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop); } static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num, @@ -890,7 +907,6 @@ static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count, /**************************************************************************** * SRC initializations ****************************************************************************/ -#ifdef BCM_CNIC /* called during init func stage */ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2, dma_addr_t t2_mapping, int src_cid_count) @@ -915,5 +931,4 @@ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2, U64_HI((u64)t2_mapping + (src_cid_count-1) * sizeof(struct src_ent))); } -#endif #endif /* BNX2X_INIT_OPS_H */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index e2e45ee5df33..09096b43a6e9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -121,6 +121,7 @@ #define GP_STATUS_10G_XFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI #define GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS #define GP_STATUS_10G_SFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI +#define GP_STATUS_20G_KR2 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2 #define LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD #define LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD #define LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD @@ -137,7 +138,16 @@ #define LINK_20GTFD LINK_STATUS_SPEED_AND_DUPLEX_20GTFD #define LINK_20GXFD LINK_STATUS_SPEED_AND_DUPLEX_20GXFD - +#define LINK_UPDATE_MASK \ + (LINK_STATUS_SPEED_AND_DUPLEX_MASK | \ + LINK_STATUS_LINK_UP | \ + LINK_STATUS_PHYSICAL_LINK_FLAG | \ + LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \ + LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \ + LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \ + LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \ + LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \ + LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE) #define SFP_EEPROM_CON_TYPE_ADDR 0x2 #define SFP_EEPROM_CON_TYPE_VAL_LC 0x7 @@ -244,6 +254,12 @@ static int bnx2x_check_lfa(struct link_params *params) if (!(link_status & LINK_STATUS_LINK_UP)) return LFA_LINK_DOWN; + /* if loaded after BOOT from SAN, don't flap the link in any case and + * rely on link set by preboot driver + */ + if (params->feature_config_flags & FEATURE_CONFIG_BOOT_FROM_SAN) + return 0; + /* Verify that loopback mode is not set */ if (params->loopback_mode) return LFA_LOOPBACK_ENABLED; @@ -1431,30 +1447,47 @@ void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars, /******************************************************************/ /* MAC/PBF section */ /******************************************************************/ -static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port) +static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, + u32 emac_base) { - u32 mode, emac_base; + u32 new_mode, cur_mode; + u32 clc_cnt; /* Set clause 45 mode, slow down the MDIO clock to 2.5MHz * (a value of 49==0x31) and make sure that the AUTO poll is off */ + cur_mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); - if (CHIP_IS_E2(bp)) - emac_base = GRCBASE_EMAC0; - else - emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0; - mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE); - mode &= ~(EMAC_MDIO_MODE_AUTO_POLL | - EMAC_MDIO_MODE_CLOCK_CNT); if (USES_WARPCORE(bp)) - mode |= (74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT); + clc_cnt = 74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT; else - mode |= (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT); + clc_cnt = 49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT; - mode |= (EMAC_MDIO_MODE_CLAUSE_45); - REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, mode); + if (((cur_mode & EMAC_MDIO_MODE_CLOCK_CNT) == clc_cnt) && + (cur_mode & (EMAC_MDIO_MODE_CLAUSE_45))) + return; + + new_mode = cur_mode & + ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT); + new_mode |= clc_cnt; + new_mode |= (EMAC_MDIO_MODE_CLAUSE_45); + DP(NETIF_MSG_LINK, "Changing emac_mode from 0x%x to 0x%x\n", + cur_mode, new_mode); + REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, new_mode); udelay(40); } + +static void bnx2x_set_mdio_emac_per_phy(struct bnx2x *bp, + struct link_params *params) +{ + u8 phy_index; + /* Set mdio clock per phy */ + for (phy_index = INT_PHY; phy_index < params->num_phys; + phy_index++) + bnx2x_set_mdio_clk(bp, params->chip_id, + params->phy[phy_index].mdio_ctrl); +} + static u8 bnx2x_is_4_port_mode(struct bnx2x *bp) { u32 port4mode_ovwr_val; @@ -1499,7 +1532,8 @@ static void bnx2x_emac_init(struct link_params *params, } timeout--; } while (val & EMAC_MODE_RESET); - bnx2x_set_mdio_clk(bp, params->chip_id, port); + + bnx2x_set_mdio_emac_per_phy(bp, params); /* Set mac address */ val = ((params->mac_addr[0] << 8) | params->mac_addr[1]); @@ -1655,7 +1689,10 @@ static void bnx2x_xmac_init(struct link_params *params, u32 max_speed) * ports of the path */ - if ((CHIP_NUM(bp) == CHIP_NUM_57840_4_10) && + if (((CHIP_NUM(bp) == CHIP_NUM_57840_4_10) || + (CHIP_NUM(bp) == CHIP_NUM_57840_2_20) || + (CHIP_NUM(bp) == CHIP_NUM_57840_OBSOLETE)) && + is_port4mode && (REG_RD(bp, MISC_REG_RESET_REG_2) & MISC_REGISTERS_RESET_REG_2_XMAC)) { DP(NETIF_MSG_LINK, @@ -1751,6 +1788,18 @@ static int bnx2x_xmac_enable(struct link_params *params, */ REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0); + /* When XMAC is in XLGMII mode, disable sending idles for fault + * detection. + */ + if (!(params->phy[INT_PHY].flags & FLAGS_TX_ERROR_CHECK)) { + REG_WR(bp, xmac_base + XMAC_REG_RX_LSS_CTRL, + (XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE | + XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE)); + REG_WR(bp, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0); + REG_WR(bp, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, + XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS | + XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS); + } /* Set Max packet size */ REG_WR(bp, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710); @@ -1771,6 +1820,12 @@ static int bnx2x_xmac_enable(struct link_params *params, /* Enable TX and RX */ val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN; + /* Set MAC in XLGMII mode for dual-mode */ + if ((vars->line_speed == SPEED_20000) && + (params->phy[INT_PHY].supported & + SUPPORTED_20000baseKR2_Full)) + val |= XMAC_CTRL_REG_XLGMII_ALIGN_ENB; + /* Check loopback mode */ if (lb) val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK; @@ -2087,6 +2142,16 @@ static void bnx2x_update_mng(struct link_params *params, u32 link_status) port_mb[params->port].link_status), link_status); } +static void bnx2x_update_link_attr(struct link_params *params, u32 link_attr) +{ + struct bnx2x *bp = params->bp; + + if (SHMEM2_HAS(bp, link_attr_sync)) + REG_WR(bp, params->shmem2_base + + offsetof(struct shmem2_region, + link_attr_sync[params->port]), link_attr); +} + static void bnx2x_update_pfc_nig(struct link_params *params, struct link_vars *vars, struct bnx2x_nig_brb_pfc_port_params *nig_params) @@ -2117,7 +2182,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params, if (CHIP_IS_E3(bp)) ppp_enable = 0; else - ppp_enable = 1; + ppp_enable = 1; xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN : NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN); xcm_out_en = 0; @@ -2238,7 +2303,6 @@ int bnx2x_update_pfc(struct link_params *params, return bnx2x_status; } - static int bnx2x_bmac1_enable(struct link_params *params, struct link_vars *vars, u8 is_lb) @@ -2642,6 +2706,13 @@ static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy, u32 val; u16 i; int rc = 0; + u32 chip_id; + if (phy->flags & FLAGS_MDC_MDIO_WA_G) { + chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) | + ((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12); + bnx2x_set_mdio_clk(bp, chip_id, phy->mdio_ctrl); + } + if (phy->flags & FLAGS_MDC_MDIO_WA_B0) bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS, EMAC_MDIO_STATUS_10MB); @@ -2710,6 +2781,13 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy, u32 tmp; u8 i; int rc = 0; + u32 chip_id; + if (phy->flags & FLAGS_MDC_MDIO_WA_G) { + chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) | + ((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12); + bnx2x_set_mdio_clk(bp, chip_id, phy->mdio_ctrl); + } + if (phy->flags & FLAGS_MDC_MDIO_WA_B0) bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS, EMAC_MDIO_STATUS_10MB); @@ -3138,6 +3216,15 @@ static void bnx2x_cl45_read_or_write(struct bnx2x *bp, struct bnx2x_phy *phy, bnx2x_cl45_write(bp, phy, devad, reg, val | or_val); } +static void bnx2x_cl45_read_and_write(struct bnx2x *bp, + struct bnx2x_phy *phy, + u8 devad, u16 reg, u16 and_val) +{ + u16 val; + bnx2x_cl45_read(bp, phy, devad, reg, &val); + bnx2x_cl45_write(bp, phy, devad, reg, val & and_val); +} + int bnx2x_phy_read(struct link_params *params, u8 phy_addr, u8 devad, u16 reg, u16 *ret_val) { @@ -3295,6 +3382,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port) DEFAULT_PHY_DEV_ADDR); } +static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy, + struct link_params *params, + u32 action) +{ + struct bnx2x *bp = params->bp; + switch (action) { + case PHY_INIT: + /* Set correct devad */ + REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0); + REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18, + phy->def_md_devad); + break; + } +} + static void bnx2x_xgxs_deassert(struct link_params *params) { struct bnx2x *bp = params->bp; @@ -3309,10 +3411,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params) REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val); udelay(500); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); - - REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0); - REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, - params->phy[INT_PHY].def_md_devad); + bnx2x_xgxs_specific_func(¶ms->phy[INT_PHY], params, + PHY_INIT); } static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy, @@ -3529,6 +3629,44 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy, * init configuration, and set/clear SGMII flag. Internal * phy init is done purely in phy_init stage. */ +static void bnx2x_warpcore_enable_AN_KR2(struct bnx2x_phy *phy, + struct link_params *params, + struct link_vars *vars) +{ + struct bnx2x *bp = params->bp; + u16 i; + static struct bnx2x_reg_set reg_set[] = { + /* Step 1 - Program the TX/RX alignment markers */ + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0xa157}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xcbe2}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0x7537}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0xa157}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xcbe2}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0x7537}, + /* Step 2 - Configure the NP registers */ + {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000a}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6400}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0620}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0157}, + {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x6464}, + {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x3150}, + {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x3150}, + {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0157}, + {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0620} + }; + DP(NETIF_MSG_LINK, "Enabling 20G-KR2\n"); + + bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_CL49_USERB0_CTRL, (3<<6)); + + for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++) + bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg, + reg_set[i].val); + + /* Start KR2 work-around timer which handles BCM8073 link-parner */ + vars->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE; + bnx2x_update_link_attr(params, vars->link_attr_sync); +} static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy, struct link_params *params) @@ -3542,22 +3680,36 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy, MDIO_WC_REG_DIGITAL4_MISC5, 0xc000); } +static void bnx2x_warpcore_restart_AN_KR(struct bnx2x_phy *phy, + struct link_params *params) +{ + /* Restart autoneg on the leading lane only */ + struct bnx2x *bp = params->bp; + u16 lane = bnx2x_get_warpcore_lane(phy, params); + CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, + MDIO_AER_BLOCK_AER_REG, lane); + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, + MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200); + + /* Restore AER */ + bnx2x_set_aer_mmd(params, phy); +} + static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, struct link_params *params, struct link_vars *vars) { - u16 val16 = 0, lane, i; + u16 lane, i, cl72_ctrl, an_adv = 0; + u16 ucode_ver; struct bnx2x *bp = params->bp; static struct bnx2x_reg_set reg_set[] = { {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, - {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0}, - {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0}, - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff}, - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555}, {MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0}, {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415}, {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190}, /* Disable Autoneg: re-enable it after adv is done. */ - {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0} + {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0}, + {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0}, }; DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n"); /* Set to default registers that may be overriden by 10G force */ @@ -3565,12 +3717,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl); + cl72_ctrl &= 0x08ff; + cl72_ctrl |= 0x3800; + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl); + /* Check adding advertisement for 1G KX */ if (((vars->line_speed == SPEED_AUTO_NEG) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || (vars->line_speed == SPEED_1000)) { u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2; - val16 |= (1<<5); + an_adv |= (1<<5); /* Enable CL37 1G Parallel Detect */ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1); @@ -3580,11 +3739,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) || (vars->line_speed == SPEED_10000)) { /* Check adding advertisement for 10G KR */ - val16 |= (1<<7); + an_adv |= (1<<7); /* Enable 10G Parallel Detect */ + CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, + MDIO_AER_BLOCK_AER_REG, 0); + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 1); - + bnx2x_set_aer_mmd(params, phy); DP(NETIF_MSG_LINK, "Advertize 10G\n"); } @@ -3595,6 +3757,16 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) | (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) | (0x09 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET))); + /* Configure the next lane if dual mode */ + if (phy->flags & FLAGS_WC_DUAL_MODE) + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_TX0_TX_DRIVER + 0x10*(lane+1), + ((0x02 << + MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) | + (0x06 << + MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) | + (0x09 << + MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET))); bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL, 0x03f0); @@ -3604,7 +3776,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, /* Advertised speeds */ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, - MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16); + MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv); /* Advertised and set FEC (Forward Error Correction) */ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, @@ -3628,9 +3800,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, /* Set KR Autoneg Work-Around flag for Warpcore version older than D108 */ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_UC_INFO_B1_VERSION, &val16); - if (val16 < 0xd108) { - DP(NETIF_MSG_LINK, "Enable AN KR work-around\n"); + MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver); + if (ucode_ver < 0xd108) { + DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n", + ucode_ver); vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY; } bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, @@ -3640,10 +3813,26 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1f); - /* Enable Autoneg */ - bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, - MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200); + if (((phy->req_line_speed == SPEED_AUTO_NEG) && + (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) || + (phy->req_line_speed == SPEED_20000)) { + + CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, + MDIO_AER_BLOCK_AER_REG, lane); + + bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_RX1_PCI_CTRL + (0x10*lane), + (1<<11)); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXS_X2_CONTROL3, 0x7); + bnx2x_set_aer_mmd(params, phy); + + bnx2x_warpcore_enable_AN_KR2(phy, params, vars); + } + + /* Enable Autoneg: only on the main lane */ + bnx2x_warpcore_restart_AN_KR(phy, params); } static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy, @@ -3651,36 +3840,42 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy, struct link_vars *vars) { struct bnx2x *bp = params->bp; - u16 i; + u16 val16, i, lane; static struct bnx2x_reg_set reg_set[] = { /* Disable Autoneg */ {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, - {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0x3f00}, {MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0}, {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0}, {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1}, {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa}, - /* Disable CL36 PCS Tx */ - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0}, - /* Double Wide Single Data Rate @ pll rate */ - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF}, /* Leave cl72 training enable, needed for KR */ - {MDIO_PMA_DEVAD, - MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150, - 0x2} + {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2} }; for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++) bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); - /* Leave CL72 enabled */ - bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, - 0x3800); + lane = bnx2x_get_warpcore_lane(phy, params); + /* Global registers */ + CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, + MDIO_AER_BLOCK_AER_REG, 0); + /* Disable CL36 PCS Tx */ + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); + val16 &= ~(0x0011 << lane); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); + val16 |= (0x0303 << (lane << 1)); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); + /* Restore AER */ + bnx2x_set_aer_mmd(params, phy); /* Set speed via PMA/PMD register */ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040); @@ -3726,27 +3921,21 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy, bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0); /* Disable 100FX Enable and Auto-Detect */ - bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_FX100_CTRL1, &val); - bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_FX100_CTRL1, (val & 0xFFFA)); + bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_FX100_CTRL1, 0xFFFA); /* Disable 100FX Idle detect */ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_FX100_CTRL3, 0x0080); /* Set Block address to Remote PHY & Clear forced_speed[5] */ - bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_DIGITAL4_MISC3, &val); - bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_DIGITAL4_MISC3, (val & 0xFF7F)); + bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_DIGITAL4_MISC3, 0xFF7F); /* Turn off auto-detect & fiber mode */ - bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val); - bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, - (val & 0xFFEE)); + bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, + 0xFFEE); /* Set filter_force_link, disable_false_link and parallel_detect */ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, @@ -3808,22 +3997,65 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100); /* Release tx_fifo_reset */ + bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, + 0xFFFE); + /* Release rxSeqStart */ + bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, 0x7FFF); +} + +static void bnx2x_warpcore_set_20G_force_KR2(struct bnx2x_phy *phy, + struct link_params *params) +{ + u16 val; + struct bnx2x *bp = params->bp; + /* Set global registers, so set AER lane to 0 */ + CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, + MDIO_AER_BLOCK_AER_REG, 0); + + /* Disable sequencer */ + bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, ~(1<<13)); + + bnx2x_set_aer_mmd(params, phy); + + bnx2x_cl45_read_and_write(bp, phy, MDIO_PMA_DEVAD, + MDIO_WC_REG_PMD_KR_CONTROL, ~(1<<1)); + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_CTRL, 0); + /* Turn off CL73 */ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val); + MDIO_WC_REG_CL73_USERB0_CTRL, &val); + val &= ~(1<<5); + val |= (1<<6); bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, val & 0xFFFE); + MDIO_WC_REG_CL73_USERB0_CTRL, val); + + /* Set 20G KR2 force speed */ + bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x1f); + + bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_DIGITAL4_MISC3, (1<<7)); - /* Release rxSeqStart */ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val); + MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &val); + val &= ~(3<<14); + val |= (1<<15); bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val & 0x7FFF)); -} + MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, val); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0x835A); -static void bnx2x_warpcore_set_20G_KR2(struct bnx2x *bp, - struct bnx2x_phy *phy) -{ - DP(NETIF_MSG_LINK, "KR2 still not supported !!!\n"); + /* Enable sequencer (over lane 0) */ + CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, + MDIO_AER_BLOCK_AER_REG, 0); + + bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, (1<<13)); + + bnx2x_set_aer_mmd(params, phy); } static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp, @@ -3893,20 +4125,16 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy, u16 val16, digctrl_kx1, digctrl_kx2; /* Clear XFI clock comp in non-10G single lane mode. */ - bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_RX66_CONTROL, &val16); - bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_RX66_CONTROL, val16 & ~(3<<13)); + bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_RX66_CONTROL, ~(3<<13)); bnx2x_warpcore_set_lpi_passthrough(phy, params); if (always_autoneg || phy->req_line_speed == SPEED_AUTO_NEG) { /* SGMII Autoneg */ - bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16); - bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_COMBO_IEEE0_MIICTRL, - val16 | 0x1000); + bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_COMBO_IEEE0_MIICTRL, + 0x1000); DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n"); } else { bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, @@ -4048,7 +4276,7 @@ static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp, if ((cfg_pin < PIN_CFG_GPIO0_P0) || (cfg_pin > PIN_CFG_GPIO3_P1)) { DP(NETIF_MSG_LINK, - "ERROR: Invalid cfg pin %x for module detect indication\n", + "No cfg pin %x for module detect indication\n", cfg_pin); return -EINVAL; } @@ -4059,7 +4287,7 @@ static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp, *gpio_num = MISC_REGISTERS_GPIO_3; *gpio_port = port; } - DP(NETIF_MSG_LINK, "MOD_ABS int GPIO%d_P%d\n", *gpio_num, *gpio_port); + return 0; } @@ -4082,7 +4310,7 @@ static int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy, return 0; } static int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy, - struct link_params *params) + struct link_params *params) { u16 gp2_status_reg0, lane; struct bnx2x *bp = params->bp; @@ -4096,8 +4324,8 @@ static int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy, } static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy, - struct link_params *params, - struct link_vars *vars) + struct link_params *params, + struct link_vars *vars) { struct bnx2x *bp = params->bp; u32 serdes_net_if; @@ -4125,7 +4353,7 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy, case PORT_HW_CFG_NET_SERDES_IF_KR: /* Do we get link yet? */ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 0x81d1, - &gp_status1); + &gp_status1); lnkup = (gp_status1 >> (8+lane)) & 0x1;/* 1G */ /*10G KR*/ lnkup_kr = (gp_status1 >> (12+lane)) & 0x1; @@ -4177,6 +4405,27 @@ static void bnx2x_warpcore_config_sfi(struct bnx2x_phy *phy, } } +static void bnx2x_sfp_e3_set_transmitter(struct link_params *params, + struct bnx2x_phy *phy, + u8 tx_en) +{ + struct bnx2x *bp = params->bp; + u32 cfg_pin; + u8 port = params->port; + + cfg_pin = REG_RD(bp, params->shmem_base + + offsetof(struct shmem_region, + dev_info.port_hw_config[port].e3_sfp_ctrl)) & + PORT_HW_CFG_E3_TX_LASER_MASK; + /* Set the !tx_en since this pin is DISABLE_TX_LASER */ + DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en); + + /* For 20G, the expected pin to be used is 3 pins after the current */ + bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1); + if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G) + bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1); +} + static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy, struct link_params *params, struct link_vars *vars) @@ -4237,9 +4486,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy, break; case PORT_HW_CFG_NET_SERDES_IF_SFI: - /* Issue Module detection */ + /* Issue Module detection if module is plugged, or + * enabled transmitter to avoid current leakage in case + * no module is connected + */ if (bnx2x_is_sfp_module_plugged(phy, params)) bnx2x_sfp_module_detection(phy, params); + else + bnx2x_sfp_e3_set_transmitter(params, phy, 1); bnx2x_warpcore_config_sfi(phy, params); break; @@ -4255,16 +4509,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy, bnx2x_sfp_module_detection(phy, params); break; - case PORT_HW_CFG_NET_SERDES_IF_KR2: - if (vars->line_speed != SPEED_20000) { - DP(NETIF_MSG_LINK, "Speed not supported yet\n"); - return; + if (!params->loopback_mode) { + bnx2x_warpcore_enable_AN_KR(phy, params, vars); + } else { + DP(NETIF_MSG_LINK, "Setting KR 20G-Force\n"); + bnx2x_warpcore_set_20G_force_KR2(phy, params); } - DP(NETIF_MSG_LINK, "Setting 20G KR2\n"); - bnx2x_warpcore_set_20G_KR2(bp, phy); break; - default: DP(NETIF_MSG_LINK, "Unsupported Serdes Net Interface 0x%x\n", @@ -4278,67 +4530,58 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy, DP(NETIF_MSG_LINK, "Exit config init\n"); } -static void bnx2x_sfp_e3_set_transmitter(struct link_params *params, - struct bnx2x_phy *phy, - u8 tx_en) -{ - struct bnx2x *bp = params->bp; - u32 cfg_pin; - u8 port = params->port; - - cfg_pin = REG_RD(bp, params->shmem_base + - offsetof(struct shmem_region, - dev_info.port_hw_config[port].e3_sfp_ctrl)) & - PORT_HW_CFG_TX_LASER_MASK; - /* Set the !tx_en since this pin is DISABLE_TX_LASER */ - DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en); - /* For 20G, the expected pin to be used is 3 pins after the current */ - - bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1); - if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G) - bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1); -} - static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy, struct link_params *params) { struct bnx2x *bp = params->bp; - u16 val16; + u16 val16, lane; bnx2x_sfp_e3_set_transmitter(params, phy, 0); - bnx2x_set_mdio_clk(bp, params->chip_id, params->port); + bnx2x_set_mdio_emac_per_phy(bp, params); bnx2x_set_aer_mmd(params, phy); /* Global register */ bnx2x_warpcore_reset_lane(bp, phy, 1); /* Clear loopback settings (if any) */ /* 10G & 20G */ - bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16); - bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 & - 0xBFFF); + bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0xBFFF); - bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16); - bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 & 0xfffe); + bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_IEEE0BLK_MIICNTL, 0xfffe); /* Update those 1-copy registers */ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, 0); /* Enable 1G MDIO (1-copy) */ + bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, + ~0x10); + + bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL2, 0xff00); + lane = bnx2x_get_warpcore_lane(phy, params); + /* Disable CL36 PCS Tx */ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, - &val16); + MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); + val16 |= (0x11 << lane); + if (phy->flags & FLAGS_WC_DUAL_MODE) + val16 |= (0x22 << lane); bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, - val16 & ~0x10); + MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16); + MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); + val16 &= ~(0x0303 << (lane << 1)); + val16 |= (0x0101 << (lane << 1)); + if (phy->flags & FLAGS_WC_DUAL_MODE) { + val16 &= ~(0x0c0c << (lane << 1)); + val16 |= (0x0404 << (lane << 1)); + } + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_XGXSBLK1_LANECTRL2, - val16 & 0xff00); + MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); + /* Restore AER */ + bnx2x_set_aer_mmd(params, phy); } @@ -4351,8 +4594,9 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy, DP(NETIF_MSG_LINK, "Setting Warpcore loopback type %x, speed %d\n", params->loopback_mode, phy->req_line_speed); - if (phy->req_line_speed < SPEED_10000) { - /* 10/100/1000 */ + if (phy->req_line_speed < SPEED_10000 || + phy->supported & SUPPORTED_20000baseKR2_Full) { + /* 10/100/1000/20G-KR2 */ /* Update those 1-copy registers */ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, @@ -4365,18 +4609,20 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy, lane = bnx2x_get_warpcore_lane(phy, params); bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16); + val16 |= (1<<lane); + if (phy->flags & FLAGS_WC_DUAL_MODE) + val16 |= (2<<lane); bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_XGXSBLK1_LANECTRL2, - val16 | (1<<lane)); + MDIO_WC_REG_XGXSBLK1_LANECTRL2, + val16); /* Switch back to 4-copy registers */ bnx2x_set_aer_mmd(params, phy); } else { - /* 10G & 20G */ + /* 10G / 20G-DXGXS */ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0x4000); - bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1); } @@ -4541,6 +4787,10 @@ void bnx2x_link_status_update(struct link_params *params, params->feature_config_flags &= ~FEATURE_CONFIG_PFC_ENABLED; + if (SHMEM2_HAS(bp, link_attr_sync)) + vars->link_attr_sync = SHMEM2_RD(bp, + link_attr_sync[params->port]); + DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x int_mask 0x%x\n", vars->link_status, vars->phy_link_up, vars->aeu_int_mask); DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n", @@ -5270,6 +5520,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy, vars->link_status |= LINK_10GTFD; break; case GP_STATUS_20G_DXGXS: + case GP_STATUS_20G_KR2: vars->line_speed = SPEED_20000; vars->link_status |= LINK_20GTFD; break; @@ -5377,7 +5628,15 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy, int rc = 0; lane = bnx2x_get_warpcore_lane(phy, params); /* Read gp_status */ - if (phy->req_line_speed > SPEED_10000) { + if ((params->loopback_mode) && + (phy->flags & FLAGS_WC_DUAL_MODE)) { + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up); + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up); + link_up &= 0x1; + } else if ((phy->req_line_speed > SPEED_10000) && + (phy->supported & SUPPORTED_20000baseMLD2_Full)) { u16 temp_link_up; bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 1, &temp_link_up); @@ -5390,12 +5649,22 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy, bnx2x_ext_phy_resolve_fc(phy, params, vars); } else { bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_GP2_STATUS_GP_2_1, &gp_status1); + MDIO_WC_REG_GP2_STATUS_GP_2_1, + &gp_status1); DP(NETIF_MSG_LINK, "0x81d1 = 0x%x\n", gp_status1); - /* Check for either KR or generic link up. */ - gp_status1 = ((gp_status1 >> 8) & 0xf) | - ((gp_status1 >> 12) & 0xf); - link_up = gp_status1 & (1 << lane); + /* Check for either KR, 1G, or AN up. */ + link_up = ((gp_status1 >> 8) | + (gp_status1 >> 12) | + (gp_status1)) & + (1 << lane); + if (phy->supported & SUPPORTED_20000baseKR2_Full) { + u16 an_link; + bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_STATUS, &an_link); + bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_STATUS, &an_link); + link_up |= (an_link & (1<<2)); + } if (link_up && SINGLE_MEDIA_DIRECT(params)) { u16 pd, gp_status4; if (phy->req_line_speed == SPEED_AUTO_NEG) { @@ -5460,7 +5729,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy, if ((lane & 1) == 0) gp_speed <<= 8; gp_speed &= 0x3f00; - + link_up = !!link_up; rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed, duplex); @@ -6296,15 +6565,7 @@ static int bnx2x_update_link_down(struct link_params *params, vars->mac_type = MAC_TYPE_NONE; /* Update shared memory */ - vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK | - LINK_STATUS_LINK_UP | - LINK_STATUS_PHYSICAL_LINK_FLAG | - LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | - LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | - LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | - LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | - LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | - LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE); + vars->link_status &= ~LINK_UPDATE_MASK; vars->line_speed = 0; bnx2x_update_mng(params, vars->link_status); @@ -6452,6 +6713,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars) u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed; u8 active_external_phy = INT_PHY; vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; + vars->link_status &= ~LINK_UPDATE_MASK; for (phy_index = INT_PHY; phy_index < params->num_phys; phy_index++) { phy_vars[phy_index].flow_ctrl = 0; @@ -6628,7 +6890,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars) } else if (prev_line_speed != vars->line_speed) { REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); - usleep_range(1000, 2000); + usleep_range(1000, 2000); } } @@ -6698,7 +6960,7 @@ void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port) { bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_LOW, port); - usleep_range(1000, 2000); + usleep_range(1000, 2000); bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_HIGH, port); } @@ -6839,7 +7101,7 @@ static int bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp, MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &fw_msgout); - usleep_range(1000, 2000); + usleep_range(1000, 2000); } while (fw_ver1 == 0 || fw_ver1 == 0x4321 || ((fw_msgout & 0xff) != 0x03 && (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073))); @@ -7549,13 +7811,12 @@ static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy, if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) == MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE) return 0; - usleep_range(1000, 2000); + usleep_range(1000, 2000); } return -EINVAL; } static void bnx2x_warpcore_power_module(struct link_params *params, - struct bnx2x_phy *phy, u8 power) { u32 pin_cfg; @@ -7579,7 +7840,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params, static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy, struct link_params *params, u16 addr, u8 byte_cnt, - u8 *o_buf) + u8 *o_buf, u8 is_init) { int rc = 0; u8 i, j = 0, cnt = 0; @@ -7596,11 +7857,11 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy, /* 4 byte aligned address */ addr32 = addr & (~0x3); do { - if (cnt == I2C_WA_PWR_ITER) { - bnx2x_warpcore_power_module(params, phy, 0); + if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) { + bnx2x_warpcore_power_module(params, 0); /* Note that 100us are not enough here */ - usleep_range(1000,1000); - bnx2x_warpcore_power_module(params, phy, 1); + usleep_range(1000, 2000); + bnx2x_warpcore_power_module(params, 1); } rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt, data_array); @@ -7660,7 +7921,7 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy, /* Wait appropriate time for two-wire command to finish before * polling the status register */ - usleep_range(1000, 2000); + usleep_range(1000, 2000); /* Wait up to 500us for command complete status */ for (i = 0; i < 100; i++) { @@ -7696,7 +7957,7 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy, if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) == MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE) return 0; - usleep_range(1000, 2000); + usleep_range(1000, 2000); } return -EINVAL; @@ -7719,7 +7980,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy, break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr, - byte_cnt, o_buf); + byte_cnt, o_buf, 0); break; } return rc; @@ -7731,9 +7992,8 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy, { struct bnx2x *bp = params->bp; u32 sync_offset = 0, phy_idx, media_types; - u8 val[2], check_limiting_mode = 0; + u8 gport, val[2], check_limiting_mode = 0; *edc_mode = EDC_MODE_LIMITING; - phy->media_type = ETH_PHY_UNSPECIFIED; /* First check for copper cable */ if (bnx2x_read_sfp_module_eeprom(phy, @@ -7788,8 +8048,15 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy, SFP_EEPROM_COMP_CODE_LR_MASK | SFP_EEPROM_COMP_CODE_LRM_MASK)) == 0) { DP(NETIF_MSG_LINK, "1G Optic module detected\n"); + gport = params->port; phy->media_type = ETH_PHY_SFP_1G_FIBER; phy->req_line_speed = SPEED_1000; + if (!CHIP_IS_E1x(bp)) + gport = BP_PATH(bp) + (params->port << 1); + netdev_err(bp->dev, "Warning: Link speed was forced to 1000Mbps." + " Current SFP module in port %d is not" + " compliant with 10G Ethernet\n", + gport); } else { int idx, cfg_idx = 0; DP(NETIF_MSG_LINK, "10G Optic module detected\n"); @@ -7923,6 +8190,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy, { u8 val; + int rc; struct bnx2x *bp = params->bp; u16 timeout; /* Initialization time after hot-plug may take up to 300ms for @@ -7930,8 +8198,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy, */ for (timeout = 0; timeout < 60; timeout++) { - if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val) - == 0) { + if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) + rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, + params, 1, + 1, &val, 1); + else + rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, + &val); + if (rc == 0) { DP(NETIF_MSG_LINK, "SFP+ module initialization took %d ms\n", timeout * 5); @@ -7939,7 +8213,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy, } usleep_range(5000, 10000); } - return -EINVAL; + rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val); + return rc; } static void bnx2x_8727_power_module(struct bnx2x *bp, @@ -8178,7 +8453,7 @@ static void bnx2x_warpcore_hw_reset(struct bnx2x_phy *phy, struct link_params *params) { struct bnx2x *bp = params->bp; - bnx2x_warpcore_power_module(params, phy, 0); + bnx2x_warpcore_power_module(params, 0); /* Put Warpcore in low power mode */ REG_WR(bp, MISC_REG_WC0_RESET, 0x0c0e); @@ -8201,7 +8476,7 @@ static void bnx2x_power_sfp_module(struct link_params *params, bnx2x_8727_power_module(params->bp, phy, power); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: - bnx2x_warpcore_power_module(params, phy, power); + bnx2x_warpcore_power_module(params, power); break; default: break; @@ -8274,7 +8549,8 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy, u32 val = REG_RD(bp, params->shmem_base + offsetof(struct shmem_region, dev_info. port_feature_config[params->port].config)); - + /* Enabled transmitter by default */ + bnx2x_sfp_set_transmitter(params, phy, 1); DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n", params->port); /* Power up module */ @@ -8307,14 +8583,12 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy, */ bnx2x_set_limiting_mode(params, phy, edc_mode); - /* Enable transmit for this module if the module is approved, or - * if unapproved modules should also enable the Tx laser + /* Disable transmit for this module if the module is not approved, and + * laser needs to be disabled. */ - if (rc == 0 || - (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) != - PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) - bnx2x_sfp_set_transmitter(params, phy, 1); - else + if ((rc) && + ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == + PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)) bnx2x_sfp_set_transmitter(params, phy, 0); return rc; @@ -8326,11 +8600,13 @@ void bnx2x_handle_module_detect_int(struct link_params *params) struct bnx2x_phy *phy; u32 gpio_val; u8 gpio_num, gpio_port; - if (CHIP_IS_E3(bp)) + if (CHIP_IS_E3(bp)) { phy = ¶ms->phy[INT_PHY]; - else + /* Always enable TX laser,will be disabled in case of fault */ + bnx2x_sfp_set_transmitter(params, phy, 1); + } else { phy = ¶ms->phy[EXT_PHY1]; - + } if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id, params->shmem_base, params->port, &gpio_num, &gpio_port) == -EINVAL) { @@ -8346,7 +8622,7 @@ void bnx2x_handle_module_detect_int(struct link_params *params) /* Call the handling function in case module is detected */ if (gpio_val == 0) { - bnx2x_set_mdio_clk(bp, params->chip_id, params->port); + bnx2x_set_mdio_emac_per_phy(bp, params); bnx2x_set_aer_mmd(params, phy); bnx2x_power_sfp_module(params, phy, 1); @@ -8375,10 +8651,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params) DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n"); } } else { - u32 val = REG_RD(bp, params->shmem_base + - offsetof(struct shmem_region, dev_info. - port_feature_config[params->port]. - config)); bnx2x_set_gpio_int(bp, gpio_num, MISC_REGISTERS_GPIO_INT_OUTPUT_SET, gpio_port); @@ -8386,10 +8658,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params) * Disable transmit for this module */ phy->media_type = ETH_PHY_NOT_PRESENT; - if (((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == - PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) || - CHIP_IS_E3(bp)) - bnx2x_sfp_set_transmitter(params, phy, 0); } } @@ -9129,6 +9397,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &rx_alarm_status); + bnx2x_8727_power_module(params->bp, phy, 0); return 0; } } /* Over current check */ @@ -9233,20 +9502,28 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy, struct bnx2x *bp, u8 port) { - u16 val, fw_ver1, fw_ver2, cnt; + u16 val, fw_ver2, cnt, i; + static struct bnx2x_reg_set reg_set[] = { + {MDIO_PMA_DEVAD, 0xA819, 0x0014}, + {MDIO_PMA_DEVAD, 0xA81A, 0xc200}, + {MDIO_PMA_DEVAD, 0xA81B, 0x0000}, + {MDIO_PMA_DEVAD, 0xA81C, 0x0300}, + {MDIO_PMA_DEVAD, 0xA817, 0x0009} + }; + u16 fw_ver1; - if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) { + if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) || + (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) { bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1); bnx2x_save_spirom_version(bp, port, fw_ver1 & 0xfff, phy->ver_addr); } else { /* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */ /* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */ - bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014); - bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200); - bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000); - bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300); - bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009); + for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); + i++) + bnx2x_cl45_write(bp, phy, reg_set[i].devad, + reg_set[i].reg, reg_set[i].val); for (cnt = 0; cnt < 100; cnt++) { bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val); @@ -9294,8 +9571,16 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy, static void bnx2x_848xx_set_led(struct bnx2x *bp, struct bnx2x_phy *phy) { - u16 val, offset; - + u16 val, offset, i; + static struct bnx2x_reg_set reg_set[] = { + {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0080}, + {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x0018}, + {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x0006}, + {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_BLINK, 0x0000}, + {MDIO_PMA_DEVAD, MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH, + MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ}, + {MDIO_AN_DEVAD, 0xFFFB, 0xFFFD} + }; /* PHYC_CTL_LED_CTL */ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, @@ -9307,49 +9592,20 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, val); - bnx2x_cl45_write(bp, phy, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_8481_LED1_MASK, - 0x80); - - bnx2x_cl45_write(bp, phy, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_8481_LED2_MASK, - 0x18); - - /* Select activity source by Tx and Rx, as suggested by PHY AE */ - bnx2x_cl45_write(bp, phy, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_8481_LED3_MASK, - 0x0006); - - /* Select the closest activity blink rate to that in 10/100/1000 */ - bnx2x_cl45_write(bp, phy, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_8481_LED3_BLINK, - 0); - - /* Configure the blink rate to ~15.9 Hz */ - bnx2x_cl45_write(bp, phy, - MDIO_PMA_DEVAD, - MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH, - MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ); + for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++) + bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg, + reg_set[i].val); - if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) + if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) || + (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) offset = MDIO_PMA_REG_84833_CTL_LED_CTL_1; else offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1; - bnx2x_cl45_read(bp, phy, - MDIO_PMA_DEVAD, offset, &val); - val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/ - bnx2x_cl45_write(bp, phy, - MDIO_PMA_DEVAD, offset, val); - - /* 'Interrupt Mask' */ - bnx2x_cl45_write(bp, phy, - MDIO_AN_DEVAD, - 0xFFFB, 0xFFFD); + /* stretch_en for LED3*/ + bnx2x_cl45_read_or_write(bp, phy, + MDIO_PMA_DEVAD, offset, + MDIO_PMA_REG_84823_LED3_STRETCH_EN); } static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy, @@ -9359,7 +9615,8 @@ static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy, struct bnx2x *bp = params->bp; switch (action) { case PHY_INIT: - if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) { + if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) && + (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) { /* Save spirom version */ bnx2x_save_848xx_spirom_version(phy, bp, params->port); } @@ -9380,7 +9637,7 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, struct link_vars *vars) { struct bnx2x *bp = params->bp; - u16 autoneg_val, an_1000_val, an_10_100_val, an_10g_val; + u16 autoneg_val, an_1000_val, an_10_100_val; bnx2x_848xx_specific_func(phy, params, PHY_INIT); bnx2x_cl45_write(bp, phy, @@ -9479,11 +9736,12 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, if (phy->req_duplex == DUPLEX_FULL) autoneg_val |= (1<<8); - /* Always write this if this is not 84833. - * For 84833, write it only when it's a forced speed. + /* Always write this if this is not 84833/4. + * For 84833/4, write it only when it's a forced speed. */ - if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) || - ((autoneg_val & (1<<12)) == 0)) + if (((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) && + (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) || + ((autoneg_val & (1<<12)) == 0)) bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val); @@ -9495,14 +9753,11 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, DP(NETIF_MSG_LINK, "Advertising 10G\n"); /* Restart autoneg for 10G*/ - bnx2x_cl45_read(bp, phy, - MDIO_AN_DEVAD, - MDIO_AN_REG_8481_10GBASE_T_AN_CTRL, - &an_10g_val); - bnx2x_cl45_write(bp, phy, - MDIO_AN_DEVAD, - MDIO_AN_REG_8481_10GBASE_T_AN_CTRL, - an_10g_val | 0x1000); + bnx2x_cl45_read_or_write( + bp, phy, + MDIO_AN_DEVAD, + MDIO_AN_REG_8481_10GBASE_T_AN_CTRL, + 0x1000); bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x3200); @@ -9535,9 +9790,8 @@ static int bnx2x_8481_config_init(struct bnx2x_phy *phy, #define PHY84833_CMDHDLR_WAIT 300 #define PHY84833_CMDHDLR_MAX_ARGS 5 static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy, - struct link_params *params, - u16 fw_cmd, - u16 cmd_args[], int argc) + struct link_params *params, u16 fw_cmd, + u16 cmd_args[], int argc) { int idx; u16 val; @@ -9551,7 +9805,7 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy, MDIO_84833_CMD_HDLR_STATUS, &val); if (val == PHY84833_STATUS_CMD_OPEN_FOR_CMDS) break; - usleep_range(1000, 2000); + usleep_range(1000, 2000); } if (idx >= PHY84833_CMDHDLR_WAIT) { DP(NETIF_MSG_LINK, "FW cmd: FW not ready.\n"); @@ -9572,7 +9826,7 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy, if ((val == PHY84833_STATUS_CMD_COMPLETE_PASS) || (val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) break; - usleep_range(1000, 2000); + usleep_range(1000, 2000); } if ((idx >= PHY84833_CMDHDLR_WAIT) || (val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) { @@ -9591,7 +9845,6 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy, return 0; } - static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy, struct link_params *params, struct link_vars *vars) @@ -9739,11 +9992,11 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, struct bnx2x *bp = params->bp; u8 port, initialize = 1; u16 val; - u32 actual_phy_selection, cms_enable; + u32 actual_phy_selection; u16 cmd_args[PHY84833_CMDHDLR_MAX_ARGS]; int rc = 0; - usleep_range(1000, 2000); + usleep_range(1000, 2000); if (!(CHIP_IS_E1x(bp))) port = BP_PATH(bp); @@ -9765,7 +10018,8 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, /* Wait for GPHY to come out of reset */ msleep(50); - if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) { + if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) && + (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) { /* BCM84823 requires that XGXS links up first @ 10G for normal * behavior. */ @@ -9821,7 +10075,8 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n", params->multi_phy_config, val); - if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) { + if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) || + (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) { bnx2x_84833_pair_swap_cfg(phy, params, vars); /* Keep AutogrEEEn disabled. */ @@ -9841,7 +10096,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, bnx2x_save_848xx_spirom_version(phy, bp, params->port); /* 84833 PHY has a better feature and doesn't need to support this. */ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) { - cms_enable = REG_RD(bp, params->shmem_base + + u32 cms_enable = REG_RD(bp, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port].default_cfg)) & PORT_HW_CFG_ENABLE_CMS_MASK; @@ -9870,7 +10125,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, return rc; } - if ((params->req_duplex[actual_phy_selection] == DUPLEX_FULL) && + if ((phy->req_duplex == DUPLEX_FULL) && (params->eee_mode & EEE_MODE_ADV_LPI) && (bnx2x_eee_calc_timer(params) || !(params->eee_mode & EEE_MODE_ENABLE_LPI))) @@ -9878,22 +10133,20 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, else rc = bnx2x_8483x_disable_eee(phy, params, vars); if (rc) { - DP(NETIF_MSG_LINK, "Failed to set EEE advertisment\n"); + DP(NETIF_MSG_LINK, "Failed to set EEE advertisement\n"); return rc; } } else { vars->eee_status &= ~SHMEM_EEE_SUPPORTED_MASK; } - if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) { + if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) || + (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) { /* Bring PHY out of super isolate mode as the final step. */ - bnx2x_cl45_read(bp, phy, - MDIO_CTL_DEVAD, - MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val); - val &= ~MDIO_84833_SUPER_ISOLATE; - bnx2x_cl45_write(bp, phy, - MDIO_CTL_DEVAD, - MDIO_84833_TOP_CFG_XGPHY_STRAP1, val); + bnx2x_cl45_read_and_write(bp, phy, + MDIO_CTL_DEVAD, + MDIO_84833_TOP_CFG_XGPHY_STRAP1, + (u16)~MDIO_84833_SUPER_ISOLATE); } return rc; } @@ -10027,7 +10280,6 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, return link_up; } - static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len) { int status = 0; @@ -10899,7 +11151,7 @@ static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy, /* STATIC PHY DECLARATION */ /******************************************************************/ -static struct bnx2x_phy phy_null = { +static const struct bnx2x_phy phy_null = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN, .addr = 0, .def_md_devad = 0, @@ -10925,7 +11177,7 @@ static struct bnx2x_phy phy_null = { .phy_specific_func = (phy_specific_func_t)NULL }; -static struct bnx2x_phy phy_serdes = { +static const struct bnx2x_phy phy_serdes = { .type = PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT, .addr = 0xff, .def_md_devad = 0, @@ -10960,7 +11212,7 @@ static struct bnx2x_phy phy_serdes = { .phy_specific_func = (phy_specific_func_t)NULL }; -static struct bnx2x_phy phy_xgxs = { +static const struct bnx2x_phy phy_xgxs = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, .addr = 0xff, .def_md_devad = 0, @@ -10993,14 +11245,13 @@ static struct bnx2x_phy phy_xgxs = { .format_fw_ver = (format_fw_ver_t)NULL, .hw_reset = (hw_reset_t)NULL, .set_link_led = (set_link_led_t)NULL, - .phy_specific_func = (phy_specific_func_t)NULL + .phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func }; -static struct bnx2x_phy phy_warpcore = { +static const struct bnx2x_phy phy_warpcore = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, .addr = 0xff, .def_md_devad = 0, - .flags = (FLAGS_HW_LOCK_REQUIRED | - FLAGS_TX_ERROR_CHECK), + .flags = FLAGS_TX_ERROR_CHECK, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, @@ -11034,7 +11285,7 @@ static struct bnx2x_phy phy_warpcore = { }; -static struct bnx2x_phy phy_7101 = { +static const struct bnx2x_phy phy_7101 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101, .addr = 0xff, .def_md_devad = 0, @@ -11063,11 +11314,11 @@ static struct bnx2x_phy phy_7101 = { .set_link_led = (set_link_led_t)bnx2x_7101_set_link_led, .phy_specific_func = (phy_specific_func_t)NULL }; -static struct bnx2x_phy phy_8073 = { +static const struct bnx2x_phy phy_8073 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073, .addr = 0xff, .def_md_devad = 0, - .flags = FLAGS_HW_LOCK_REQUIRED, + .flags = 0, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, @@ -11094,7 +11345,7 @@ static struct bnx2x_phy phy_8073 = { .set_link_led = (set_link_led_t)NULL, .phy_specific_func = (phy_specific_func_t)bnx2x_8073_specific_func }; -static struct bnx2x_phy phy_8705 = { +static const struct bnx2x_phy phy_8705 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705, .addr = 0xff, .def_md_devad = 0, @@ -11122,7 +11373,7 @@ static struct bnx2x_phy phy_8705 = { .set_link_led = (set_link_led_t)NULL, .phy_specific_func = (phy_specific_func_t)NULL }; -static struct bnx2x_phy phy_8706 = { +static const struct bnx2x_phy phy_8706 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706, .addr = 0xff, .def_md_devad = 0, @@ -11152,12 +11403,11 @@ static struct bnx2x_phy phy_8706 = { .phy_specific_func = (phy_specific_func_t)NULL }; -static struct bnx2x_phy phy_8726 = { +static const struct bnx2x_phy phy_8726 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, .addr = 0xff, .def_md_devad = 0, - .flags = (FLAGS_HW_LOCK_REQUIRED | - FLAGS_INIT_XGXS_FIRST | + .flags = (FLAGS_INIT_XGXS_FIRST | FLAGS_TX_ERROR_CHECK), .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, @@ -11185,7 +11435,7 @@ static struct bnx2x_phy phy_8726 = { .phy_specific_func = (phy_specific_func_t)NULL }; -static struct bnx2x_phy phy_8727 = { +static const struct bnx2x_phy phy_8727 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, .addr = 0xff, .def_md_devad = 0, @@ -11215,7 +11465,7 @@ static struct bnx2x_phy phy_8727 = { .set_link_led = (set_link_led_t)bnx2x_8727_set_link_led, .phy_specific_func = (phy_specific_func_t)bnx2x_8727_specific_func }; -static struct bnx2x_phy phy_8481 = { +static const struct bnx2x_phy phy_8481 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481, .addr = 0xff, .def_md_devad = 0, @@ -11251,7 +11501,7 @@ static struct bnx2x_phy phy_8481 = { .phy_specific_func = (phy_specific_func_t)NULL }; -static struct bnx2x_phy phy_84823 = { +static const struct bnx2x_phy phy_84823 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823, .addr = 0xff, .def_md_devad = 0, @@ -11288,7 +11538,7 @@ static struct bnx2x_phy phy_84823 = { .phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func }; -static struct bnx2x_phy phy_84833 = { +static const struct bnx2x_phy phy_84833 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833, .addr = 0xff, .def_md_devad = 0, @@ -11323,7 +11573,41 @@ static struct bnx2x_phy phy_84833 = { .phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func }; -static struct bnx2x_phy phy_54618se = { +static const struct bnx2x_phy phy_84834 = { + .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834, + .addr = 0xff, + .def_md_devad = 0, + .flags = FLAGS_FAN_FAILURE_DET_REQ | + FLAGS_REARM_LATCH_SIGNAL, + .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, + .mdio_ctrl = 0, + .supported = (SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_10000baseT_Full | + SUPPORTED_TP | + SUPPORTED_Autoneg | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause), + .media_type = ETH_PHY_BASE_T, + .ver_addr = 0, + .req_flow_ctrl = 0, + .req_line_speed = 0, + .speed_cap_mask = 0, + .req_duplex = 0, + .rsrv = 0, + .config_init = (config_init_t)bnx2x_848x3_config_init, + .read_status = (read_status_t)bnx2x_848xx_read_status, + .link_reset = (link_reset_t)bnx2x_848x3_link_reset, + .config_loopback = (config_loopback_t)NULL, + .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver, + .hw_reset = (hw_reset_t)bnx2x_84833_hw_reset_phy, + .set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led, + .phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func +}; + +static const struct bnx2x_phy phy_54618se = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE, .addr = 0xff, .def_md_devad = 0, @@ -11465,6 +11749,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port, phy->media_type = ETH_PHY_BASE_T; break; case PORT_HW_CFG_NET_SERDES_IF_XFI: + phy->supported &= (SUPPORTED_1000baseT_Full | + SUPPORTED_10000baseT_Full | + SUPPORTED_FIBRE | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause); phy->media_type = ETH_PHY_XFP_FIBER; break; case PORT_HW_CFG_NET_SERDES_IF_SFI: @@ -11496,9 +11785,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port, phy->media_type = ETH_PHY_KR; phy->flags |= FLAGS_WC_DUAL_MODE; phy->supported &= (SUPPORTED_20000baseKR2_Full | + SUPPORTED_Autoneg | SUPPORTED_FIBRE | SUPPORTED_Pause | SUPPORTED_Asym_Pause); + phy->flags &= ~FLAGS_TX_ERROR_CHECK; break; default: DP(NETIF_MSG_LINK, "Unknown WC interface type 0x%x\n", @@ -11597,6 +11888,9 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp, case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833: *phy = phy_84833; break; + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834: + *phy = phy_84834; + break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE: *phy = phy_54618se; @@ -11653,9 +11947,10 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp, } phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port); - if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) && + if (((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) || + (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) && (phy->ver_addr)) { - /* Remove 100Mb link supported for BCM84833 when phy fw + /* Remove 100Mb link supported for BCM84833/4 when phy fw * version lower than or equal to 1.39 */ u32 raw_ver = REG_RD(bp, phy->ver_addr); @@ -11665,12 +11960,6 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp, SUPPORTED_100baseT_Full); } - /* In case mdc/mdio_access of the external phy is different than the - * mdc/mdio access of the XGXS, a HW lock must be taken in each access - * to prevent one port interfere with another port's CL45 operations. - */ - if (mdc_mdio_access != SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH) - phy->flags |= FLAGS_HW_LOCK_REQUIRED; DP(NETIF_MSG_LINK, "phy_type 0x%x port %d found in index %d\n", phy_type, port, phy_index); DP(NETIF_MSG_LINK, " addr=0x%x, mdio_ctl=0x%x\n", @@ -11795,7 +12084,6 @@ u32 bnx2x_phy_selection(struct link_params *params) return return_cfg; } - int bnx2x_phy_probe(struct link_params *params) { u8 phy_index, actual_phy_idx; @@ -11839,6 +12127,10 @@ int bnx2x_phy_probe(struct link_params *params) FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET) phy->flags &= ~FLAGS_TX_ERROR_CHECK; + if (!(params->feature_config_flags & + FEATURE_CONFIG_MT_SUPPORT)) + phy->flags |= FLAGS_MDC_MDIO_WA_G; + sync_offset = params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port].media_type); @@ -11866,8 +12158,8 @@ int bnx2x_phy_probe(struct link_params *params) return 0; } -void bnx2x_init_bmac_loopback(struct link_params *params, - struct link_vars *vars) +static void bnx2x_init_bmac_loopback(struct link_params *params, + struct link_vars *vars) { struct bnx2x *bp = params->bp; vars->link_up = 1; @@ -11886,8 +12178,8 @@ void bnx2x_init_bmac_loopback(struct link_params *params, REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); } -void bnx2x_init_emac_loopback(struct link_params *params, - struct link_vars *vars) +static void bnx2x_init_emac_loopback(struct link_params *params, + struct link_vars *vars) { struct bnx2x *bp = params->bp; vars->link_up = 1; @@ -11905,8 +12197,8 @@ void bnx2x_init_emac_loopback(struct link_params *params, REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); } -void bnx2x_init_xmac_loopback(struct link_params *params, - struct link_vars *vars) +static void bnx2x_init_xmac_loopback(struct link_params *params, + struct link_vars *vars) { struct bnx2x *bp = params->bp; vars->link_up = 1; @@ -11931,8 +12223,8 @@ void bnx2x_init_xmac_loopback(struct link_params *params, REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); } -void bnx2x_init_umac_loopback(struct link_params *params, - struct link_vars *vars) +static void bnx2x_init_umac_loopback(struct link_params *params, + struct link_vars *vars) { struct bnx2x *bp = params->bp; vars->link_up = 1; @@ -11946,17 +12238,21 @@ void bnx2x_init_umac_loopback(struct link_params *params, REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); } -void bnx2x_init_xgxs_loopback(struct link_params *params, - struct link_vars *vars) +static void bnx2x_init_xgxs_loopback(struct link_params *params, + struct link_vars *vars) { struct bnx2x *bp = params->bp; - vars->link_up = 1; - vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; - vars->duplex = DUPLEX_FULL; + struct bnx2x_phy *int_phy = ¶ms->phy[INT_PHY]; + vars->link_up = 1; + vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; + vars->duplex = DUPLEX_FULL; if (params->req_line_speed[0] == SPEED_1000) - vars->line_speed = SPEED_1000; + vars->line_speed = SPEED_1000; + else if ((params->req_line_speed[0] == SPEED_20000) || + (int_phy->flags & FLAGS_WC_DUAL_MODE)) + vars->line_speed = SPEED_20000; else - vars->line_speed = SPEED_10000; + vars->line_speed = SPEED_10000; if (!USES_WARPCORE(bp)) bnx2x_xgxs_deassert(params); @@ -11976,34 +12272,30 @@ void bnx2x_init_xgxs_loopback(struct link_params *params, bnx2x_bmac_enable(params, vars, 0, 1); } - if (params->loopback_mode == LOOPBACK_XGXS) { - /* set 10G XGXS loopback */ - params->phy[INT_PHY].config_loopback( - ¶ms->phy[INT_PHY], - params); - - } else { - /* set external phy loopback */ - u8 phy_index; - for (phy_index = EXT_PHY1; - phy_index < params->num_phys; phy_index++) { - if (params->phy[phy_index].config_loopback) - params->phy[phy_index].config_loopback( - ¶ms->phy[phy_index], - params); - } - } - REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); + if (params->loopback_mode == LOOPBACK_XGXS) { + /* Set 10G XGXS loopback */ + int_phy->config_loopback(int_phy, params); + } else { + /* Set external phy loopback */ + u8 phy_index; + for (phy_index = EXT_PHY1; + phy_index < params->num_phys; phy_index++) + if (params->phy[phy_index].config_loopback) + params->phy[phy_index].config_loopback( + ¶ms->phy[phy_index], + params); + } + REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed); } -static void bnx2x_set_rx_filter(struct link_params *params, u8 en) +void bnx2x_set_rx_filter(struct link_params *params, u8 en) { struct bnx2x *bp = params->bp; u8 val = en * 0x1F; - /* Open the gate between the NIG to the BRB */ + /* Open / close the gate between the NIG and the BRB */ if (!CHIP_IS_E1x(bp)) val |= en * 0x20; REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK + params->port*4, val); @@ -12277,7 +12569,7 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars, * Hold it as vars low */ /* Clear link led */ - bnx2x_set_mdio_clk(bp, params->chip_id, port); + bnx2x_set_mdio_emac_per_phy(bp, params); bnx2x_set_led(params, vars, LED_MODE_OFF, 0); if (reset_ext_phy) { @@ -12628,7 +12920,7 @@ static int bnx2x_8727_common_init_phy(struct bnx2x *bp, /* Initiate PHY reset*/ bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_LOW, port); - usleep_range(1000, 2000); + usleep_range(1000, 2000); bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_HIGH, port); @@ -12716,7 +13008,8 @@ static int bnx2x_84833_common_init_phy(struct bnx2x *bp, } static int bnx2x_84833_pre_init_phy(struct bnx2x *bp, - struct bnx2x_phy *phy) + struct bnx2x_phy *phy, + u8 port) { u16 val, cnt; /* Wait for FW completing its initialization. */ @@ -12726,7 +13019,7 @@ static int bnx2x_84833_pre_init_phy(struct bnx2x *bp, MDIO_PMA_REG_CTRL, &val); if (!(val & (1<<15))) break; - usleep_range(1000, 2000); + usleep_range(1000, 2000); } if (cnt >= 1500) { DP(NETIF_MSG_LINK, "84833 reset timeout\n"); @@ -12743,26 +13036,28 @@ static int bnx2x_84833_pre_init_phy(struct bnx2x *bp, MDIO_84833_TOP_CFG_XGPHY_STRAP1, val); /* Save spirom version */ - bnx2x_save_848xx_spirom_version(phy, bp, PORT_0); + bnx2x_save_848xx_spirom_version(phy, bp, port); return 0; } int bnx2x_pre_init_phy(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base, - u32 chip_id) + u32 chip_id, + u8 port) { int rc = 0; struct bnx2x_phy phy; - bnx2x_set_mdio_clk(bp, chip_id, PORT_0); if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, shmem2_base, - PORT_0, &phy)) { + port, &phy) != 0) { DP(NETIF_MSG_LINK, "populate_phy failed\n"); return -EINVAL; } + bnx2x_set_mdio_clk(bp, chip_id, phy.mdio_ctrl); switch (phy.type) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833: - rc = bnx2x_84833_pre_init_phy(bp, &phy); + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834: + rc = bnx2x_84833_pre_init_phy(bp, &phy, port); break; default: break; @@ -12799,6 +13094,7 @@ static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[], phy_index, chip_id); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834: /* GPIO3's are linked, and so both need to be toggled * to obtain required 2us pulse. */ @@ -12830,8 +13126,9 @@ int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[], u32 phy_ver, val; u8 phy_index = 0; u32 ext_phy_type, ext_phy_config; - bnx2x_set_mdio_clk(bp, chip_id, PORT_0); - bnx2x_set_mdio_clk(bp, chip_id, PORT_1); + + bnx2x_set_mdio_clk(bp, chip_id, GRCBASE_EMAC0); + bnx2x_set_mdio_clk(bp, chip_id, GRCBASE_EMAC1); DP(NETIF_MSG_LINK, "Begin common phy init\n"); if (CHIP_IS_E3(bp)) { /* Enable EPIO */ @@ -12892,6 +13189,7 @@ static void bnx2x_check_over_curr(struct link_params *params, " error.\n", params->port); vars->phy_flags |= PHY_OVER_CURRENT_FLAG; + bnx2x_warpcore_power_module(params, 0); } } else vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG; @@ -12919,7 +13217,7 @@ static u8 bnx2x_analyze_link_error(struct link_params *params, DP(NETIF_MSG_LINK, "Analyze TX Fault\n"); break; default: - DP(NETIF_MSG_LINK, "Analyze UNKOWN\n"); + DP(NETIF_MSG_LINK, "Analyze UNKNOWN\n"); } DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up, old_status, status); @@ -13071,6 +13369,108 @@ static void bnx2x_sfp_tx_fault_detection(struct bnx2x_phy *phy, } } } +static void bnx2x_disable_kr2(struct link_params *params, + struct link_vars *vars, + struct bnx2x_phy *phy) +{ + struct bnx2x *bp = params->bp; + int i; + static struct bnx2x_reg_set reg_set[] = { + /* Step 1 - Program the TX/RX alignment markers */ + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000}, + {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002}, + {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000}, + {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7}, + {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7}, + {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002}, + {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000} + }; + DP(NETIF_MSG_LINK, "Disabling 20G-KR2\n"); + + for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++) + bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg, + reg_set[i].val); + vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE; + bnx2x_update_link_attr(params, vars->link_attr_sync); + + /* Restart AN on leading lane */ + bnx2x_warpcore_restart_AN_KR(phy, params); +} + +static void bnx2x_kr2_recovery(struct link_params *params, + struct link_vars *vars, + struct bnx2x_phy *phy) +{ + struct bnx2x *bp = params->bp; + DP(NETIF_MSG_LINK, "KR2 recovery\n"); + bnx2x_warpcore_enable_AN_KR2(phy, params, vars); + bnx2x_warpcore_restart_AN_KR(phy, params); +} + +static void bnx2x_check_kr2_wa(struct link_params *params, + struct link_vars *vars, + struct bnx2x_phy *phy) +{ + struct bnx2x *bp = params->bp; + u16 base_page, next_page, not_kr2_device, lane; + int sigdet = bnx2x_warpcore_get_sigdet(phy, params); + + if (!sigdet) { + if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) + bnx2x_kr2_recovery(params, vars, phy); + return; + } + + lane = bnx2x_get_warpcore_lane(phy, params); + CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, + MDIO_AER_BLOCK_AER_REG, lane); + bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_LP_AUTO_NEG, &base_page); + bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, + MDIO_AN_REG_LP_AUTO_NEG2, &next_page); + bnx2x_set_aer_mmd(params, phy); + + /* CL73 has not begun yet */ + if (base_page == 0) { + if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) + bnx2x_kr2_recovery(params, vars, phy); + return; + } + + /* In case NP bit is not set in the BasePage, or it is set, + * but only KX is advertised, declare this link partner as non-KR2 + * device. + */ + not_kr2_device = (((base_page & 0x8000) == 0) || + (((base_page & 0x8000) && + ((next_page & 0xe0) == 0x2)))); + + /* In case KR2 is already disabled, check if we need to re-enable it */ + if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) { + if (!not_kr2_device) { + DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page, + next_page); + bnx2x_kr2_recovery(params, vars, phy); + } + return; + } + /* KR2 is enabled, but not KR2 device */ + if (not_kr2_device) { + /* Disable KR2 on both lanes */ + DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page, next_page); + bnx2x_disable_kr2(params, vars, phy); + return; + } +} + void bnx2x_period_func(struct link_params *params, struct link_vars *vars) { u16 phy_idx; @@ -13088,6 +13488,9 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars) if (CHIP_IS_E3(bp)) { struct bnx2x_phy *phy = ¶ms->phy[INT_PHY]; bnx2x_set_aer_mmd(params, phy); + if ((phy->supported & SUPPORTED_20000baseKR2_Full) && + (phy->speed_cap_mask & SPEED_20000)) + bnx2x_check_kr2_wa(params, vars, phy); bnx2x_check_over_curr(params, vars); if (vars->rx_tx_asic_rst) bnx2x_warpcore_config_runtime(phy, params, vars); @@ -13108,27 +13511,7 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars) bnx2x_update_mng(params, vars->link_status); } } - - } - -} - -u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base) -{ - u8 phy_index; - struct bnx2x_phy phy; - for (phy_index = INT_PHY; phy_index < MAX_PHYS; - phy_index++) { - if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base, - 0, &phy) != 0) { - DP(NETIF_MSG_LINK, "populate phy failed\n"); - return 0; - } - - if (phy.flags & FLAGS_HW_LOCK_REQUIRED) - return 1; } - return 0; } u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h index 9165b89a4b19..ee6e7ec85457 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h @@ -139,8 +139,6 @@ struct bnx2x_phy { u8 addr; u8 def_md_devad; u16 flags; - /* Require HW lock */ -#define FLAGS_HW_LOCK_REQUIRED (1<<0) /* No Over-Current detection */ #define FLAGS_NOC (1<<1) /* Fan failure detection required */ @@ -156,6 +154,7 @@ struct bnx2x_phy { #define FLAGS_MDC_MDIO_WA_B0 (1<<10) #define FLAGS_TX_ERROR_CHECK (1<<12) #define FLAGS_EEE (1<<13) +#define FLAGS_MDC_MDIO_WA_G (1<<15) /* preemphasis values for the rx side */ u16 rx_preemphasis[4]; @@ -267,6 +266,9 @@ struct link_params { #define FEATURE_CONFIG_AUTOGREEEN_ENABLED (1<<9) #define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10) #define FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET (1<<11) +#define FEATURE_CONFIG_MT_SUPPORT (1<<13) +#define FEATURE_CONFIG_BOOT_FROM_SAN (1<<14) + /* Will be populated during common init */ struct bnx2x_phy phy[MAX_PHYS]; @@ -347,6 +349,8 @@ struct link_vars { u8 rx_tx_asic_rst; u8 turn_to_run_wc_rt; u16 rsrv2; + /* The same definitions as the shmem2 parameter */ + u32 link_attr_sync; }; /***********************************************************/ @@ -418,10 +422,6 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy, void bnx2x_hw_reset_phy(struct link_params *params); -/* Checks if HW lock is required for this phy/board type */ -u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, - u32 shmem2_base); - /* Check swap bit and adjust PHY order */ u32 bnx2x_phy_selection(struct link_params *params); @@ -432,7 +432,8 @@ int bnx2x_phy_probe(struct link_params *params); u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base, u8 port); - +/* Open / close the gate between the NIG and the BRB */ +void bnx2x_set_rx_filter(struct link_params *params, u8 en); /* DCBX structs */ @@ -459,9 +460,6 @@ struct bnx2x_nig_brb_pfc_port_params { u32 rx_cos_priority_mask[DCBX_MAX_NUM_COS]; u32 llfc_high_priority_classes; u32 llfc_low_priority_classes; - /* BRB */ - u32 cos0_pauseable; - u32 cos1_pauseable; }; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 2bf4c08efad9..c9ec54730d1d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -79,7 +79,7 @@ /* Time in jiffies before concluding the transmitter is hung */ #define TX_TIMEOUT (5*HZ) -static char version[] __devinitdata = +static char version[] = "Broadcom NetXtreme II 5771x/578xx 10/20-Gigabit Ethernet Driver " DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; @@ -127,6 +127,17 @@ MODULE_PARM_DESC(debug, " Default debug msglevel"); struct workqueue_struct *bnx2x_wq; +struct bnx2x_mac_vals { + u32 xmac_addr; + u32 xmac_val; + u32 emac_addr; + u32 emac_val; + u32 umac_addr; + u32 umac_val; + u32 bmac_addr; + u32 bmac_val[2]; +}; + enum bnx2x_board_type { BCM57710 = 0, BCM57711, @@ -149,7 +160,7 @@ enum bnx2x_board_type { /* indexed by board_type, above */ static struct { char *name; -} board_info[] __devinitdata = { +} board_info[] = { { "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" }, { "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" }, { "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" }, @@ -791,10 +802,9 @@ void bnx2x_panic_dump(struct bnx2x *bp) /* host sb data */ -#ifdef BCM_CNIC if (IS_FCOE_FP(fp)) continue; -#endif + BNX2X_ERR(" run indexes ("); for (j = 0; j < HC_SB_MAX_SM; j++) pr_cont("0x%x%s", @@ -859,7 +869,7 @@ void bnx2x_panic_dump(struct bnx2x *bp) #ifdef BNX2X_STOP_ON_ERROR /* Rings */ /* Rx */ - for_each_rx_queue(bp, i) { + for_each_valid_rx_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; start = RX_BD(le16_to_cpu(*fp->rx_cons_sb) - 10); @@ -893,7 +903,7 @@ void bnx2x_panic_dump(struct bnx2x *bp) } /* Tx */ - for_each_tx_queue(bp, i) { + for_each_valid_tx_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; for_each_cos_in_tx_queue(fp, cos) { struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos]; @@ -1483,7 +1493,7 @@ static void bnx2x_igu_int_disable(struct bnx2x *bp) BNX2X_ERR("BUG! proper val not read from IGU!\n"); } -void bnx2x_int_disable(struct bnx2x *bp) +static void bnx2x_int_disable(struct bnx2x *bp) { if (bp->common.int_block == INT_BLOCK_HC) bnx2x_hc_int_disable(bp); @@ -1504,9 +1514,8 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw) if (msix) { synchronize_irq(bp->msix_table[0].vector); offset = 1; -#ifdef BCM_CNIC - offset++; -#endif + if (CNIC_SUPPORT(bp)) + offset++; for_each_eth_queue(bp, i) synchronize_irq(bp->msix_table[offset++].vector); } else @@ -1588,9 +1597,8 @@ static bool bnx2x_trylock_leader_lock(struct bnx2x *bp) return bnx2x_trylock_hw_lock(bp, bnx2x_get_leader_lock_resource(bp)); } -#ifdef BCM_CNIC static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err); -#endif + void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe) { @@ -1720,7 +1728,7 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) for_each_eth_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; - mask = 0x2 << (fp->index + CNIC_PRESENT); + mask = 0x2 << (fp->index + CNIC_SUPPORT(bp)); if (status & mask) { /* Handle Rx or Tx according to SB id */ prefetch(fp->rx_cons_sb); @@ -1732,22 +1740,23 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) } } -#ifdef BCM_CNIC - mask = 0x2; - if (status & (mask | 0x1)) { - struct cnic_ops *c_ops = NULL; + if (CNIC_SUPPORT(bp)) { + mask = 0x2; + if (status & (mask | 0x1)) { + struct cnic_ops *c_ops = NULL; - if (likely(bp->state == BNX2X_STATE_OPEN)) { - rcu_read_lock(); - c_ops = rcu_dereference(bp->cnic_ops); - if (c_ops) - c_ops->cnic_handler(bp->cnic_data, NULL); - rcu_read_unlock(); - } + if (likely(bp->state == BNX2X_STATE_OPEN)) { + rcu_read_lock(); + c_ops = rcu_dereference(bp->cnic_ops); + if (c_ops) + c_ops->cnic_handler(bp->cnic_data, + NULL); + rcu_read_unlock(); + } - status &= ~mask; + status &= ~mask; + } } -#endif if (unlikely(status & 0x1)) { queue_delayed_work(bnx2x_wq, &bp->sp_task, 0); @@ -2034,40 +2043,39 @@ int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port) return 0; } -static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode) +static int bnx2x_set_spio(struct bnx2x *bp, int spio, u32 mode) { - u32 spio_mask = (1 << spio_num); u32 spio_reg; - if ((spio_num < MISC_REGISTERS_SPIO_4) || - (spio_num > MISC_REGISTERS_SPIO_7)) { - BNX2X_ERR("Invalid SPIO %d\n", spio_num); + /* Only 2 SPIOs are configurable */ + if ((spio != MISC_SPIO_SPIO4) && (spio != MISC_SPIO_SPIO5)) { + BNX2X_ERR("Invalid SPIO 0x%x\n", spio); return -EINVAL; } bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_SPIO); /* read SPIO and mask except the float bits */ - spio_reg = (REG_RD(bp, MISC_REG_SPIO) & MISC_REGISTERS_SPIO_FLOAT); + spio_reg = (REG_RD(bp, MISC_REG_SPIO) & MISC_SPIO_FLOAT); switch (mode) { - case MISC_REGISTERS_SPIO_OUTPUT_LOW: - DP(NETIF_MSG_HW, "Set SPIO %d -> output low\n", spio_num); + case MISC_SPIO_OUTPUT_LOW: + DP(NETIF_MSG_HW, "Set SPIO 0x%x -> output low\n", spio); /* clear FLOAT and set CLR */ - spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS); - spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_CLR_POS); + spio_reg &= ~(spio << MISC_SPIO_FLOAT_POS); + spio_reg |= (spio << MISC_SPIO_CLR_POS); break; - case MISC_REGISTERS_SPIO_OUTPUT_HIGH: - DP(NETIF_MSG_HW, "Set SPIO %d -> output high\n", spio_num); + case MISC_SPIO_OUTPUT_HIGH: + DP(NETIF_MSG_HW, "Set SPIO 0x%x -> output high\n", spio); /* clear FLOAT and set SET */ - spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS); - spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_SET_POS); + spio_reg &= ~(spio << MISC_SPIO_FLOAT_POS); + spio_reg |= (spio << MISC_SPIO_SET_POS); break; - case MISC_REGISTERS_SPIO_INPUT_HI_Z: - DP(NETIF_MSG_HW, "Set SPIO %d -> input\n", spio_num); + case MISC_SPIO_INPUT_HI_Z: + DP(NETIF_MSG_HW, "Set SPIO 0x%x -> input\n", spio); /* set FLOAT */ - spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS); + spio_reg |= (spio << MISC_SPIO_FLOAT_POS); break; default: @@ -2106,22 +2114,25 @@ void bnx2x_calc_fc_adv(struct bnx2x *bp) } } -u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) +static void bnx2x_set_requested_fc(struct bnx2x *bp) { - if (!BP_NOMCP(bp)) { - u8 rc; - int cfx_idx = bnx2x_get_link_cfg_idx(bp); - u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx]; - /* - * Initialize link parameters structure variables - * It is recommended to turn off RX FC for jumbo frames - * for better performance - */ - if (CHIP_IS_E1x(bp) && (bp->dev->mtu > 5000)) - bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX; - else - bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH; + /* Initialize link parameters structure variables + * It is recommended to turn off RX FC for jumbo frames + * for better performance + */ + if (CHIP_IS_E1x(bp) && (bp->dev->mtu > 5000)) + bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX; + else + bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH; +} + +int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) +{ + int rc, cfx_idx = bnx2x_get_link_cfg_idx(bp); + u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx]; + if (!BP_NOMCP(bp)) { + bnx2x_set_requested_fc(bp); bnx2x_acquire_phy_lock(bp); if (load_mode == LOAD_DIAG) { @@ -2150,11 +2161,11 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) bnx2x_calc_fc_adv(bp); - if (CHIP_REV_IS_SLOW(bp) && bp->link_vars.link_up) { + if (bp->link_vars.link_up) { bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); bnx2x_link_report(bp); - } else - queue_delayed_work(bnx2x_wq, &bp->period_task, 0); + } + queue_delayed_work(bnx2x_wq, &bp->period_task, 0); bp->link_params.req_line_speed[cfx_idx] = req_line_speed; return rc; } @@ -3075,11 +3086,13 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp) static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp) { -#ifdef BCM_CNIC struct bnx2x_dcbx_app_params *app = &bp->dcbx_port_params.app; struct fcoe_stats_info *fcoe_stat = &bp->slowpath->drv_info_to_mcp.fcoe_stat; + if (!CNIC_LOADED(bp)) + return; + memcpy(fcoe_stat->mac_local + MAC_LEADING_ZERO_CNT, bp->fip_mac, ETH_ALEN); @@ -3162,16 +3175,17 @@ static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp) /* ask L5 driver to add data to the struct */ bnx2x_cnic_notify(bp, CNIC_CTL_FCOE_STATS_GET_CMD); -#endif } static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp) { -#ifdef BCM_CNIC struct bnx2x_dcbx_app_params *app = &bp->dcbx_port_params.app; struct iscsi_stats_info *iscsi_stat = &bp->slowpath->drv_info_to_mcp.iscsi_stat; + if (!CNIC_LOADED(bp)) + return; + memcpy(iscsi_stat->mac_local + MAC_LEADING_ZERO_CNT, bp->cnic_eth_dev.iscsi_mac, ETH_ALEN); @@ -3180,7 +3194,6 @@ static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp) /* ask L5 driver to add data to the struct */ bnx2x_cnic_notify(bp, CNIC_CTL_ISCSI_STATS_GET_CMD); -#endif } /* called due to MCP event (on pmf): @@ -3589,6 +3602,21 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted) /* now set back the mask */ if (asserted & ATTN_NIG_FOR_FUNC) { + /* Verify that IGU ack through BAR was written before restoring + * NIG mask. This loop should exit after 2-3 iterations max. + */ + if (bp->common.int_block != INT_BLOCK_HC) { + u32 cnt = 0, igu_acked; + do { + igu_acked = REG_RD(bp, + IGU_REG_ATTENTION_ACK_BITS); + } while (((igu_acked & ATTN_NIG_FOR_FUNC) == 0) && + (++cnt < MAX_IGU_ATTN_ACK_TO)); + if (!igu_acked) + DP(NETIF_MSG_HW, + "Failed to verify IGU ack on time\n"); + barrier(); + } REG_WR(bp, nig_int_mask_addr, nig_mask); bnx2x_release_phy_lock(bp); } @@ -4572,7 +4600,6 @@ static void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod) mmiowb(); /* keep prod updates ordered */ } -#ifdef BCM_CNIC static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid, union event_ring_elem *elem) { @@ -4594,7 +4621,6 @@ static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid, bnx2x_cnic_cfc_comp(bp, cid, err); return 0; } -#endif static void bnx2x_handle_mcast_eqe(struct bnx2x *bp) { @@ -4635,11 +4661,9 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp, switch (elem->message.data.eth_event.echo >> BNX2X_SWCID_SHIFT) { case BNX2X_FILTER_MAC_PENDING: DP(BNX2X_MSG_SP, "Got SETUP_MAC completions\n"); -#ifdef BCM_CNIC - if (cid == BNX2X_ISCSI_ETH_CID(bp)) + if (CNIC_LOADED(bp) && (cid == BNX2X_ISCSI_ETH_CID(bp))) vlan_mac_obj = &bp->iscsi_l2_mac_obj; else -#endif vlan_mac_obj = &bp->sp_objs[cid].mac_obj; break; @@ -4665,9 +4689,7 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp, } -#ifdef BCM_CNIC static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start); -#endif static void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp) { @@ -4678,14 +4700,12 @@ static void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp) /* Send rx_mode command again if was requested */ if (test_and_clear_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state)) bnx2x_set_storm_rx_mode(bp); -#ifdef BCM_CNIC else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED, &bp->sp_state)) bnx2x_set_iscsi_eth_rx_mode(bp, true); else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED, &bp->sp_state)) bnx2x_set_iscsi_eth_rx_mode(bp, false); -#endif netif_addr_unlock_bh(bp->dev); } @@ -4747,7 +4767,6 @@ static void bnx2x_after_function_update(struct bnx2x *bp) q); } -#ifdef BCM_CNIC if (!NO_FCOE(bp)) { fp = &bp->fp[FCOE_IDX(bp)]; queue_params.q_obj = &bnx2x_sp_obj(bp, fp).q_obj; @@ -4770,22 +4789,16 @@ static void bnx2x_after_function_update(struct bnx2x *bp) bnx2x_link_report(bp); bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0); } -#else - /* If no FCoE ring - ACK MCP now */ - bnx2x_link_report(bp); - bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0); -#endif /* BCM_CNIC */ } static struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj( struct bnx2x *bp, u32 cid) { DP(BNX2X_MSG_SP, "retrieving fp from cid %d\n", cid); -#ifdef BCM_CNIC - if (cid == BNX2X_FCOE_ETH_CID(bp)) + + if (CNIC_LOADED(bp) && (cid == BNX2X_FCOE_ETH_CID(bp))) return &bnx2x_fcoe_sp_obj(bp, q_obj); else -#endif return &bp->sp_objs[CID_TO_FP(cid, bp)].q_obj; } @@ -4793,6 +4806,7 @@ static void bnx2x_eq_int(struct bnx2x *bp) { u16 hw_cons, sw_cons, sw_prod; union event_ring_elem *elem; + u8 echo; u32 cid; u8 opcode; int spqe_cnt = 0; @@ -4847,10 +4861,11 @@ static void bnx2x_eq_int(struct bnx2x *bp) */ DP(BNX2X_MSG_SP, "got delete ramrod for MULTI[%d]\n", cid); -#ifdef BCM_CNIC - if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem)) + + if (CNIC_LOADED(bp) && + !bnx2x_cnic_handle_cfc_del(bp, cid, elem)) goto next_spqe; -#endif + q_obj = bnx2x_cid_to_q_obj(bp, cid); if (q_obj->complete_cmd(bp, q_obj, BNX2X_Q_CMD_CFC_DEL)) @@ -4875,21 +4890,34 @@ static void bnx2x_eq_int(struct bnx2x *bp) break; bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED); goto next_spqe; + case EVENT_RING_OPCODE_FUNCTION_UPDATE: - DP(BNX2X_MSG_SP | BNX2X_MSG_MCP, - "AFEX: ramrod completed FUNCTION_UPDATE\n"); - f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_AFEX_UPDATE); + echo = elem->message.data.function_update_event.echo; + if (echo == SWITCH_UPDATE) { + DP(BNX2X_MSG_SP | NETIF_MSG_IFUP, + "got FUNC_SWITCH_UPDATE ramrod\n"); + if (f_obj->complete_cmd( + bp, f_obj, BNX2X_F_CMD_SWITCH_UPDATE)) + break; - /* We will perform the Queues update from sp_rtnl task - * as all Queue SP operations should run under - * rtnl_lock. - */ - smp_mb__before_clear_bit(); - set_bit(BNX2X_SP_RTNL_AFEX_F_UPDATE, - &bp->sp_rtnl_state); - smp_mb__after_clear_bit(); + } else { + DP(BNX2X_MSG_SP | BNX2X_MSG_MCP, + "AFEX: ramrod completed FUNCTION_UPDATE\n"); + f_obj->complete_cmd(bp, f_obj, + BNX2X_F_CMD_AFEX_UPDATE); + + /* We will perform the Queues update from + * sp_rtnl task as all Queue SP operations + * should run under rtnl_lock. + */ + smp_mb__before_clear_bit(); + set_bit(BNX2X_SP_RTNL_AFEX_F_UPDATE, + &bp->sp_rtnl_state); + smp_mb__after_clear_bit(); + + schedule_delayed_work(&bp->sp_rtnl_task, 0); + } - schedule_delayed_work(&bp->sp_rtnl_task, 0); goto next_spqe; case EVENT_RING_OPCODE_AFEX_VIF_LISTS: @@ -4999,11 +5027,10 @@ static void bnx2x_sp_task(struct work_struct *work) /* SP events: STAT_QUERY and others */ if (status & BNX2X_DEF_SB_IDX) { -#ifdef BCM_CNIC struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp); - if ((!NO_FCOE(bp)) && - (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { + if (FCOE_INIT(bp) && + (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { /* * Prevent local bottom-halves from running as * we are going to change the local NAPI list. @@ -5012,7 +5039,7 @@ static void bnx2x_sp_task(struct work_struct *work) napi_schedule(&bnx2x_fcoe(bp, napi)); local_bh_enable(); } -#endif + /* Handle EQ completions */ bnx2x_eq_int(bp); @@ -5050,8 +5077,7 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) return IRQ_HANDLED; #endif -#ifdef BCM_CNIC - { + if (CNIC_LOADED(bp)) { struct cnic_ops *c_ops; rcu_read_lock(); @@ -5060,7 +5086,7 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) c_ops->cnic_handler(bp->cnic_data, NULL); rcu_read_unlock(); } -#endif + queue_delayed_work(bnx2x_wq, &bp->sp_task, 0); return IRQ_HANDLED; @@ -5498,12 +5524,10 @@ void bnx2x_set_storm_rx_mode(struct bnx2x *bp) unsigned long rx_mode_flags = 0, ramrod_flags = 0; unsigned long rx_accept_flags = 0, tx_accept_flags = 0; -#ifdef BCM_CNIC if (!NO_FCOE(bp)) /* Configure rx_mode of FCoE Queue */ __set_bit(BNX2X_RX_MODE_FCOE_ETH, &rx_mode_flags); -#endif switch (bp->rx_mode) { case BNX2X_RX_MODE_NONE: @@ -5624,12 +5648,12 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code) static inline u8 bnx2x_fp_igu_sb_id(struct bnx2x_fastpath *fp) { - return fp->bp->igu_base_sb + fp->index + CNIC_PRESENT; + return fp->bp->igu_base_sb + fp->index + CNIC_SUPPORT(fp->bp); } static inline u8 bnx2x_fp_fw_sb_id(struct bnx2x_fastpath *fp) { - return fp->bp->base_fw_ndsb + fp->index + CNIC_PRESENT; + return fp->bp->base_fw_ndsb + fp->index + CNIC_SUPPORT(fp->bp); } static u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp) @@ -5720,23 +5744,25 @@ static void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata) txdata->tx_pkt = 0; } +static void bnx2x_init_tx_rings_cnic(struct bnx2x *bp) +{ + int i; + + for_each_tx_queue_cnic(bp, i) + bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[0]); +} static void bnx2x_init_tx_rings(struct bnx2x *bp) { int i; u8 cos; - for_each_tx_queue(bp, i) + for_each_eth_queue(bp, i) for_each_cos_in_tx_queue(&bp->fp[i], cos) bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[cos]); } -void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) +void bnx2x_nic_init_cnic(struct bnx2x *bp) { - int i; - - for_each_eth_queue(bp, i) - bnx2x_init_eth_fp(bp, i); -#ifdef BCM_CNIC if (!NO_FCOE(bp)) bnx2x_init_fcoe_fp(bp); @@ -5744,8 +5770,22 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) BNX2X_VF_ID_INVALID, false, bnx2x_cnic_fw_sb_id(bp), bnx2x_cnic_igu_sb_id(bp)); -#endif + /* ensure status block indices were read */ + rmb(); + bnx2x_init_rx_rings_cnic(bp); + bnx2x_init_tx_rings_cnic(bp); + + /* flush all */ + mb(); + mmiowb(); +} +void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) +{ + int i; + + for_each_eth_queue(bp, i) + bnx2x_init_eth_fp(bp, i); /* Initialize MOD_ABS interrupts */ bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id, bp->common.shmem_base, bp->common.shmem2_base, @@ -6031,10 +6071,9 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) msleep(50); bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON); bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON); -#ifndef BCM_CNIC - /* set NIC mode */ - REG_WR(bp, PRS_REG_NIC_MODE, 1); -#endif + if (!CNIC_SUPPORT(bp)) + /* set NIC mode */ + REG_WR(bp, PRS_REG_NIC_MODE, 1); /* Enable inputs of parser neighbor blocks */ REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x7fffffff); @@ -6049,6 +6088,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) static void bnx2x_enable_blocks_attention(struct bnx2x *bp) { + u32 val; + REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0); if (!CHIP_IS_E1x(bp)) REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0x40); @@ -6082,17 +6123,14 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp) /* REG_WR(bp, CSEM_REG_CSEM_INT_MASK_0, 0); */ /* REG_WR(bp, CSEM_REG_CSEM_INT_MASK_1, 0); */ - if (CHIP_REV_IS_FPGA(bp)) - REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000); - else if (!CHIP_IS_E1x(bp)) - REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, - (PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF - | PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT - | PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN - | PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED - | PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED)); - else - REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x480000); + val = PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT | + PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF | + PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN; + if (!CHIP_IS_E1x(bp)) + val |= PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED | + PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED; + REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, val); + REG_WR(bp, TSDM_REG_TSDM_INT_MASK_0, 0); REG_WR(bp, TSDM_REG_TSDM_INT_MASK_1, 0); REG_WR(bp, TCM_REG_TCM_INT_MASK, 0); @@ -6185,18 +6223,16 @@ static void bnx2x_setup_fan_failure_detection(struct bnx2x *bp) return; /* Fan failure is indicated by SPIO 5 */ - bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5, - MISC_REGISTERS_SPIO_INPUT_HI_Z); + bnx2x_set_spio(bp, MISC_SPIO_SPIO5, MISC_SPIO_INPUT_HI_Z); /* set to active low mode */ val = REG_RD(bp, MISC_REG_SPIO_INT); - val |= ((1 << MISC_REGISTERS_SPIO_5) << - MISC_REGISTERS_SPIO_INT_OLD_SET_POS); + val |= (MISC_SPIO_SPIO5 << MISC_SPIO_INT_OLD_SET_POS); REG_WR(bp, MISC_REG_SPIO_INT, val); /* enable interrupt to signal the IGU */ val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN); - val |= (1 << MISC_REGISTERS_SPIO_5); + val |= MISC_SPIO_SPIO5; REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val); } @@ -6256,6 +6292,10 @@ void bnx2x_pf_disable(struct bnx2x *bp) static void bnx2x__common_init_phy(struct bnx2x *bp) { u32 shmem_base[2], shmem2_base[2]; + /* Avoid common init in case MFW supports LFA */ + if (SHMEM2_RD(bp, size) > + (u32)offsetof(struct shmem2_region, lfa_host_addr[BP_PORT(bp)])) + return; shmem_base[0] = bp->common.shmem_base; shmem2_base[0] = bp->common.shmem2_base; if (!CHIP_IS_E1x(bp)) { @@ -6522,9 +6562,8 @@ static int bnx2x_init_hw_common(struct bnx2x *bp) REG_WR(bp, QM_REG_SOFT_RESET, 1); REG_WR(bp, QM_REG_SOFT_RESET, 0); -#ifdef BCM_CNIC - bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON); -#endif + if (CNIC_SUPPORT(bp)) + bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON); bnx2x_init_block(bp, BLOCK_DORQ, PHASE_COMMON); REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT); @@ -6611,18 +6650,18 @@ static int bnx2x_init_hw_common(struct bnx2x *bp) bnx2x_init_block(bp, BLOCK_SRC, PHASE_COMMON); -#ifdef BCM_CNIC - REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672); - REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc); - REG_WR(bp, SRC_REG_KEYSEARCH_2, 0x223aef9b); - REG_WR(bp, SRC_REG_KEYSEARCH_3, 0x26001e3a); - REG_WR(bp, SRC_REG_KEYSEARCH_4, 0x7ae91116); - REG_WR(bp, SRC_REG_KEYSEARCH_5, 0x5ce5230b); - REG_WR(bp, SRC_REG_KEYSEARCH_6, 0x298d8adf); - REG_WR(bp, SRC_REG_KEYSEARCH_7, 0x6eb0ff09); - REG_WR(bp, SRC_REG_KEYSEARCH_8, 0x1830f82f); - REG_WR(bp, SRC_REG_KEYSEARCH_9, 0x01e46be7); -#endif + if (CNIC_SUPPORT(bp)) { + REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672); + REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc); + REG_WR(bp, SRC_REG_KEYSEARCH_2, 0x223aef9b); + REG_WR(bp, SRC_REG_KEYSEARCH_3, 0x26001e3a); + REG_WR(bp, SRC_REG_KEYSEARCH_4, 0x7ae91116); + REG_WR(bp, SRC_REG_KEYSEARCH_5, 0x5ce5230b); + REG_WR(bp, SRC_REG_KEYSEARCH_6, 0x298d8adf); + REG_WR(bp, SRC_REG_KEYSEARCH_7, 0x6eb0ff09); + REG_WR(bp, SRC_REG_KEYSEARCH_8, 0x1830f82f); + REG_WR(bp, SRC_REG_KEYSEARCH_9, 0x01e46be7); + } REG_WR(bp, SRC_REG_SOFT_RST, 0); if (sizeof(union cdu_context) != 1024) @@ -6786,16 +6825,17 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) /* QM cid (connection) count */ bnx2x_qm_init_cid_count(bp, bp->qm_cid_count, INITOP_SET); -#ifdef BCM_CNIC - bnx2x_init_block(bp, BLOCK_TM, init_phase); - REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20); - REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31); -#endif + if (CNIC_SUPPORT(bp)) { + bnx2x_init_block(bp, BLOCK_TM, init_phase); + REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20); + REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31); + } bnx2x_init_block(bp, BLOCK_DORQ, init_phase); + bnx2x_init_block(bp, BLOCK_BRB1, init_phase); + if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) { - bnx2x_init_block(bp, BLOCK_BRB1, init_phase); if (IS_MF(bp)) low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246); @@ -6876,9 +6916,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0); } -#ifdef BCM_CNIC - bnx2x_init_block(bp, BLOCK_SRC, init_phase); -#endif + if (CNIC_SUPPORT(bp)) + bnx2x_init_block(bp, BLOCK_SRC, init_phase); + bnx2x_init_block(bp, BLOCK_CDU, init_phase); bnx2x_init_block(bp, BLOCK_CFC, init_phase); @@ -6954,7 +6994,7 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) /* If SPIO5 is set to generate interrupts, enable it for this port */ val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN); - if (val & (1 << MISC_REGISTERS_SPIO_5)) { + if (val & MISC_SPIO_SPIO5) { u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); val = REG_RD(bp, reg_addr); @@ -7039,6 +7079,130 @@ static void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func) bnx2x_ilt_wr(bp, i, 0); } + +static void bnx2x_init_searcher(struct bnx2x *bp) +{ + int port = BP_PORT(bp); + bnx2x_src_init_t2(bp, bp->t2, bp->t2_mapping, SRC_CONN_NUM); + /* T1 hash bits value determines the T1 number of entries */ + REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, SRC_HASH_BITS); +} + +static inline int bnx2x_func_switch_update(struct bnx2x *bp, int suspend) +{ + int rc; + struct bnx2x_func_state_params func_params = {NULL}; + struct bnx2x_func_switch_update_params *switch_update_params = + &func_params.params.switch_update; + + /* Prepare parameters for function state transitions */ + __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags); + __set_bit(RAMROD_RETRY, &func_params.ramrod_flags); + + func_params.f_obj = &bp->func_obj; + func_params.cmd = BNX2X_F_CMD_SWITCH_UPDATE; + + /* Function parameters */ + switch_update_params->suspend = suspend; + + rc = bnx2x_func_state_change(bp, &func_params); + + return rc; +} + +static int bnx2x_reset_nic_mode(struct bnx2x *bp) +{ + int rc, i, port = BP_PORT(bp); + int vlan_en = 0, mac_en[NUM_MACS]; + + + /* Close input from network */ + if (bp->mf_mode == SINGLE_FUNCTION) { + bnx2x_set_rx_filter(&bp->link_params, 0); + } else { + vlan_en = REG_RD(bp, port ? NIG_REG_LLH1_FUNC_EN : + NIG_REG_LLH0_FUNC_EN); + REG_WR(bp, port ? NIG_REG_LLH1_FUNC_EN : + NIG_REG_LLH0_FUNC_EN, 0); + for (i = 0; i < NUM_MACS; i++) { + mac_en[i] = REG_RD(bp, port ? + (NIG_REG_LLH1_FUNC_MEM_ENABLE + + 4 * i) : + (NIG_REG_LLH0_FUNC_MEM_ENABLE + + 4 * i)); + REG_WR(bp, port ? (NIG_REG_LLH1_FUNC_MEM_ENABLE + + 4 * i) : + (NIG_REG_LLH0_FUNC_MEM_ENABLE + 4 * i), 0); + } + } + + /* Close BMC to host */ + REG_WR(bp, port ? NIG_REG_P0_TX_MNG_HOST_ENABLE : + NIG_REG_P1_TX_MNG_HOST_ENABLE, 0); + + /* Suspend Tx switching to the PF. Completion of this ramrod + * further guarantees that all the packets of that PF / child + * VFs in BRB were processed by the Parser, so it is safe to + * change the NIC_MODE register. + */ + rc = bnx2x_func_switch_update(bp, 1); + if (rc) { + BNX2X_ERR("Can't suspend tx-switching!\n"); + return rc; + } + + /* Change NIC_MODE register */ + REG_WR(bp, PRS_REG_NIC_MODE, 0); + + /* Open input from network */ + if (bp->mf_mode == SINGLE_FUNCTION) { + bnx2x_set_rx_filter(&bp->link_params, 1); + } else { + REG_WR(bp, port ? NIG_REG_LLH1_FUNC_EN : + NIG_REG_LLH0_FUNC_EN, vlan_en); + for (i = 0; i < NUM_MACS; i++) { + REG_WR(bp, port ? (NIG_REG_LLH1_FUNC_MEM_ENABLE + + 4 * i) : + (NIG_REG_LLH0_FUNC_MEM_ENABLE + 4 * i), + mac_en[i]); + } + } + + /* Enable BMC to host */ + REG_WR(bp, port ? NIG_REG_P0_TX_MNG_HOST_ENABLE : + NIG_REG_P1_TX_MNG_HOST_ENABLE, 1); + + /* Resume Tx switching to the PF */ + rc = bnx2x_func_switch_update(bp, 0); + if (rc) { + BNX2X_ERR("Can't resume tx-switching!\n"); + return rc; + } + + DP(NETIF_MSG_IFUP, "NIC MODE disabled\n"); + return 0; +} + +int bnx2x_init_hw_func_cnic(struct bnx2x *bp) +{ + int rc; + + bnx2x_ilt_init_op_cnic(bp, INITOP_SET); + + if (CONFIGURE_NIC_MODE(bp)) { + /* Configrue searcher as part of function hw init */ + bnx2x_init_searcher(bp); + + /* Reset NIC mode */ + rc = bnx2x_reset_nic_mode(bp); + if (rc) + BNX2X_ERR("Can't change NIC mode!\n"); + return rc; + } + + return 0; +} + static int bnx2x_init_hw_func(struct bnx2x *bp) { int port = BP_PORT(bp); @@ -7081,17 +7245,16 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) } bnx2x_ilt_init_op(bp, INITOP_SET); -#ifdef BCM_CNIC - bnx2x_src_init_t2(bp, bp->t2, bp->t2_mapping, SRC_CONN_NUM); - - /* T1 hash bits value determines the T1 number of entries */ - REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, SRC_HASH_BITS); -#endif + if (!CONFIGURE_NIC_MODE(bp)) { + bnx2x_init_searcher(bp); + REG_WR(bp, PRS_REG_NIC_MODE, 0); + DP(NETIF_MSG_IFUP, "NIC MODE disabled\n"); + } else { + /* Set NIC mode */ + REG_WR(bp, PRS_REG_NIC_MODE, 1); + DP(NETIF_MSG_IFUP, "NIC MODE configrued\n"); -#ifndef BCM_CNIC - /* set NIC mode */ - REG_WR(bp, PRS_REG_NIC_MODE, 1); -#endif /* BCM_CNIC */ + } if (!CHIP_IS_E1x(bp)) { u32 pf_conf = IGU_PF_CONF_FUNC_EN; @@ -7342,6 +7505,20 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) } +void bnx2x_free_mem_cnic(struct bnx2x *bp) +{ + bnx2x_ilt_mem_op_cnic(bp, ILT_MEMOP_FREE); + + if (!CHIP_IS_E1x(bp)) + BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping, + sizeof(struct host_hc_status_block_e2)); + else + BNX2X_PCI_FREE(bp->cnic_sb.e1x_sb, bp->cnic_sb_mapping, + sizeof(struct host_hc_status_block_e1x)); + + BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, SRC_T2_SZ); +} + void bnx2x_free_mem(struct bnx2x *bp) { int i; @@ -7366,17 +7543,6 @@ void bnx2x_free_mem(struct bnx2x *bp) BNX2X_FREE(bp->ilt->lines); -#ifdef BCM_CNIC - if (!CHIP_IS_E1x(bp)) - BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping, - sizeof(struct host_hc_status_block_e2)); - else - BNX2X_PCI_FREE(bp->cnic_sb.e1x_sb, bp->cnic_sb_mapping, - sizeof(struct host_hc_status_block_e1x)); - - BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, SRC_T2_SZ); -#endif - BNX2X_PCI_FREE(bp->spq, bp->spq_mapping, BCM_PAGE_SIZE); BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping, @@ -7444,24 +7610,44 @@ alloc_mem_err: return -ENOMEM; } - -int bnx2x_alloc_mem(struct bnx2x *bp) +int bnx2x_alloc_mem_cnic(struct bnx2x *bp) { - int i, allocated, context_size; - -#ifdef BCM_CNIC if (!CHIP_IS_E1x(bp)) /* size = the status block + ramrod buffers */ BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping, sizeof(struct host_hc_status_block_e2)); else - BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb, &bp->cnic_sb_mapping, - sizeof(struct host_hc_status_block_e1x)); + BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb, + &bp->cnic_sb_mapping, + sizeof(struct + host_hc_status_block_e1x)); - /* allocate searcher T2 table */ - BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ); -#endif + if (CONFIGURE_NIC_MODE(bp)) + /* allocate searcher T2 table, as it wan't allocated before */ + BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ); + + /* write address to which L5 should insert its values */ + bp->cnic_eth_dev.addr_drv_info_to_mcp = + &bp->slowpath->drv_info_to_mcp; + + if (bnx2x_ilt_mem_op_cnic(bp, ILT_MEMOP_ALLOC)) + goto alloc_mem_err; + + return 0; + +alloc_mem_err: + bnx2x_free_mem_cnic(bp); + BNX2X_ERR("Can't allocate memory\n"); + return -ENOMEM; +} + +int bnx2x_alloc_mem(struct bnx2x *bp) +{ + int i, allocated, context_size; + if (!CONFIGURE_NIC_MODE(bp)) + /* allocate searcher T2 table */ + BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ); BNX2X_PCI_ALLOC(bp->def_status_blk, &bp->def_status_blk_mapping, sizeof(struct host_sp_status_block)); @@ -7469,11 +7655,6 @@ int bnx2x_alloc_mem(struct bnx2x *bp) BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping, sizeof(struct bnx2x_slowpath)); -#ifdef BCM_CNIC - /* write address to which L5 should insert its values */ - bp->cnic_eth_dev.addr_drv_info_to_mcp = &bp->slowpath->drv_info_to_mcp; -#endif - /* Allocated memory for FW statistics */ if (bnx2x_alloc_fw_stats_mem(bp)) goto alloc_mem_err; @@ -7595,14 +7776,12 @@ int bnx2x_set_eth_mac(struct bnx2x *bp, bool set) { unsigned long ramrod_flags = 0; -#ifdef BCM_CNIC if (is_zero_ether_addr(bp->dev->dev_addr) && (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) { DP(NETIF_MSG_IFUP | NETIF_MSG_IFDOWN, "Ignoring Zero MAC for STORAGE SD mode\n"); return 0; } -#endif DP(NETIF_MSG_IFUP, "Adding Eth MAC\n"); @@ -7631,7 +7810,8 @@ void bnx2x_set_int_mode(struct bnx2x *bp) bnx2x_enable_msi(bp); /* falling through... */ case INT_MODE_INTx: - bp->num_queues = 1 + NON_ETH_CONTEXT_USE; + bp->num_ethernet_queues = 1; + bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues; BNX2X_DEV_INFO("set number of queues to 1\n"); break; default: @@ -7643,9 +7823,10 @@ void bnx2x_set_int_mode(struct bnx2x *bp) bp->flags & USING_SINGLE_MSIX_FLAG) { /* failed to enable multiple MSI-X */ BNX2X_DEV_INFO("Failed to enable multiple MSI-X (%d), set number of queues to %d\n", - bp->num_queues, 1 + NON_ETH_CONTEXT_USE); + bp->num_queues, + 1 + bp->num_cnic_queues); - bp->num_queues = 1 + NON_ETH_CONTEXT_USE; + bp->num_queues = 1 + bp->num_cnic_queues; /* Try to enable MSI */ if (!(bp->flags & USING_SINGLE_MSIX_FLAG) && @@ -7678,9 +7859,9 @@ void bnx2x_ilt_set_info(struct bnx2x *bp) ilt_client->flags = ILT_CLIENT_SKIP_MEM; ilt_client->start = line; line += bnx2x_cid_ilt_lines(bp); -#ifdef BCM_CNIC - line += CNIC_ILT_LINES; -#endif + + if (CNIC_SUPPORT(bp)) + line += CNIC_ILT_LINES; ilt_client->end = line - 1; DP(NETIF_MSG_IFUP, "ilt client[CDU]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n", @@ -7713,49 +7894,43 @@ void bnx2x_ilt_set_info(struct bnx2x *bp) ilog2(ilt_client->page_size >> 12)); } - /* SRC */ - ilt_client = &ilt->clients[ILT_CLIENT_SRC]; -#ifdef BCM_CNIC - ilt_client->client_num = ILT_CLIENT_SRC; - ilt_client->page_size = SRC_ILT_PAGE_SZ; - ilt_client->flags = 0; - ilt_client->start = line; - line += SRC_ILT_LINES; - ilt_client->end = line - 1; - DP(NETIF_MSG_IFUP, - "ilt client[SRC]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n", - ilt_client->start, - ilt_client->end, - ilt_client->page_size, - ilt_client->flags, - ilog2(ilt_client->page_size >> 12)); + if (CNIC_SUPPORT(bp)) { + /* SRC */ + ilt_client = &ilt->clients[ILT_CLIENT_SRC]; + ilt_client->client_num = ILT_CLIENT_SRC; + ilt_client->page_size = SRC_ILT_PAGE_SZ; + ilt_client->flags = 0; + ilt_client->start = line; + line += SRC_ILT_LINES; + ilt_client->end = line - 1; -#else - ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM); -#endif + DP(NETIF_MSG_IFUP, + "ilt client[SRC]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n", + ilt_client->start, + ilt_client->end, + ilt_client->page_size, + ilt_client->flags, + ilog2(ilt_client->page_size >> 12)); - /* TM */ - ilt_client = &ilt->clients[ILT_CLIENT_TM]; -#ifdef BCM_CNIC - ilt_client->client_num = ILT_CLIENT_TM; - ilt_client->page_size = TM_ILT_PAGE_SZ; - ilt_client->flags = 0; - ilt_client->start = line; - line += TM_ILT_LINES; - ilt_client->end = line - 1; + /* TM */ + ilt_client = &ilt->clients[ILT_CLIENT_TM]; + ilt_client->client_num = ILT_CLIENT_TM; + ilt_client->page_size = TM_ILT_PAGE_SZ; + ilt_client->flags = 0; + ilt_client->start = line; + line += TM_ILT_LINES; + ilt_client->end = line - 1; - DP(NETIF_MSG_IFUP, - "ilt client[TM]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n", - ilt_client->start, - ilt_client->end, - ilt_client->page_size, - ilt_client->flags, - ilog2(ilt_client->page_size >> 12)); + DP(NETIF_MSG_IFUP, + "ilt client[TM]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n", + ilt_client->start, + ilt_client->end, + ilt_client->page_size, + ilt_client->flags, + ilog2(ilt_client->page_size >> 12)); + } -#else - ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM); -#endif BUG_ON(line > ILT_MAX_LINES); } @@ -7822,7 +7997,7 @@ static void bnx2x_pf_q_prep_init(struct bnx2x *bp, } } -int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp, +static int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp, struct bnx2x_queue_state_params *q_params, struct bnx2x_queue_setup_tx_only_params *tx_only_params, int tx_index, bool leading) @@ -7923,6 +8098,9 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp, /* Set the command */ q_params.cmd = BNX2X_Q_CMD_SETUP; + if (IS_FCOE_FP(fp)) + bp->fcoe_init = true; + /* Change the state to SETUP */ rc = bnx2x_queue_state_change(bp, &q_params); if (rc) { @@ -8036,12 +8214,12 @@ static void bnx2x_reset_func(struct bnx2x *bp) SB_DISABLED); } -#ifdef BCM_CNIC - /* CNIC SB */ - REG_WR8(bp, BAR_CSTRORM_INTMEM + - CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(bnx2x_cnic_fw_sb_id(bp)), - SB_DISABLED); -#endif + if (CNIC_LOADED(bp)) + /* CNIC SB */ + REG_WR8(bp, BAR_CSTRORM_INTMEM + + CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET + (bnx2x_cnic_fw_sb_id(bp)), SB_DISABLED); + /* SP SB */ REG_WR8(bp, BAR_CSTRORM_INTMEM + CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func), @@ -8060,19 +8238,19 @@ static void bnx2x_reset_func(struct bnx2x *bp) REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0); } -#ifdef BCM_CNIC - /* Disable Timer scan */ - REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0); - /* - * Wait for at least 10ms and up to 2 second for the timers scan to - * complete - */ - for (i = 0; i < 200; i++) { - msleep(10); - if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4)) - break; + if (CNIC_LOADED(bp)) { + /* Disable Timer scan */ + REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0); + /* + * Wait for at least 10ms and up to 2 second for the timers + * scan to complete + */ + for (i = 0; i < 200; i++) { + msleep(10); + if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4)) + break; + } } -#endif /* Clear ILT */ bnx2x_clear_func_ilt(bp, func); @@ -8408,13 +8586,24 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link) /* Close multi and leading connections * Completions for ramrods are collected in a synchronous way */ - for_each_queue(bp, i) + for_each_eth_queue(bp, i) if (bnx2x_stop_queue(bp, i)) #ifdef BNX2X_STOP_ON_ERROR return; #else goto unload_error; #endif + + if (CNIC_LOADED(bp)) { + for_each_cnic_queue(bp, i) + if (bnx2x_stop_queue(bp, i)) +#ifdef BNX2X_STOP_ON_ERROR + return; +#else + goto unload_error; +#endif + } + /* If SP settings didn't get completed so far - something * very wrong has happen. */ @@ -8436,6 +8625,8 @@ unload_error: bnx2x_netif_stop(bp, 1); /* Delete all NAPI objects */ bnx2x_del_all_napi(bp); + if (CNIC_LOADED(bp)) + bnx2x_del_all_napi_cnic(bp); /* Release IRQs */ bnx2x_free_irq(bp); @@ -8557,7 +8748,8 @@ static void bnx2x_reset_mcp_prep(struct bnx2x *bp, u32 *magic_val) /* Get shmem offset */ shmem = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR); - validity_offset = offsetof(struct shmem_region, validity_map[0]); + validity_offset = + offsetof(struct shmem_region, validity_map[BP_PORT(bp)]); /* Clear validity map flags */ if (shmem > 0) @@ -8650,7 +8842,11 @@ static void bnx2x_process_kill_chip_reset(struct bnx2x *bp, bool global) MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU | MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE; - /* Don't reset the following blocks */ + /* Don't reset the following blocks. + * Important: per port blocks (such as EMAC, BMAC, UMAC) can't be + * reset, as in 4 port device they might still be owned + * by the MCP (there is only one leader per path). + */ not_reset_mask1 = MISC_REGISTERS_RESET_REG_1_RST_HC | MISC_REGISTERS_RESET_REG_1_RST_PXPV | @@ -8666,19 +8862,19 @@ static void bnx2x_process_kill_chip_reset(struct bnx2x *bp, bool global) MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE | MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B | MISC_REGISTERS_RESET_REG_2_RST_ATC | - MISC_REGISTERS_RESET_REG_2_PGLC; + MISC_REGISTERS_RESET_REG_2_PGLC | + MISC_REGISTERS_RESET_REG_2_RST_BMAC0 | + MISC_REGISTERS_RESET_REG_2_RST_BMAC1 | + MISC_REGISTERS_RESET_REG_2_RST_EMAC0 | + MISC_REGISTERS_RESET_REG_2_RST_EMAC1 | + MISC_REGISTERS_RESET_REG_2_UMAC0 | + MISC_REGISTERS_RESET_REG_2_UMAC1; /* * Keep the following blocks in reset: * - all xxMACs are handled by the bnx2x_link code. */ stay_reset2 = - MISC_REGISTERS_RESET_REG_2_RST_BMAC0 | - MISC_REGISTERS_RESET_REG_2_RST_BMAC1 | - MISC_REGISTERS_RESET_REG_2_RST_EMAC0 | - MISC_REGISTERS_RESET_REG_2_RST_EMAC1 | - MISC_REGISTERS_RESET_REG_2_UMAC0 | - MISC_REGISTERS_RESET_REG_2_UMAC1 | MISC_REGISTERS_RESET_REG_2_XMAC | MISC_REGISTERS_RESET_REG_2_XMAC_SOFT; @@ -8768,6 +8964,7 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global) int cnt = 1000; u32 val = 0; u32 sr_cnt, blk_cnt, port_is_idle_0, port_is_idle_1, pgl_exp_rom2; + u32 tags_63_32 = 0; /* Empty the Tetris buffer, wait for 1s */ @@ -8777,10 +8974,14 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global) port_is_idle_0 = REG_RD(bp, PXP2_REG_RD_PORT_IS_IDLE_0); port_is_idle_1 = REG_RD(bp, PXP2_REG_RD_PORT_IS_IDLE_1); pgl_exp_rom2 = REG_RD(bp, PXP2_REG_PGL_EXP_ROM2); + if (CHIP_IS_E3(bp)) + tags_63_32 = REG_RD(bp, PGLUE_B_REG_TAGS_63_32); + if ((sr_cnt == 0x7e) && (blk_cnt == 0xa0) && ((port_is_idle_0 & 0x1) == 0x1) && ((port_is_idle_1 & 0x1) == 0x1) && - (pgl_exp_rom2 == 0xffffffff)) + (pgl_exp_rom2 == 0xffffffff) && + (!CHIP_IS_E3(bp) || (tags_63_32 == 0xffffffff))) break; usleep_range(1000, 1000); } while (cnt-- > 0); @@ -8837,9 +9038,6 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global) /* TBD: Add resetting the NO_MCP mode DB here */ - /* PXP */ - bnx2x_pxp_prep(bp); - /* Open the gates #2, #3 and #4 */ bnx2x_set_234_gates(bp, false); @@ -8849,7 +9047,7 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global) return 0; } -int bnx2x_leader_reset(struct bnx2x *bp) +static int bnx2x_leader_reset(struct bnx2x *bp) { int rc = 0; bool global = bnx2x_reset_is_global(bp); @@ -9233,12 +9431,19 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp) bnx2x_undi_int_disable_e1h(bp); } -static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp) +static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, + struct bnx2x_mac_vals *vals) { u32 val, base_addr, offset, mask, reset_reg; bool mac_stopped = false; u8 port = BP_PORT(bp); + /* reset addresses as they also mark which values were changed */ + vals->bmac_addr = 0; + vals->umac_addr = 0; + vals->xmac_addr = 0; + vals->emac_addr = 0; + reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); if (!CHIP_IS_E3(bp)) { @@ -9260,14 +9465,18 @@ static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp) */ wb_data[0] = REG_RD(bp, base_addr + offset); wb_data[1] = REG_RD(bp, base_addr + offset + 0x4); + vals->bmac_addr = base_addr + offset; + vals->bmac_val[0] = wb_data[0]; + vals->bmac_val[1] = wb_data[1]; wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; - REG_WR(bp, base_addr + offset, wb_data[0]); - REG_WR(bp, base_addr + offset + 0x4, wb_data[1]); + REG_WR(bp, vals->bmac_addr, wb_data[0]); + REG_WR(bp, vals->bmac_addr + 0x4, wb_data[1]); } BNX2X_DEV_INFO("Disable emac Rx\n"); - REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0); - + vals->emac_addr = NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4; + vals->emac_val = REG_RD(bp, vals->emac_addr); + REG_WR(bp, vals->emac_addr, 0); mac_stopped = true; } else { if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { @@ -9278,14 +9487,18 @@ static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp) val & ~(1 << 1)); REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI, val | (1 << 1)); - REG_WR(bp, base_addr + XMAC_REG_CTRL, 0); + vals->xmac_addr = base_addr + XMAC_REG_CTRL; + vals->xmac_val = REG_RD(bp, vals->xmac_addr); + REG_WR(bp, vals->xmac_addr, 0); mac_stopped = true; } mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; if (mask & reset_reg) { BNX2X_DEV_INFO("Disable umac Rx\n"); base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; - REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0); + vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG; + vals->umac_val = REG_RD(bp, vals->umac_addr); + REG_WR(bp, vals->umac_addr, 0); mac_stopped = true; } } @@ -9300,8 +9513,7 @@ static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp) #define BNX2X_PREV_UNDI_BD(val) ((val) >> 16 & 0xffff) #define BNX2X_PREV_UNDI_PROD(rcq, bd) ((bd) << 16 | (rcq)) -static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, - u8 inc) +static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, u8 inc) { u16 rcq, bd; u32 tmp_reg = REG_RD(bp, BNX2X_PREV_UNDI_PROD_ADDR(port)); @@ -9316,7 +9528,7 @@ static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, port, bd, rcq); } -static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp) +static int bnx2x_prev_mcp_done(struct bnx2x *bp) { u32 rc = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET); @@ -9328,7 +9540,21 @@ static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp) return 0; } -static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp) +static struct bnx2x_prev_path_list * + bnx2x_prev_path_get_entry(struct bnx2x *bp) +{ + struct bnx2x_prev_path_list *tmp_list; + + list_for_each_entry(tmp_list, &bnx2x_prev_list, list) + if (PCI_SLOT(bp->pdev->devfn) == tmp_list->slot && + bp->pdev->bus->number == tmp_list->bus && + BP_PATH(bp) == tmp_list->path) + return tmp_list; + + return NULL; +} + +static bool bnx2x_prev_is_path_marked(struct bnx2x *bp) { struct bnx2x_prev_path_list *tmp_list; int rc = false; @@ -9352,7 +9578,7 @@ static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp) return rc; } -static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp) +static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi) { struct bnx2x_prev_path_list *tmp_list; int rc; @@ -9366,6 +9592,7 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp) tmp_list->bus = bp->pdev->bus->number; tmp_list->slot = PCI_SLOT(bp->pdev->devfn); tmp_list->path = BP_PATH(bp); + tmp_list->undi = after_undi ? (1 << BP_PORT(bp)) : 0; rc = down_interruptible(&bnx2x_prev_sem); if (rc) { @@ -9381,7 +9608,7 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp) return rc; } -static int __devinit bnx2x_do_flr(struct bnx2x *bp) +static int bnx2x_do_flr(struct bnx2x *bp) { int i; u16 status; @@ -9421,7 +9648,7 @@ clear: return 0; } -static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp) +static int bnx2x_prev_unload_uncommon(struct bnx2x *bp) { int rc; @@ -9459,15 +9686,20 @@ static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp) return rc; } -static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp) +static int bnx2x_prev_unload_common(struct bnx2x *bp) { u32 reset_reg, tmp_reg = 0, rc; + bool prev_undi = false; + struct bnx2x_mac_vals mac_vals; + /* It is possible a previous function received 'common' answer, * but hasn't loaded yet, therefore creating a scenario of * multiple functions receiving 'common' on the same path. */ BNX2X_DEV_INFO("Common unload Flow\n"); + memset(&mac_vals, 0, sizeof(mac_vals)); + if (bnx2x_prev_is_path_marked(bp)) return bnx2x_prev_mcp_done(bp); @@ -9476,10 +9708,12 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp) /* Reset should be performed after BRB is emptied */ if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) { u32 timer_count = 1000; - bool prev_undi = false; /* Close the MAC Rx to prevent BRB from filling up */ - bnx2x_prev_unload_close_mac(bp); + bnx2x_prev_unload_close_mac(bp, &mac_vals); + + /* close LLH filters towards the BRB */ + bnx2x_set_rx_filter(&bp->link_params, 0); /* Check if the UNDI driver was previously loaded * UNDI driver initializes CID offset for normal bell to 0x7 @@ -9526,7 +9760,18 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp) /* No packets are in the pipeline, path is ready for reset */ bnx2x_reset_common(bp); - rc = bnx2x_prev_mark_path(bp); + if (mac_vals.xmac_addr) + REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val); + if (mac_vals.umac_addr) + REG_WR(bp, mac_vals.umac_addr, mac_vals.umac_val); + if (mac_vals.emac_addr) + REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val); + if (mac_vals.bmac_addr) { + REG_WR(bp, mac_vals.bmac_addr, mac_vals.bmac_val[0]); + REG_WR(bp, mac_vals.bmac_addr + 4, mac_vals.bmac_val[1]); + } + + rc = bnx2x_prev_mark_path(bp, prev_undi); if (rc) { bnx2x_prev_mcp_done(bp); return rc; @@ -9542,19 +9787,23 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp) * to clear the interrupt which detected this from the pglueb and the was done * bit */ -static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp) +static void bnx2x_prev_interrupted_dmae(struct bnx2x *bp) { - u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); - if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { - BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); - REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp)); + if (!CHIP_IS_E1x(bp)) { + u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); + if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { + BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); + REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, + 1 << BP_FUNC(bp)); + } } } -static int __devinit bnx2x_prev_unload(struct bnx2x *bp) +static int bnx2x_prev_unload(struct bnx2x *bp) { int time_counter = 10; u32 rc, fw, hw_lock_reg, hw_lock_val; + struct bnx2x_prev_path_list *prev_list; BNX2X_DEV_INFO("Entering Previous Unload Flow\n"); /* clear hw from errors which may have resulted from an interrupted @@ -9613,12 +9862,18 @@ static int __devinit bnx2x_prev_unload(struct bnx2x *bp) rc = -EBUSY; } + /* Mark function if its port was used to boot from SAN */ + prev_list = bnx2x_prev_path_get_entry(bp); + if (prev_list && (prev_list->undi & (1 << BP_PORT(bp)))) + bp->link_params.feature_config_flags |= + FEATURE_CONFIG_BOOT_FROM_SAN; + BNX2X_DEV_INFO("Finished Previous Unload Flow [%d]\n", rc); return rc; } -static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) +static void bnx2x_get_common_hwinfo(struct bnx2x *bp) { u32 val, val2, val3, val4, id, boot_mode; u16 pmc; @@ -9697,6 +9952,14 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) bp->link_params.shmem_base = bp->common.shmem_base; bp->link_params.shmem2_base = bp->common.shmem2_base; + if (SHMEM2_RD(bp, size) > + (u32)offsetof(struct shmem2_region, lfa_host_addr[BP_PORT(bp)])) + bp->link_params.lfa_base = + REG_RD(bp, bp->common.shmem2_base + + (u32)offsetof(struct shmem2_region, + lfa_host_addr[BP_PORT(bp)])); + else + bp->link_params.lfa_base = 0; BNX2X_DEV_INFO("shmem offset 0x%x shmem2 offset 0x%x\n", bp->common.shmem_base, bp->common.shmem2_base); @@ -9744,6 +10007,11 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) bp->link_params.feature_config_flags |= (val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ? FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0; + + bp->link_params.feature_config_flags |= + (val >= REQ_BC_VER_4_MT_SUPPORTED) ? + FEATURE_CONFIG_MT_SUPPORT : 0; + bp->flags |= (val >= REQ_BC_VER_4_PFC_STATS_SUPPORTED) ? BC_SUPPORTS_PFC_STATS : 0; @@ -9788,7 +10056,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) #define IGU_FID(val) GET_FIELD((val), IGU_REG_MAPPING_MEMORY_FID) #define IGU_VEC(val) GET_FIELD((val), IGU_REG_MAPPING_MEMORY_VECTOR) -static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp) +static int bnx2x_get_igu_cam_info(struct bnx2x *bp) { int pfid = BP_FUNC(bp); int igu_sb_id; @@ -9805,7 +10073,7 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp) bp->igu_dsb_id = E1HVN_MAX * FP_SB_MAX_E1x + (CHIP_MODE_IS_4_PORT(bp) ? pfid : vn); - return; + return 0; } /* IGU in normal mode - read CAM */ @@ -9839,12 +10107,15 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp) bp->igu_sb_cnt = min_t(int, bp->igu_sb_cnt, igu_sb_cnt); #endif - if (igu_sb_cnt == 0) + if (igu_sb_cnt == 0) { BNX2X_ERR("CAM configuration error\n"); + return -EINVAL; + } + + return 0; } -static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp, - u32 switch_cfg) +static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) { int cfg_size = 0, idx, port = BP_PORT(bp); @@ -9942,7 +10213,7 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp, bp->port.supported[1]); } -static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp) +static void bnx2x_link_settings_requested(struct bnx2x *bp) { u32 link_config, idx, cfg_size = 0; bp->port.advertising[0] = 0; @@ -10111,11 +10382,13 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp) bp->link_params.req_flow_ctrl[idx] = (link_config & PORT_FEATURE_FLOW_CONTROL_MASK); - if ((bp->link_params.req_flow_ctrl[idx] == - BNX2X_FLOW_CTRL_AUTO) && - !(bp->port.supported[idx] & SUPPORTED_Autoneg)) { - bp->link_params.req_flow_ctrl[idx] = - BNX2X_FLOW_CTRL_NONE; + if (bp->link_params.req_flow_ctrl[idx] == + BNX2X_FLOW_CTRL_AUTO) { + if (!(bp->port.supported[idx] & SUPPORTED_Autoneg)) + bp->link_params.req_flow_ctrl[idx] = + BNX2X_FLOW_CTRL_NONE; + else + bnx2x_set_requested_fc(bp); } BNX2X_DEV_INFO("req_line_speed %d req_duplex %d req_flow_ctrl 0x%x advertising 0x%x\n", @@ -10126,7 +10399,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp) } } -static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi) +static void bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi) { mac_hi = cpu_to_be16(mac_hi); mac_lo = cpu_to_be32(mac_lo); @@ -10134,7 +10407,7 @@ static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi) memcpy(mac_buf + sizeof(mac_hi), &mac_lo, sizeof(mac_lo)); } -static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) +static void bnx2x_get_port_hwinfo(struct bnx2x *bp) { int port = BP_PORT(bp); u32 config; @@ -10195,17 +10468,6 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) bp->mdio.prtad = XGXS_EXT_PHY_ADDR(ext_phy_config); - /* - * Check if hw lock is required to access MDC/MDIO bus to the PHY(s) - * In MF mode, it is set to cover self test cases - */ - if (IS_MF(bp)) - bp->port.need_hw_lock = 1; - else - bp->port.need_hw_lock = bnx2x_hw_lock_required(bp, - bp->common.shmem_base, - bp->common.shmem2_base); - /* Configure link feature according to nvram value */ eee_mode = (((SHMEM_RD(bp, dev_info. port_feature_config[port].eee_power_mode)) & @@ -10223,12 +10485,15 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) void bnx2x_get_iscsi_info(struct bnx2x *bp) { u32 no_flags = NO_ISCSI_FLAG; -#ifdef BCM_CNIC int port = BP_PORT(bp); - u32 max_iscsi_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp, drv_lic_key[port].max_iscsi_conn); + if (!CNIC_SUPPORT(bp)) { + bp->flags |= no_flags; + return; + } + /* Get the number of maximum allowed iSCSI connections */ bp->cnic_eth_dev.max_iscsi_conn = (max_iscsi_conn & BNX2X_MAX_ISCSI_INIT_CONN_MASK) >> @@ -10243,13 +10508,10 @@ void bnx2x_get_iscsi_info(struct bnx2x *bp) */ if (!bp->cnic_eth_dev.max_iscsi_conn) bp->flags |= no_flags; -#else - bp->flags |= no_flags; -#endif + } -#ifdef BCM_CNIC -static void __devinit bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func) +static void bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func) { /* Port info */ bp->cnic_eth_dev.fcoe_wwn_port_name_hi = @@ -10263,16 +10525,18 @@ static void __devinit bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func) bp->cnic_eth_dev.fcoe_wwn_node_name_lo = MF_CFG_RD(bp, func_ext_config[func].fcoe_wwn_node_name_lower); } -#endif -static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp) +static void bnx2x_get_fcoe_info(struct bnx2x *bp) { -#ifdef BCM_CNIC int port = BP_PORT(bp); int func = BP_ABS_FUNC(bp); - u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp, drv_lic_key[port].max_fcoe_conn); + if (!CNIC_SUPPORT(bp)) { + bp->flags |= NO_FCOE_FLAG; + return; + } + /* Get the number of maximum allowed FCoE connections */ bp->cnic_eth_dev.max_fcoe_conn = (max_fcoe_conn & BNX2X_MAX_FCOE_INIT_CONN_MASK) >> @@ -10307,8 +10571,9 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp) if (BNX2X_MF_EXT_PROTOCOL_FCOE(bp) && !CHIP_IS_E1x(bp)) bnx2x_get_ext_wwn_info(bp, func); - } else if (IS_MF_FCOE_SD(bp)) + } else if (IS_MF_FCOE_SD(bp) && !CHIP_IS_E1x(bp)) { bnx2x_get_ext_wwn_info(bp, func); + } BNX2X_DEV_INFO("max_fcoe_conn 0x%x\n", bp->cnic_eth_dev.max_fcoe_conn); @@ -10318,12 +10583,9 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp) */ if (!bp->cnic_eth_dev.max_fcoe_conn) bp->flags |= NO_FCOE_FLAG; -#else - bp->flags |= NO_FCOE_FLAG; -#endif } -static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp) +static void bnx2x_get_cnic_info(struct bnx2x *bp) { /* * iSCSI may be dynamically disabled but reading @@ -10334,143 +10596,162 @@ static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp) bnx2x_get_fcoe_info(bp); } -static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) +static void bnx2x_get_cnic_mac_hwinfo(struct bnx2x *bp) { u32 val, val2; int func = BP_ABS_FUNC(bp); int port = BP_PORT(bp); -#ifdef BCM_CNIC u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac; u8 *fip_mac = bp->fip_mac; -#endif - /* Zero primary MAC configuration */ - memset(bp->dev->dev_addr, 0, ETH_ALEN); - - if (BP_NOMCP(bp)) { - BNX2X_ERROR("warning: random MAC workaround active\n"); - eth_hw_addr_random(bp->dev); - } else if (IS_MF(bp)) { - val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper); - val = MF_CFG_RD(bp, func_mf_config[func].mac_lower); - if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) && - (val != FUNC_MF_CFG_LOWERMAC_DEFAULT)) - bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2); - -#ifdef BCM_CNIC - /* - * iSCSI and FCoE NPAR MACs: if there is no either iSCSI or + if (IS_MF(bp)) { + /* iSCSI and FCoE NPAR MACs: if there is no either iSCSI or * FCoE MAC then the appropriate feature should be disabled. - * - * In non SD mode features configuration comes from - * struct func_ext_config. + * In non SD mode features configuration comes from struct + * func_ext_config. */ - if (!IS_MF_SD(bp)) { + if (!IS_MF_SD(bp) && !CHIP_IS_E1x(bp)) { u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg); if (cfg & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD) { val2 = MF_CFG_RD(bp, func_ext_config[func]. - iscsi_mac_addr_upper); + iscsi_mac_addr_upper); val = MF_CFG_RD(bp, func_ext_config[func]. - iscsi_mac_addr_lower); + iscsi_mac_addr_lower); bnx2x_set_mac_buf(iscsi_mac, val, val2); - BNX2X_DEV_INFO("Read iSCSI MAC: %pM\n", - iscsi_mac); - } else + BNX2X_DEV_INFO + ("Read iSCSI MAC: %pM\n", iscsi_mac); + } else { bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG; + } if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) { val2 = MF_CFG_RD(bp, func_ext_config[func]. - fcoe_mac_addr_upper); + fcoe_mac_addr_upper); val = MF_CFG_RD(bp, func_ext_config[func]. - fcoe_mac_addr_lower); + fcoe_mac_addr_lower); bnx2x_set_mac_buf(fip_mac, val, val2); - BNX2X_DEV_INFO("Read FCoE L2 MAC: %pM\n", - fip_mac); - - } else + BNX2X_DEV_INFO + ("Read FCoE L2 MAC: %pM\n", fip_mac); + } else { bp->flags |= NO_FCOE_FLAG; + } bp->mf_ext_config = cfg; } else { /* SD MODE */ - if (IS_MF_STORAGE_SD(bp)) { - if (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp)) { - /* use primary mac as iscsi mac */ - memcpy(iscsi_mac, bp->dev->dev_addr, - ETH_ALEN); - - BNX2X_DEV_INFO("SD ISCSI MODE\n"); - BNX2X_DEV_INFO("Read iSCSI MAC: %pM\n", - iscsi_mac); - } else { /* FCoE */ - memcpy(fip_mac, bp->dev->dev_addr, - ETH_ALEN); - BNX2X_DEV_INFO("SD FCoE MODE\n"); - BNX2X_DEV_INFO("Read FIP MAC: %pM\n", - fip_mac); - } - /* Zero primary MAC configuration */ - memset(bp->dev->dev_addr, 0, ETH_ALEN); + if (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp)) { + /* use primary mac as iscsi mac */ + memcpy(iscsi_mac, bp->dev->dev_addr, ETH_ALEN); + + BNX2X_DEV_INFO("SD ISCSI MODE\n"); + BNX2X_DEV_INFO + ("Read iSCSI MAC: %pM\n", iscsi_mac); + } else if (BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp)) { + /* use primary mac as fip mac */ + memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN); + BNX2X_DEV_INFO("SD FCoE MODE\n"); + BNX2X_DEV_INFO + ("Read FIP MAC: %pM\n", fip_mac); } } + if (IS_MF_STORAGE_SD(bp)) + /* Zero primary MAC configuration */ + memset(bp->dev->dev_addr, 0, ETH_ALEN); + if (IS_MF_FCOE_AFEX(bp)) /* use FIP MAC as primary MAC */ memcpy(bp->dev->dev_addr, fip_mac, ETH_ALEN); -#endif } else { - /* in SF read MACs from port configuration */ - val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper); - val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower); - bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2); - -#ifdef BCM_CNIC val2 = SHMEM_RD(bp, dev_info.port_hw_config[port]. - iscsi_mac_upper); + iscsi_mac_upper); val = SHMEM_RD(bp, dev_info.port_hw_config[port]. - iscsi_mac_lower); + iscsi_mac_lower); bnx2x_set_mac_buf(iscsi_mac, val, val2); val2 = SHMEM_RD(bp, dev_info.port_hw_config[port]. - fcoe_fip_mac_upper); + fcoe_fip_mac_upper); val = SHMEM_RD(bp, dev_info.port_hw_config[port]. - fcoe_fip_mac_lower); + fcoe_fip_mac_lower); bnx2x_set_mac_buf(fip_mac, val, val2); -#endif } - memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN); - memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN); - -#ifdef BCM_CNIC - /* Disable iSCSI if MAC configuration is - * invalid. - */ + /* Disable iSCSI OOO if MAC configuration is invalid. */ if (!is_valid_ether_addr(iscsi_mac)) { - bp->flags |= NO_ISCSI_FLAG; + bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG; memset(iscsi_mac, 0, ETH_ALEN); } - /* Disable FCoE if MAC configuration is - * invalid. - */ + /* Disable FCoE if MAC configuration is invalid. */ if (!is_valid_ether_addr(fip_mac)) { bp->flags |= NO_FCOE_FLAG; memset(bp->fip_mac, 0, ETH_ALEN); } -#endif +} + +static void bnx2x_get_mac_hwinfo(struct bnx2x *bp) +{ + u32 val, val2; + int func = BP_ABS_FUNC(bp); + int port = BP_PORT(bp); + + /* Zero primary MAC configuration */ + memset(bp->dev->dev_addr, 0, ETH_ALEN); + + if (BP_NOMCP(bp)) { + BNX2X_ERROR("warning: random MAC workaround active\n"); + eth_hw_addr_random(bp->dev); + } else if (IS_MF(bp)) { + val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper); + val = MF_CFG_RD(bp, func_mf_config[func].mac_lower); + if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) && + (val != FUNC_MF_CFG_LOWERMAC_DEFAULT)) + bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2); + + if (CNIC_SUPPORT(bp)) + bnx2x_get_cnic_mac_hwinfo(bp); + } else { + /* in SF read MACs from port configuration */ + val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper); + val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower); + bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2); + + if (CNIC_SUPPORT(bp)) + bnx2x_get_cnic_mac_hwinfo(bp); + } + + memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN); + memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN); if (!bnx2x_is_valid_ether_addr(bp, bp->dev->dev_addr)) dev_err(&bp->pdev->dev, "bad Ethernet MAC address configuration: %pM\n" "change it manually before bringing up the appropriate network interface\n", bp->dev->dev_addr); +} +static bool bnx2x_get_dropless_info(struct bnx2x *bp) +{ + int tmp; + u32 cfg; + if (IS_MF(bp) && !CHIP_IS_E1x(bp)) { + /* Take function: tmp = func */ + tmp = BP_ABS_FUNC(bp); + cfg = MF_CFG_RD(bp, func_ext_config[tmp].func_cfg); + cfg = !!(cfg & MACP_FUNC_CFG_PAUSE_ON_HOST_RING); + } else { + /* Take port: tmp = port */ + tmp = BP_PORT(bp); + cfg = SHMEM_RD(bp, + dev_info.port_hw_config[tmp].generic_features); + cfg = !!(cfg & PORT_HW_CFG_PAUSE_ON_HOST_RING_ENABLED); + } + return cfg; } -static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) +static int bnx2x_get_hwinfo(struct bnx2x *bp) { int /*abs*/func = BP_ABS_FUNC(bp); int vn; @@ -10512,6 +10793,8 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) if (REG_RD(bp, IGU_REG_RESET_MEMORIES)) { dev_err(&bp->pdev->dev, "FORCING Normal Mode failed!!!\n"); + bnx2x_release_hw_lock(bp, + HW_LOCK_RESOURCE_RESET); return -EPERM; } } @@ -10522,9 +10805,10 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) } else BNX2X_DEV_INFO("IGU Normal Mode\n"); - bnx2x_get_igu_cam_info(bp); - + rc = bnx2x_get_igu_cam_info(bp); bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET); + if (rc) + return rc; } /* @@ -10693,7 +10977,7 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) return rc; } -static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp) +static void bnx2x_read_fwinfo(struct bnx2x *bp) { int cnt, i, block_end, rodi; char vpd_start[BNX2X_VPD_LEN+1]; @@ -10778,7 +11062,7 @@ out_not_found: return; } -static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp) +static void bnx2x_set_modes_bitmap(struct bnx2x *bp) { u32 flags = 0; @@ -10828,7 +11112,7 @@ static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp) INIT_MODE_FLAGS(bp) = flags; } -static int __devinit bnx2x_init_bp(struct bnx2x *bp) +static int bnx2x_init_bp(struct bnx2x *bp) { int func; int rc; @@ -10836,9 +11120,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) mutex_init(&bp->port.phy_mutex); mutex_init(&bp->fw_mb_mutex); spin_lock_init(&bp->stats_lock); -#ifdef BCM_CNIC - mutex_init(&bp->cnic_mutex); -#endif + INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task); @@ -10876,10 +11158,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) dev_err(&bp->pdev->dev, "MCP disabled, must load devices in order!\n"); bp->disable_tpa = disable_tpa; - -#ifdef BCM_CNIC bp->disable_tpa |= IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp); -#endif /* Set TPA flags */ if (bp->disable_tpa) { @@ -10893,7 +11172,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) if (CHIP_IS_E1(bp)) bp->dropless_fc = 0; else - bp->dropless_fc = dropless_fc; + bp->dropless_fc = dropless_fc | bnx2x_get_dropless_info(bp); bp->mrrs = mrrs; @@ -10910,15 +11189,20 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) bp->timer.data = (unsigned long) bp; bp->timer.function = bnx2x_timer; - bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON); - bnx2x_dcbx_init_params(bp); + if (SHMEM2_HAS(bp, dcbx_lldp_params_offset) && + SHMEM2_HAS(bp, dcbx_lldp_dcbx_stat_offset) && + SHMEM2_RD(bp, dcbx_lldp_params_offset) && + SHMEM2_RD(bp, dcbx_lldp_dcbx_stat_offset)) { + bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON); + bnx2x_dcbx_init_params(bp); + } else { + bnx2x_dcbx_set_state(bp, false, BNX2X_DCBX_ENABLED_OFF); + } -#ifdef BCM_CNIC if (CHIP_IS_E1x(bp)) bp->cnic_base_cl_id = FP_SB_MAX_E1x; else bp->cnic_base_cl_id = FP_SB_MAX_E2; -#endif /* multiple tx priority */ if (CHIP_IS_E1x(bp)) @@ -10928,6 +11212,16 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) if (CHIP_IS_E3B0(bp)) bp->max_cos = BNX2X_MULTI_TX_COS_E3B0; + /* We need at least one default status block for slow-path events, + * second status block for the L2 queue, and a third status block for + * CNIC if supproted. + */ + if (CNIC_SUPPORT(bp)) + bp->min_msix_vec_cnt = 3; + else + bp->min_msix_vec_cnt = 2; + BNX2X_DEV_INFO("bp->min_msix_vec_cnt %d", bp->min_msix_vec_cnt); + return rc; } @@ -11164,11 +11458,9 @@ void bnx2x_set_rx_mode(struct net_device *dev) } bp->rx_mode = rx_mode; -#ifdef BCM_CNIC /* handle ISCSI SD mode */ if (IS_MF_ISCSI_SD(bp)) bp->rx_mode = BNX2X_RX_MODE_NONE; -#endif /* Schedule the rx_mode command */ if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) { @@ -11280,7 +11572,7 @@ static const struct net_device_ops bnx2x_netdev_ops = { #endif .ndo_setup_tc = bnx2x_setup_tc, -#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC) +#ifdef NETDEV_FCOE_WWNN .ndo_fcoe_get_wwn = bnx2x_fcoe_get_wwn, #endif }; @@ -11303,9 +11595,8 @@ static int bnx2x_set_coherency_mask(struct bnx2x *bp) return 0; } -static int __devinit bnx2x_init_dev(struct pci_dev *pdev, - struct net_device *dev, - unsigned long board_type) +static int bnx2x_init_dev(struct pci_dev *pdev, struct net_device *dev, + unsigned long board_type) { struct bnx2x *bp; int rc; @@ -11342,6 +11633,14 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, goto err_out_disable; } + pci_read_config_dword(pdev, PCICFG_REVISION_ID_OFFSET, &pci_cfg_dword); + if ((pci_cfg_dword & PCICFG_REVESION_ID_MASK) == + PCICFG_REVESION_ID_ERROR_VAL) { + pr_err("PCI device error, probably due to fan failure, aborting\n"); + rc = -ENODEV; + goto err_out_disable; + } + if (atomic_read(&pdev->enable_cnt) == 1) { rc = pci_request_regions(pdev, DRV_MODULE_NAME); if (rc) { @@ -11477,8 +11776,7 @@ err_out: return rc; } -static void __devinit bnx2x_get_pcie_width_speed(struct bnx2x *bp, - int *width, int *speed) +static void bnx2x_get_pcie_width_speed(struct bnx2x *bp, int *width, int *speed) { u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL); @@ -11746,9 +12044,8 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp) { int cid_count = BNX2X_L2_MAX_CID(bp); -#ifdef BCM_CNIC - cid_count += CNIC_CID_MAX; -#endif + if (CNIC_SUPPORT(bp)) + cid_count += CNIC_CID_MAX; return roundup(cid_count, QM_CID_ROUND); } @@ -11758,7 +12055,8 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp) * @dev: pci device * */ -static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev) +static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev, + int cnic_cnt) { int pos; u16 control; @@ -11770,7 +12068,7 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev) * one fast path queue: one FP queue + SB for CNIC */ if (!pos) - return 1 + CNIC_PRESENT; + return 1 + cnic_cnt; /* * The value in the PCI configuration space is the index of the last @@ -11782,14 +12080,16 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev) return control & PCI_MSIX_FLAGS_QSIZE; } -static int __devinit bnx2x_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *); + +static int bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev = NULL; struct bnx2x *bp; int pcie_width, pcie_speed; int rc, max_non_def_sbs; int rx_count, tx_count, rss_count, doorbell_size; + int cnic_cnt; /* * An estimated maximum supported CoS number according to the chip * version. @@ -11833,21 +12133,22 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, return -ENODEV; } - max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev); + cnic_cnt = 1; + max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt); WARN_ON(!max_non_def_sbs); /* Maximum number of RSS queues: one IGU SB goes to CNIC */ - rss_count = max_non_def_sbs - CNIC_PRESENT; + rss_count = max_non_def_sbs - cnic_cnt; /* Maximum number of netdev Rx queues: RSS + FCoE L2 */ - rx_count = rss_count + FCOE_PRESENT; + rx_count = rss_count + cnic_cnt; /* * Maximum number of netdev Tx queues: * Maximum TSS queues * Maximum supported number of CoS + FCoE L2 */ - tx_count = rss_count * max_cos_est + FCOE_PRESENT; + tx_count = rss_count * max_cos_est + cnic_cnt; /* dev zeroed in init_etherdev */ dev = alloc_etherdev_mqs(sizeof(*bp), tx_count, rx_count); @@ -11858,6 +12159,9 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, bp->igu_sb_cnt = max_non_def_sbs; bp->msg_enable = debug; + bp->cnic_support = cnic_cnt; + bp->cnic_probe = bnx2x_cnic_probe; + pci_set_drvdata(pdev, dev); rc = bnx2x_init_dev(pdev, dev, ent->driver_data); @@ -11866,6 +12170,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, return rc; } + BNX2X_DEV_INFO("Cnic support is %s\n", CNIC_SUPPORT(bp) ? "on" : "off"); BNX2X_DEV_INFO("max_non_def_sbs %d\n", max_non_def_sbs); BNX2X_DEV_INFO("Allocated netdev with %d tx and %d rx queues\n", @@ -11898,13 +12203,19 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, /* calc qm_cid_count */ bp->qm_cid_count = bnx2x_set_qm_cid_count(bp); -#ifdef BCM_CNIC - /* disable FCOE L2 queue for E1x */ + /* disable FCOE L2 queue for E1x*/ if (CHIP_IS_E1x(bp)) bp->flags |= NO_FCOE_FLAG; -#endif - + /* disable FCOE for 57840 device, until FW supports it */ + switch (ent->driver_data) { + case BCM57840_O: + case BCM57840_4_10: + case BCM57840_2_20: + case BCM57840_MFO: + case BCM57840_MF: + bp->flags |= NO_FCOE_FLAG; + } /* Set bp->num_queues for MSI-X mode*/ bnx2x_set_num_queues(bp); @@ -11920,14 +12231,13 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, goto init_one_exit; } -#ifdef BCM_CNIC + if (!NO_FCOE(bp)) { /* Add storage MAC address */ rtnl_lock(); dev_addr_add(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN); rtnl_unlock(); } -#endif bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed); @@ -11961,7 +12271,7 @@ init_one_exit: return rc; } -static void __devexit bnx2x_remove_one(struct pci_dev *pdev) +static void bnx2x_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct bnx2x *bp; @@ -11972,14 +12282,12 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) } bp = netdev_priv(dev); -#ifdef BCM_CNIC /* Delete storage MAC address */ if (!NO_FCOE(bp)) { rtnl_lock(); dev_addr_del(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN); rtnl_unlock(); } -#endif #ifdef BCM_DCBNL /* Delete app tlvs from dcbnl */ @@ -12027,15 +12335,17 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) bp->rx_mode = BNX2X_RX_MODE_NONE; -#ifdef BCM_CNIC - bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD); -#endif + if (CNIC_LOADED(bp)) + bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD); + /* Stop Tx */ bnx2x_tx_disable(bp); bnx2x_netif_stop(bp, 0); /* Delete all NAPI objects */ bnx2x_del_all_napi(bp); + if (CNIC_LOADED(bp)) + bnx2x_del_all_napi_cnic(bp); del_timer_sync(&bp->timer); @@ -12176,7 +12486,7 @@ static struct pci_driver bnx2x_pci_driver = { .name = DRV_MODULE_NAME, .id_table = bnx2x_pci_tbl, .probe = bnx2x_init_one, - .remove = __devexit_p(bnx2x_remove_one), + .remove = bnx2x_remove_one, .suspend = bnx2x_suspend, .resume = bnx2x_resume, .err_handler = &bnx2x_err_handler, @@ -12226,7 +12536,6 @@ void bnx2x_notify_link_changed(struct bnx2x *bp) module_init(bnx2x_init); module_exit(bnx2x_cleanup); -#ifdef BCM_CNIC /** * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s). * @@ -12679,12 +12988,31 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops, { struct bnx2x *bp = netdev_priv(dev); struct cnic_eth_dev *cp = &bp->cnic_eth_dev; + int rc; + + DP(NETIF_MSG_IFUP, "Register_cnic called\n"); if (ops == NULL) { BNX2X_ERR("NULL ops received\n"); return -EINVAL; } + if (!CNIC_SUPPORT(bp)) { + BNX2X_ERR("Can't register CNIC when not supported\n"); + return -EOPNOTSUPP; + } + + if (!CNIC_LOADED(bp)) { + rc = bnx2x_load_cnic(bp); + if (rc) { + BNX2X_ERR("CNIC-related load failed\n"); + return rc; + } + + } + + bp->cnic_enabled = true; + bp->cnic_kwq = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!bp->cnic_kwq) return -ENOMEM; @@ -12774,7 +13102,5 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev) cp->starting_cid); return cp; } -EXPORT_SYMBOL(bnx2x_cnic_probe); -#endif /* BCM_CNIC */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index 1b1999d34c71..bc2f65b32649 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h @@ -2107,6 +2107,7 @@ #define NIG_REG_LLH1_ERROR_MASK 0x10090 /* [RW 8] event id for llh1 */ #define NIG_REG_LLH1_EVENT_ID 0x10088 +#define NIG_REG_LLH1_FUNC_EN 0x16104 #define NIG_REG_LLH1_FUNC_MEM 0x161c0 #define NIG_REG_LLH1_FUNC_MEM_ENABLE 0x16160 #define NIG_REG_LLH1_FUNC_MEM_SIZE 16 @@ -2302,6 +2303,15 @@ * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to * accommodate the 9 input clients to ETS arbiter. */ #define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB 0x18684 +/* [RW 1] MCP-to-host path enable. Set this bit to enable the routing of MCP + * packets to BRB LB interface to forward the packet to the host. All + * packets from MCP are forwarded to the network when this bit is cleared - + * regardless of the configured destination in tx_mng_destination register. + * When MCP-to-host paths for both ports 0 and 1 are disabled - the arbiter + * for BRB LB interface is bypassed and PBF LB traffic is always selected to + * send to BRB LB. + */ +#define NIG_REG_P0_TX_MNG_HOST_ENABLE 0x182f4 #define NIG_REG_P1_HWPFC_ENABLE 0x181d0 #define NIG_REG_P1_MAC_IN_EN 0x185c0 /* [RW 1] Output enable for TX MAC interface */ @@ -2418,6 +2428,12 @@ #define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB 0x186e4 /* [R 1] TX FIFO for transmitting data to MAC is empty. */ #define NIG_REG_P1_TX_MACFIFO_EMPTY 0x18594 +/* [RW 1] MCP-to-host path enable. Set this bit to enable the routing of MCP + * packets to BRB LB interface to forward the packet to the host. All + * packets from MCP are forwarded to the network when this bit is cleared - + * regardless of the configured destination in tx_mng_destination register. + */ +#define NIG_REG_P1_TX_MNG_HOST_ENABLE 0x182f8 /* [R 1] FIFO empty status of the MCP TX FIFO used for storing MCP packets forwarded to the host. */ #define NIG_REG_P1_TX_MNG_HOST_FIFO_EMPTY 0x182b8 @@ -5482,6 +5498,7 @@ #define XMAC_CTRL_REG_RX_EN (0x1<<1) #define XMAC_CTRL_REG_SOFT_RESET (0x1<<6) #define XMAC_CTRL_REG_TX_EN (0x1<<0) +#define XMAC_CTRL_REG_XLGMII_ALIGN_ENB (0x1<<7) #define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN (0x1<<18) #define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN (0x1<<17) #define XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON (0x1<<1) @@ -5502,11 +5519,14 @@ #define XMAC_REG_PAUSE_CTRL 0x68 #define XMAC_REG_PFC_CTRL 0x70 #define XMAC_REG_PFC_CTRL_HI 0x74 +#define XMAC_REG_RX_LSS_CTRL 0x50 #define XMAC_REG_RX_LSS_STATUS 0x58 /* [RW 14] Maximum packet size in receive direction; exclusive of preamble & * CRC in strip mode */ #define XMAC_REG_RX_MAX_SIZE 0x40 #define XMAC_REG_TX_CTRL 0x20 +#define XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE (0x1<<0) +#define XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE (0x1<<1) /* [RW 16] Indirect access to the XX table of the XX protection mechanism. The fields are:[4:0] - tail pointer; 9:5] - Link List size; 14:10] - header pointer. */ @@ -5922,6 +5942,16 @@ #define MISC_REGISTERS_SPIO_OUTPUT_HIGH 1 #define MISC_REGISTERS_SPIO_OUTPUT_LOW 0 #define MISC_REGISTERS_SPIO_SET_POS 8 +#define MISC_SPIO_CLR_POS 16 +#define MISC_SPIO_FLOAT (0xffL<<24) +#define MISC_SPIO_FLOAT_POS 24 +#define MISC_SPIO_INPUT_HI_Z 2 +#define MISC_SPIO_INT_OLD_SET_POS 16 +#define MISC_SPIO_OUTPUT_HIGH 1 +#define MISC_SPIO_OUTPUT_LOW 0 +#define MISC_SPIO_SET_POS 8 +#define MISC_SPIO_SPIO4 0x10 +#define MISC_SPIO_SPIO5 0x20 #define HW_LOCK_MAX_RESOURCE_VALUE 31 #define HW_LOCK_RESOURCE_DCBX_ADMIN_MIB 13 #define HW_LOCK_RESOURCE_DRV_FLAGS 10 @@ -6130,7 +6160,9 @@ #define PCICFG_COMMAND_INT_DISABLE (1<<10) #define PCICFG_COMMAND_RESERVED (0x1f<<11) #define PCICFG_STATUS_OFFSET 0x06 -#define PCICFG_REVESION_ID_OFFSET 0x08 +#define PCICFG_REVISION_ID_OFFSET 0x08 +#define PCICFG_REVESION_ID_MASK 0xff +#define PCICFG_REVESION_ID_ERROR_VAL 0xff #define PCICFG_CACHE_LINE_SIZE 0x0c #define PCICFG_LATENCY_TIMER 0x0d #define PCICFG_BAR_1_LOW 0x10 @@ -6672,6 +6704,7 @@ #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI 0x1B00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS 0x1E00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI 0x1F00 +#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2 0x3900 #define MDIO_REG_BANK_10G_PARALLEL_DETECT 0x8130 @@ -7046,7 +7079,8 @@ Theotherbitsarereservedandshouldbezero*/ #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2 0x12 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY 0x4000 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ 0x8000 -#define MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150 0x96 +#define MDIO_WC_REG_PCS_STATUS2 0x0021 +#define MDIO_WC_REG_PMD_KR_CONTROL 0x0096 #define MDIO_WC_REG_XGXSBLK0_XGXSCONTROL 0x8000 #define MDIO_WC_REG_XGXSBLK0_MISCCONTROL1 0x800e #define MDIO_WC_REG_XGXSBLK1_DESKEW 0x8010 @@ -7078,6 +7112,7 @@ Theotherbitsarereservedandshouldbezero*/ #define MDIO_WC_REG_PAR_DET_10G_STATUS 0x8130 #define MDIO_WC_REG_PAR_DET_10G_CTRL 0x8131 #define MDIO_WC_REG_XGXS_X2_CONTROL2 0x8141 +#define MDIO_WC_REG_XGXS_X2_CONTROL3 0x8142 #define MDIO_WC_REG_XGXS_RX_LN_SWAP1 0x816B #define MDIO_WC_REG_XGXS_TX_LN_SWAP1 0x8169 #define MDIO_WC_REG_GP2_STATUS_GP_2_0 0x81d0 @@ -7112,6 +7147,7 @@ Theotherbitsarereservedandshouldbezero*/ #define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET 0x0a #define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_MASK 0x7c00 #define MDIO_WC_REG_TX_FIR_TAP_ENABLE 0x8000 +#define MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP 0x82e2 #define MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL 0x82e3 #define MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL 0x82e6 #define MDIO_WC_REG_CL72_USERB0_CL72_BR_DEF_CTRL 0x82e7 @@ -7129,9 +7165,16 @@ Theotherbitsarereservedandshouldbezero*/ #define MDIO_WC_REG_DIGITAL4_MISC5 0x833e #define MDIO_WC_REG_DIGITAL5_MISC6 0x8345 #define MDIO_WC_REG_DIGITAL5_MISC7 0x8349 +#define MDIO_WC_REG_DIGITAL5_LINK_STATUS 0x834d #define MDIO_WC_REG_DIGITAL5_ACTUAL_SPEED 0x834e #define MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL 0x8350 #define MDIO_WC_REG_CL49_USERB0_CTRL 0x8368 +#define MDIO_WC_REG_CL73_USERB0_CTRL 0x8370 +#define MDIO_WC_REG_CL73_USERB0_USTAT 0x8371 +#define MDIO_WC_REG_CL73_BAM_CTRL1 0x8372 +#define MDIO_WC_REG_CL73_BAM_CTRL2 0x8373 +#define MDIO_WC_REG_CL73_BAM_CTRL3 0x8374 +#define MDIO_WC_REG_CL73_BAM_CODE_FIELD 0x837b #define MDIO_WC_REG_EEE_COMBO_CONTROL0 0x8390 #define MDIO_WC_REG_TX66_CONTROL 0x83b0 #define MDIO_WC_REG_RX66_CONTROL 0x83c0 @@ -7145,7 +7188,17 @@ Theotherbitsarereservedandshouldbezero*/ #define MDIO_WC_REG_RX66_SCW3_MASK 0x83c9 #define MDIO_WC_REG_FX100_CTRL1 0x8400 #define MDIO_WC_REG_FX100_CTRL3 0x8402 - +#define MDIO_WC_REG_CL82_USERB1_TX_CTRL5 0x8436 +#define MDIO_WC_REG_CL82_USERB1_TX_CTRL6 0x8437 +#define MDIO_WC_REG_CL82_USERB1_TX_CTRL7 0x8438 +#define MDIO_WC_REG_CL82_USERB1_TX_CTRL9 0x8439 +#define MDIO_WC_REG_CL82_USERB1_RX_CTRL10 0x843a +#define MDIO_WC_REG_CL82_USERB1_RX_CTRL11 0x843b +#define MDIO_WC_REG_ETA_CL73_OUI1 0x8453 +#define MDIO_WC_REG_ETA_CL73_OUI2 0x8454 +#define MDIO_WC_REG_ETA_CL73_OUI3 0x8455 +#define MDIO_WC_REG_ETA_CL73_LD_BAM_CODE 0x8456 +#define MDIO_WC_REG_ETA_CL73_LD_UD_CODE 0x8457 #define MDIO_WC_REG_MICROBLK_CMD 0xffc2 #define MDIO_WC_REG_MICROBLK_DL_STATUS 0xffc5 #define MDIO_WC_REG_MICROBLK_CMD3 0xffcc diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index a4fb5c0207be..09b625e0fdaa 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -5350,12 +5350,24 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp, else if ((cmd == BNX2X_F_CMD_AFEX_VIFLISTS) && (!test_bit(BNX2X_F_CMD_STOP, &o->pending))) next_state = BNX2X_F_STATE_STARTED; + + /* Switch_update ramrod can be sent in either started or + * tx_stopped state, and it doesn't change the state. + */ + else if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) && + (!test_bit(BNX2X_F_CMD_STOP, &o->pending))) + next_state = BNX2X_F_STATE_STARTED; + else if (cmd == BNX2X_F_CMD_TX_STOP) next_state = BNX2X_F_STATE_TX_STOPPED; break; case BNX2X_F_STATE_TX_STOPPED: - if (cmd == BNX2X_F_CMD_TX_START) + if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) && + (!test_bit(BNX2X_F_CMD_STOP, &o->pending))) + next_state = BNX2X_F_STATE_TX_STOPPED; + + else if (cmd == BNX2X_F_CMD_TX_START) next_state = BNX2X_F_STATE_STARTED; break; @@ -5637,6 +5649,28 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp, U64_LO(data_mapping), NONE_CONNECTION_TYPE); } +static inline int bnx2x_func_send_switch_update(struct bnx2x *bp, + struct bnx2x_func_state_params *params) +{ + struct bnx2x_func_sp_obj *o = params->f_obj; + struct function_update_data *rdata = + (struct function_update_data *)o->rdata; + dma_addr_t data_mapping = o->rdata_mapping; + struct bnx2x_func_switch_update_params *switch_update_params = + ¶ms->params.switch_update; + + memset(rdata, 0, sizeof(*rdata)); + + /* Fill the ramrod data with provided parameters */ + rdata->tx_switch_suspend_change_flg = 1; + rdata->tx_switch_suspend = switch_update_params->suspend; + rdata->echo = SWITCH_UPDATE; + + return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0, + U64_HI(data_mapping), + U64_LO(data_mapping), NONE_CONNECTION_TYPE); +} + static inline int bnx2x_func_send_afex_update(struct bnx2x *bp, struct bnx2x_func_state_params *params) { @@ -5657,6 +5691,7 @@ static inline int bnx2x_func_send_afex_update(struct bnx2x *bp, cpu_to_le16(afex_update_params->afex_default_vlan); rdata->allowed_priorities_change_flg = 1; rdata->allowed_priorities = afex_update_params->allowed_priorities; + rdata->echo = AFEX_UPDATE; /* No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element @@ -5773,6 +5808,8 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp, return bnx2x_func_send_tx_stop(bp, params); case BNX2X_F_CMD_TX_START: return bnx2x_func_send_tx_start(bp, params); + case BNX2X_F_CMD_SWITCH_UPDATE: + return bnx2x_func_send_switch_update(bp, params); default: BNX2X_ERR("Unknown command: %d\n", params->cmd); return -EINVAL; @@ -5818,16 +5855,30 @@ int bnx2x_func_state_change(struct bnx2x *bp, struct bnx2x_func_state_params *params) { struct bnx2x_func_sp_obj *o = params->f_obj; - int rc; + int rc, cnt = 300; enum bnx2x_func_cmd cmd = params->cmd; unsigned long *pending = &o->pending; mutex_lock(&o->one_pending_mutex); /* Check that the requested transition is legal */ - if (o->check_transition(bp, o, params)) { + rc = o->check_transition(bp, o, params); + if ((rc == -EBUSY) && + (test_bit(RAMROD_RETRY, ¶ms->ramrod_flags))) { + while ((rc == -EBUSY) && (--cnt > 0)) { + mutex_unlock(&o->one_pending_mutex); + msleep(10); + mutex_lock(&o->one_pending_mutex); + rc = o->check_transition(bp, o, params); + } + if (rc == -EBUSY) { + mutex_unlock(&o->one_pending_mutex); + BNX2X_ERR("timeout waiting for previous ramrod completion\n"); + return rc; + } + } else if (rc) { mutex_unlock(&o->one_pending_mutex); - return -EINVAL; + return rc; } /* Set "pending" bit */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index acf2fe4ca608..adbd91b1bdfc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h @@ -40,6 +40,12 @@ enum { * pending commands list. */ RAMROD_CONT, + /* If there is another pending ramrod, wait until it finishes and + * re-try to submit this one. This flag can be set only in sleepable + * context, and should not be set from the context that completes the + * ramrods as deadlock will occur. + */ + RAMROD_RETRY, }; typedef enum { @@ -1061,6 +1067,7 @@ enum bnx2x_func_cmd { BNX2X_F_CMD_AFEX_VIFLISTS, BNX2X_F_CMD_TX_STOP, BNX2X_F_CMD_TX_START, + BNX2X_F_CMD_SWITCH_UPDATE, BNX2X_F_CMD_MAX, }; @@ -1103,6 +1110,10 @@ struct bnx2x_func_start_params { u8 network_cos_mode; }; +struct bnx2x_func_switch_update_params { + u8 suspend; +}; + struct bnx2x_func_afex_update_params { u16 vif_id; u16 afex_default_vlan; @@ -1136,6 +1147,7 @@ struct bnx2x_func_state_params { struct bnx2x_func_hw_init_params hw_init; struct bnx2x_func_hw_reset_params hw_reset; struct bnx2x_func_start_params start; + struct bnx2x_func_switch_update_params switch_update; struct bnx2x_func_afex_update_params afex_update; struct bnx2x_func_afex_viflists_params afex_viflists; struct bnx2x_func_tx_start_params tx_start; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index 348ed02d3c69..89ec0667140a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -1149,6 +1149,7 @@ static void bnx2x_drv_stats_update(struct bnx2x *bp) UPDATE_ESTAT_QSTAT(rx_err_discard_pkt); UPDATE_ESTAT_QSTAT(rx_skb_alloc_failed); UPDATE_ESTAT_QSTAT(hw_csum_err); + UPDATE_ESTAT_QSTAT(driver_filtered_tx_pkt); } } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h index 24b8e505b60c..b4d7b26c7fe7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h @@ -203,6 +203,7 @@ struct bnx2x_eth_stats { /* Recovery */ u32 recoverable_error; u32 unrecoverable_error; + u32 driver_filtered_tx_pkt; /* src: Clear-on-Read register; Will not survive PMF Migration */ u32 eee_tx_lpi; }; @@ -264,6 +265,7 @@ struct bnx2x_eth_q_stats { u32 total_tpa_aggregated_frames_lo; u32 total_tpa_bytes_hi; u32 total_tpa_bytes_lo; + u32 driver_filtered_tx_pkt; }; struct bnx2x_eth_stats_old { @@ -315,6 +317,7 @@ struct bnx2x_eth_q_stats_old { u32 rx_err_discard_pkt_old; u32 rx_skb_alloc_failed_old; u32 hw_csum_err_old; + u32 driver_filtered_tx_pkt_old; }; struct bnx2x_net_stats_old { diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index cc8434fd606e..df8c30d1a52c 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c @@ -40,8 +40,10 @@ #include <net/ip6_checksum.h> #include <scsi/iscsi_if.h> +#define BCM_CNIC 1 #include "cnic_if.h" #include "bnx2.h" +#include "bnx2x/bnx2x.h" #include "bnx2x/bnx2x_reg.h" #include "bnx2x/bnx2x_fw_defs.h" #include "bnx2x/bnx2x_hsi.h" @@ -51,10 +53,10 @@ #include "cnic.h" #include "cnic_defs.h" -#define DRV_MODULE_NAME "cnic" +#define CNIC_MODULE_NAME "cnic" -static char version[] __devinitdata = - "Broadcom NetXtreme II CNIC Driver " DRV_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n"; +static char version[] = + "Broadcom NetXtreme II CNIC Driver " CNIC_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Michael Chan <mchan@broadcom.com> and John(Zongxi) " "Chen (zongxi@broadcom.com"); @@ -724,7 +726,7 @@ static void cnic_free_dma(struct cnic_dev *dev, struct cnic_dma *dma) for (i = 0; i < dma->num_pages; i++) { if (dma->pg_arr[i]) { - dma_free_coherent(&dev->pcidev->dev, BCM_PAGE_SIZE, + dma_free_coherent(&dev->pcidev->dev, BNX2_PAGE_SIZE, dma->pg_arr[i], dma->pg_map_arr[i]); dma->pg_arr[i] = NULL; } @@ -783,7 +785,7 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma, for (i = 0; i < pages; i++) { dma->pg_arr[i] = dma_alloc_coherent(&dev->pcidev->dev, - BCM_PAGE_SIZE, + BNX2_PAGE_SIZE, &dma->pg_map_arr[i], GFP_ATOMIC); if (dma->pg_arr[i] == NULL) @@ -792,8 +794,8 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma, if (!use_pg_tbl) return 0; - dma->pgtbl_size = ((pages * 8) + BCM_PAGE_SIZE - 1) & - ~(BCM_PAGE_SIZE - 1); + dma->pgtbl_size = ((pages * 8) + BNX2_PAGE_SIZE - 1) & + ~(BNX2_PAGE_SIZE - 1); dma->pgtbl = dma_alloc_coherent(&dev->pcidev->dev, dma->pgtbl_size, &dma->pgtbl_map, GFP_ATOMIC); if (dma->pgtbl == NULL) @@ -895,11 +897,11 @@ static int cnic_alloc_context(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; - if (CHIP_NUM(cp) == CHIP_NUM_5709) { + if (BNX2_CHIP(cp) == BNX2_CHIP_5709) { int i, k, arr_size; - cp->ctx_blk_size = BCM_PAGE_SIZE; - cp->cids_per_blk = BCM_PAGE_SIZE / 128; + cp->ctx_blk_size = BNX2_PAGE_SIZE; + cp->cids_per_blk = BNX2_PAGE_SIZE / 128; arr_size = BNX2_MAX_CID / cp->cids_per_blk * sizeof(struct cnic_ctx); cp->ctx_arr = kzalloc(arr_size, GFP_KERNEL); @@ -931,7 +933,7 @@ static int cnic_alloc_context(struct cnic_dev *dev) for (i = 0; i < cp->ctx_blks; i++) { cp->ctx_arr[i].ctx = dma_alloc_coherent(&dev->pcidev->dev, - BCM_PAGE_SIZE, + BNX2_PAGE_SIZE, &cp->ctx_arr[i].mapping, GFP_KERNEL); if (cp->ctx_arr[i].ctx == NULL) @@ -1011,7 +1013,7 @@ static int __cnic_alloc_uio_rings(struct cnic_uio_dev *udev, int pages) if (udev->l2_ring) return 0; - udev->l2_ring_size = pages * BCM_PAGE_SIZE; + udev->l2_ring_size = pages * BNX2_PAGE_SIZE; udev->l2_ring = dma_alloc_coherent(&udev->pdev->dev, udev->l2_ring_size, &udev->l2_ring_map, GFP_KERNEL | __GFP_COMP); @@ -1234,8 +1236,6 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev) int i, j, n, ret, pages; struct cnic_dma *kwq_16_dma = &cp->kwq_16_data_info; - cp->iro_arr = ethdev->iro_arr; - cp->max_cid_space = MAX_ISCSI_TBL_SZ; cp->iscsi_start_cid = start_cid; cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ; @@ -1430,6 +1430,7 @@ static void cnic_reply_bnx2x_kcqes(struct cnic_dev *dev, int ulp_type, static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct iscsi_kwqe_init1 *req1 = (struct iscsi_kwqe_init1 *) kwqe; int hq_bds, pages; u32 pfid = cp->pfid; @@ -1512,6 +1513,7 @@ static int cnic_bnx2x_iscsi_init2(struct cnic_dev *dev, struct kwqe *kwqe) { struct iscsi_kwqe_init2 *req2 = (struct iscsi_kwqe_init2 *) kwqe; struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); u32 pfid = cp->pfid; struct iscsi_kcqe kcqe; struct kcqe *cqes[1]; @@ -2048,6 +2050,7 @@ static void cnic_init_storm_conn_bufs(struct cnic_dev *dev, static void cnic_init_bnx2x_mac(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); u32 pfid = cp->pfid; u8 *mac = dev->mac_addr; @@ -2084,6 +2087,7 @@ static void cnic_init_bnx2x_mac(struct cnic_dev *dev) static void cnic_bnx2x_set_tcp_timestamp(struct cnic_dev *dev, int tcp_ts) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); u8 xstorm_flags = XSTORM_L5CM_TCP_FLAGS_WND_SCL_EN; u16 tstorm_flags = 0; @@ -2103,6 +2107,7 @@ static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[], u32 num, int *work) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct l4_kwq_connect_req1 *kwqe1 = (struct l4_kwq_connect_req1 *) wqes[0]; struct l4_kwq_connect_req3 *kwqe3; @@ -2898,7 +2903,7 @@ static int cnic_l2_completion(struct cnic_local *cp) u16 hw_cons, sw_cons; struct cnic_uio_dev *udev = cp->udev; union eth_rx_cqe *cqe, *cqe_ring = (union eth_rx_cqe *) - (udev->l2_ring + (2 * BCM_PAGE_SIZE)); + (udev->l2_ring + (2 * BNX2_PAGE_SIZE)); u32 cmd; int comp = 0; @@ -3853,12 +3858,17 @@ static int cnic_cm_abort(struct cnic_sock *csk) return cnic_cm_abort_req(csk); /* Getting here means that we haven't started connect, or - * connect was not successful. + * connect was not successful, or it has been reset by the target. */ cp->close_conn(csk, opcode); - if (csk->state != opcode) + if (csk->state != opcode) { + /* Wait for remote reset sequence to complete */ + while (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags)) + msleep(1); + return -EALREADY; + } return 0; } @@ -3872,6 +3882,10 @@ static int cnic_cm_close(struct cnic_sock *csk) csk->state = L4_KCQE_OPCODE_VALUE_CLOSE_COMP; return cnic_cm_close_req(csk); } else { + /* Wait for remote reset sequence to complete */ + while (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags)) + msleep(1); + return -EALREADY; } return 0; @@ -4200,6 +4214,7 @@ static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev) static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); u32 pfid = cp->pfid; u32 port = CNIC_PORT(cp); @@ -4349,7 +4364,7 @@ static int cnic_setup_5709_context(struct cnic_dev *dev, int valid) int ret = 0, i; u32 valid_bit = valid ? BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID : 0; - if (CHIP_NUM(cp) != CHIP_NUM_5709) + if (BNX2_CHIP(cp) != BNX2_CHIP_5709) return 0; for (i = 0; i < cp->ctx_blks; i++) { @@ -4357,7 +4372,7 @@ static int cnic_setup_5709_context(struct cnic_dev *dev, int valid) u32 idx = cp->ctx_arr[i].cid / cp->cids_per_blk; u32 val; - memset(cp->ctx_arr[i].ctx, 0, BCM_PAGE_SIZE); + memset(cp->ctx_arr[i].ctx, 0, BNX2_PAGE_SIZE); CNIC_WR(dev, BNX2_CTX_HOST_PAGE_TBL_DATA0, (cp->ctx_arr[i].mapping & 0xffffffff) | valid_bit); @@ -4499,7 +4514,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) u32 cid_addr, tx_cid, sb_id; u32 val, offset0, offset1, offset2, offset3; int i; - struct tx_bd *txbd; + struct bnx2_tx_bd *txbd; dma_addr_t buf_map, ring_map = udev->l2_ring_map; struct status_block *s_blk = cp->status_blk.gen; @@ -4517,7 +4532,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) cp->tx_cons = *cp->tx_cons_ptr; cid_addr = GET_CID_ADDR(tx_cid); - if (CHIP_NUM(cp) == CHIP_NUM_5709) { + if (BNX2_CHIP(cp) == BNX2_CHIP_5709) { u32 cid_addr2 = GET_CID_ADDR(tx_cid + 4) + 0x40; for (i = 0; i < PHY_CTX_SIZE; i += 4) @@ -4545,7 +4560,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) txbd = udev->l2_ring; buf_map = udev->l2_buf_map; - for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) { + for (i = 0; i < BNX2_MAX_TX_DESC_CNT; i++, txbd++) { txbd->tx_bd_haddr_hi = (u64) buf_map >> 32; txbd->tx_bd_haddr_lo = (u64) buf_map & 0xffffffff; } @@ -4565,7 +4580,7 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev) struct cnic_uio_dev *udev = cp->udev; u32 cid_addr, sb_id, val, coal_reg, coal_val; int i; - struct rx_bd *rxbd; + struct bnx2_rx_bd *rxbd; struct status_block *s_blk = cp->status_blk.gen; dma_addr_t ring_map = udev->l2_ring_map; @@ -4601,8 +4616,8 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev) val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id); cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val); - rxbd = udev->l2_ring + BCM_PAGE_SIZE; - for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) { + rxbd = udev->l2_ring + BNX2_PAGE_SIZE; + for (i = 0; i < BNX2_MAX_RX_DESC_CNT; i++, rxbd++) { dma_addr_t buf_map; int n = (i % cp->l2_rx_ring_size) + 1; @@ -4612,11 +4627,11 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev) rxbd->rx_bd_haddr_hi = (u64) buf_map >> 32; rxbd->rx_bd_haddr_lo = (u64) buf_map & 0xffffffff; } - val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32; + val = (u64) (ring_map + BNX2_PAGE_SIZE) >> 32; cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val); rxbd->rx_bd_haddr_hi = val; - val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff; + val = (u64) (ring_map + BNX2_PAGE_SIZE) & 0xffffffff; cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val); rxbd->rx_bd_haddr_lo = val; @@ -4662,7 +4677,7 @@ static void cnic_set_bnx2_mac(struct cnic_dev *dev) CNIC_WR(dev, BNX2_EMAC_MAC_MATCH5, val); val = 4 | BNX2_RPM_SORT_USER2_BC_EN; - if (CHIP_NUM(cp) != CHIP_NUM_5709) + if (BNX2_CHIP(cp) != BNX2_CHIP_5709) val |= BNX2_RPM_SORT_USER2_PROM_VLAN; CNIC_WR(dev, BNX2_RPM_SORT_USER2, 0x0); @@ -4682,10 +4697,10 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) val = CNIC_RD(dev, BNX2_MQ_CONFIG); val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE; - if (BCM_PAGE_BITS > 12) + if (BNX2_PAGE_BITS > 12) val |= (12 - 8) << 4; else - val |= (BCM_PAGE_BITS - 8) << 4; + val |= (BNX2_PAGE_BITS - 8) << 4; CNIC_WR(dev, BNX2_MQ_CONFIG, val); @@ -4708,20 +4723,20 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) cp->kwq_con_idx = 0; set_bit(CNIC_LCL_FL_KWQ_INIT, &cp->cnic_local_flags); - if (CHIP_NUM(cp) == CHIP_NUM_5706 || CHIP_NUM(cp) == CHIP_NUM_5708) + if (BNX2_CHIP(cp) == BNX2_CHIP_5706 || BNX2_CHIP(cp) == BNX2_CHIP_5708) cp->kwq_con_idx_ptr = &sblk->status_rx_quick_consumer_index15; else cp->kwq_con_idx_ptr = &sblk->status_cmd_consumer_index; /* Initialize the kernel work queue context. */ val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE | - (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ; + (BNX2_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ; cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_TYPE, val); - val = (BCM_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16; + val = (BNX2_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16; cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val); - val = ((BCM_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT; + val = ((BNX2_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT; cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val); val = (u32) ((u64) cp->kwq_info.pgtbl_map >> 32); @@ -4741,13 +4756,13 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) /* Initialize the kernel complete queue context. */ val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE | - (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ; + (BNX2_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ; cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_TYPE, val); - val = (BCM_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16; + val = (BNX2_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16; cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val); - val = ((BCM_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT; + val = ((BNX2_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT; cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val); val = (u32) ((u64) cp->kcq1.dma.pgtbl_map >> 32); @@ -4843,6 +4858,7 @@ static inline void cnic_storm_memset_hc_disable(struct cnic_dev *dev, u16 sb_id, u8 sb_index, u8 disable) { + struct bnx2x *bp = netdev_priv(dev->netdev); u32 addr = BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) + @@ -4860,6 +4876,7 @@ static inline void cnic_storm_memset_hc_disable(struct cnic_dev *dev, static void cnic_enable_bnx2x_int(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); u8 sb_id = cp->status_blk_num; CNIC_WR8(dev, BAR_CSTRORM_INTMEM + @@ -4886,10 +4903,10 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev, u32 cli = cp->ethdev->iscsi_l2_client_id; u32 val; - memset(txbd, 0, BCM_PAGE_SIZE); + memset(txbd, 0, BNX2_PAGE_SIZE); buf_map = udev->l2_buf_map; - for (i = 0; i < MAX_TX_DESC_CNT; i += 3, txbd += 3) { + for (i = 0; i < BNX2_MAX_TX_DESC_CNT; i += 3, txbd += 3) { struct eth_tx_start_bd *start_bd = &txbd->start_bd; struct eth_tx_parse_bd_e1x *pbd_e1x = &((txbd + 1)->parse_bd_e1x); @@ -4908,9 +4925,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev, if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) pbd_e2->parsing_data = (UNICAST_ADDRESS << - ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT); + ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT); else - pbd_e1x->global_data = (UNICAST_ADDRESS << + pbd_e1x->global_data = (UNICAST_ADDRESS << ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE_SHIFT); } @@ -4945,9 +4962,9 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, struct cnic_local *cp = dev->cnic_priv; struct cnic_uio_dev *udev = cp->udev; struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (udev->l2_ring + - BCM_PAGE_SIZE); + BNX2_PAGE_SIZE); struct eth_rx_cqe_next_page *rxcqe = (struct eth_rx_cqe_next_page *) - (udev->l2_ring + (2 * BCM_PAGE_SIZE)); + (udev->l2_ring + (2 * BNX2_PAGE_SIZE)); struct host_sp_status_block *sb = cp->bnx2x_def_status_blk; int i; u32 cli = cp->ethdev->iscsi_l2_client_id; @@ -4971,20 +4988,20 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, rxbd->addr_lo = cpu_to_le32(buf_map & 0xffffffff); } - val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32; + val = (u64) (ring_map + BNX2_PAGE_SIZE) >> 32; rxbd->addr_hi = cpu_to_le32(val); data->rx.bd_page_base.hi = cpu_to_le32(val); - val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff; + val = (u64) (ring_map + BNX2_PAGE_SIZE) & 0xffffffff; rxbd->addr_lo = cpu_to_le32(val); data->rx.bd_page_base.lo = cpu_to_le32(val); rxcqe += BNX2X_MAX_RCQ_DESC_CNT; - val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) >> 32; + val = (u64) (ring_map + (2 * BNX2_PAGE_SIZE)) >> 32; rxcqe->addr_hi = cpu_to_le32(val); data->rx.cqe_page_base.hi = cpu_to_le32(val); - val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) & 0xffffffff; + val = (u64) (ring_map + (2 * BNX2_PAGE_SIZE)) & 0xffffffff; rxcqe->addr_lo = cpu_to_le32(val); data->rx.cqe_page_base.lo = cpu_to_le32(val); @@ -5009,6 +5026,7 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, static void cnic_init_bnx2x_kcq(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); u32 pfid = cp->pfid; cp->kcq1.io_addr = BAR_CSTRORM_INTMEM + @@ -5047,37 +5065,17 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev) static int cnic_start_bnx2x_hw(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct cnic_eth_dev *ethdev = cp->ethdev; - int func = CNIC_FUNC(cp), ret; + int func, ret; u32 pfid; dev->stats_addr = ethdev->addr_drv_info_to_mcp; - cp->port_mode = CHIP_PORT_MODE_NONE; - - if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) { - u32 val; + cp->port_mode = bp->common.chip_port_mode; + cp->pfid = bp->pfid; + cp->func = bp->pf_num; - pci_read_config_dword(dev->pcidev, PCICFG_ME_REGISTER, &val); - cp->func = (u8) ((val & ME_REG_ABS_PF_NUM) >> - ME_REG_ABS_PF_NUM_SHIFT); - func = CNIC_FUNC(cp); - - val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN_OVWR); - if (!(val & 1)) - val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN); - else - val = (val >> 1) & 1; - - if (val) { - cp->port_mode = CHIP_4_PORT_MODE; - cp->pfid = func >> 1; - } else { - cp->port_mode = CHIP_2_PORT_MODE; - cp->pfid = func & 0x6; - } - } else { - cp->pfid = func; - } + func = CNIC_FUNC(cp); pfid = cp->pfid; ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ, @@ -5144,6 +5142,7 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev) static void cnic_init_rings(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); struct cnic_uio_dev *udev = cp->udev; if (test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags)) @@ -5249,8 +5248,8 @@ static void cnic_shutdown_rings(struct cnic_dev *dev) msleep(10); } clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags); - rx_ring = udev->l2_ring + BCM_PAGE_SIZE; - memset(rx_ring, 0, BCM_PAGE_SIZE); + rx_ring = udev->l2_ring + BNX2_PAGE_SIZE; + memset(rx_ring, 0, BNX2_PAGE_SIZE); } static int cnic_register_netdev(struct cnic_dev *dev) @@ -5344,8 +5343,28 @@ static void cnic_stop_bnx2_hw(struct cnic_dev *dev) static void cnic_stop_bnx2x_hw(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); + u32 hc_index = HC_INDEX_ISCSI_EQ_CONS; + u32 sb_id = cp->status_blk_num; + u32 idx_off, syn_off; cnic_free_irq(dev); + + if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) { + idx_off = offsetof(struct hc_status_block_e2, index_values) + + (hc_index * sizeof(u16)); + + syn_off = CSTORM_HC_SYNC_LINE_INDEX_E2_OFFSET(hc_index, sb_id); + } else { + idx_off = offsetof(struct hc_status_block_e1x, index_values) + + (hc_index * sizeof(u16)); + + syn_off = CSTORM_HC_SYNC_LINE_INDEX_E1X_OFFSET(hc_index, sb_id); + } + CNIC_WR16(dev, BAR_CSTRORM_INTMEM + syn_off, 0); + CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_OFFSET(sb_id) + + idx_off, 0); + *cp->kcq1.hw_prod_idx_ptr = 0; CNIC_WR(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_EQ_CONS_OFFSET(cp->pfid, 0), 0); @@ -5431,14 +5450,12 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev) struct pci_dev *pdev; struct cnic_dev *cdev; struct cnic_local *cp; + struct bnx2 *bp = netdev_priv(dev); struct cnic_eth_dev *ethdev = NULL; - struct cnic_eth_dev *(*probe)(struct net_device *) = NULL; - probe = symbol_get(bnx2_cnic_probe); - if (probe) { - ethdev = (*probe)(dev); - symbol_put(bnx2_cnic_probe); - } + if (bp->cnic_probe) + ethdev = (bp->cnic_probe)(dev); + if (!ethdev) return NULL; @@ -5493,14 +5510,12 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev) struct pci_dev *pdev; struct cnic_dev *cdev; struct cnic_local *cp; + struct bnx2x *bp = netdev_priv(dev); struct cnic_eth_dev *ethdev = NULL; - struct cnic_eth_dev *(*probe)(struct net_device *) = NULL; - probe = symbol_get(bnx2x_cnic_probe); - if (probe) { - ethdev = (*probe)(dev); - symbol_put(bnx2x_cnic_probe); - } + if (bp->cnic_probe) + ethdev = bp->cnic_probe(dev); + if (!ethdev) return NULL; diff --git a/drivers/net/ethernet/broadcom/cnic.h b/drivers/net/ethernet/broadcom/cnic.h index 148604c3fa0c..62c670619ae6 100644 --- a/drivers/net/ethernet/broadcom/cnic.h +++ b/drivers/net/ethernet/broadcom/cnic.h @@ -80,18 +80,18 @@ #define CNIC_LOCAL_PORT_MAX 61024 #define CNIC_LOCAL_PORT_RANGE (CNIC_LOCAL_PORT_MAX - CNIC_LOCAL_PORT_MIN) -#define KWQE_CNT (BCM_PAGE_SIZE / sizeof(struct kwqe)) -#define KCQE_CNT (BCM_PAGE_SIZE / sizeof(struct kcqe)) +#define KWQE_CNT (BNX2_PAGE_SIZE / sizeof(struct kwqe)) +#define KCQE_CNT (BNX2_PAGE_SIZE / sizeof(struct kcqe)) #define MAX_KWQE_CNT (KWQE_CNT - 1) #define MAX_KCQE_CNT (KCQE_CNT - 1) #define MAX_KWQ_IDX ((KWQ_PAGE_CNT * KWQE_CNT) - 1) #define MAX_KCQ_IDX ((KCQ_PAGE_CNT * KCQE_CNT) - 1) -#define KWQ_PG(x) (((x) & ~MAX_KWQE_CNT) >> (BCM_PAGE_BITS - 5)) +#define KWQ_PG(x) (((x) & ~MAX_KWQE_CNT) >> (BNX2_PAGE_BITS - 5)) #define KWQ_IDX(x) ((x) & MAX_KWQE_CNT) -#define KCQ_PG(x) (((x) & ~MAX_KCQE_CNT) >> (BCM_PAGE_BITS - 5)) +#define KCQ_PG(x) (((x) & ~MAX_KCQE_CNT) >> (BNX2_PAGE_BITS - 5)) #define KCQ_IDX(x) ((x) & MAX_KCQE_CNT) #define BNX2X_NEXT_KCQE(x) (((x) & (MAX_KCQE_CNT - 1)) == \ @@ -186,14 +186,6 @@ struct kcq_info { u16 (*hw_idx)(u16); }; -struct iro { - u32 base; - u16 m1; - u16 m2; - u16 m3; - u16 size; -}; - struct cnic_uio_dev { struct uio_info cnic_uinfo; u32 uio_dev; @@ -241,9 +233,6 @@ struct cnic_local { u16 rx_cons; u16 tx_cons; - const struct iro *iro_arr; -#define IRO (((struct cnic_local *) dev->cnic_priv)->iro_arr) - struct cnic_dma kwq_info; struct kwqe **kwq; @@ -316,9 +305,6 @@ struct cnic_local { int func; u32 pfid; u8 port_mode; -#define CHIP_4_PORT_MODE 0 -#define CHIP_2_PORT_MODE 1 -#define CHIP_PORT_MODE_NONE 2 u32 shmem_base; @@ -420,11 +406,11 @@ struct bnx2x_bd_chain_next { BNX2X_CHIP_IS_57840(x)) #define BNX2X_CHIP_IS_E2_PLUS(x) (BNX2X_CHIP_IS_E2(x) || BNX2X_CHIP_IS_E3(x)) -#define IS_E1H_OFFSET BNX2X_CHIP_IS_E1H(cp->chip_id) - -#define BNX2X_RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_bd)) +#define BNX2X_RX_DESC_CNT (BNX2_PAGE_SIZE / \ + sizeof(struct eth_rx_bd)) #define BNX2X_MAX_RX_DESC_CNT (BNX2X_RX_DESC_CNT - 2) -#define BNX2X_RCQ_DESC_CNT (BCM_PAGE_SIZE / sizeof(union eth_rx_cqe)) +#define BNX2X_RCQ_DESC_CNT (BNX2_PAGE_SIZE / \ + sizeof(union eth_rx_cqe)) #define BNX2X_MAX_RCQ_DESC_CNT (BNX2X_RCQ_DESC_CNT - 1) #define BNX2X_NEXT_RCQE(x) (((x) & BNX2X_MAX_RCQ_DESC_CNT) == \ diff --git a/drivers/net/ethernet/broadcom/cnic_if.h b/drivers/net/ethernet/broadcom/cnic_if.h index 865095aad1f6..2a35436f9095 100644 --- a/drivers/net/ethernet/broadcom/cnic_if.h +++ b/drivers/net/ethernet/broadcom/cnic_if.h @@ -14,8 +14,8 @@ #include "bnx2x/bnx2x_mfw_req.h" -#define CNIC_MODULE_VERSION "2.5.14" -#define CNIC_MODULE_RELDATE "Sep 30, 2012" +#define CNIC_MODULE_VERSION "2.5.16" +#define CNIC_MODULE_RELDATE "Dec 05, 2012" #define CNIC_ULP_RDMA 0 #define CNIC_ULP_ISCSI 1 @@ -353,7 +353,4 @@ extern int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops); extern int cnic_unregister_driver(int ulp_type); -extern struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev); -extern struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev); - #endif diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c index 49e7a258da8a..3a1c8a3cf7c9 100644 --- a/drivers/net/ethernet/broadcom/sb1250-mac.c +++ b/drivers/net/ethernet/broadcom/sb1250-mac.c @@ -2586,7 +2586,7 @@ static int sbmac_poll(struct napi_struct *napi, int budget) } -static int __devinit sbmac_probe(struct platform_device *pldev) +static int sbmac_probe(struct platform_device *pldev) { struct net_device *dev; struct sbmac_softc *sc; diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index a8800ac10df9..bdb086934cd9 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -54,6 +54,9 @@ #include <asm/byteorder.h> #include <linux/uaccess.h> +#include <uapi/linux/net_tstamp.h> +#include <linux/ptp_clock_kernel.h> + #ifdef CONFIG_SPARC #include <asm/idprom.h> #include <asm/prom.h> @@ -90,10 +93,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 125 +#define TG3_MIN_NUM 128 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "September 26, 2012" +#define DRV_MODULE_RELDATE "December 03, 2012" #define RESET_KIND_SHUTDOWN 0 #define RESET_KIND_INIT 1 @@ -211,7 +214,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define FIRMWARE_TG3TSO "tigon/tg3_tso.bin" #define FIRMWARE_TG3TSO5 "tigon/tg3_tso5.bin" -static char version[] __devinitdata = +static char version[] = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")"; MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)"); @@ -226,6 +229,9 @@ static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ module_param(tg3_debug, int, 0); MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); +#define TG3_DRV_DATA_FLAG_10_100_ONLY 0x0001 +#define TG3_DRV_DATA_FLAG_5705_10_100 0x0002 + static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)}, @@ -245,20 +251,28 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY | + TG3_DRV_DATA_FLAG_5705_10_100}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY | + TG3_DRV_DATA_FLAG_5705_10_100}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY | + TG3_DRV_DATA_FLAG_5705_10_100}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)}, @@ -266,8 +280,13 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)}, + {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5787M, + PCI_VENDOR_ID_LENOVO, + TG3PCI_SUBDEVICE_ID_LENOVO_5787M), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)}, @@ -286,18 +305,28 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_G)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_F)}, + {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780, + PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_A), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, + {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780, + PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_B), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717_C)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795), + .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)}, @@ -398,19 +427,27 @@ static const struct { }; #define TG3_NUM_STATS ARRAY_SIZE(ethtool_stats_keys) +#define TG3_NVRAM_TEST 0 +#define TG3_LINK_TEST 1 +#define TG3_REGISTER_TEST 2 +#define TG3_MEMORY_TEST 3 +#define TG3_MAC_LOOPB_TEST 4 +#define TG3_PHY_LOOPB_TEST 5 +#define TG3_EXT_LOOPB_TEST 6 +#define TG3_INTERRUPT_TEST 7 static const struct { const char string[ETH_GSTRING_LEN]; } ethtool_test_keys[] = { - { "nvram test (online) " }, - { "link test (online) " }, - { "register test (offline)" }, - { "memory test (offline)" }, - { "mac loopback test (offline)" }, - { "phy loopback test (offline)" }, - { "ext loopback test (offline)" }, - { "interrupt test (offline)" }, + [TG3_NVRAM_TEST] = { "nvram test (online) " }, + [TG3_LINK_TEST] = { "link test (online) " }, + [TG3_REGISTER_TEST] = { "register test (offline)" }, + [TG3_MEMORY_TEST] = { "memory test (offline)" }, + [TG3_MAC_LOOPB_TEST] = { "mac loopback test (offline)" }, + [TG3_PHY_LOOPB_TEST] = { "phy loopback test (offline)" }, + [TG3_EXT_LOOPB_TEST] = { "ext loopback test (offline)" }, + [TG3_INTERRUPT_TEST] = { "interrupt test (offline)" }, }; #define TG3_NUM_TEST ARRAY_SIZE(ethtool_test_keys) @@ -1246,14 +1283,26 @@ static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set) return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg); } -#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \ - MII_TG3_AUXCTL_ACTL_TX_6DB) +static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable) +{ + u32 val; + int err; + + err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val); + + if (err) + return err; + if (enable) -#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_TX_6DB); + val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + else + val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + + err = tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, + val | MII_TG3_AUXCTL_ACTL_TX_6DB); + + return err; +} static int tg3_bmcr_reset(struct tg3 *tp) { @@ -2186,7 +2235,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) otp = tp->phy_otp; - if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) + if (tg3_phy_toggle_auxctl_smdsp(tp, true)) return; phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); @@ -2211,7 +2260,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) @@ -2247,9 +2296,9 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) if (!tp->setlpicnt) { if (current_link_up == 1 && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } val = tr32(TG3_CPMU_EEE_MODE); @@ -2265,11 +2314,11 @@ static void tg3_phy_eee_enable(struct tg3 *tp) (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || tg3_flag(tp, 57765_CLASS)) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { val = MII_TG3_DSP_TAP26_ALNOKO | MII_TG3_DSP_TAP26_RMRXSTO; tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } val = tr32(TG3_CPMU_EEE_MODE); @@ -2413,7 +2462,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_CTRL1000, CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (err) return err; @@ -2434,7 +2483,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); tg3_writephy(tp, MII_CTRL1000, phy9_orig); @@ -2447,6 +2496,18 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) return err; } +static void tg3_carrier_on(struct tg3 *tp) +{ + netif_carrier_on(tp->dev); + tp->link_up = true; +} + +static void tg3_carrier_off(struct tg3 *tp) +{ + netif_carrier_off(tp->dev); + tp->link_up = false; +} + /* This will reset the tigon3 PHY if there is no valid * link unless the FORCE argument is non-zero. */ @@ -2465,8 +2526,8 @@ static int tg3_phy_reset(struct tg3 *tp) if (err != 0) return -EBUSY; - if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) { - netif_carrier_off(tp->dev); + if (netif_running(tp->dev) && tp->link_up) { + tg3_carrier_off(tp); tg3_link_report(tp); } @@ -2523,10 +2584,10 @@ static int tg3_phy_reset(struct tg3 *tp) out: if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x201f, 0x2aaa); tg3_phydsp_write(tp, 0x000a, 0x0323); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { @@ -2535,14 +2596,14 @@ out: } if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x000a, 0x310b); tg3_phydsp_write(tp, 0x201f, 0x9506); tg3_phydsp_write(tp, 0x401f, 0x14e2); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); @@ -2551,7 +2612,7 @@ out: } else tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } @@ -3960,7 +4021,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) tw32(TG3_CPMU_EEE_MODE, tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (!err) { u32 err2; @@ -3993,7 +4054,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) MII_TG3_DSP_CH34TP2_HIBW01); } - err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + err2 = tg3_phy_toggle_auxctl_smdsp(tp, false); if (!err) err = err2; } @@ -4160,6 +4221,24 @@ static bool tg3_phy_copper_fetch_rmtadv(struct tg3 *tp, u32 *rmtadv) return true; } +static bool tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up) +{ + if (curr_link_up != tp->link_up) { + if (curr_link_up) { + tg3_carrier_on(tp); + } else { + tg3_carrier_off(tp); + if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) + tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; + } + + tg3_link_report(tp); + return true; + } + + return false; +} + static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) { int current_link_up; @@ -4192,7 +4271,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && - netif_carrier_ok(tp->dev)) { + tp->link_up) { tg3_readphy(tp, MII_BMSR, &bmsr); if (!tg3_readphy(tp, MII_BMSR, &bmsr) && !(bmsr & BMSR_LSTATUS)) @@ -4434,13 +4513,7 @@ relink: PCI_EXP_LNKCTL_CLKREQ_EN); } - if (current_link_up != netif_carrier_ok(tp->dev)) { - if (current_link_up) - netif_carrier_on(tp->dev); - else - netif_carrier_off(tp->dev); - tg3_link_report(tp); - } + tg3_test_and_report_link_chg(tp, current_link_up); return 0; } @@ -5080,7 +5153,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) orig_active_duplex = tp->link_config.active_duplex; if (!tg3_flag(tp, HW_AUTONEG) && - netif_carrier_ok(tp->dev) && + tp->link_up && tg3_flag(tp, INIT_COMPLETE)) { mac_status = tr32(MAC_STATUS); mac_status &= (MAC_STATUS_PCS_SYNCED | @@ -5158,13 +5231,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) LED_CTRL_TRAFFIC_OVERRIDE)); } - if (current_link_up != netif_carrier_ok(tp->dev)) { - if (current_link_up) - netif_carrier_on(tp->dev); - else - netif_carrier_off(tp->dev); - tg3_link_report(tp); - } else { + if (!tg3_test_and_report_link_chg(tp, current_link_up)) { u32 now_pause_cfg = tp->link_config.active_flowctrl; if (orig_pause_cfg != now_pause_cfg || orig_active_speed != tp->link_config.active_speed || @@ -5257,7 +5324,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) new_bmcr |= BMCR_SPEED1000; /* Force a linkdown */ - if (netif_carrier_ok(tp->dev)) { + if (tp->link_up) { u32 adv; err |= tg3_readphy(tp, MII_ADVERTISE, &adv); @@ -5269,7 +5336,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) BMCR_ANRESTART | BMCR_ANENABLE); udelay(10); - netif_carrier_off(tp->dev); + tg3_carrier_off(tp); } tg3_writephy(tp, MII_BMCR, new_bmcr); bmcr = new_bmcr; @@ -5335,15 +5402,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) tp->link_config.active_speed = current_speed; tp->link_config.active_duplex = current_duplex; - if (current_link_up != netif_carrier_ok(tp->dev)) { - if (current_link_up) - netif_carrier_on(tp->dev); - else { - netif_carrier_off(tp->dev); - tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; - } - tg3_link_report(tp); - } + tg3_test_and_report_link_chg(tp, current_link_up); return err; } @@ -5355,7 +5414,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp) return; } - if (!netif_carrier_ok(tp->dev) && + if (!tp->link_up && (tp->link_config.autoneg == AUTONEG_ENABLE)) { u32 bmcr; @@ -5385,7 +5444,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp) tp->phy_flags |= TG3_PHYFLG_PARALLEL_DETECT; } } - } else if (netif_carrier_ok(tp->dev) && + } else if (tp->link_up && (tp->link_config.autoneg == AUTONEG_ENABLE) && (tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT)) { u32 phy2; @@ -5451,7 +5510,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) (32 << TX_LENGTHS_SLOT_TIME_SHIFT)); if (!tg3_flag(tp, 5705_PLUS)) { - if (netif_carrier_ok(tp->dev)) { + if (tp->link_up) { tw32(HOSTCC_STAT_COAL_TICKS, tp->coal.stats_block_coalesce_usecs); } else { @@ -5461,7 +5520,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) if (tg3_flag(tp, ASPM_WORKAROUND)) { val = tr32(PCIE_PWR_MGMT_THRESH); - if (!netif_carrier_ok(tp->dev)) + if (!tp->link_up) val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) | tp->pwrmgmt_thresh; else @@ -5472,6 +5531,190 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) return err; } +/* tp->lock must be held */ +static u64 tg3_refclk_read(struct tg3 *tp) +{ + u64 stamp = tr32(TG3_EAV_REF_CLCK_LSB); + return stamp | (u64)tr32(TG3_EAV_REF_CLCK_MSB) << 32; +} + +/* tp->lock must be held */ +static void tg3_refclk_write(struct tg3 *tp, u64 newval) +{ + tw32(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_STOP); + tw32(TG3_EAV_REF_CLCK_LSB, newval & 0xffffffff); + tw32(TG3_EAV_REF_CLCK_MSB, newval >> 32); + tw32_f(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_RESUME); +} + +static inline void tg3_full_lock(struct tg3 *tp, int irq_sync); +static inline void tg3_full_unlock(struct tg3 *tp); +static int tg3_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) +{ + struct tg3 *tp = netdev_priv(dev); + + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + if (tp->ptp_clock) + info->phc_index = ptp_clock_index(tp->ptp_clock); + else + info->phc_index = -1; + + info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); + + info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) | + (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) | + (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | + (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT); + return 0; +} + +static int tg3_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) +{ + struct tg3 *tp = container_of(ptp, struct tg3, ptp_info); + bool neg_adj = false; + u32 correction = 0; + + if (ppb < 0) { + neg_adj = true; + ppb = -ppb; + } + + /* Frequency adjustment is performed using hardware with a 24 bit + * accumulator and a programmable correction value. On each clk, the + * correction value gets added to the accumulator and when it + * overflows, the time counter is incremented/decremented. + * + * So conversion from ppb to correction value is + * ppb * (1 << 24) / 1000000000 + */ + correction = div_u64((u64)ppb * (1 << 24), 1000000000ULL) & + TG3_EAV_REF_CLK_CORRECT_MASK; + + tg3_full_lock(tp, 0); + + if (correction) + tw32(TG3_EAV_REF_CLK_CORRECT_CTL, + TG3_EAV_REF_CLK_CORRECT_EN | + (neg_adj ? TG3_EAV_REF_CLK_CORRECT_NEG : 0) | correction); + else + tw32(TG3_EAV_REF_CLK_CORRECT_CTL, 0); + + tg3_full_unlock(tp); + + return 0; +} + +static int tg3_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + struct tg3 *tp = container_of(ptp, struct tg3, ptp_info); + + tg3_full_lock(tp, 0); + tp->ptp_adjust += delta; + tg3_full_unlock(tp); + + return 0; +} + +static int tg3_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts) +{ + u64 ns; + u32 remainder; + struct tg3 *tp = container_of(ptp, struct tg3, ptp_info); + + tg3_full_lock(tp, 0); + ns = tg3_refclk_read(tp); + ns += tp->ptp_adjust; + tg3_full_unlock(tp); + + ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); + ts->tv_nsec = remainder; + + return 0; +} + +static int tg3_ptp_settime(struct ptp_clock_info *ptp, + const struct timespec *ts) +{ + u64 ns; + struct tg3 *tp = container_of(ptp, struct tg3, ptp_info); + + ns = timespec_to_ns(ts); + + tg3_full_lock(tp, 0); + tg3_refclk_write(tp, ns); + tp->ptp_adjust = 0; + tg3_full_unlock(tp); + + return 0; +} + +static int tg3_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + return -EOPNOTSUPP; +} + +static const struct ptp_clock_info tg3_ptp_caps = { + .owner = THIS_MODULE, + .name = "tg3 clock", + .max_adj = 250000000, + .n_alarm = 0, + .n_ext_ts = 0, + .n_per_out = 0, + .pps = 0, + .adjfreq = tg3_ptp_adjfreq, + .adjtime = tg3_ptp_adjtime, + .gettime = tg3_ptp_gettime, + .settime = tg3_ptp_settime, + .enable = tg3_ptp_enable, +}; + +static void tg3_hwclock_to_timestamp(struct tg3 *tp, u64 hwclock, + struct skb_shared_hwtstamps *timestamp) +{ + memset(timestamp, 0, sizeof(struct skb_shared_hwtstamps)); + timestamp->hwtstamp = ns_to_ktime((hwclock & TG3_TSTAMP_MASK) + + tp->ptp_adjust); +} + +/* tp->lock must be held */ +static void tg3_ptp_init(struct tg3 *tp) +{ + if (!tg3_flag(tp, PTP_CAPABLE)) + return; + + /* Initialize the hardware clock to the system time. */ + tg3_refclk_write(tp, ktime_to_ns(ktime_get_real())); + tp->ptp_adjust = 0; + tp->ptp_info = tg3_ptp_caps; +} + +/* tp->lock must be held */ +static void tg3_ptp_resume(struct tg3 *tp) +{ + if (!tg3_flag(tp, PTP_CAPABLE)) + return; + + tg3_refclk_write(tp, ktime_to_ns(ktime_get_real()) + tp->ptp_adjust); + tp->ptp_adjust = 0; +} + +static void tg3_ptp_fini(struct tg3 *tp) +{ + if (!tg3_flag(tp, PTP_CAPABLE) || !tp->ptp_clock) + return; + + ptp_clock_unregister(tp->ptp_clock); + tp->ptp_clock = NULL; + tp->ptp_adjust = 0; +} + static inline int tg3_irq_sync(struct tg3 *tp) { return tp->irq_sync; @@ -5652,6 +5895,16 @@ static void tg3_tx(struct tg3_napi *tnapi) return; } + if (tnapi->tx_ring[sw_idx].len_flags & TXD_FLAG_HWTSTAMP) { + struct skb_shared_hwtstamps timestamp; + u64 hwclock = tr32(TG3_TX_TSTAMP_LSB); + hwclock |= (u64)tr32(TG3_TX_TSTAMP_MSB) << 32; + + tg3_hwclock_to_timestamp(tp, hwclock, ×tamp); + + skb_tstamp_tx(skb, ×tamp); + } + pci_unmap_single(tp->pdev, dma_unmap_addr(ri, mapping), skb_headlen(skb), @@ -5919,6 +6172,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) dma_addr_t dma_addr; u32 opaque_key, desc_idx, *post_ptr; u8 *data; + u64 tstamp = 0; desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; @@ -5953,6 +6207,14 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - ETH_FCS_LEN; + if ((desc->type_flags & RXD_FLAG_PTPSTAT_MASK) == + RXD_FLAG_PTPSTAT_PTPV1 || + (desc->type_flags & RXD_FLAG_PTPSTAT_MASK) == + RXD_FLAG_PTPSTAT_PTPV2) { + tstamp = tr32(TG3_RX_TSTAMP_LSB); + tstamp |= (u64)tr32(TG3_RX_TSTAMP_MSB) << 32; + } + if (len > TG3_RX_COPY_THRESH(tp)) { int skb_size; unsigned int frag_size; @@ -5996,6 +6258,10 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) } skb_put(skb, len); + if (tstamp) + tg3_hwclock_to_timestamp(tp, tstamp, + skb_hwtstamps(skb)); + if ((tp->dev->features & NETIF_F_RXCSUM) && (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) && (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK) @@ -6477,17 +6743,24 @@ static inline void tg3_netif_stop(struct tg3 *tp) { tp->dev->trans_start = jiffies; /* prevent tx timeout */ tg3_napi_disable(tp); + netif_carrier_off(tp->dev); netif_tx_disable(tp->dev); } +/* tp->lock must be held */ static inline void tg3_netif_start(struct tg3 *tp) { + tg3_ptp_resume(tp); + /* NOTE: unconditional netif_tx_wake_all_queues is only * appropriate so long as all callers are assured to * have free tx slots (such as after tg3_init_hw) */ netif_tx_wake_all_queues(tp->dev); + if (tp->link_up) + netif_carrier_on(tp->dev); + tg3_napi_enable(tp); tp->napi[0].hw_status->status |= SD_STATUS_UPDATED; tg3_enable_ints(tp); @@ -6689,6 +6962,9 @@ static void tg3_poll_controller(struct net_device *dev) int i; struct tg3 *tp = netdev_priv(dev); + if (tg3_irq_sync(tp)) + return; + for (i = 0; i < tp->irq_cnt; i++) tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]); } @@ -7046,6 +7322,12 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) vlan = vlan_tx_tag_get(skb); } + if ((unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) && + tg3_flag(tp, TX_TSTAMP_EN)) { + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + base_flags |= TXD_FLAG_HWTSTAMP; + } + len = skb_headlen(skb); mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE); @@ -8386,7 +8668,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq); tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq); - if (!netif_carrier_ok(tp->dev)) + if (!tp->link_up) val = 0; tw32(HOSTCC_STAT_COAL_TICKS, val); @@ -8662,14 +8944,14 @@ static void tg3_rss_check_indir_tbl(struct tg3 *tp) if (!tg3_flag(tp, SUPPORT_MSIX)) return; - if (tp->irq_cnt <= 2) { + if (tp->rxq_cnt == 1) { memset(&tp->rss_ind_tbl[0], 0, sizeof(tp->rss_ind_tbl)); return; } /* Validate table against current IRQ count */ for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) { - if (tp->rss_ind_tbl[i] >= tp->irq_cnt - 1) + if (tp->rss_ind_tbl[i] >= tp->rxq_cnt) break; } @@ -8914,9 +9196,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) */ tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; - tw32(GRC_MODE, - tp->grc_mode | - (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP)); + val = GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP; + if (tp->rxptpctl) + tw32(TG3_RX_PTP_CTL, + tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK); + + if (tg3_flag(tp, PTP_CAPABLE)) + val |= GRC_MODE_TIME_SYNC_ENABLE; + + tw32(GRC_MODE, tp->grc_mode | val); /* Setup the timer prescalar register. Clock is always 66Mhz. */ val = tr32(GRC_MISC_CFG); @@ -9679,7 +9967,7 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) { struct tg3_hw_stats *sp = tp->hw_stats; - if (!netif_carrier_ok(tp->dev)) + if (!tp->link_up) return; TG3_STAT_ADD32(&sp->tx_octets, MAC_TX_STATS_OCTETS); @@ -9823,11 +10111,11 @@ static void tg3_timer(unsigned long __opaque) u32 mac_stat = tr32(MAC_STATUS); int need_setup = 0; - if (netif_carrier_ok(tp->dev) && + if (tp->link_up && (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)) { need_setup = 1; } - if (!netif_carrier_ok(tp->dev) && + if (!tp->link_up && (mac_stat & (MAC_STATUS_PCS_SYNCED | MAC_STATUS_SIGNAL_DET))) { need_setup = 1; @@ -9890,7 +10178,7 @@ restart_timer: add_timer(&tp->timer); } -static void __devinit tg3_timer_init(struct tg3 *tp) +static void tg3_timer_init(struct tg3 *tp) { if (tg3_flag(tp, TAGGED_STATUS) && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && @@ -10316,7 +10604,8 @@ static void tg3_ints_fini(struct tg3 *tp) tg3_flag_clear(tp, ENABLE_TSS); } -static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq) +static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq, + bool init) { struct net_device *dev = tp->dev; int i, err; @@ -10395,6 +10684,12 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq) tg3_flag_set(tp, INIT_COMPLETE); tg3_enable_ints(tp); + if (init) + tg3_ptp_init(tp); + else + tg3_ptp_resume(tp); + + tg3_full_unlock(tp); netif_tx_start_all_queues(dev); @@ -10429,10 +10724,8 @@ static void tg3_stop(struct tg3 *tp) { int i; - tg3_napi_disable(tp); tg3_reset_task_cancel(tp); - - netif_tx_disable(tp->dev); + tg3_netif_stop(tp); tg3_timer_stop(tp); @@ -10481,7 +10774,7 @@ static int tg3_open(struct net_device *dev) } } - netif_carrier_off(tp->dev); + tg3_carrier_off(tp); err = tg3_power_up(tp); if (err) @@ -10494,11 +10787,19 @@ static int tg3_open(struct net_device *dev) tg3_full_unlock(tp); - err = tg3_start(tp, true, true); + err = tg3_start(tp, true, true, true); if (err) { tg3_frob_aux_power(tp, false); pci_set_power_state(tp->pdev, PCI_D3hot); } + + if (tg3_flag(tp, PTP_CAPABLE)) { + tp->ptp_clock = ptp_clock_register(&tp->ptp_info, + &tp->pdev->dev); + if (IS_ERR(tp->ptp_clock)) + tp->ptp_clock = NULL; + } + return err; } @@ -10506,6 +10807,8 @@ static int tg3_close(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); + tg3_ptp_fini(tp); + tg3_stop(tp); /* Clear stats across close / open calls */ @@ -10514,7 +10817,7 @@ static int tg3_close(struct net_device *dev) tg3_power_down(tp); - netif_carrier_off(tp->dev); + tg3_carrier_off(tp); return 0; } @@ -10888,7 +11191,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->advertising |= ADVERTISED_Asym_Pause; } } - if (netif_running(dev) && netif_carrier_ok(dev)) { + if (netif_running(dev) && tp->link_up) { ethtool_cmd_speed_set(cmd, tp->link_config.active_speed); cmd->duplex = tp->link_config.active_duplex; cmd->lp_advertising = tp->link_config.rmt_adv; @@ -11406,9 +11709,9 @@ static int tg3_set_channels(struct net_device *dev, tg3_stop(tp); - netif_carrier_off(dev); + tg3_carrier_off(tp); - tg3_start(tp, true, false); + tg3_start(tp, true, false, false); return 0; } @@ -11755,7 +12058,7 @@ static int tg3_test_link(struct tg3 *tp) max = TG3_COPPER_TIMEOUT_SEC; for (i = 0; i < max; i++) { - if (netif_carrier_ok(tp->dev)) + if (tp->link_up) return 0; if (msleep_interruptible(1000)) @@ -12326,19 +12629,19 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk) tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP; if (!netif_running(tp->dev)) { - data[0] = TG3_LOOPBACK_FAILED; - data[1] = TG3_LOOPBACK_FAILED; + data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED; + data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED; if (do_extlpbk) - data[2] = TG3_LOOPBACK_FAILED; + data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED; goto done; } err = tg3_reset_hw(tp, 1); if (err) { - data[0] = TG3_LOOPBACK_FAILED; - data[1] = TG3_LOOPBACK_FAILED; + data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED; + data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED; if (do_extlpbk) - data[2] = TG3_LOOPBACK_FAILED; + data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED; goto done; } @@ -12361,11 +12664,11 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk) tg3_mac_loopback(tp, true); if (tg3_run_loopback(tp, ETH_FRAME_LEN, false)) - data[0] |= TG3_STD_LOOPBACK_FAILED; + data[TG3_MAC_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED; if (tg3_flag(tp, JUMBO_RING_ENABLE) && tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false)) - data[0] |= TG3_JMB_LOOPBACK_FAILED; + data[TG3_MAC_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED; tg3_mac_loopback(tp, false); } @@ -12384,13 +12687,13 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk) } if (tg3_run_loopback(tp, ETH_FRAME_LEN, false)) - data[1] |= TG3_STD_LOOPBACK_FAILED; + data[TG3_PHY_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED; if (tg3_flag(tp, TSO_CAPABLE) && tg3_run_loopback(tp, ETH_FRAME_LEN, true)) - data[1] |= TG3_TSO_LOOPBACK_FAILED; + data[TG3_PHY_LOOPB_TEST] |= TG3_TSO_LOOPBACK_FAILED; if (tg3_flag(tp, JUMBO_RING_ENABLE) && tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false)) - data[1] |= TG3_JMB_LOOPBACK_FAILED; + data[TG3_PHY_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED; if (do_extlpbk) { tg3_phy_lpbk_set(tp, 0, true); @@ -12402,13 +12705,16 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk) mdelay(40); if (tg3_run_loopback(tp, ETH_FRAME_LEN, false)) - data[2] |= TG3_STD_LOOPBACK_FAILED; + data[TG3_EXT_LOOPB_TEST] |= + TG3_STD_LOOPBACK_FAILED; if (tg3_flag(tp, TSO_CAPABLE) && tg3_run_loopback(tp, ETH_FRAME_LEN, true)) - data[2] |= TG3_TSO_LOOPBACK_FAILED; + data[TG3_EXT_LOOPB_TEST] |= + TG3_TSO_LOOPBACK_FAILED; if (tg3_flag(tp, JUMBO_RING_ENABLE) && tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false)) - data[2] |= TG3_JMB_LOOPBACK_FAILED; + data[TG3_EXT_LOOPB_TEST] |= + TG3_JMB_LOOPBACK_FAILED; } /* Re-enable gphy autopowerdown. */ @@ -12416,7 +12722,8 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk) tg3_phy_toggle_apd(tp, true); } - err = (data[0] | data[1] | data[2]) ? -EIO : 0; + err = (data[TG3_MAC_LOOPB_TEST] | data[TG3_PHY_LOOPB_TEST] | + data[TG3_EXT_LOOPB_TEST]) ? -EIO : 0; done: tp->phy_flags |= eee_cap; @@ -12441,11 +12748,11 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, if (tg3_test_nvram(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; - data[0] = 1; + data[TG3_NVRAM_TEST] = 1; } if (!doextlpbk && tg3_test_link(tp)) { etest->flags |= ETH_TEST_FL_FAILED; - data[1] = 1; + data[TG3_LINK_TEST] = 1; } if (etest->flags & ETH_TEST_FL_OFFLINE) { int err, err2 = 0, irq_sync = 0; @@ -12457,7 +12764,6 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, } tg3_full_lock(tp, irq_sync); - tg3_halt(tp, RESET_KIND_SUSPEND, 1); err = tg3_nvram_lock(tp); tg3_halt_cpu(tp, RX_CPU_BASE); @@ -12471,25 +12777,25 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, if (tg3_test_registers(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; - data[2] = 1; + data[TG3_REGISTER_TEST] = 1; } if (tg3_test_memory(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; - data[3] = 1; + data[TG3_MEMORY_TEST] = 1; } if (doextlpbk) etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE; - if (tg3_test_loopback(tp, &data[4], doextlpbk)) + if (tg3_test_loopback(tp, data, doextlpbk)) etest->flags |= ETH_TEST_FL_FAILED; tg3_full_unlock(tp); if (tg3_test_interrupt(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; - data[7] = 1; + data[TG3_INTERRUPT_TEST] = 1; } tg3_full_lock(tp, 0); @@ -12512,6 +12818,96 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, } +static int tg3_hwtstamp_ioctl(struct net_device *dev, + struct ifreq *ifr, int cmd) +{ + struct tg3 *tp = netdev_priv(dev); + struct hwtstamp_config stmpconf; + + if (!tg3_flag(tp, PTP_CAPABLE)) + return -EINVAL; + + if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) + return -EFAULT; + + if (stmpconf.flags) + return -EINVAL; + + switch (stmpconf.tx_type) { + case HWTSTAMP_TX_ON: + tg3_flag_set(tp, TX_TSTAMP_EN); + break; + case HWTSTAMP_TX_OFF: + tg3_flag_clear(tp, TX_TSTAMP_EN); + break; + default: + return -ERANGE; + } + + switch (stmpconf.rx_filter) { + case HWTSTAMP_FILTER_NONE: + tp->rxptpctl = 0; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN | + TG3_RX_PTP_CTL_ALL_V1_EVENTS; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN | + TG3_RX_PTP_CTL_SYNC_EVNT; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN | + TG3_RX_PTP_CTL_DELAY_REQ; + break; + case HWTSTAMP_FILTER_PTP_V2_EVENT: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN | + TG3_RX_PTP_CTL_ALL_V2_EVENTS; + break; + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | + TG3_RX_PTP_CTL_ALL_V2_EVENTS; + break; + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | + TG3_RX_PTP_CTL_ALL_V2_EVENTS; + break; + case HWTSTAMP_FILTER_PTP_V2_SYNC: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN | + TG3_RX_PTP_CTL_SYNC_EVNT; + break; + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | + TG3_RX_PTP_CTL_SYNC_EVNT; + break; + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | + TG3_RX_PTP_CTL_SYNC_EVNT; + break; + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN | + TG3_RX_PTP_CTL_DELAY_REQ; + break; + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | + TG3_RX_PTP_CTL_DELAY_REQ; + break; + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | + TG3_RX_PTP_CTL_DELAY_REQ; + break; + default: + return -ERANGE; + } + + if (netif_running(dev) && tp->rxptpctl) + tw32(TG3_RX_PTP_CTL, + tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK); + + return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? + -EFAULT : 0; +} + static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mii_ioctl_data *data = if_mii(ifr); @@ -12562,6 +12958,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return err; + case SIOCSHWTSTAMP: + return tg3_hwtstamp_ioctl(dev, ifr, cmd); + default: /* do nothing */ break; @@ -12663,7 +13062,7 @@ static const struct ethtool_ops tg3_ethtool_ops = { .set_rxfh_indir = tg3_set_rxfh_indir, .get_channels = tg3_get_channels, .set_channels = tg3_set_channels, - .get_ts_info = ethtool_op_get_ts_info, + .get_ts_info = tg3_get_ts_info, }; static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, @@ -12779,7 +13178,7 @@ static const struct net_device_ops tg3_netdev_ops = { #endif }; -static void __devinit tg3_get_eeprom_size(struct tg3 *tp) +static void tg3_get_eeprom_size(struct tg3 *tp) { u32 cursize, val, magic; @@ -12813,7 +13212,7 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp) tp->nvram_size = cursize; } -static void __devinit tg3_get_nvram_size(struct tg3 *tp) +static void tg3_get_nvram_size(struct tg3 *tp) { u32 val; @@ -12846,7 +13245,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp) tp->nvram_size = TG3_NVRAM_SIZE_512KB; } -static void __devinit tg3_get_nvram_info(struct tg3 *tp) +static void tg3_get_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -12897,7 +13296,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp) } } -static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1) +static void tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1) { switch (nvmcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) { case FLASH_5752PAGE_SIZE_256: @@ -12924,7 +13323,7 @@ static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1) } } -static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) +static void tg3_get_5752_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -12965,7 +13364,7 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp) } } -static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) +static void tg3_get_5755_nvram_info(struct tg3 *tp) { u32 nvcfg1, protect = 0; @@ -13021,7 +13420,7 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp) } } -static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) +static void tg3_get_5787_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -13059,7 +13458,7 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp) } } -static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp) +static void tg3_get_5761_nvram_info(struct tg3 *tp) { u32 nvcfg1, protect = 0; @@ -13134,14 +13533,14 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp) } } -static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp) +static void tg3_get_5906_nvram_info(struct tg3 *tp) { tp->nvram_jedecnum = JEDEC_ATMEL; tg3_flag_set(tp, NVRAM_BUFFERED); tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE; } -static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp) +static void tg3_get_57780_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -13214,7 +13613,7 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp) } -static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) +static void tg3_get_5717_nvram_info(struct tg3 *tp) { u32 nvcfg1; @@ -13292,7 +13691,7 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp) tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS); } -static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) +static void tg3_get_5720_nvram_info(struct tg3 *tp) { u32 nvcfg1, nvmpinstrp; @@ -13405,7 +13804,7 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp) } /* Chips other than 5700/5701 use the NVRAM for fetching info. */ -static void __devinit tg3_nvram_init(struct tg3 *tp) +static void tg3_nvram_init(struct tg3 *tp) { tw32_f(GRC_EEPROM_ADDR, (EEPROM_ADDR_FSM_RESET | @@ -13475,7 +13874,7 @@ struct subsys_tbl_ent { u32 phy_id; }; -static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = { +static struct subsys_tbl_ent subsys_id_to_phy_id[] = { /* Broadcom boards. */ { TG3PCI_SUBVENDOR_ID_BROADCOM, TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, TG3_PHY_ID_BCM5401 }, @@ -13539,7 +13938,7 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = { TG3PCI_SUBDEVICE_ID_IBM_5703SAX2, 0 } }; -static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp) +static struct subsys_tbl_ent *tg3_lookup_by_subsys(struct tg3 *tp) { int i; @@ -13553,7 +13952,7 @@ static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp) return NULL; } -static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) +static void tg3_get_eeprom_hw_cfg(struct tg3 *tp) { u32 val; @@ -13753,7 +14152,7 @@ done: device_set_wakeup_capable(&tp->pdev->dev, false); } -static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd) +static int tg3_issue_otp_command(struct tg3 *tp, u32 cmd) { int i; u32 val; @@ -13776,7 +14175,7 @@ static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd) * configuration is a 32-bit value that straddles the alignment boundary. * We do two 32-bit reads and then shift and merge the results. */ -static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp) +static u32 tg3_read_otp_phycfg(struct tg3 *tp) { u32 bhalf_otp, thalf_otp; @@ -13802,7 +14201,7 @@ static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp) return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16); } -static void __devinit tg3_phy_init_link_config(struct tg3 *tp) +static void tg3_phy_init_link_config(struct tg3 *tp) { u32 adv = ADVERTISED_Autoneg; @@ -13829,7 +14228,7 @@ static void __devinit tg3_phy_init_link_config(struct tg3 *tp) tp->old_link = -1; } -static int __devinit tg3_phy_probe(struct tg3 *tp) +static int tg3_phy_probe(struct tg3 *tp) { u32 hw_phy_id_1, hw_phy_id_2; u32 hw_phy_id, hw_phy_id_masked; @@ -13957,7 +14356,7 @@ skip_phy_reset: return err; } -static void __devinit tg3_read_vpd(struct tg3 *tp) +static void tg3_read_vpd(struct tg3 *tp) { u8 *vpd_data; unsigned int block_end, rosize, len; @@ -14026,7 +14425,8 @@ out_not_found: out_no_vpd: if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { - if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717) + if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C) strcpy(tp->board_part_number, "BCM5717"); else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718) strcpy(tp->board_part_number, "BCM5718"); @@ -14077,7 +14477,7 @@ nomatch: } } -static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset) +static int tg3_fw_img_is_valid(struct tg3 *tp, u32 offset) { u32 val; @@ -14090,7 +14490,7 @@ static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset) return 1; } -static void __devinit tg3_read_bc_ver(struct tg3 *tp) +static void tg3_read_bc_ver(struct tg3 *tp) { u32 val, offset, start, ver_offset; int i, dst_off; @@ -14142,7 +14542,7 @@ static void __devinit tg3_read_bc_ver(struct tg3 *tp) } } -static void __devinit tg3_read_hwsb_ver(struct tg3 *tp) +static void tg3_read_hwsb_ver(struct tg3 *tp) { u32 val, major, minor; @@ -14158,7 +14558,7 @@ static void __devinit tg3_read_hwsb_ver(struct tg3 *tp) snprintf(&tp->fw_ver[0], 32, "sb v%d.%02d", major, minor); } -static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val) +static void tg3_read_sb_ver(struct tg3 *tp, u32 val) { u32 offset, major, minor, build; @@ -14213,7 +14613,7 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val) } } -static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp) +static void tg3_read_mgmtfw_ver(struct tg3 *tp) { u32 val, offset, start; int i, vlen; @@ -14265,7 +14665,7 @@ static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp) } } -static void __devinit tg3_probe_ncsi(struct tg3 *tp) +static void tg3_probe_ncsi(struct tg3 *tp) { u32 apedata; @@ -14281,7 +14681,7 @@ static void __devinit tg3_probe_ncsi(struct tg3 *tp) tg3_flag_set(tp, APE_HAS_NCSI); } -static void __devinit tg3_read_dash_ver(struct tg3 *tp) +static void tg3_read_dash_ver(struct tg3 *tp) { int vlen; u32 apedata; @@ -14304,7 +14704,7 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp) (apedata & APE_FW_VERSION_BLDMSK)); } -static void __devinit tg3_read_fw_ver(struct tg3 *tp) +static void tg3_read_fw_ver(struct tg3 *tp) { u32 val; bool vpd_vers = false; @@ -14357,7 +14757,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = { { }, }; -static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp) +static struct pci_dev *tg3_find_peer(struct tg3 *tp) { struct pci_dev *peer; unsigned int func, devnr = tp->pdev->devfn & ~7; @@ -14385,7 +14785,7 @@ static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp) return peer; } -static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg) +static void tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg) { tp->pci_chip_rev_id = misc_ctrl_reg >> MISC_HOST_CTRL_CHIPREV_SHIFT; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) { @@ -14397,6 +14797,7 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg) tg3_flag_set(tp, CPMU_PRESENT); if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720) @@ -14424,6 +14825,9 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg) if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW) tp->pci_chip_rev_id = CHIPREV_ID_5752_A0; + if (tp->pci_chip_rev_id == CHIPREV_ID_5717_C0) + tp->pci_chip_rev_id = CHIPREV_ID_5720_A0; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) @@ -14462,7 +14866,29 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg) tg3_flag_set(tp, 5705_PLUS); } -static int __devinit tg3_get_invariants(struct tg3 *tp) +static bool tg3_10_100_only_device(struct tg3 *tp, + const struct pci_device_id *ent) +{ + u32 grc_misc_cfg = tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK; + + if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 && + (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) || + (tp->phy_flags & TG3_PHYFLG_IS_FET)) + return true; + + if (ent->driver_data & TG3_DRV_DATA_FLAG_10_100_ONLY) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { + if (ent->driver_data & TG3_DRV_DATA_FLAG_5705_10_100) + return true; + } else { + return true; + } + } + + return false; +} + +static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent) { u32 misc_ctrl_reg; u32 pci_state_reg, grc_misc_cfg; @@ -15141,22 +15567,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) else tp->mac_mode = 0; - /* these are limited to 10/100 only */ - if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 && - (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) || - (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && - tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && - (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) || - (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && - (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 || - (tp->phy_flags & TG3_PHYFLG_IS_FET)) + if (tg3_10_100_only_device(tp, ent)) tp->phy_flags |= TG3_PHYFLG_10_100_ONLY; err = tg3_phy_probe(tp); @@ -15236,7 +15647,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } #ifdef CONFIG_SPARC -static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp) +static int tg3_get_macaddr_sparc(struct tg3 *tp) { struct net_device *dev = tp->dev; struct pci_dev *pdev = tp->pdev; @@ -15253,7 +15664,7 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp) return -ENODEV; } -static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp) +static int tg3_get_default_macaddr_sparc(struct tg3 *tp) { struct net_device *dev = tp->dev; @@ -15263,7 +15674,7 @@ static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp) } #endif -static int __devinit tg3_get_device_address(struct tg3 *tp) +static int tg3_get_device_address(struct tg3 *tp) { struct net_device *dev = tp->dev; u32 hi, lo, mac_offset; @@ -15342,7 +15753,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) #define BOUNDARY_SINGLE_CACHELINE 1 #define BOUNDARY_MULTI_CACHELINE 2 -static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val) +static u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val) { int cacheline_size; u8 byte; @@ -15483,7 +15894,8 @@ out: return val; } -static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device) +static int tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, + int size, int to_device) { struct tg3_internal_buffer_desc test_desc; u32 sram_dma_descs; @@ -15570,7 +15982,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_dma_wait_state_chipsets) = { { }, }; -static int __devinit tg3_test_dma(struct tg3 *tp) +static int tg3_test_dma(struct tg3 *tp) { dma_addr_t buf_dma; u32 *buf, saved_dma_rwctrl; @@ -15760,7 +16172,7 @@ out_nofree: return ret; } -static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) +static void tg3_init_bufmgr_config(struct tg3 *tp) { if (tg3_flag(tp, 57765_PLUS)) { tp->bufmgr_config.mbuf_read_dma_low_water = @@ -15816,7 +16228,7 @@ static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER; } -static char * __devinit tg3_phy_string(struct tg3 *tp) +static char *tg3_phy_string(struct tg3 *tp) { switch (tp->phy_id & TG3_PHY_ID_MASK) { case TG3_PHY_ID_BCM5400: return "5400"; @@ -15847,7 +16259,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) } } -static char * __devinit tg3_bus_string(struct tg3 *tp, char *str) +static char *tg3_bus_string(struct tg3 *tp, char *str) { if (tg3_flag(tp, PCI_EXPRESS)) { strcpy(str, "PCI Express"); @@ -15883,7 +16295,7 @@ static char * __devinit tg3_bus_string(struct tg3 *tp, char *str) return str; } -static void __devinit tg3_init_coal(struct tg3 *tp) +static void tg3_init_coal(struct tg3 *tp) { struct ethtool_coalesce *ec = &tp->coal; @@ -15914,7 +16326,7 @@ static void __devinit tg3_init_coal(struct tg3 *tp) } } -static int __devinit tg3_init_one(struct pci_dev *pdev, +static int tg3_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; @@ -15970,6 +16382,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->pm_cap = pm_cap; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; + tp->irq_sync = 1; if (tg3_debug > 0) tp->msg_enable = tg3_debug; @@ -16013,6 +16426,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761SE || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720) { @@ -16034,7 +16448,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, dev->netdev_ops = &tg3_netdev_ops; dev->irq = pdev->irq; - err = tg3_get_invariants(tp); + err = tg3_get_invariants(tp, ent); if (err) { dev_err(&pdev->dev, "Problem fetching invariants of chip, aborting\n"); @@ -16209,6 +16623,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) + tg3_flag_set(tp, PTP_CAPABLE); + if (tg3_flag(tp, 5717_PLUS)) { /* Resume a low-power mode */ tg3_frob_aux_power(tp, false); @@ -16293,7 +16711,7 @@ err_out_disable_pdev: return err; } -static void __devexit tg3_remove_one(struct pci_dev *pdev) +static void tg3_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -16534,8 +16952,8 @@ static void tg3_io_resume(struct pci_dev *pdev) tg3_full_lock(tp, 0); tg3_flag_set(tp, INIT_COMPLETE); err = tg3_restart_hw(tp, 1); - tg3_full_unlock(tp); if (err) { + tg3_full_unlock(tp); netdev_err(netdev, "Cannot restart hardware after reset.\n"); goto done; } @@ -16546,6 +16964,8 @@ static void tg3_io_resume(struct pci_dev *pdev) tg3_netif_start(tp); + tg3_full_unlock(tp); + tg3_phy_start(tp); done: @@ -16562,7 +16982,7 @@ static struct pci_driver tg3_driver = { .name = DRV_MODULE_NAME, .id_table = tg3_pci_tbl, .probe = tg3_init_one, - .remove = __devexit_p(tg3_remove_one), + .remove = tg3_remove_one, .err_handler = &tg3_err_handler, .driver.pm = TG3_PM_OPS, }; diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index d9308c32102e..d330e81f5793 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -44,12 +44,14 @@ #define TG3PCI_DEVICE_TIGON3_5761S 0x1688 #define TG3PCI_DEVICE_TIGON3_5761SE 0x1689 #define TG3PCI_DEVICE_TIGON3_57780 0x1692 +#define TG3PCI_DEVICE_TIGON3_5787M 0x1693 #define TG3PCI_DEVICE_TIGON3_57760 0x1690 #define TG3PCI_DEVICE_TIGON3_57790 0x1694 #define TG3PCI_DEVICE_TIGON3_57788 0x1691 #define TG3PCI_DEVICE_TIGON3_5785_G 0x1699 /* GPHY */ #define TG3PCI_DEVICE_TIGON3_5785_F 0x16a0 /* 10/100 only */ #define TG3PCI_DEVICE_TIGON3_5717 0x1655 +#define TG3PCI_DEVICE_TIGON3_5717_C 0x1665 #define TG3PCI_DEVICE_TIGON3_5718 0x1656 #define TG3PCI_DEVICE_TIGON3_57781 0x16b1 #define TG3PCI_DEVICE_TIGON3_57785 0x16b5 @@ -95,6 +97,10 @@ #define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2 0x0099 #define TG3PCI_SUBVENDOR_ID_IBM PCI_VENDOR_ID_IBM #define TG3PCI_SUBDEVICE_ID_IBM_5703SAX2 0x0281 +#define TG3PCI_SUBDEVICE_ID_ACER_57780_A 0x0601 +#define TG3PCI_SUBDEVICE_ID_ACER_57780_B 0x0612 +#define TG3PCI_SUBDEVICE_ID_LENOVO_5787M 0x3056 + /* 0x30 --> 0x64 unused */ #define TG3PCI_MSI_DATA 0x00000064 /* 0x66 --> 0x68 unused */ @@ -149,6 +155,7 @@ #define CHIPREV_ID_57780_A0 0x57780000 #define CHIPREV_ID_57780_A1 0x57780001 #define CHIPREV_ID_5717_A0 0x05717000 +#define CHIPREV_ID_5717_C0 0x05717200 #define CHIPREV_ID_57765_A0 0x57785000 #define CHIPREV_ID_5719_A0 0x05719000 #define CHIPREV_ID_5720_A0 0x05720000 @@ -765,7 +772,10 @@ #define SG_DIG_MAC_ACK_STATUS 0x00000004 #define SG_DIG_AUTONEG_COMPLETE 0x00000002 #define SG_DIG_AUTONEG_ERROR 0x00000001 -/* 0x5b8 --> 0x600 unused */ +#define TG3_TX_TSTAMP_LSB 0x000005c0 +#define TG3_TX_TSTAMP_MSB 0x000005c4 +#define TG3_TSTAMP_MASK 0x7fffffffffffffff +/* 0x5c8 --> 0x600 unused */ #define MAC_TX_MAC_STATE_BASE 0x00000600 /* 16 bytes */ #define MAC_RX_MAC_STATE_BASE 0x00000610 /* 20 bytes */ /* 0x624 --> 0x670 unused */ @@ -782,7 +792,36 @@ #define MAC_RSS_HASH_KEY_7 0x0000068c #define MAC_RSS_HASH_KEY_8 0x00000690 #define MAC_RSS_HASH_KEY_9 0x00000694 -/* 0x698 --> 0x800 unused */ +/* 0x698 --> 0x6b0 unused */ + +#define TG3_RX_TSTAMP_LSB 0x000006b0 +#define TG3_RX_TSTAMP_MSB 0x000006b4 +/* 0x6b8 --> 0x6c8 unused */ + +#define TG3_RX_PTP_CTL 0x000006c8 +#define TG3_RX_PTP_CTL_SYNC_EVNT 0x00000001 +#define TG3_RX_PTP_CTL_DELAY_REQ 0x00000002 +#define TG3_RX_PTP_CTL_PDLAY_REQ 0x00000004 +#define TG3_RX_PTP_CTL_PDLAY_RES 0x00000008 +#define TG3_RX_PTP_CTL_ALL_V1_EVENTS (TG3_RX_PTP_CTL_SYNC_EVNT | \ + TG3_RX_PTP_CTL_DELAY_REQ) +#define TG3_RX_PTP_CTL_ALL_V2_EVENTS (TG3_RX_PTP_CTL_SYNC_EVNT | \ + TG3_RX_PTP_CTL_DELAY_REQ | \ + TG3_RX_PTP_CTL_PDLAY_REQ | \ + TG3_RX_PTP_CTL_PDLAY_RES) +#define TG3_RX_PTP_CTL_FOLLOW_UP 0x00000100 +#define TG3_RX_PTP_CTL_DELAY_RES 0x00000200 +#define TG3_RX_PTP_CTL_PDRES_FLW_UP 0x00000400 +#define TG3_RX_PTP_CTL_ANNOUNCE 0x00000800 +#define TG3_RX_PTP_CTL_SIGNALING 0x00001000 +#define TG3_RX_PTP_CTL_MANAGEMENT 0x00002000 +#define TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN 0x00800000 +#define TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN 0x01000000 +#define TG3_RX_PTP_CTL_RX_PTP_V2_EN (TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | \ + TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN) +#define TG3_RX_PTP_CTL_RX_PTP_V1_EN 0x02000000 +#define TG3_RX_PTP_CTL_HWTS_INTERLOCK 0x04000000 +/* 0x6cc --> 0x800 unused */ #define MAC_TX_STATS_OCTETS 0x00000800 #define MAC_TX_STATS_RESV1 0x00000804 @@ -1662,6 +1701,7 @@ #define GRC_MODE_HOST_STACKUP 0x00010000 #define GRC_MODE_HOST_SENDBDS 0x00020000 #define GRC_MODE_HTX2B_ENABLE 0x00040000 +#define GRC_MODE_TIME_SYNC_ENABLE 0x00080000 #define GRC_MODE_NO_TX_PHDR_CSUM 0x00100000 #define GRC_MODE_NVRAM_WR_ENABLE 0x00200000 #define GRC_MODE_PCIE_TL_SEL 0x00000000 @@ -1764,7 +1804,17 @@ #define GRC_VCPU_EXT_CTRL_DISABLE_WOL 0x20000000 #define GRC_FASTBOOT_PC 0x00006894 /* 5752, 5755, 5787 */ -/* 0x6c00 --> 0x7000 unused */ +#define TG3_EAV_REF_CLCK_LSB 0x00006900 +#define TG3_EAV_REF_CLCK_MSB 0x00006904 +#define TG3_EAV_REF_CLCK_CTL 0x00006908 +#define TG3_EAV_REF_CLCK_CTL_STOP 0x00000002 +#define TG3_EAV_REF_CLCK_CTL_RESUME 0x00000004 +#define TG3_EAV_REF_CLK_CORRECT_CTL 0x00006928 +#define TG3_EAV_REF_CLK_CORRECT_EN (1 << 31) +#define TG3_EAV_REF_CLK_CORRECT_NEG (1 << 30) + +#define TG3_EAV_REF_CLK_CORRECT_MASK 0xffffff +/* 0x690c --> 0x7000 unused */ /* NVRAM Control registers */ #define NVRAM_CMD 0x00007000 @@ -2432,6 +2482,7 @@ struct tg3_tx_buffer_desc { #define TXD_FLAG_IP_FRAG 0x0008 #define TXD_FLAG_JMB_PKT 0x0008 #define TXD_FLAG_IP_FRAG_END 0x0010 +#define TXD_FLAG_HWTSTAMP 0x0020 #define TXD_FLAG_VLAN 0x0040 #define TXD_FLAG_COAL_NOW 0x0080 #define TXD_FLAG_CPU_PRE_DMA 0x0100 @@ -2473,6 +2524,9 @@ struct tg3_rx_buffer_desc { #define RXD_FLAG_IP_CSUM 0x1000 #define RXD_FLAG_TCPUDP_CSUM 0x2000 #define RXD_FLAG_IS_TCP 0x4000 +#define RXD_FLAG_PTPSTAT_MASK 0x0210 +#define RXD_FLAG_PTPSTAT_PTPV1 0x0010 +#define RXD_FLAG_PTPSTAT_PTPV2 0x0200 u32 ip_tcp_csum; #define RXD_IPCSUM_MASK 0xffff0000 @@ -2963,9 +3017,11 @@ enum TG3_FLAGS { TG3_FLAG_USE_JUMBO_BDFLAG, TG3_FLAG_L1PLLPD_EN, TG3_FLAG_APE_HAS_NCSI, + TG3_FLAG_TX_TSTAMP_EN, TG3_FLAG_4K_FIFO_LIMIT, TG3_FLAG_5719_RDMA_BUG, TG3_FLAG_RESET_TASK_PENDING, + TG3_FLAG_PTP_CAPABLE, TG3_FLAG_5705_PLUS, TG3_FLAG_IS_5788, TG3_FLAG_5750_PLUS, @@ -3034,6 +3090,10 @@ struct tg3 { u32 coal_now; u32 msg_enable; + struct ptp_clock_info ptp_info; + struct ptp_clock *ptp_clock; + s64 ptp_adjust; + /* begin "tx thread" cacheline section */ void (*write32_tx_mbox) (struct tg3 *, u32, u32); @@ -3101,6 +3161,7 @@ struct tg3 { u32 dma_rwctrl; u32 coalesce_mode; u32 pwrmgmt_thresh; + u32 rxptpctl; /* PCI block */ u32 pci_chip_rev_id; @@ -3262,6 +3323,7 @@ struct tg3 { #if IS_ENABLED(CONFIG_HWMON) struct device *hwmon_dev; #endif + bool link_up; }; #endif /* !(_T3_H) */ diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c index 959c58ef972a..3227fdde521b 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c @@ -2273,7 +2273,6 @@ bfa_ioc_get_type(struct bfa_ioc *ioc) static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num) { - memset(serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN); memcpy(serial_num, (void *)ioc->attr->brcd_serialnum, BFA_ADAPTER_SERIAL_NUM_LEN); @@ -2282,7 +2281,6 @@ bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num) static void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver) { - memset(fw_ver, 0, BFA_VERSION_LEN); memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN); } @@ -2304,7 +2302,6 @@ bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev) static void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver) { - memset(optrom_ver, 0, BFA_VERSION_LEN); memcpy(optrom_ver, ioc->attr->optrom_version, BFA_VERSION_LEN); } @@ -2312,7 +2309,6 @@ bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver) static void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer) { - memset(manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN); memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); } diff --git a/drivers/net/ethernet/brocade/bna/bfi_enet.h b/drivers/net/ethernet/brocade/bna/bfi_enet.h index eef6e1f8aecc..7d10e335c27d 100644 --- a/drivers/net/ethernet/brocade/bna/bfi_enet.h +++ b/drivers/net/ethernet/brocade/bna/bfi_enet.h @@ -787,6 +787,7 @@ struct bfi_enet_stats_bpc { /* MAC Rx Statistics */ struct bfi_enet_stats_mac { + u64 stats_clr_cnt; /* times this stats cleared */ u64 frame_64; /* both rx and tx counter */ u64 frame_65_127; /* both rx and tx counter */ u64 frame_128_255; /* both rx and tx counter */ diff --git a/drivers/net/ethernet/brocade/bna/bna.h b/drivers/net/ethernet/brocade/bna/bna.h index ede532b4e9db..25dae757e9c4 100644 --- a/drivers/net/ethernet/brocade/bna/bna.h +++ b/drivers/net/ethernet/brocade/bna/bna.h @@ -138,6 +138,8 @@ do { \ #define BNA_QE_INDX_ADD(_qe_idx, _qe_num, _q_depth) \ ((_qe_idx) = ((_qe_idx) + (_qe_num)) & ((_q_depth) - 1)) +#define BNA_QE_INDX_INC(_idx, _q_depth) BNA_QE_INDX_ADD(_idx, 1, _q_depth) + #define BNA_Q_INDEX_CHANGE(_old_idx, _updated_idx, _q_depth) \ (((_updated_idx) - (_old_idx)) & ((_q_depth) - 1)) diff --git a/drivers/net/ethernet/brocade/bna/bna_hw_defs.h b/drivers/net/ethernet/brocade/bna/bna_hw_defs.h index b8c4e21fbf4c..af3f7bb0b3b8 100644 --- a/drivers/net/ethernet/brocade/bna/bna_hw_defs.h +++ b/drivers/net/ethernet/brocade/bna/bna_hw_defs.h @@ -46,7 +46,8 @@ #define BFI_MAX_INTERPKT_COUNT 0xFF #define BFI_MAX_INTERPKT_TIMEO 0xF /* in 0.5us units */ #define BFI_TX_COALESCING_TIMEO 20 /* 20 * 5 = 100us */ -#define BFI_TX_INTERPKT_COUNT 32 +#define BFI_TX_INTERPKT_COUNT 12 /* Pkt Cnt = 12 */ +#define BFI_TX_INTERPKT_TIMEO 15 /* 15 * 0.5 = 7.5us */ #define BFI_RX_COALESCING_TIMEO 12 /* 12 * 5 = 60us */ #define BFI_RX_INTERPKT_COUNT 6 /* Pkt Cnt = 6 */ #define BFI_RX_INTERPKT_TIMEO 3 /* 3 * 0.5 = 1.5us */ diff --git a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c index 71144b396e02..ea6f4a036401 100644 --- a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c +++ b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c @@ -1355,6 +1355,8 @@ bfa_fsm_state_decl(bna_rx, stopped, struct bna_rx, enum bna_rx_event); bfa_fsm_state_decl(bna_rx, start_wait, struct bna_rx, enum bna_rx_event); +bfa_fsm_state_decl(bna_rx, start_stop_wait, + struct bna_rx, enum bna_rx_event); bfa_fsm_state_decl(bna_rx, rxf_start_wait, struct bna_rx, enum bna_rx_event); bfa_fsm_state_decl(bna_rx, started, @@ -1432,7 +1434,7 @@ static void bna_rx_sm_start_wait(struct bna_rx *rx, { switch (event) { case RX_E_STOP: - bfa_fsm_set_state(rx, bna_rx_sm_stop_wait); + bfa_fsm_set_state(rx, bna_rx_sm_start_stop_wait); break; case RX_E_FAIL: @@ -1488,6 +1490,29 @@ bna_rx_sm_rxf_stop_wait(struct bna_rx *rx, enum bna_rx_event event) } +static void +bna_rx_sm_start_stop_wait_entry(struct bna_rx *rx) +{ +} + +static void +bna_rx_sm_start_stop_wait(struct bna_rx *rx, enum bna_rx_event event) +{ + switch (event) { + case RX_E_FAIL: + case RX_E_STOPPED: + bfa_fsm_set_state(rx, bna_rx_sm_stopped); + break; + + case RX_E_STARTED: + bna_rx_enet_stop(rx); + break; + + default: + bfa_sm_fault(event); + } +} + void bna_rx_sm_started_entry(struct bna_rx *rx) { @@ -1908,6 +1933,9 @@ bna_rxq_qpt_setup(struct bna_rxq *rxq, struct bna_mem_descr *swqpt_mem, struct bna_mem_descr *page_mem) { + u8 *kva; + u64 dma; + struct bna_dma_addr bna_dma; int i; rxq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb; @@ -1917,13 +1945,21 @@ bna_rxq_qpt_setup(struct bna_rxq *rxq, rxq->qpt.page_size = page_size; rxq->rcb->sw_qpt = (void **) swqpt_mem->kva; + rxq->rcb->sw_q = page_mem->kva; + + kva = page_mem->kva; + BNA_GET_DMA_ADDR(&page_mem->dma, dma); for (i = 0; i < rxq->qpt.page_count; i++) { - rxq->rcb->sw_qpt[i] = page_mem[i].kva; + rxq->rcb->sw_qpt[i] = kva; + kva += PAGE_SIZE; + + BNA_SET_DMA_ADDR(dma, &bna_dma); ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].lsb = - page_mem[i].dma.lsb; + bna_dma.lsb; ((struct bna_dma_addr *)rxq->qpt.kv_qpt_ptr)[i].msb = - page_mem[i].dma.msb; + bna_dma.msb; + dma += PAGE_SIZE; } } @@ -1935,6 +1971,9 @@ bna_rxp_cqpt_setup(struct bna_rxp *rxp, struct bna_mem_descr *swqpt_mem, struct bna_mem_descr *page_mem) { + u8 *kva; + u64 dma; + struct bna_dma_addr bna_dma; int i; rxp->cq.qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb; @@ -1944,14 +1983,21 @@ bna_rxp_cqpt_setup(struct bna_rxp *rxp, rxp->cq.qpt.page_size = page_size; rxp->cq.ccb->sw_qpt = (void **) swqpt_mem->kva; + rxp->cq.ccb->sw_q = page_mem->kva; + + kva = page_mem->kva; + BNA_GET_DMA_ADDR(&page_mem->dma, dma); for (i = 0; i < rxp->cq.qpt.page_count; i++) { - rxp->cq.ccb->sw_qpt[i] = page_mem[i].kva; + rxp->cq.ccb->sw_qpt[i] = kva; + kva += PAGE_SIZE; + BNA_SET_DMA_ADDR(dma, &bna_dma); ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].lsb = - page_mem[i].dma.lsb; + bna_dma.lsb; ((struct bna_dma_addr *)rxp->cq.qpt.kv_qpt_ptr)[i].msb = - page_mem[i].dma.msb; + bna_dma.msb; + dma += PAGE_SIZE; } } @@ -2250,8 +2296,8 @@ bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info) res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_type = BNA_RES_T_MEM; mem_info = &res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info; mem_info->mem_type = BNA_MEM_T_DMA; - mem_info->len = PAGE_SIZE; - mem_info->num = cpage_count * q_cfg->num_paths; + mem_info->len = PAGE_SIZE * cpage_count; + mem_info->num = q_cfg->num_paths; res_info[BNA_RX_RES_MEM_T_DQPT].res_type = BNA_RES_T_MEM; mem_info = &res_info[BNA_RX_RES_MEM_T_DQPT].res_u.mem_info; @@ -2268,8 +2314,8 @@ bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info) res_info[BNA_RX_RES_MEM_T_DPAGE].res_type = BNA_RES_T_MEM; mem_info = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info; mem_info->mem_type = BNA_MEM_T_DMA; - mem_info->len = PAGE_SIZE; - mem_info->num = dpage_count * q_cfg->num_paths; + mem_info->len = PAGE_SIZE * dpage_count; + mem_info->num = q_cfg->num_paths; res_info[BNA_RX_RES_MEM_T_HQPT].res_type = BNA_RES_T_MEM; mem_info = &res_info[BNA_RX_RES_MEM_T_HQPT].res_u.mem_info; @@ -2286,8 +2332,8 @@ bna_rx_res_req(struct bna_rx_config *q_cfg, struct bna_res_info *res_info) res_info[BNA_RX_RES_MEM_T_HPAGE].res_type = BNA_RES_T_MEM; mem_info = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info; mem_info->mem_type = BNA_MEM_T_DMA; - mem_info->len = (hpage_count ? PAGE_SIZE : 0); - mem_info->num = (hpage_count ? (hpage_count * q_cfg->num_paths) : 0); + mem_info->len = PAGE_SIZE * hpage_count; + mem_info->num = (hpage_count ? q_cfg->num_paths : 0); res_info[BNA_RX_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM; mem_info = &res_info[BNA_RX_RES_MEM_T_IBIDX].res_u.mem_info; @@ -2332,7 +2378,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad, struct bna_mem_descr *dsqpt_mem; struct bna_mem_descr *hpage_mem; struct bna_mem_descr *dpage_mem; - int i, cpage_idx = 0, dpage_idx = 0, hpage_idx = 0; + int i; int dpage_count, hpage_count, rcb_idx; if (!bna_rx_res_check(rx_mod, rx_cfg)) @@ -2352,14 +2398,14 @@ bna_rx_create(struct bna *bna, struct bnad *bnad, hpage_mem = &res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.mdl[0]; dpage_mem = &res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.mdl[0]; - page_count = res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.num / - rx_cfg->num_paths; + page_count = res_info[BNA_RX_RES_MEM_T_CQPT_PAGE].res_u.mem_info.len / + PAGE_SIZE; - dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.num / - rx_cfg->num_paths; + dpage_count = res_info[BNA_RX_RES_MEM_T_DPAGE].res_u.mem_info.len / + PAGE_SIZE; - hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.num / - rx_cfg->num_paths; + hpage_count = res_info[BNA_RX_RES_MEM_T_HPAGE].res_u.mem_info.len / + PAGE_SIZE; rx = bna_rx_get(rx_mod, rx_cfg->rx_type); rx->bna = bna; @@ -2446,10 +2492,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad, q0->rx_packets_with_error = q0->rxbuf_alloc_failed = 0; bna_rxq_qpt_setup(q0, rxp, dpage_count, PAGE_SIZE, - &dqpt_mem[i], &dsqpt_mem[i], &dpage_mem[dpage_idx]); - q0->rcb->page_idx = dpage_idx; - q0->rcb->page_count = dpage_count; - dpage_idx += dpage_count; + &dqpt_mem[i], &dsqpt_mem[i], &dpage_mem[i]); if (rx->rcb_setup_cbfn) rx->rcb_setup_cbfn(bnad, q0->rcb); @@ -2475,10 +2518,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad, bna_rxq_qpt_setup(q1, rxp, hpage_count, PAGE_SIZE, &hqpt_mem[i], &hsqpt_mem[i], - &hpage_mem[hpage_idx]); - q1->rcb->page_idx = hpage_idx; - q1->rcb->page_count = hpage_count; - hpage_idx += hpage_count; + &hpage_mem[i]); if (rx->rcb_setup_cbfn) rx->rcb_setup_cbfn(bnad, q1->rcb); @@ -2510,10 +2550,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad, rxp->cq.ccb->id = i; bna_rxp_cqpt_setup(rxp, page_count, PAGE_SIZE, - &cqpt_mem[i], &cswqpt_mem[i], &cpage_mem[cpage_idx]); - rxp->cq.ccb->page_idx = cpage_idx; - rxp->cq.ccb->page_count = page_count; - cpage_idx += page_count; + &cqpt_mem[i], &cswqpt_mem[i], &cpage_mem[i]); if (rx->ccb_setup_cbfn) rx->ccb_setup_cbfn(bnad, rxp->cq.ccb); @@ -3230,6 +3267,9 @@ bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size, struct bna_mem_descr *swqpt_mem, struct bna_mem_descr *page_mem) { + u8 *kva; + u64 dma; + struct bna_dma_addr bna_dma; int i; txq->qpt.hw_qpt_ptr.lsb = qpt_mem->dma.lsb; @@ -3239,14 +3279,21 @@ bna_txq_qpt_setup(struct bna_txq *txq, int page_count, int page_size, txq->qpt.page_size = page_size; txq->tcb->sw_qpt = (void **) swqpt_mem->kva; + txq->tcb->sw_q = page_mem->kva; + + kva = page_mem->kva; + BNA_GET_DMA_ADDR(&page_mem->dma, dma); for (i = 0; i < page_count; i++) { - txq->tcb->sw_qpt[i] = page_mem[i].kva; + txq->tcb->sw_qpt[i] = kva; + kva += PAGE_SIZE; + BNA_SET_DMA_ADDR(dma, &bna_dma); ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].lsb = - page_mem[i].dma.lsb; + bna_dma.lsb; ((struct bna_dma_addr *)txq->qpt.kv_qpt_ptr)[i].msb = - page_mem[i].dma.msb; + bna_dma.msb; + dma += PAGE_SIZE; } } @@ -3430,8 +3477,8 @@ bna_tx_res_req(int num_txq, int txq_depth, struct bna_res_info *res_info) res_info[BNA_TX_RES_MEM_T_PAGE].res_type = BNA_RES_T_MEM; mem_info = &res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info; mem_info->mem_type = BNA_MEM_T_DMA; - mem_info->len = PAGE_SIZE; - mem_info->num = num_txq * page_count; + mem_info->len = PAGE_SIZE * page_count; + mem_info->num = num_txq; res_info[BNA_TX_RES_MEM_T_IBIDX].res_type = BNA_RES_T_MEM; mem_info = &res_info[BNA_TX_RES_MEM_T_IBIDX].res_u.mem_info; @@ -3457,14 +3504,11 @@ bna_tx_create(struct bna *bna, struct bnad *bnad, struct bna_txq *txq; struct list_head *qe; int page_count; - int page_size; - int page_idx; int i; intr_info = &res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info; - page_count = (res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.num) / - tx_cfg->num_txq; - page_size = res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.len; + page_count = (res_info[BNA_TX_RES_MEM_T_PAGE].res_u.mem_info.len) / + PAGE_SIZE; /** * Get resources @@ -3529,7 +3573,6 @@ bna_tx_create(struct bna *bna, struct bnad *bnad, /* TxQ */ i = 0; - page_idx = 0; list_for_each(qe, &tx->txq_q) { txq = (struct bna_txq *)qe; txq->tcb = (struct bna_tcb *) @@ -3551,7 +3594,7 @@ bna_tx_create(struct bna *bna, struct bnad *bnad, if (intr_info->intr_type == BNA_INTR_T_INTX) txq->ib.intr_vector = (1 << txq->ib.intr_vector); txq->ib.coalescing_timeo = tx_cfg->coalescing_timeo; - txq->ib.interpkt_timeo = 0; /* Not used */ + txq->ib.interpkt_timeo = BFI_TX_INTERPKT_TIMEO; txq->ib.interpkt_count = BFI_TX_INTERPKT_COUNT; /* TCB */ @@ -3569,14 +3612,11 @@ bna_tx_create(struct bna *bna, struct bnad *bnad, txq->tcb->id = i; /* QPT, SWQPT, Pages */ - bna_txq_qpt_setup(txq, page_count, page_size, + bna_txq_qpt_setup(txq, page_count, PAGE_SIZE, &res_info[BNA_TX_RES_MEM_T_QPT].res_u.mem_info.mdl[i], &res_info[BNA_TX_RES_MEM_T_SWQPT].res_u.mem_info.mdl[i], &res_info[BNA_TX_RES_MEM_T_PAGE]. - res_u.mem_info.mdl[page_idx]); - txq->tcb->page_idx = page_idx; - txq->tcb->page_count = page_count; - page_idx += page_count; + res_u.mem_info.mdl[i]); /* Callback to bnad for setting up TCB */ if (tx->tcb_setup_cbfn) diff --git a/drivers/net/ethernet/brocade/bna/bna_types.h b/drivers/net/ethernet/brocade/bna/bna_types.h index d3eb8bddfb2a..dc50f7836b6d 100644 --- a/drivers/net/ethernet/brocade/bna/bna_types.h +++ b/drivers/net/ethernet/brocade/bna/bna_types.h @@ -430,6 +430,7 @@ struct bna_ib { struct bna_tcb { /* Fast path */ void **sw_qpt; + void *sw_q; void *unmap_q; u32 producer_index; u32 consumer_index; @@ -437,8 +438,6 @@ struct bna_tcb { u32 q_depth; void __iomem *q_dbell; struct bna_ib_dbell *i_dbell; - int page_idx; - int page_count; /* Control path */ struct bna_txq *txq; struct bnad *bnad; @@ -563,13 +562,12 @@ struct bna_tx_mod { struct bna_rcb { /* Fast path */ void **sw_qpt; + void *sw_q; void *unmap_q; u32 producer_index; u32 consumer_index; u32 q_depth; void __iomem *q_dbell; - int page_idx; - int page_count; /* Control path */ struct bna_rxq *rxq; struct bna_ccb *ccb; @@ -626,6 +624,7 @@ struct bna_pkt_rate { struct bna_ccb { /* Fast path */ void **sw_qpt; + void *sw_q; u32 producer_index; volatile u32 *hw_producer_index; u32 q_depth; @@ -633,8 +632,6 @@ struct bna_ccb { struct bna_rcb *rcb[2]; void *ctrl; /* For bnad */ struct bna_pkt_rate pkt_rate; - int page_idx; - int page_count; /* Control path */ struct bna_cq *cq; diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index ce1eac529470..7cce42dc2f20 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -61,23 +61,17 @@ static const u8 bnad_bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* * Local MACROS */ -#define BNAD_TX_UNMAPQ_DEPTH (bnad->txq_depth * 2) - -#define BNAD_RX_UNMAPQ_DEPTH (bnad->rxq_depth) - #define BNAD_GET_MBOX_IRQ(_bnad) \ (((_bnad)->cfg_flags & BNAD_CF_MSIX) ? \ ((_bnad)->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector) : \ ((_bnad)->pcidev->irq)) -#define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _depth) \ +#define BNAD_FILL_UNMAPQ_MEM_REQ(_res_info, _num, _size) \ do { \ (_res_info)->res_type = BNA_RES_T_MEM; \ (_res_info)->res_u.mem_info.mem_type = BNA_MEM_T_KVA; \ (_res_info)->res_u.mem_info.num = (_num); \ - (_res_info)->res_u.mem_info.len = \ - sizeof(struct bnad_unmap_q) + \ - (sizeof(struct bnad_skb_unmap) * ((_depth) - 1)); \ + (_res_info)->res_u.mem_info.len = (_size); \ } while (0) static void @@ -103,48 +97,58 @@ bnad_remove_from_list(struct bnad *bnad) static void bnad_cq_cleanup(struct bnad *bnad, struct bna_ccb *ccb) { - struct bna_cq_entry *cmpl, *next_cmpl; - unsigned int wi_range, wis = 0, ccb_prod = 0; + struct bna_cq_entry *cmpl; int i; - BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt, cmpl, - wi_range); - for (i = 0; i < ccb->q_depth; i++) { - wis++; - if (likely(--wi_range)) - next_cmpl = cmpl + 1; - else { - BNA_QE_INDX_ADD(ccb_prod, wis, ccb->q_depth); - wis = 0; - BNA_CQ_QPGE_PTR_GET(ccb_prod, ccb->sw_qpt, - next_cmpl, wi_range); - } + cmpl = &((struct bna_cq_entry *)ccb->sw_q)[i]; cmpl->valid = 0; - cmpl = next_cmpl; } } +/* Tx Datapath functions */ + + +/* Caller should ensure that the entry at unmap_q[index] is valid */ static u32 -bnad_pci_unmap_skb(struct device *pdev, struct bnad_skb_unmap *array, - u32 index, u32 depth, struct sk_buff *skb, u32 frag) +bnad_tx_buff_unmap(struct bnad *bnad, + struct bnad_tx_unmap *unmap_q, + u32 q_depth, u32 index) { - int j; - array[index].skb = NULL; - - dma_unmap_single(pdev, dma_unmap_addr(&array[index], dma_addr), - skb_headlen(skb), DMA_TO_DEVICE); - dma_unmap_addr_set(&array[index], dma_addr, 0); - BNA_QE_INDX_ADD(index, 1, depth); + struct bnad_tx_unmap *unmap; + struct sk_buff *skb; + int vector, nvecs; + + unmap = &unmap_q[index]; + nvecs = unmap->nvecs; + + skb = unmap->skb; + unmap->skb = NULL; + unmap->nvecs = 0; + dma_unmap_single(&bnad->pcidev->dev, + dma_unmap_addr(&unmap->vectors[0], dma_addr), + skb_headlen(skb), DMA_TO_DEVICE); + dma_unmap_addr_set(&unmap->vectors[0], dma_addr, 0); + nvecs--; + + vector = 0; + while (nvecs) { + vector++; + if (vector == BFI_TX_MAX_VECTORS_PER_WI) { + vector = 0; + BNA_QE_INDX_INC(index, q_depth); + unmap = &unmap_q[index]; + } - for (j = 0; j < frag; j++) { - dma_unmap_page(pdev, dma_unmap_addr(&array[index], dma_addr), - skb_frag_size(&skb_shinfo(skb)->frags[j]), - DMA_TO_DEVICE); - dma_unmap_addr_set(&array[index], dma_addr, 0); - BNA_QE_INDX_ADD(index, 1, depth); + dma_unmap_page(&bnad->pcidev->dev, + dma_unmap_addr(&unmap->vectors[vector], dma_addr), + skb_shinfo(skb)->frags[nvecs].size, DMA_TO_DEVICE); + dma_unmap_addr_set(&unmap->vectors[vector], dma_addr, 0); + nvecs--; } + BNA_QE_INDX_INC(index, q_depth); + return index; } @@ -154,80 +158,64 @@ bnad_pci_unmap_skb(struct device *pdev, struct bnad_skb_unmap *array, * so DMA unmap & freeing is fine. */ static void -bnad_txq_cleanup(struct bnad *bnad, - struct bna_tcb *tcb) +bnad_txq_cleanup(struct bnad *bnad, struct bna_tcb *tcb) { - u32 unmap_cons; - struct bnad_unmap_q *unmap_q = tcb->unmap_q; - struct bnad_skb_unmap *unmap_array; - struct sk_buff *skb = NULL; - int q; - - unmap_array = unmap_q->unmap_array; + struct bnad_tx_unmap *unmap_q = tcb->unmap_q; + struct sk_buff *skb; + int i; - for (q = 0; q < unmap_q->q_depth; q++) { - skb = unmap_array[q].skb; + for (i = 0; i < tcb->q_depth; i++) { + skb = unmap_q[i].skb; if (!skb) continue; - - unmap_cons = q; - unmap_cons = bnad_pci_unmap_skb(&bnad->pcidev->dev, unmap_array, - unmap_cons, unmap_q->q_depth, skb, - skb_shinfo(skb)->nr_frags); + bnad_tx_buff_unmap(bnad, unmap_q, tcb->q_depth, i); dev_kfree_skb_any(skb); } } -/* Data Path Handlers */ - /* * bnad_txcmpl_process : Frees the Tx bufs on Tx completion * Can be called in a) Interrupt context * b) Sending context */ static u32 -bnad_txcmpl_process(struct bnad *bnad, - struct bna_tcb *tcb) +bnad_txcmpl_process(struct bnad *bnad, struct bna_tcb *tcb) { - u32 unmap_cons, sent_packets = 0, sent_bytes = 0; - u16 wis, updated_hw_cons; - struct bnad_unmap_q *unmap_q = tcb->unmap_q; - struct bnad_skb_unmap *unmap_array; - struct sk_buff *skb; + u32 sent_packets = 0, sent_bytes = 0; + u32 wis, unmap_wis, hw_cons, cons, q_depth; + struct bnad_tx_unmap *unmap_q = tcb->unmap_q; + struct bnad_tx_unmap *unmap; + struct sk_buff *skb; /* Just return if TX is stopped */ if (!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) return 0; - updated_hw_cons = *(tcb->hw_consumer_index); - - wis = BNA_Q_INDEX_CHANGE(tcb->consumer_index, - updated_hw_cons, tcb->q_depth); + hw_cons = *(tcb->hw_consumer_index); + cons = tcb->consumer_index; + q_depth = tcb->q_depth; + wis = BNA_Q_INDEX_CHANGE(cons, hw_cons, q_depth); BUG_ON(!(wis <= BNA_QE_IN_USE_CNT(tcb, tcb->q_depth))); - unmap_array = unmap_q->unmap_array; - unmap_cons = unmap_q->consumer_index; - - prefetch(&unmap_array[unmap_cons + 1]); while (wis) { - skb = unmap_array[unmap_cons].skb; + unmap = &unmap_q[cons]; + + skb = unmap->skb; sent_packets++; sent_bytes += skb->len; - wis -= BNA_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags); - unmap_cons = bnad_pci_unmap_skb(&bnad->pcidev->dev, unmap_array, - unmap_cons, unmap_q->q_depth, skb, - skb_shinfo(skb)->nr_frags); + unmap_wis = BNA_TXQ_WI_NEEDED(unmap->nvecs); + wis -= unmap_wis; + cons = bnad_tx_buff_unmap(bnad, unmap_q, q_depth, cons); dev_kfree_skb_any(skb); } /* Update consumer pointers. */ - tcb->consumer_index = updated_hw_cons; - unmap_q->consumer_index = unmap_cons; + tcb->consumer_index = hw_cons; tcb->txq->tx_packets += sent_packets; tcb->txq->tx_bytes += sent_bytes; @@ -278,133 +266,306 @@ bnad_msix_tx(int irq, void *data) return IRQ_HANDLED; } -static void -bnad_rcb_cleanup(struct bnad *bnad, struct bna_rcb *rcb) +static inline void +bnad_rxq_alloc_uninit(struct bnad *bnad, struct bna_rcb *rcb) { - struct bnad_unmap_q *unmap_q = rcb->unmap_q; + struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q; + + unmap_q->reuse_pi = -1; + unmap_q->alloc_order = -1; + unmap_q->map_size = 0; + unmap_q->type = BNAD_RXBUF_NONE; +} + +/* Default is page-based allocation. Multi-buffer support - TBD */ +static int +bnad_rxq_alloc_init(struct bnad *bnad, struct bna_rcb *rcb) +{ + struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q; + int mtu, order; + + bnad_rxq_alloc_uninit(bnad, rcb); + + mtu = bna_enet_mtu_get(&bnad->bna.enet); + order = get_order(mtu); + + if (bna_is_small_rxq(rcb->id)) { + unmap_q->alloc_order = 0; + unmap_q->map_size = rcb->rxq->buffer_size; + } else { + unmap_q->alloc_order = order; + unmap_q->map_size = + (rcb->rxq->buffer_size > 2048) ? + PAGE_SIZE << order : 2048; + } + + BUG_ON(((PAGE_SIZE << order) % unmap_q->map_size)); + + unmap_q->type = BNAD_RXBUF_PAGE; + + return 0; +} + +static inline void +bnad_rxq_cleanup_page(struct bnad *bnad, struct bnad_rx_unmap *unmap) +{ + if (!unmap->page) + return; + + dma_unmap_page(&bnad->pcidev->dev, + dma_unmap_addr(&unmap->vector, dma_addr), + unmap->vector.len, DMA_FROM_DEVICE); + put_page(unmap->page); + unmap->page = NULL; + dma_unmap_addr_set(&unmap->vector, dma_addr, 0); + unmap->vector.len = 0; +} - rcb->producer_index = 0; - rcb->consumer_index = 0; +static inline void +bnad_rxq_cleanup_skb(struct bnad *bnad, struct bnad_rx_unmap *unmap) +{ + if (!unmap->skb) + return; - unmap_q->producer_index = 0; - unmap_q->consumer_index = 0; + dma_unmap_single(&bnad->pcidev->dev, + dma_unmap_addr(&unmap->vector, dma_addr), + unmap->vector.len, DMA_FROM_DEVICE); + dev_kfree_skb_any(unmap->skb); + unmap->skb = NULL; + dma_unmap_addr_set(&unmap->vector, dma_addr, 0); + unmap->vector.len = 0; } static void bnad_rxq_cleanup(struct bnad *bnad, struct bna_rcb *rcb) { - struct bnad_unmap_q *unmap_q; - struct bnad_skb_unmap *unmap_array; - struct sk_buff *skb; - int unmap_cons; + struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q; + int i; - unmap_q = rcb->unmap_q; - unmap_array = unmap_q->unmap_array; - for (unmap_cons = 0; unmap_cons < unmap_q->q_depth; unmap_cons++) { - skb = unmap_array[unmap_cons].skb; - if (!skb) - continue; - unmap_array[unmap_cons].skb = NULL; - dma_unmap_single(&bnad->pcidev->dev, - dma_unmap_addr(&unmap_array[unmap_cons], - dma_addr), - rcb->rxq->buffer_size, - DMA_FROM_DEVICE); - dev_kfree_skb(skb); + for (i = 0; i < rcb->q_depth; i++) { + struct bnad_rx_unmap *unmap = &unmap_q->unmap[i]; + + if (BNAD_RXBUF_IS_PAGE(unmap_q->type)) + bnad_rxq_cleanup_page(bnad, unmap); + else + bnad_rxq_cleanup_skb(bnad, unmap); } - bnad_rcb_cleanup(bnad, rcb); + bnad_rxq_alloc_uninit(bnad, rcb); } -static void -bnad_rxq_post(struct bnad *bnad, struct bna_rcb *rcb) +static u32 +bnad_rxq_refill_page(struct bnad *bnad, struct bna_rcb *rcb, u32 nalloc) { - u16 to_alloc, alloced, unmap_prod, wi_range; - struct bnad_unmap_q *unmap_q = rcb->unmap_q; - struct bnad_skb_unmap *unmap_array; + u32 alloced, prod, q_depth; + struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q; + struct bnad_rx_unmap *unmap, *prev; struct bna_rxq_entry *rxent; - struct sk_buff *skb; + struct page *page; + u32 page_offset, alloc_size; dma_addr_t dma_addr; + prod = rcb->producer_index; + q_depth = rcb->q_depth; + + alloc_size = PAGE_SIZE << unmap_q->alloc_order; alloced = 0; - to_alloc = - BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth); - unmap_array = unmap_q->unmap_array; - unmap_prod = unmap_q->producer_index; + while (nalloc--) { + unmap = &unmap_q->unmap[prod]; - BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent, wi_range); + if (unmap_q->reuse_pi < 0) { + page = alloc_pages(GFP_ATOMIC | __GFP_COMP, + unmap_q->alloc_order); + page_offset = 0; + } else { + prev = &unmap_q->unmap[unmap_q->reuse_pi]; + page = prev->page; + page_offset = prev->page_offset + unmap_q->map_size; + get_page(page); + } + + if (unlikely(!page)) { + BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed); + rcb->rxq->rxbuf_alloc_failed++; + goto finishing; + } + + dma_addr = dma_map_page(&bnad->pcidev->dev, page, page_offset, + unmap_q->map_size, DMA_FROM_DEVICE); + + unmap->page = page; + unmap->page_offset = page_offset; + dma_unmap_addr_set(&unmap->vector, dma_addr, dma_addr); + unmap->vector.len = unmap_q->map_size; + page_offset += unmap_q->map_size; + + if (page_offset < alloc_size) + unmap_q->reuse_pi = prod; + else + unmap_q->reuse_pi = -1; + + rxent = &((struct bna_rxq_entry *)rcb->sw_q)[prod]; + BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr); + BNA_QE_INDX_INC(prod, q_depth); + alloced++; + } + +finishing: + if (likely(alloced)) { + rcb->producer_index = prod; + smp_mb(); + if (likely(test_bit(BNAD_RXQ_POST_OK, &rcb->flags))) + bna_rxq_prod_indx_doorbell(rcb); + } + + return alloced; +} + +static u32 +bnad_rxq_refill_skb(struct bnad *bnad, struct bna_rcb *rcb, u32 nalloc) +{ + u32 alloced, prod, q_depth, buff_sz; + struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q; + struct bnad_rx_unmap *unmap; + struct bna_rxq_entry *rxent; + struct sk_buff *skb; + dma_addr_t dma_addr; + + buff_sz = rcb->rxq->buffer_size; + prod = rcb->producer_index; + q_depth = rcb->q_depth; + + alloced = 0; + while (nalloc--) { + unmap = &unmap_q->unmap[prod]; + + skb = netdev_alloc_skb_ip_align(bnad->netdev, buff_sz); - while (to_alloc--) { - if (!wi_range) - BNA_RXQ_QPGE_PTR_GET(unmap_prod, rcb->sw_qpt, rxent, - wi_range); - skb = netdev_alloc_skb_ip_align(bnad->netdev, - rcb->rxq->buffer_size); if (unlikely(!skb)) { BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed); rcb->rxq->rxbuf_alloc_failed++; goto finishing; } - unmap_array[unmap_prod].skb = skb; dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data, - rcb->rxq->buffer_size, - DMA_FROM_DEVICE); - dma_unmap_addr_set(&unmap_array[unmap_prod], dma_addr, - dma_addr); - BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr); - BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth); + buff_sz, DMA_FROM_DEVICE); + + unmap->skb = skb; + dma_unmap_addr_set(&unmap->vector, dma_addr, dma_addr); + unmap->vector.len = buff_sz; - rxent++; - wi_range--; + rxent = &((struct bna_rxq_entry *)rcb->sw_q)[prod]; + BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr); + BNA_QE_INDX_INC(prod, q_depth); alloced++; } finishing: if (likely(alloced)) { - unmap_q->producer_index = unmap_prod; - rcb->producer_index = unmap_prod; + rcb->producer_index = prod; smp_mb(); if (likely(test_bit(BNAD_RXQ_POST_OK, &rcb->flags))) bna_rxq_prod_indx_doorbell(rcb); } + + return alloced; } static inline void -bnad_refill_rxq(struct bnad *bnad, struct bna_rcb *rcb) +bnad_rxq_post(struct bnad *bnad, struct bna_rcb *rcb) { - struct bnad_unmap_q *unmap_q = rcb->unmap_q; + struct bnad_rx_unmap_q *unmap_q = rcb->unmap_q; + u32 to_alloc; - if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) { - if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth) - >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT) - bnad_rxq_post(bnad, rcb); - smp_mb__before_clear_bit(); - clear_bit(BNAD_RXQ_REFILL, &rcb->flags); + to_alloc = BNA_QE_FREE_CNT(rcb, rcb->q_depth); + if (!(to_alloc >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)) + return; + + if (BNAD_RXBUF_IS_PAGE(unmap_q->type)) + bnad_rxq_refill_page(bnad, rcb, to_alloc); + else + bnad_rxq_refill_skb(bnad, rcb, to_alloc); +} + +#define flags_cksum_prot_mask (BNA_CQ_EF_IPV4 | BNA_CQ_EF_L3_CKSUM_OK | \ + BNA_CQ_EF_IPV6 | \ + BNA_CQ_EF_TCP | BNA_CQ_EF_UDP | \ + BNA_CQ_EF_L4_CKSUM_OK) + +#define flags_tcp4 (BNA_CQ_EF_IPV4 | BNA_CQ_EF_L3_CKSUM_OK | \ + BNA_CQ_EF_TCP | BNA_CQ_EF_L4_CKSUM_OK) +#define flags_tcp6 (BNA_CQ_EF_IPV6 | \ + BNA_CQ_EF_TCP | BNA_CQ_EF_L4_CKSUM_OK) +#define flags_udp4 (BNA_CQ_EF_IPV4 | BNA_CQ_EF_L3_CKSUM_OK | \ + BNA_CQ_EF_UDP | BNA_CQ_EF_L4_CKSUM_OK) +#define flags_udp6 (BNA_CQ_EF_IPV6 | \ + BNA_CQ_EF_UDP | BNA_CQ_EF_L4_CKSUM_OK) + +static inline struct sk_buff * +bnad_cq_prepare_skb(struct bnad_rx_ctrl *rx_ctrl, + struct bnad_rx_unmap_q *unmap_q, + struct bnad_rx_unmap *unmap, + u32 length, u32 flags) +{ + struct bnad *bnad = rx_ctrl->bnad; + struct sk_buff *skb; + + if (BNAD_RXBUF_IS_PAGE(unmap_q->type)) { + skb = napi_get_frags(&rx_ctrl->napi); + if (unlikely(!skb)) + return NULL; + + dma_unmap_page(&bnad->pcidev->dev, + dma_unmap_addr(&unmap->vector, dma_addr), + unmap->vector.len, DMA_FROM_DEVICE); + skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, + unmap->page, unmap->page_offset, length); + skb->len += length; + skb->data_len += length; + skb->truesize += length; + + unmap->page = NULL; + unmap->vector.len = 0; + + return skb; } + + skb = unmap->skb; + BUG_ON(!skb); + + dma_unmap_single(&bnad->pcidev->dev, + dma_unmap_addr(&unmap->vector, dma_addr), + unmap->vector.len, DMA_FROM_DEVICE); + + skb_put(skb, length); + + skb->protocol = eth_type_trans(skb, bnad->netdev); + + unmap->skb = NULL; + unmap->vector.len = 0; + return skb; } static u32 bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget) { - struct bna_cq_entry *cmpl, *next_cmpl; + struct bna_cq_entry *cq, *cmpl; struct bna_rcb *rcb = NULL; - unsigned int wi_range, packets = 0, wis = 0; - struct bnad_unmap_q *unmap_q; - struct bnad_skb_unmap *unmap_array; + struct bnad_rx_unmap_q *unmap_q; + struct bnad_rx_unmap *unmap; struct sk_buff *skb; - u32 flags, unmap_cons; struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate; - struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl); - - if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)) - return 0; + struct bnad_rx_ctrl *rx_ctrl = ccb->ctrl; + u32 packets = 0, length = 0, flags, masked_flags; prefetch(bnad->netdev); - BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl, - wi_range); - BUG_ON(!(wi_range <= ccb->q_depth)); - while (cmpl->valid && packets < budget) { + + cq = ccb->sw_q; + cmpl = &cq[ccb->producer_index]; + + while (cmpl->valid && (packets < budget)) { packets++; + flags = ntohl(cmpl->flags); + length = ntohs(cmpl->length); BNA_UPDATE_PKT_CNT(pkt_rt, ntohs(cmpl->length)); if (bna_is_small_rxq(cmpl->rxq_id)) @@ -413,83 +574,63 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget) rcb = ccb->rcb[0]; unmap_q = rcb->unmap_q; - unmap_array = unmap_q->unmap_array; - unmap_cons = unmap_q->consumer_index; - - skb = unmap_array[unmap_cons].skb; - BUG_ON(!(skb)); - unmap_array[unmap_cons].skb = NULL; - dma_unmap_single(&bnad->pcidev->dev, - dma_unmap_addr(&unmap_array[unmap_cons], - dma_addr), - rcb->rxq->buffer_size, - DMA_FROM_DEVICE); - BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth); - - /* Should be more efficient ? Performance ? */ - BNA_QE_INDX_ADD(rcb->consumer_index, 1, rcb->q_depth); - - wis++; - if (likely(--wi_range)) - next_cmpl = cmpl + 1; - else { - BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth); - wis = 0; - BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, - next_cmpl, wi_range); - BUG_ON(!(wi_range <= ccb->q_depth)); - } - prefetch(next_cmpl); + unmap = &unmap_q->unmap[rcb->consumer_index]; + + if (unlikely(flags & (BNA_CQ_EF_MAC_ERROR | + BNA_CQ_EF_FCS_ERROR | + BNA_CQ_EF_TOO_LONG))) { + if (BNAD_RXBUF_IS_PAGE(unmap_q->type)) + bnad_rxq_cleanup_page(bnad, unmap); + else + bnad_rxq_cleanup_skb(bnad, unmap); - flags = ntohl(cmpl->flags); - if (unlikely - (flags & - (BNA_CQ_EF_MAC_ERROR | BNA_CQ_EF_FCS_ERROR | - BNA_CQ_EF_TOO_LONG))) { - dev_kfree_skb_any(skb); rcb->rxq->rx_packets_with_error++; goto next; } - skb_put(skb, ntohs(cmpl->length)); + skb = bnad_cq_prepare_skb(ccb->ctrl, unmap_q, unmap, + length, flags); + + if (unlikely(!skb)) + break; + + masked_flags = flags & flags_cksum_prot_mask; + if (likely ((bnad->netdev->features & NETIF_F_RXCSUM) && - (((flags & BNA_CQ_EF_IPV4) && - (flags & BNA_CQ_EF_L3_CKSUM_OK)) || - (flags & BNA_CQ_EF_IPV6)) && - (flags & (BNA_CQ_EF_TCP | BNA_CQ_EF_UDP)) && - (flags & BNA_CQ_EF_L4_CKSUM_OK))) + ((masked_flags == flags_tcp4) || + (masked_flags == flags_udp4) || + (masked_flags == flags_tcp6) || + (masked_flags == flags_udp6)))) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb_checksum_none_assert(skb); rcb->rxq->rx_packets++; - rcb->rxq->rx_bytes += skb->len; - skb->protocol = eth_type_trans(skb, bnad->netdev); + rcb->rxq->rx_bytes += length; if (flags & BNA_CQ_EF_VLAN) __vlan_hwaccel_put_tag(skb, ntohs(cmpl->vlan_tag)); - if (skb->ip_summed == CHECKSUM_UNNECESSARY) - napi_gro_receive(&rx_ctrl->napi, skb); + if (BNAD_RXBUF_IS_PAGE(unmap_q->type)) + napi_gro_frags(&rx_ctrl->napi); else netif_receive_skb(skb); next: cmpl->valid = 0; - cmpl = next_cmpl; + BNA_QE_INDX_INC(rcb->consumer_index, rcb->q_depth); + BNA_QE_INDX_INC(ccb->producer_index, ccb->q_depth); + cmpl = &cq[ccb->producer_index]; } - BNA_QE_INDX_ADD(ccb->producer_index, wis, ccb->q_depth); - + napi_gro_flush(&rx_ctrl->napi, false); if (likely(test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))) bna_ib_ack_disable_irq(ccb->i_dbell, packets); - bnad_refill_rxq(bnad, ccb->rcb[0]); + bnad_rxq_post(bnad, ccb->rcb[0]); if (ccb->rcb[1]) - bnad_refill_rxq(bnad, ccb->rcb[1]); - - clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags); + bnad_rxq_post(bnad, ccb->rcb[1]); return packets; } @@ -764,12 +905,9 @@ bnad_cb_tcb_setup(struct bnad *bnad, struct bna_tcb *tcb) { struct bnad_tx_info *tx_info = (struct bnad_tx_info *)tcb->txq->tx->priv; - struct bnad_unmap_q *unmap_q = tcb->unmap_q; + tcb->priv = tcb; tx_info->tcb[tcb->id] = tcb; - unmap_q->producer_index = 0; - unmap_q->consumer_index = 0; - unmap_q->q_depth = BNAD_TX_UNMAPQ_DEPTH; } static void @@ -783,16 +921,6 @@ bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb) } static void -bnad_cb_rcb_setup(struct bnad *bnad, struct bna_rcb *rcb) -{ - struct bnad_unmap_q *unmap_q = rcb->unmap_q; - - unmap_q->producer_index = 0; - unmap_q->consumer_index = 0; - unmap_q->q_depth = BNAD_RX_UNMAPQ_DEPTH; -} - -static void bnad_cb_ccb_setup(struct bnad *bnad, struct bna_ccb *ccb) { struct bnad_rx_info *rx_info = @@ -878,10 +1006,9 @@ bnad_tx_cleanup(struct delayed_work *work) struct bnad_tx_info *tx_info = container_of(work, struct bnad_tx_info, tx_cleanup_work); struct bnad *bnad = NULL; - struct bnad_unmap_q *unmap_q; struct bna_tcb *tcb; unsigned long flags; - uint32_t i, pending = 0; + u32 i, pending = 0; for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) { tcb = tx_info->tcb[i]; @@ -897,10 +1024,6 @@ bnad_tx_cleanup(struct delayed_work *work) bnad_txq_cleanup(bnad, tcb); - unmap_q = tcb->unmap_q; - unmap_q->producer_index = 0; - unmap_q->consumer_index = 0; - smp_mb__before_clear_bit(); clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags); } @@ -916,7 +1039,6 @@ bnad_tx_cleanup(struct delayed_work *work) spin_unlock_irqrestore(&bnad->bna_lock, flags); } - static void bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tx *tx) { @@ -965,7 +1087,7 @@ bnad_rx_cleanup(void *work) struct bnad_rx_ctrl *rx_ctrl; struct bnad *bnad = NULL; unsigned long flags; - uint32_t i; + u32 i; for (i = 0; i < BNAD_MAX_RXP_PER_RX; i++) { rx_ctrl = &rx_info->rx_ctrl[i]; @@ -1022,9 +1144,7 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx) struct bna_ccb *ccb; struct bna_rcb *rcb; struct bnad_rx_ctrl *rx_ctrl; - struct bnad_unmap_q *unmap_q; - int i; - int j; + int i, j; for (i = 0; i < BNAD_MAX_RXP_PER_RX; i++) { rx_ctrl = &rx_info->rx_ctrl[i]; @@ -1039,19 +1159,10 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx) if (!rcb) continue; + bnad_rxq_alloc_init(bnad, rcb); set_bit(BNAD_RXQ_STARTED, &rcb->flags); set_bit(BNAD_RXQ_POST_OK, &rcb->flags); - unmap_q = rcb->unmap_q; - - /* Now allocate & post buffers for this RCB */ - /* !!Allocation in callback context */ - if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) { - if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth) - >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT) - bnad_rxq_post(bnad, rcb); - smp_mb__before_clear_bit(); - clear_bit(BNAD_RXQ_REFILL, &rcb->flags); - } + bnad_rxq_post(bnad, rcb); } } } @@ -1775,10 +1886,9 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id) spin_unlock_irqrestore(&bnad->bna_lock, flags); /* Fill Unmap Q memory requirements */ - BNAD_FILL_UNMAPQ_MEM_REQ( - &res_info[BNA_TX_RES_MEM_T_UNMAPQ], - bnad->num_txq_per_tx, - BNAD_TX_UNMAPQ_DEPTH); + BNAD_FILL_UNMAPQ_MEM_REQ(&res_info[BNA_TX_RES_MEM_T_UNMAPQ], + bnad->num_txq_per_tx, (sizeof(struct bnad_tx_unmap) * + bnad->txq_depth)); /* Allocate resources */ err = bnad_tx_res_alloc(bnad, res_info, tx_id); @@ -1916,7 +2026,7 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id) &res_info[BNA_RX_RES_T_INTR].res_u.intr_info; struct bna_rx_config *rx_config = &bnad->rx_config[rx_id]; static const struct bna_rx_event_cbfn rx_cbfn = { - .rcb_setup_cbfn = bnad_cb_rcb_setup, + .rcb_setup_cbfn = NULL, .rcb_destroy_cbfn = NULL, .ccb_setup_cbfn = bnad_cb_ccb_setup, .ccb_destroy_cbfn = bnad_cb_ccb_destroy, @@ -1938,11 +2048,12 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id) spin_unlock_irqrestore(&bnad->bna_lock, flags); /* Fill Unmap Q memory requirements */ - BNAD_FILL_UNMAPQ_MEM_REQ( - &res_info[BNA_RX_RES_MEM_T_UNMAPQ], + BNAD_FILL_UNMAPQ_MEM_REQ(&res_info[BNA_RX_RES_MEM_T_UNMAPQ], rx_config->num_paths + - ((rx_config->rxp_type == BNA_RXP_SINGLE) ? 0 : - rx_config->num_paths), BNAD_RX_UNMAPQ_DEPTH); + ((rx_config->rxp_type == BNA_RXP_SINGLE) ? + 0 : rx_config->num_paths), + ((bnad->rxq_depth * sizeof(struct bnad_rx_unmap)) + + sizeof(struct bnad_rx_unmap_q))); /* Allocate resource */ err = bnad_rx_res_alloc(bnad, res_info, rx_id); @@ -2523,125 +2634,34 @@ bnad_stop(struct net_device *netdev) } /* TX */ -/* - * bnad_start_xmit : Netdev entry point for Transmit - * Called under lock held by net_device - */ -static netdev_tx_t -bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) +/* Returns 0 for success */ +static int +bnad_txq_wi_prepare(struct bnad *bnad, struct bna_tcb *tcb, + struct sk_buff *skb, struct bna_txq_entry *txqent) { - struct bnad *bnad = netdev_priv(netdev); - u32 txq_id = 0; - struct bna_tcb *tcb = bnad->tx_info[0].tcb[txq_id]; - - u16 txq_prod, vlan_tag = 0; - u32 unmap_prod, wis, wis_used, wi_range; - u32 vectors, vect_id, i, acked; - int err; - unsigned int len; - u32 gso_size; - - struct bnad_unmap_q *unmap_q = tcb->unmap_q; - dma_addr_t dma_addr; - struct bna_txq_entry *txqent; - u16 flags; - - if (unlikely(skb->len <= ETH_HLEN)) { - dev_kfree_skb(skb); - BNAD_UPDATE_CTR(bnad, tx_skb_too_short); - return NETDEV_TX_OK; - } - if (unlikely(skb_headlen(skb) > BFI_TX_MAX_DATA_PER_VECTOR)) { - dev_kfree_skb(skb); - BNAD_UPDATE_CTR(bnad, tx_skb_headlen_too_long); - return NETDEV_TX_OK; - } - if (unlikely(skb_headlen(skb) == 0)) { - dev_kfree_skb(skb); - BNAD_UPDATE_CTR(bnad, tx_skb_headlen_zero); - return NETDEV_TX_OK; - } - - /* - * Takes care of the Tx that is scheduled between clearing the flag - * and the netif_tx_stop_all_queues() call. - */ - if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) { - dev_kfree_skb(skb); - BNAD_UPDATE_CTR(bnad, tx_skb_stopping); - return NETDEV_TX_OK; - } - - vectors = 1 + skb_shinfo(skb)->nr_frags; - if (unlikely(vectors > BFI_TX_MAX_VECTORS_PER_PKT)) { - dev_kfree_skb(skb); - BNAD_UPDATE_CTR(bnad, tx_skb_max_vectors); - return NETDEV_TX_OK; - } - wis = BNA_TXQ_WI_NEEDED(vectors); /* 4 vectors per work item */ - acked = 0; - if (unlikely(wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) || - vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) { - if ((u16) (*tcb->hw_consumer_index) != - tcb->consumer_index && - !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) { - acked = bnad_txcmpl_process(bnad, tcb); - if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) - bna_ib_ack(tcb->i_dbell, acked); - smp_mb__before_clear_bit(); - clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags); - } else { - netif_stop_queue(netdev); - BNAD_UPDATE_CTR(bnad, netif_queue_stop); - } - - smp_mb(); - /* - * Check again to deal with race condition between - * netif_stop_queue here, and netif_wake_queue in - * interrupt handler which is not inside netif tx lock. - */ - if (likely - (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) || - vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) { - BNAD_UPDATE_CTR(bnad, netif_queue_stop); - return NETDEV_TX_BUSY; - } else { - netif_wake_queue(netdev); - BNAD_UPDATE_CTR(bnad, netif_queue_wakeup); - } - } - - unmap_prod = unmap_q->producer_index; - flags = 0; - - txq_prod = tcb->producer_index; - BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt, txqent, wi_range); - txqent->hdr.wi.reserved = 0; - txqent->hdr.wi.num_vectors = vectors; + u16 flags = 0; + u32 gso_size; + u16 vlan_tag = 0; if (vlan_tx_tag_present(skb)) { - vlan_tag = (u16) vlan_tx_tag_get(skb); + vlan_tag = (u16)vlan_tx_tag_get(skb); flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN); } if (test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags)) { - vlan_tag = - (tcb->priority & 0x7) << 13 | (vlan_tag & 0x1fff); + vlan_tag = ((tcb->priority & 0x7) << VLAN_PRIO_SHIFT) + | (vlan_tag & 0x1fff); flags |= (BNA_TXQ_WI_CF_INS_PRIO | BNA_TXQ_WI_CF_INS_VLAN); } - txqent->hdr.wi.vlan_tag = htons(vlan_tag); if (skb_is_gso(skb)) { gso_size = skb_shinfo(skb)->gso_size; - - if (unlikely(gso_size > netdev->mtu)) { - dev_kfree_skb(skb); + if (unlikely(gso_size > bnad->netdev->mtu)) { BNAD_UPDATE_CTR(bnad, tx_skb_mss_too_long); - return NETDEV_TX_OK; + return -EINVAL; } if (unlikely((gso_size + skb_transport_offset(skb) + - tcp_hdrlen(skb)) >= skb->len)) { + tcp_hdrlen(skb)) >= skb->len)) { txqent->hdr.wi.opcode = __constant_htons(BNA_TXQ_WI_SEND); txqent->hdr.wi.lso_mss = 0; @@ -2652,25 +2672,22 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) txqent->hdr.wi.lso_mss = htons(gso_size); } - err = bnad_tso_prepare(bnad, skb); - if (unlikely(err)) { - dev_kfree_skb(skb); + if (bnad_tso_prepare(bnad, skb)) { BNAD_UPDATE_CTR(bnad, tx_skb_tso_prepare); - return NETDEV_TX_OK; + return -EINVAL; } + flags |= (BNA_TXQ_WI_CF_IP_CKSUM | BNA_TXQ_WI_CF_TCP_CKSUM); txqent->hdr.wi.l4_hdr_size_n_offset = - htons(BNA_TXQ_WI_L4_HDR_N_OFFSET - (tcp_hdrlen(skb) >> 2, - skb_transport_offset(skb))); - } else { + htons(BNA_TXQ_WI_L4_HDR_N_OFFSET( + tcp_hdrlen(skb) >> 2, skb_transport_offset(skb))); + } else { txqent->hdr.wi.opcode = __constant_htons(BNA_TXQ_WI_SEND); txqent->hdr.wi.lso_mss = 0; - if (unlikely(skb->len > (netdev->mtu + ETH_HLEN))) { - dev_kfree_skb(skb); + if (unlikely(skb->len > (bnad->netdev->mtu + ETH_HLEN))) { BNAD_UPDATE_CTR(bnad, tx_skb_non_tso_too_long); - return NETDEV_TX_OK; + return -EINVAL; } if (skb->ip_summed == CHECKSUM_PARTIAL) { @@ -2678,11 +2695,13 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) if (skb->protocol == __constant_htons(ETH_P_IP)) proto = ip_hdr(skb)->protocol; +#ifdef NETIF_F_IPV6_CSUM else if (skb->protocol == __constant_htons(ETH_P_IPV6)) { /* nexthdr may not be TCP immediately. */ proto = ipv6_hdr(skb)->nexthdr; } +#endif if (proto == IPPROTO_TCP) { flags |= BNA_TXQ_WI_CF_TCP_CKSUM; txqent->hdr.wi.l4_hdr_size_n_offset = @@ -2692,12 +2711,11 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) BNAD_UPDATE_CTR(bnad, tcpcsum_offload); if (unlikely(skb_headlen(skb) < - skb_transport_offset(skb) + tcp_hdrlen(skb))) { - dev_kfree_skb(skb); + skb_transport_offset(skb) + + tcp_hdrlen(skb))) { BNAD_UPDATE_CTR(bnad, tx_skb_tcp_hdr); - return NETDEV_TX_OK; + return -EINVAL; } - } else if (proto == IPPROTO_UDP) { flags |= BNA_TXQ_WI_CF_UDP_CKSUM; txqent->hdr.wi.l4_hdr_size_n_offset = @@ -2706,51 +2724,149 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) BNAD_UPDATE_CTR(bnad, udpcsum_offload); if (unlikely(skb_headlen(skb) < - skb_transport_offset(skb) + + skb_transport_offset(skb) + sizeof(struct udphdr))) { - dev_kfree_skb(skb); BNAD_UPDATE_CTR(bnad, tx_skb_udp_hdr); - return NETDEV_TX_OK; + return -EINVAL; } } else { - dev_kfree_skb(skb); + BNAD_UPDATE_CTR(bnad, tx_skb_csum_err); - return NETDEV_TX_OK; + return -EINVAL; } - } else { + } else txqent->hdr.wi.l4_hdr_size_n_offset = 0; - } } txqent->hdr.wi.flags = htons(flags); - txqent->hdr.wi.frame_length = htonl(skb->len); - unmap_q->unmap_array[unmap_prod].skb = skb; + return 0; +} + +/* + * bnad_start_xmit : Netdev entry point for Transmit + * Called under lock held by net_device + */ +static netdev_tx_t +bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct bnad *bnad = netdev_priv(netdev); + u32 txq_id = 0; + struct bna_tcb *tcb = NULL; + struct bnad_tx_unmap *unmap_q, *unmap, *head_unmap; + u32 prod, q_depth, vect_id; + u32 wis, vectors, len; + int i; + dma_addr_t dma_addr; + struct bna_txq_entry *txqent; + len = skb_headlen(skb); - txqent->vector[0].length = htons(len); - dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data, - skb_headlen(skb), DMA_TO_DEVICE); - dma_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr, - dma_addr); - BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[0].host_addr); - BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth); + /* Sanity checks for the skb */ - vect_id = 0; - wis_used = 1; + if (unlikely(skb->len <= ETH_HLEN)) { + dev_kfree_skb(skb); + BNAD_UPDATE_CTR(bnad, tx_skb_too_short); + return NETDEV_TX_OK; + } + if (unlikely(len > BFI_TX_MAX_DATA_PER_VECTOR)) { + dev_kfree_skb(skb); + BNAD_UPDATE_CTR(bnad, tx_skb_headlen_zero); + return NETDEV_TX_OK; + } + if (unlikely(len == 0)) { + dev_kfree_skb(skb); + BNAD_UPDATE_CTR(bnad, tx_skb_headlen_zero); + return NETDEV_TX_OK; + } + + tcb = bnad->tx_info[0].tcb[txq_id]; + q_depth = tcb->q_depth; + prod = tcb->producer_index; + + unmap_q = tcb->unmap_q; - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + /* + * Takes care of the Tx that is scheduled between clearing the flag + * and the netif_tx_stop_all_queues() call. + */ + if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) { + dev_kfree_skb(skb); + BNAD_UPDATE_CTR(bnad, tx_skb_stopping); + return NETDEV_TX_OK; + } + + vectors = 1 + skb_shinfo(skb)->nr_frags; + wis = BNA_TXQ_WI_NEEDED(vectors); /* 4 vectors per work item */ + + if (unlikely(vectors > BFI_TX_MAX_VECTORS_PER_PKT)) { + dev_kfree_skb(skb); + BNAD_UPDATE_CTR(bnad, tx_skb_max_vectors); + return NETDEV_TX_OK; + } + + /* Check for available TxQ resources */ + if (unlikely(wis > BNA_QE_FREE_CNT(tcb, q_depth))) { + if ((*tcb->hw_consumer_index != tcb->consumer_index) && + !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) { + u32 sent; + sent = bnad_txcmpl_process(bnad, tcb); + if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) + bna_ib_ack(tcb->i_dbell, sent); + smp_mb__before_clear_bit(); + clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags); + } else { + netif_stop_queue(netdev); + BNAD_UPDATE_CTR(bnad, netif_queue_stop); + } + + smp_mb(); + /* + * Check again to deal with race condition between + * netif_stop_queue here, and netif_wake_queue in + * interrupt handler which is not inside netif tx lock. + */ + if (likely(wis > BNA_QE_FREE_CNT(tcb, q_depth))) { + BNAD_UPDATE_CTR(bnad, netif_queue_stop); + return NETDEV_TX_BUSY; + } else { + netif_wake_queue(netdev); + BNAD_UPDATE_CTR(bnad, netif_queue_wakeup); + } + } + + txqent = &((struct bna_txq_entry *)tcb->sw_q)[prod]; + head_unmap = &unmap_q[prod]; + + /* Program the opcode, flags, frame_len, num_vectors in WI */ + if (bnad_txq_wi_prepare(bnad, tcb, skb, txqent)) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + txqent->hdr.wi.reserved = 0; + txqent->hdr.wi.num_vectors = vectors; + + head_unmap->skb = skb; + head_unmap->nvecs = 0; + + /* Program the vectors */ + unmap = head_unmap; + dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data, + len, DMA_TO_DEVICE); + BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[0].host_addr); + txqent->vector[0].length = htons(len); + dma_unmap_addr_set(&unmap->vectors[0], dma_addr, dma_addr); + head_unmap->nvecs++; + + for (i = 0, vect_id = 0; i < vectors - 1; i++) { const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; u16 size = skb_frag_size(frag); if (unlikely(size == 0)) { - unmap_prod = unmap_q->producer_index; - - unmap_prod = bnad_pci_unmap_skb(&bnad->pcidev->dev, - unmap_q->unmap_array, - unmap_prod, unmap_q->q_depth, skb, - i); + /* Undo the changes starting at tcb->producer_index */ + bnad_tx_buff_unmap(bnad, unmap_q, q_depth, + tcb->producer_index); dev_kfree_skb(skb); BNAD_UPDATE_CTR(bnad, tx_skb_frag_zero); return NETDEV_TX_OK; @@ -2758,47 +2874,35 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) len += size; - if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) { + vect_id++; + if (vect_id == BFI_TX_MAX_VECTORS_PER_WI) { vect_id = 0; - if (--wi_range) - txqent++; - else { - BNA_QE_INDX_ADD(txq_prod, wis_used, - tcb->q_depth); - wis_used = 0; - BNA_TXQ_QPGE_PTR_GET(txq_prod, tcb->sw_qpt, - txqent, wi_range); - } - wis_used++; + BNA_QE_INDX_INC(prod, q_depth); + txqent = &((struct bna_txq_entry *)tcb->sw_q)[prod]; txqent->hdr.wi_ext.opcode = __constant_htons(BNA_TXQ_WI_EXTENSION); + unmap = &unmap_q[prod]; } - BUG_ON(!(size <= BFI_TX_MAX_DATA_PER_VECTOR)); - txqent->vector[vect_id].length = htons(size); dma_addr = skb_frag_dma_map(&bnad->pcidev->dev, frag, 0, size, DMA_TO_DEVICE); - dma_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr, - dma_addr); BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr); - BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth); + txqent->vector[vect_id].length = htons(size); + dma_unmap_addr_set(&unmap->vectors[vect_id], dma_addr, + dma_addr); + head_unmap->nvecs++; } if (unlikely(len != skb->len)) { - unmap_prod = unmap_q->producer_index; - - unmap_prod = bnad_pci_unmap_skb(&bnad->pcidev->dev, - unmap_q->unmap_array, unmap_prod, - unmap_q->q_depth, skb, - skb_shinfo(skb)->nr_frags); + /* Undo the changes starting at tcb->producer_index */ + bnad_tx_buff_unmap(bnad, unmap_q, q_depth, tcb->producer_index); dev_kfree_skb(skb); BNAD_UPDATE_CTR(bnad, tx_skb_len_mismatch); return NETDEV_TX_OK; } - unmap_q->producer_index = unmap_prod; - BNA_QE_INDX_ADD(txq_prod, wis_used, tcb->q_depth); - tcb->producer_index = txq_prod; + BNA_QE_INDX_INC(prod, q_depth); + tcb->producer_index = prod; smp_mb(); @@ -3226,7 +3330,7 @@ bnad_pci_uninit(struct pci_dev *pdev) pci_disable_device(pdev); } -static int __devinit +static int bnad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pcidev_id) { @@ -3320,7 +3424,6 @@ bnad_pci_probe(struct pci_dev *pdev, if (err) goto res_free; - /* Set up timers */ setup_timer(&bnad->bna.ioceth.ioc.ioc_timer, bnad_ioc_timeout, ((unsigned long)bnad)); @@ -3426,7 +3529,7 @@ unlock_mutex: return err; } -static void __devexit +static void bnad_pci_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -3490,7 +3593,7 @@ static struct pci_driver bnad_pci_driver = { .name = BNAD_NAME, .id_table = bnad_pci_id_table, .probe = bnad_pci_probe, - .remove = __devexit_p(bnad_pci_remove), + .remove = bnad_pci_remove, }; static int __init diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h index d78339224751..c1d0bc059bfd 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.h +++ b/drivers/net/ethernet/brocade/bna/bnad.h @@ -71,7 +71,7 @@ struct bnad_rx_ctrl { #define BNAD_NAME "bna" #define BNAD_NAME_LEN 64 -#define BNAD_VERSION "3.0.23.0" +#define BNAD_VERSION "3.1.2.1" #define BNAD_MAILBOX_MSIX_INDEX 0 #define BNAD_MAILBOX_MSIX_VECTORS 1 @@ -83,12 +83,9 @@ struct bnad_rx_ctrl { #define BNAD_IOCETH_TIMEOUT 10000 -#define BNAD_MAX_Q_DEPTH 0x10000 -#define BNAD_MIN_Q_DEPTH 0x200 - -#define BNAD_MAX_RXQ_DEPTH (BNAD_MAX_Q_DEPTH / bnad_rxqs_per_cq) -/* keeping MAX TX and RX Q depth equal */ -#define BNAD_MAX_TXQ_DEPTH BNAD_MAX_RXQ_DEPTH +#define BNAD_MIN_Q_DEPTH 512 +#define BNAD_MAX_RXQ_DEPTH 2048 +#define BNAD_MAX_TXQ_DEPTH 2048 #define BNAD_JUMBO_MTU 9000 @@ -101,9 +98,8 @@ struct bnad_rx_ctrl { #define BNAD_TXQ_TX_STARTED 1 /* Bit positions for rcb->flags */ -#define BNAD_RXQ_REFILL 0 -#define BNAD_RXQ_STARTED 1 -#define BNAD_RXQ_POST_OK 2 +#define BNAD_RXQ_STARTED 0 +#define BNAD_RXQ_POST_OK 1 /* Resource limits */ #define BNAD_NUM_TXQ (bnad->num_tx * bnad->num_txq_per_tx) @@ -221,18 +217,43 @@ struct bnad_rx_info { struct work_struct rx_cleanup_work; } ____cacheline_aligned; -/* Unmap queues for Tx / Rx cleanup */ -struct bnad_skb_unmap { +struct bnad_tx_vector { + DEFINE_DMA_UNMAP_ADDR(dma_addr); +}; + +struct bnad_tx_unmap { struct sk_buff *skb; + u32 nvecs; + struct bnad_tx_vector vectors[BFI_TX_MAX_VECTORS_PER_WI]; +}; + +struct bnad_rx_vector { DEFINE_DMA_UNMAP_ADDR(dma_addr); + u32 len; +}; + +struct bnad_rx_unmap { + struct page *page; + u32 page_offset; + struct sk_buff *skb; + struct bnad_rx_vector vector; }; -struct bnad_unmap_q { - u32 producer_index; - u32 consumer_index; - u32 q_depth; - /* This should be the last one */ - struct bnad_skb_unmap unmap_array[1]; +enum bnad_rxbuf_type { + BNAD_RXBUF_NONE = 0, + BNAD_RXBUF_SKB = 1, + BNAD_RXBUF_PAGE = 2, + BNAD_RXBUF_MULTI = 3 +}; + +#define BNAD_RXBUF_IS_PAGE(_type) ((_type) == BNAD_RXBUF_PAGE) + +struct bnad_rx_unmap_q { + int reuse_pi; + int alloc_order; + u32 map_size; + enum bnad_rxbuf_type type; + struct bnad_rx_unmap unmap[0]; }; /* Bit mask values for bnad->cfg_flags */ @@ -252,11 +273,6 @@ struct bnad_unmap_q { #define BNAD_RF_STATS_TIMER_RUNNING 5 #define BNAD_RF_TX_PRIO_SET 6 - -/* Define for Fast Path flags */ -/* Defined as bit positions */ -#define BNAD_FP_IN_RX_PATH 0 - struct bnad { struct net_device *netdev; u32 id; @@ -284,8 +300,8 @@ struct bnad { u8 tx_coalescing_timeo; u8 rx_coalescing_timeo; - struct bna_rx_config rx_config[BNAD_MAX_RX]; - struct bna_tx_config tx_config[BNAD_MAX_TX]; + struct bna_rx_config rx_config[BNAD_MAX_RX] ____cacheline_aligned; + struct bna_tx_config tx_config[BNAD_MAX_TX] ____cacheline_aligned; void __iomem *bar0; /* BAR0 address */ diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c index 40e1e84f4984..455b5a2e59d4 100644 --- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c +++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c @@ -102,6 +102,7 @@ static const char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = { "rx_unmap_q_alloc_failed", "rxbuf_alloc_failed", + "mac_stats_clr_cnt", "mac_frame_64", "mac_frame_65_127", "mac_frame_128_255", diff --git a/drivers/net/ethernet/brocade/bna/cna.h b/drivers/net/ethernet/brocade/bna/cna.h index 32e8f178ab76..14ca9317c915 100644 --- a/drivers/net/ethernet/brocade/bna/cna.h +++ b/drivers/net/ethernet/brocade/bna/cna.h @@ -37,8 +37,8 @@ extern char bfa_version[]; -#define CNA_FW_FILE_CT "ctfw.bin" -#define CNA_FW_FILE_CT2 "ct2fw.bin" +#define CNA_FW_FILE_CT "ctfw-3.1.0.0.bin" +#define CNA_FW_FILE_CT2 "ct2fw-3.1.0.0.bin" #define FC_SYMNAME_MAX 256 /*!< max name server symbolic name size */ #pragma pack(1) diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig index db931916da08..ceb0de0cf62c 100644 --- a/drivers/net/ethernet/cadence/Kconfig +++ b/drivers/net/ethernet/cadence/Kconfig @@ -2,13 +2,10 @@ # Atmel device configuration # -config HAVE_NET_MACB - bool - config NET_CADENCE bool "Cadence devices" + depends on HAS_IOMEM default y - depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200) ---help--- If you have a network (Ethernet) card belonging to this class, say Y. Make sure you know the name of your card. Read the Ethernet-HOWTO, @@ -25,16 +22,14 @@ if NET_CADENCE config ARM_AT91_ETHER tristate "AT91RM9200 Ethernet support" - depends on ARM && ARCH_AT91RM9200 select NET_CORE - select MII + select MACB ---help--- If you wish to compile a kernel for the AT91RM9200 and enable ethernet support, then you should always answer Y to this. config MACB tristate "Cadence MACB/GEM support" - depends on HAVE_NET_MACB select PHYLIB ---help--- The Cadence MACB ethernet interface is found on many Atmel AT32 and diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c index 4e980a7886fb..3becdb2deb46 100644 --- a/drivers/net/ethernet/cadence/at91_ether.c +++ b/drivers/net/ethernet/cadence/at91_ether.c @@ -6,11 +6,6 @@ * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc. * Initial version by Rick Bronson 01/11/2003 * - * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker - * (Polaroid Corporation) - * - * Realtek RTL8201(B)L PHY support by Roman Avramenko <roman@imsystems.ru> - * * 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 the Free Software Foundation; either version @@ -20,7 +15,6 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> -#include <linux/mii.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> @@ -31,956 +25,248 @@ #include <linux/clk.h> #include <linux/gfp.h> #include <linux/phy.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_net.h> +#include <linux/pinctrl/consumer.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/mach-types.h> - -#include <mach/at91rm9200_emac.h> -#include <asm/gpio.h> -#include <mach/board.h> - -#include "at91_ether.h" - -#define DRV_NAME "at91_ether" -#define DRV_VERSION "1.0" - -#define LINK_POLL_INTERVAL (HZ) - -/* ..................................................................... */ - -/* - * Read from a EMAC register. - */ -static inline unsigned long at91_emac_read(struct at91_private *lp, unsigned int reg) -{ - return __raw_readl(lp->emac_base + reg); -} - -/* - * Write to a EMAC register. - */ -static inline void at91_emac_write(struct at91_private *lp, unsigned int reg, unsigned long value) -{ - __raw_writel(value, lp->emac_base + reg); -} - -/* ........................... PHY INTERFACE ........................... */ - -/* - * Enable the MDIO bit in MAC control register - * When not called from an interrupt-handler, access to the PHY must be - * protected by a spinlock. - */ -static void enable_mdi(struct at91_private *lp) -{ - unsigned long ctl; - - ctl = at91_emac_read(lp, AT91_EMAC_CTL); - at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */ -} - -/* - * Disable the MDIO bit in the MAC control register - */ -static void disable_mdi(struct at91_private *lp) -{ - unsigned long ctl; - - ctl = at91_emac_read(lp, AT91_EMAC_CTL); - at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */ -} - -/* - * Wait until the PHY operation is complete. - */ -static inline void at91_phy_wait(struct at91_private *lp) -{ - unsigned long timeout = jiffies + 2; - - while (!(at91_emac_read(lp, AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) { - if (time_after(jiffies, timeout)) { - printk("at91_ether: MIO timeout\n"); - break; - } - cpu_relax(); - } -} - -/* - * Write value to the a PHY register - * Note: MDI interface is assumed to already have been enabled. - */ -static void write_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int value) -{ - at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W - | ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA)); - - /* Wait until IDLE bit in Network Status register is cleared */ - at91_phy_wait(lp); -} - -/* - * Read value stored in a PHY register. - * Note: MDI interface is assumed to already have been enabled. - */ -static void read_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int *value) -{ - at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R - | ((phy_addr & 0x1f) << 23) | (address << 18)); - - /* Wait until IDLE bit in Network Status register is cleared */ - at91_phy_wait(lp); - - *value = at91_emac_read(lp, AT91_EMAC_MAN) & AT91_EMAC_DATA; -} - -/* ........................... PHY MANAGEMENT .......................... */ - -/* - * Access the PHY to determine the current link speed and mode, and update the - * MAC accordingly. - * If no link or auto-negotiation is busy, then no changes are made. - */ -static void update_linkspeed(struct net_device *dev, int silent) -{ - struct at91_private *lp = netdev_priv(dev); - unsigned int bmsr, bmcr, lpa, mac_cfg; - unsigned int speed, duplex; - - if (!mii_link_ok(&lp->mii)) { /* no link */ - netif_carrier_off(dev); - if (!silent) - printk(KERN_INFO "%s: Link down.\n", dev->name); - return; - } - - /* Link up, or auto-negotiation still in progress */ - read_phy(lp, lp->phy_address, MII_BMSR, &bmsr); - read_phy(lp, lp->phy_address, MII_BMCR, &bmcr); - if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */ - if (!(bmsr & BMSR_ANEGCOMPLETE)) - return; /* Do nothing - another interrupt generated when negotiation complete */ - - read_phy(lp, lp->phy_address, MII_LPA, &lpa); - if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100; - else speed = SPEED_10; - if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL; - else duplex = DUPLEX_HALF; - } else { - speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; - duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; - } - - /* Update the MAC */ - mac_cfg = at91_emac_read(lp, AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD); - if (speed == SPEED_100) { - if (duplex == DUPLEX_FULL) /* 100 Full Duplex */ - mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD; - else /* 100 Half Duplex */ - mac_cfg |= AT91_EMAC_SPD; - } else { - if (duplex == DUPLEX_FULL) /* 10 Full Duplex */ - mac_cfg |= AT91_EMAC_FD; - else {} /* 10 Half Duplex */ - } - at91_emac_write(lp, AT91_EMAC_CFG, mac_cfg); - - if (!silent) - printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); - netif_carrier_on(dev); -} - -/* - * Handle interrupts from the PHY - */ -static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = (struct net_device *) dev_id; - struct at91_private *lp = netdev_priv(dev); - unsigned int phy; - - /* - * This hander is triggered on both edges, but the PHY chips expect - * level-triggering. We therefore have to check if the PHY actually has - * an IRQ pending. - */ - enable_mdi(lp); - if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { - read_phy(lp, lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */ - if (!(phy & (1 << 0))) - goto done; - } - else if (lp->phy_type == MII_LXT971A_ID) { - read_phy(lp, lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */ - if (!(phy & (1 << 2))) - goto done; - } - else if (lp->phy_type == MII_BCM5221_ID) { - read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */ - if (!(phy & (1 << 0))) - goto done; - } - else if (lp->phy_type == MII_KS8721_ID) { - read_phy(lp, lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */ - if (!(phy & ((1 << 2) | 1))) - goto done; - } - else if (lp->phy_type == MII_T78Q21x3_ID) { /* ack interrupt in Teridian PHY */ - read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &phy); - if (!(phy & ((1 << 2) | 1))) - goto done; - } - else if (lp->phy_type == MII_DP83848_ID) { - read_phy(lp, lp->phy_address, MII_DPPHYSTS_REG, &phy); /* ack interrupt in DP83848 PHY */ - if (!(phy & (1 << 7))) - goto done; - } - - update_linkspeed(dev, 0); - -done: - disable_mdi(lp); - - return IRQ_HANDLED; -} - -/* - * Initialize and enable the PHY interrupt for link-state changes - */ -static void enable_phyirq(struct net_device *dev) -{ - struct at91_private *lp = netdev_priv(dev); - unsigned int dsintr, irq_number; - int status; - - if (!gpio_is_valid(lp->board_data.phy_irq_pin)) { - /* - * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L), - * or board does not have it connected. - */ - mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL); - return; - } - - irq_number = gpio_to_irq(lp->board_data.phy_irq_pin); - status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev); - if (status) { - printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status); - return; - } - - spin_lock_irq(&lp->lock); - enable_mdi(lp); - - if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ - read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr); - dsintr = dsintr & ~0xf00; /* clear bits 8..11 */ - write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr); - } - else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ - read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr); - dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */ - write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr); - } - else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ - dsintr = (1 << 15) | ( 1 << 14); - write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr); - } - else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */ - dsintr = (1 << 10) | ( 1 << 8); - write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr); - } - else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */ - read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr); - dsintr = dsintr | 0x500; /* set bits 8, 10 */ - write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr); - } - else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */ - read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr); - dsintr = dsintr | 0x3c; /* set bits 2..5 */ - write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr); - read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr); - dsintr = dsintr | 0x3; /* set bits 0,1 */ - write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr); - } - - disable_mdi(lp); - spin_unlock_irq(&lp->lock); -} - -/* - * Disable the PHY interrupt - */ -static void disable_phyirq(struct net_device *dev) -{ - struct at91_private *lp = netdev_priv(dev); - unsigned int dsintr; - unsigned int irq_number; - - if (!gpio_is_valid(lp->board_data.phy_irq_pin)) { - del_timer_sync(&lp->check_timer); - return; - } - - spin_lock_irq(&lp->lock); - enable_mdi(lp); - - if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ - read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr); - dsintr = dsintr | 0xf00; /* set bits 8..11 */ - write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr); - } - else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ - read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr); - dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */ - write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr); - } - else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ - read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &dsintr); - dsintr = ~(1 << 14); - write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr); - } - else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */ - read_phy(lp, lp->phy_address, MII_TPISTATUS, &dsintr); - dsintr = ~((1 << 10) | (1 << 8)); - write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr); - } - else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */ - read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr); - dsintr = dsintr & ~0x500; /* clear bits 8, 10 */ - write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr); - } - else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */ - read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr); - dsintr = dsintr & ~0x3; /* clear bits 0, 1 */ - write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr); - read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr); - dsintr = dsintr & ~0x3c; /* clear bits 2..5 */ - write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr); - } - - disable_mdi(lp); - spin_unlock_irq(&lp->lock); - - irq_number = gpio_to_irq(lp->board_data.phy_irq_pin); - free_irq(irq_number, dev); /* Free interrupt handler */ -} - -/* - * Perform a software reset of the PHY. - */ -#if 0 -static void reset_phy(struct net_device *dev) -{ - struct at91_private *lp = netdev_priv(dev); - unsigned int bmcr; - - spin_lock_irq(&lp->lock); - enable_mdi(lp); - - /* Perform PHY reset */ - write_phy(lp, lp->phy_address, MII_BMCR, BMCR_RESET); - - /* Wait until PHY reset is complete */ - do { - read_phy(lp, lp->phy_address, MII_BMCR, &bmcr); - } while (!(bmcr & BMCR_RESET)); - - disable_mdi(lp); - spin_unlock_irq(&lp->lock); -} -#endif - -static void at91ether_check_link(unsigned long dev_id) -{ - struct net_device *dev = (struct net_device *) dev_id; - struct at91_private *lp = netdev_priv(dev); - - enable_mdi(lp); - update_linkspeed(dev, 1); - disable_mdi(lp); - - mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL); -} - -/* - * Perform any PHY-specific initialization. - */ -static void __init initialize_phy(struct at91_private *lp) -{ - unsigned int val; - - spin_lock_irq(&lp->lock); - enable_mdi(lp); - - if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { - read_phy(lp, lp->phy_address, MII_DSCR_REG, &val); - if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */ - lp->phy_media = PORT_FIBRE; - } else if (machine_is_csb337()) { - /* mix link activity status into LED2 link state */ - write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x0d22); - } else if (machine_is_ecbat91()) - write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x156A); - - disable_mdi(lp); - spin_unlock_irq(&lp->lock); -} - -/* ......................... ADDRESS MANAGEMENT ........................ */ - -/* - * NOTE: Your bootloader must always set the MAC address correctly before - * booting into Linux. - * - * - It must always set the MAC address after reset, even if it doesn't - * happen to access the Ethernet while it's booting. Some versions of - * U-Boot on the AT91RM9200-DK do not do this. - * - * - Likewise it must store the addresses in the correct byte order. - * MicroMonitor (uMon) on the CSB337 does this incorrectly (and - * continues to do so, for bug-compatibility). - */ - -static short __init unpack_mac_address(struct net_device *dev, unsigned int hi, unsigned int lo) -{ - char addr[6]; - - if (machine_is_csb337()) { - addr[5] = (lo & 0xff); /* The CSB337 bootloader stores the MAC the wrong-way around */ - addr[4] = (lo & 0xff00) >> 8; - addr[3] = (lo & 0xff0000) >> 16; - addr[2] = (lo & 0xff000000) >> 24; - addr[1] = (hi & 0xff); - addr[0] = (hi & 0xff00) >> 8; - } - else { - addr[0] = (lo & 0xff); - addr[1] = (lo & 0xff00) >> 8; - addr[2] = (lo & 0xff0000) >> 16; - addr[3] = (lo & 0xff000000) >> 24; - addr[4] = (hi & 0xff); - addr[5] = (hi & 0xff00) >> 8; - } - - if (is_valid_ether_addr(addr)) { - memcpy(dev->dev_addr, &addr, 6); - return 1; - } - return 0; -} - -/* - * Set the ethernet MAC address in dev->dev_addr - */ -static void __init get_mac_address(struct net_device *dev) -{ - struct at91_private *lp = netdev_priv(dev); - - /* Check Specific-Address 1 */ - if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA1H), at91_emac_read(lp, AT91_EMAC_SA1L))) - return; - /* Check Specific-Address 2 */ - if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA2H), at91_emac_read(lp, AT91_EMAC_SA2L))) - return; - /* Check Specific-Address 3 */ - if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA3H), at91_emac_read(lp, AT91_EMAC_SA3L))) - return; - /* Check Specific-Address 4 */ - if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA4H), at91_emac_read(lp, AT91_EMAC_SA4L))) - return; - - printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n"); -} - -/* - * Program the hardware MAC address from dev->dev_addr. - */ -static void update_mac_address(struct net_device *dev) -{ - struct at91_private *lp = netdev_priv(dev); - - at91_emac_write(lp, AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0])); - at91_emac_write(lp, AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4])); - - at91_emac_write(lp, AT91_EMAC_SA2L, 0); - at91_emac_write(lp, AT91_EMAC_SA2H, 0); -} - -/* - * Store the new hardware address in dev->dev_addr, and update the MAC. - */ -static int set_mac_address(struct net_device *dev, void* addr) -{ - struct sockaddr *address = addr; - - if (!is_valid_ether_addr(address->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, address->sa_data, dev->addr_len); - update_mac_address(dev); - - printk("%s: Setting MAC address to %pM\n", dev->name, - dev->dev_addr); +#include "macb.h" - return 0; -} - -static int inline hash_bit_value(int bitnr, __u8 *addr) -{ - if (addr[bitnr / 8] & (1 << (bitnr % 8))) - return 1; - return 0; -} +/* 1518 rounded up */ +#define MAX_RBUFF_SZ 0x600 +/* max number of receive buffers */ +#define MAX_RX_DESCR 9 -/* - * The hash address register is 64 bits long and takes up two locations in the memory map. - * The least significant bits are stored in EMAC_HSL and the most significant - * bits in EMAC_HSH. - * - * The unicast hash enable and the multicast hash enable bits in the network configuration - * register enable the reception of hash matched frames. The destination address is - * reduced to a 6 bit index into the 64 bit hash register using the following hash function. - * The hash function is an exclusive or of every sixth bit of the destination address. - * hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47] - * hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46] - * hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45] - * hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44] - * hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43] - * hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42] - * da[0] represents the least significant bit of the first byte received, that is, the multicast/ - * unicast indicator, and da[47] represents the most significant bit of the last byte - * received. - * If the hash index points to a bit that is set in the hash register then the frame will be - * matched according to whether the frame is multicast or unicast. - * A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and - * the hash index points to a bit set in the hash register. - * A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the - * hash index points to a bit set in the hash register. - * To receive all multicast frames, the hash register should be set with all ones and the - * multicast hash enable bit should be set in the network configuration register. - */ - -/* - * Return the hash index value for the specified address. - */ -static int hash_get_index(__u8 *addr) -{ - int i, j, bitval; - int hash_index = 0; - - for (j = 0; j < 6; j++) { - for (i = 0, bitval = 0; i < 8; i++) - bitval ^= hash_bit_value(i*6 + j, addr); - - hash_index |= (bitval << j); - } - - return hash_index; -} - -/* - * Add multicast addresses to the internal multicast-hash table. - */ -static void at91ether_sethashtable(struct net_device *dev) +/* Initialize and start the Receiver and Transmit subsystems */ +static int at91ether_start(struct net_device *dev) { - struct at91_private *lp = netdev_priv(dev); - struct netdev_hw_addr *ha; - unsigned long mc_filter[2]; - unsigned int bitnr; - - mc_filter[0] = mc_filter[1] = 0; - - netdev_for_each_mc_addr(ha, dev) { - bitnr = hash_get_index(ha->addr); - mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); - } - - at91_emac_write(lp, AT91_EMAC_HSL, mc_filter[0]); - at91_emac_write(lp, AT91_EMAC_HSH, mc_filter[1]); -} + struct macb *lp = netdev_priv(dev); + dma_addr_t addr; + u32 ctl; + int i; -/* - * Enable/Disable promiscuous and multicast modes. - */ -static void at91ether_set_multicast_list(struct net_device *dev) -{ - struct at91_private *lp = netdev_priv(dev); - unsigned long cfg; - - cfg = at91_emac_read(lp, AT91_EMAC_CFG); - - if (dev->flags & IFF_PROMISC) /* Enable promiscuous mode */ - cfg |= AT91_EMAC_CAF; - else if (dev->flags & (~IFF_PROMISC)) /* Disable promiscuous mode */ - cfg &= ~AT91_EMAC_CAF; - - if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */ - at91_emac_write(lp, AT91_EMAC_HSH, -1); - at91_emac_write(lp, AT91_EMAC_HSL, -1); - cfg |= AT91_EMAC_MTI; - } else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */ - at91ether_sethashtable(dev); - cfg |= AT91_EMAC_MTI; - } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */ - at91_emac_write(lp, AT91_EMAC_HSH, 0); - at91_emac_write(lp, AT91_EMAC_HSL, 0); - cfg &= ~AT91_EMAC_MTI; + lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev, + MAX_RX_DESCR * sizeof(struct macb_dma_desc), + &lp->rx_ring_dma, GFP_KERNEL); + if (!lp->rx_ring) { + netdev_err(dev, "unable to alloc rx ring DMA buffer\n"); + return -ENOMEM; } - at91_emac_write(lp, AT91_EMAC_CFG, cfg); -} - -/* ......................... ETHTOOL SUPPORT ........................... */ - -static int mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct at91_private *lp = netdev_priv(dev); - unsigned int value; - - read_phy(lp, phy_id, location, &value); - return value; -} - -static void mdio_write(struct net_device *dev, int phy_id, int location, int value) -{ - struct at91_private *lp = netdev_priv(dev); - - write_phy(lp, phy_id, location, value); -} - -static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct at91_private *lp = netdev_priv(dev); - int ret; - - spin_lock_irq(&lp->lock); - enable_mdi(lp); + lp->rx_buffers = dma_alloc_coherent(&lp->pdev->dev, + MAX_RX_DESCR * MAX_RBUFF_SZ, + &lp->rx_buffers_dma, GFP_KERNEL); + if (!lp->rx_buffers) { + netdev_err(dev, "unable to alloc rx data DMA buffer\n"); - ret = mii_ethtool_gset(&lp->mii, cmd); - - disable_mdi(lp); - spin_unlock_irq(&lp->lock); - - if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */ - cmd->supported = SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; + dma_free_coherent(&lp->pdev->dev, + MAX_RX_DESCR * sizeof(struct macb_dma_desc), + lp->rx_ring, lp->rx_ring_dma); + lp->rx_ring = NULL; + return -ENOMEM; } - return ret; -} - -static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct at91_private *lp = netdev_priv(dev); - int ret; - - spin_lock_irq(&lp->lock); - enable_mdi(lp); - - ret = mii_ethtool_sset(&lp->mii, cmd); - - disable_mdi(lp); - spin_unlock_irq(&lp->lock); - - return ret; -} - -static int at91ether_nwayreset(struct net_device *dev) -{ - struct at91_private *lp = netdev_priv(dev); - int ret; - - spin_lock_irq(&lp->lock); - enable_mdi(lp); - - ret = mii_nway_restart(&lp->mii); - - disable_mdi(lp); - spin_unlock_irq(&lp->lock); - - return ret; -} - -static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); - strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); -} - -static const struct ethtool_ops at91ether_ethtool_ops = { - .get_settings = at91ether_get_settings, - .set_settings = at91ether_set_settings, - .get_drvinfo = at91ether_get_drvinfo, - .nway_reset = at91ether_nwayreset, - .get_link = ethtool_op_get_link, -}; - -static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct at91_private *lp = netdev_priv(dev); - int res; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&lp->lock); - enable_mdi(lp); - res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL); - disable_mdi(lp); - spin_unlock_irq(&lp->lock); - - return res; -} - -/* ................................ MAC ................................ */ - -/* - * Initialize and start the Receiver and Transmit subsystems - */ -static void at91ether_start(struct net_device *dev) -{ - struct at91_private *lp = netdev_priv(dev); - struct recv_desc_bufs *dlist, *dlist_phys; - int i; - unsigned long ctl; - - dlist = lp->dlist; - dlist_phys = lp->dlist_phys; - + addr = lp->rx_buffers_dma; for (i = 0; i < MAX_RX_DESCR; i++) { - dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0]; - dlist->descriptors[i].size = 0; + lp->rx_ring[i].addr = addr; + lp->rx_ring[i].ctrl = 0; + addr += MAX_RBUFF_SZ; } /* Set the Wrap bit on the last descriptor */ - dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP; + lp->rx_ring[MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP); /* Reset buffer index */ - lp->rxBuffIndex = 0; + lp->rx_tail = 0; /* Program address of descriptor list in Rx Buffer Queue register */ - at91_emac_write(lp, AT91_EMAC_RBQP, (unsigned long) dlist_phys); + macb_writel(lp, RBQP, lp->rx_ring_dma); /* Enable Receive and Transmit */ - ctl = at91_emac_read(lp, AT91_EMAC_CTL); - at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE); + ctl = macb_readl(lp, NCR); + macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE)); + + return 0; } -/* - * Open the ethernet interface - */ +/* Open the ethernet interface */ static int at91ether_open(struct net_device *dev) { - struct at91_private *lp = netdev_priv(dev); - unsigned long ctl; - - if (!is_valid_ether_addr(dev->dev_addr)) - return -EADDRNOTAVAIL; - - clk_enable(lp->ether_clk); /* Re-enable Peripheral clock */ + struct macb *lp = netdev_priv(dev); + u32 ctl; + int ret; /* Clear internal statistics */ - ctl = at91_emac_read(lp, AT91_EMAC_CTL); - at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_CSR); + ctl = macb_readl(lp, NCR); + macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT)); - /* Update the MAC address (incase user has changed it) */ - update_mac_address(dev); + macb_set_hwaddr(lp); - /* Enable PHY interrupt */ - enable_phyirq(dev); + ret = at91ether_start(dev); + if (ret) + return ret; /* Enable MAC interrupts */ - at91_emac_write(lp, AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA - | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM - | AT91_EMAC_ROVR | AT91_EMAC_ABT); - - /* Determine current link speed */ - spin_lock_irq(&lp->lock); - enable_mdi(lp); - update_linkspeed(dev, 0); - disable_mdi(lp); - spin_unlock_irq(&lp->lock); - - at91ether_start(dev); + macb_writel(lp, IER, MACB_BIT(RCOMP) | + MACB_BIT(RXUBR) | + MACB_BIT(ISR_TUND) | + MACB_BIT(ISR_RLE) | + MACB_BIT(TCOMP) | + MACB_BIT(ISR_ROVR) | + MACB_BIT(HRESP)); + + /* schedule a link state check */ + phy_start(lp->phy_dev); + netif_start_queue(dev); + return 0; } -/* - * Close the interface - */ +/* Close the interface */ static int at91ether_close(struct net_device *dev) { - struct at91_private *lp = netdev_priv(dev); - unsigned long ctl; + struct macb *lp = netdev_priv(dev); + u32 ctl; /* Disable Receiver and Transmitter */ - ctl = at91_emac_read(lp, AT91_EMAC_CTL); - at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE)); - - /* Disable PHY interrupt */ - disable_phyirq(dev); + ctl = macb_readl(lp, NCR); + macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE))); /* Disable MAC interrupts */ - at91_emac_write(lp, AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA - | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM - | AT91_EMAC_ROVR | AT91_EMAC_ABT); + macb_writel(lp, IDR, MACB_BIT(RCOMP) | + MACB_BIT(RXUBR) | + MACB_BIT(ISR_TUND) | + MACB_BIT(ISR_RLE) | + MACB_BIT(TCOMP) | + MACB_BIT(ISR_ROVR) | + MACB_BIT(HRESP)); netif_stop_queue(dev); - clk_disable(lp->ether_clk); /* Disable Peripheral clock */ + dma_free_coherent(&lp->pdev->dev, + MAX_RX_DESCR * sizeof(struct macb_dma_desc), + lp->rx_ring, lp->rx_ring_dma); + lp->rx_ring = NULL; + + dma_free_coherent(&lp->pdev->dev, + MAX_RX_DESCR * MAX_RBUFF_SZ, + lp->rx_buffers, lp->rx_buffers_dma); + lp->rx_buffers = NULL; return 0; } -/* - * Transmit packet. - */ +/* Transmit packet */ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct at91_private *lp = netdev_priv(dev); + struct macb *lp = netdev_priv(dev); - if (at91_emac_read(lp, AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) { + if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) { netif_stop_queue(dev); /* Store packet information (to free when Tx completed) */ lp->skb = skb; lp->skb_length = skb->len; - lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE); - dev->stats.tx_bytes += skb->len; + lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, + DMA_TO_DEVICE); /* Set address of the data in the Transmit Address register */ - at91_emac_write(lp, AT91_EMAC_TAR, lp->skb_physaddr); + macb_writel(lp, TAR, lp->skb_physaddr); /* Set length of the packet in the Transmit Control register */ - at91_emac_write(lp, AT91_EMAC_TCR, skb->len); + macb_writel(lp, TCR, skb->len); } else { - printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n"); - return NETDEV_TX_BUSY; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb) - on this skb, he also reports -ENETDOWN and printk's, so either - we free and return(0) or don't free and return 1 */ + netdev_err(dev, "%s called, but device is busy!\n", __func__); + return NETDEV_TX_BUSY; } return NETDEV_TX_OK; } -/* - * Update the current statistics from the internal statistics registers. - */ -static struct net_device_stats *at91ether_stats(struct net_device *dev) -{ - struct at91_private *lp = netdev_priv(dev); - int ale, lenerr, seqe, lcol, ecol; - - if (netif_running(dev)) { - dev->stats.rx_packets += at91_emac_read(lp, AT91_EMAC_OK); /* Good frames received */ - ale = at91_emac_read(lp, AT91_EMAC_ALE); - dev->stats.rx_frame_errors += ale; /* Alignment errors */ - lenerr = at91_emac_read(lp, AT91_EMAC_ELR) + at91_emac_read(lp, AT91_EMAC_USF); - dev->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */ - seqe = at91_emac_read(lp, AT91_EMAC_SEQE); - dev->stats.rx_crc_errors += seqe; /* CRC error */ - dev->stats.rx_fifo_errors += at91_emac_read(lp, AT91_EMAC_DRFC);/* Receive buffer not available */ - dev->stats.rx_errors += (ale + lenerr + seqe - + at91_emac_read(lp, AT91_EMAC_CDE) + at91_emac_read(lp, AT91_EMAC_RJB)); - - dev->stats.tx_packets += at91_emac_read(lp, AT91_EMAC_FRA); /* Frames successfully transmitted */ - dev->stats.tx_fifo_errors += at91_emac_read(lp, AT91_EMAC_TUE); /* Transmit FIFO underruns */ - dev->stats.tx_carrier_errors += at91_emac_read(lp, AT91_EMAC_CSE); /* Carrier Sense errors */ - dev->stats.tx_heartbeat_errors += at91_emac_read(lp, AT91_EMAC_SQEE);/* Heartbeat error */ - - lcol = at91_emac_read(lp, AT91_EMAC_LCOL); - ecol = at91_emac_read(lp, AT91_EMAC_ECOL); - dev->stats.tx_window_errors += lcol; /* Late collisions */ - dev->stats.tx_aborted_errors += ecol; /* 16 collisions */ - - dev->stats.collisions += (at91_emac_read(lp, AT91_EMAC_SCOL) + at91_emac_read(lp, AT91_EMAC_MCOL) + lcol + ecol); - } - return &dev->stats; -} - -/* - * Extract received frame from buffer descriptors and sent to upper layers. +/* Extract received frame from buffer descriptors and sent to upper layers. * (Called from interrupt context) */ static void at91ether_rx(struct net_device *dev) { - struct at91_private *lp = netdev_priv(dev); - struct recv_desc_bufs *dlist; + struct macb *lp = netdev_priv(dev); unsigned char *p_recv; struct sk_buff *skb; unsigned int pktlen; - dlist = lp->dlist; - 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 */ + while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) { + p_recv = lp->rx_buffers + lp->rx_tail * MAX_RBUFF_SZ; + pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl); skb = netdev_alloc_skb(dev, pktlen + 2); - if (skb != NULL) { + if (skb) { skb_reserve(skb, 2); memcpy(skb_put(skb, pktlen), p_recv, pktlen); skb->protocol = eth_type_trans(skb, dev); - dev->stats.rx_bytes += pktlen; + lp->stats.rx_packets++; + lp->stats.rx_bytes += pktlen; netif_rx(skb); + } else { + lp->stats.rx_dropped++; + netdev_notice(dev, "Memory squeeze, dropping packet.\n"); } - else { - dev->stats.rx_dropped += 1; - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); - } - if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST) - dev->stats.multicast++; + if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH)) + lp->stats.multicast++; + + /* reset ownership bit */ + lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED); - dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */ - if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */ - lp->rxBuffIndex = 0; + /* wrap after last buffer */ + if (lp->rx_tail == MAX_RX_DESCR - 1) + lp->rx_tail = 0; else - lp->rxBuffIndex++; + lp->rx_tail++; } } -/* - * MAC interrupt handler - */ +/* MAC interrupt handler */ static irqreturn_t at91ether_interrupt(int irq, void *dev_id) { - struct net_device *dev = (struct net_device *) dev_id; - struct at91_private *lp = netdev_priv(dev); - unsigned long intstatus, ctl; + struct net_device *dev = dev_id; + struct macb *lp = netdev_priv(dev); + u32 intstatus, ctl; /* MAC Interrupt Status register indicates what interrupts are pending. - It is automatically cleared once read. */ - intstatus = at91_emac_read(lp, AT91_EMAC_ISR); + * It is automatically cleared once read. + */ + intstatus = macb_readl(lp, ISR); - if (intstatus & AT91_EMAC_RCOM) /* Receive complete */ + /* Receive complete */ + if (intstatus & MACB_BIT(RCOMP)) at91ether_rx(dev); - if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */ - /* The TCOM bit is set even if the transmission failed. */ - if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY)) - dev->stats.tx_errors += 1; + /* Transmit complete */ + if (intstatus & MACB_BIT(TCOMP)) { + /* The TCOM bit is set even if the transmission failed */ + if (intstatus & (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE))) + lp->stats.tx_errors++; if (lp->skb) { dev_kfree_skb_irq(lp->skb); lp->skb = NULL; dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE); + lp->stats.tx_packets++; + lp->stats.tx_bytes += lp->skb_length; } netif_wake_queue(dev); } - /* Work-around for Errata #11 */ - if (intstatus & AT91_EMAC_RBNA) { - ctl = at91_emac_read(lp, AT91_EMAC_CTL); - at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE); - at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE); + /* Work-around for EMAC Errata section 41.3.1 */ + if (intstatus & MACB_BIT(RXUBR)) { + ctl = macb_readl(lp, NCR); + macb_writel(lp, NCR, ctl & ~MACB_BIT(RE)); + macb_writel(lp, NCR, ctl | MACB_BIT(RE)); } - if (intstatus & AT91_EMAC_ROVR) - printk("%s: ROVR error\n", dev->name); + if (intstatus & MACB_BIT(ISR_ROVR)) + netdev_err(dev, "ROVR error\n"); return IRQ_HANDLED; } @@ -1000,10 +286,10 @@ static const struct net_device_ops at91ether_netdev_ops = { .ndo_open = at91ether_open, .ndo_stop = at91ether_close, .ndo_start_xmit = at91ether_start_xmit, - .ndo_get_stats = at91ether_stats, - .ndo_set_rx_mode = at91ether_set_multicast_list, - .ndo_set_mac_address = set_mac_address, - .ndo_do_ioctl = at91ether_ioctl, + .ndo_get_stats = macb_get_stats, + .ndo_set_rx_mode = macb_set_rx_mode, + .ndo_set_mac_address = eth_mac_addr, + .ndo_do_ioctl = macb_ioctl, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -1011,237 +297,195 @@ static const struct net_device_ops at91ether_netdev_ops = { #endif }; -/* - * Detect the PHY type, and its address. - */ -static int __init at91ether_phy_detect(struct at91_private *lp) +#if defined(CONFIG_OF) +static const struct of_device_id at91ether_dt_ids[] = { + { .compatible = "cdns,at91rm9200-emac" }, + { .compatible = "cdns,emac" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, at91ether_dt_ids); + +static int at91ether_get_phy_mode_dt(struct platform_device *pdev) { - unsigned int phyid1, phyid2; - unsigned long phy_id; - unsigned short phy_address = 0; - - while (phy_address < PHY_MAX_ADDR) { - /* Read the PHY ID registers */ - enable_mdi(lp); - read_phy(lp, phy_address, MII_PHYSID1, &phyid1); - read_phy(lp, phy_address, MII_PHYSID2, &phyid2); - disable_mdi(lp); - - phy_id = (phyid1 << 16) | (phyid2 & 0xfff0); - switch (phy_id) { - case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */ - case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */ - case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */ - case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */ - case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */ - case MII_DP83847_ID: /* National Semiconductor DP83847: */ - case MII_DP83848_ID: /* National Semiconductor DP83848: */ - case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */ - case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */ - case MII_T78Q21x3_ID: /* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */ - case MII_LAN83C185_ID: /* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */ - /* store detected values */ - lp->phy_type = phy_id; /* Type of PHY connected */ - lp->phy_address = phy_address; /* MDI address of PHY */ - return 1; - } + struct device_node *np = pdev->dev.of_node; - phy_address++; - } + if (np) + return of_get_phy_mode(np); - return 0; /* not detected */ + return -ENODEV; } +static int at91ether_get_hwaddr_dt(struct macb *bp) +{ + struct device_node *np = bp->pdev->dev.of_node; -/* - * Detect MAC & PHY and perform ethernet interface initialization - */ + if (np) { + const char *mac = of_get_mac_address(np); + if (mac) { + memcpy(bp->dev->dev_addr, mac, ETH_ALEN); + return 0; + } + } + + return -ENODEV; +} +#else +static int at91ether_get_phy_mode_dt(struct platform_device *pdev) +{ + return -ENODEV; +} +static int at91ether_get_hwaddr_dt(struct macb *bp) +{ + return -ENODEV; +} +#endif + +/* Detect MAC & PHY and perform ethernet interface initialization */ static int __init at91ether_probe(struct platform_device *pdev) { struct macb_platform_data *board_data = pdev->dev.platform_data; struct resource *regs; struct net_device *dev; - struct at91_private *lp; + struct phy_device *phydev; + struct pinctrl *pinctrl; + struct macb *lp; int res; + u32 reg; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) return -ENOENT; - dev = alloc_etherdev(sizeof(struct at91_private)); + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) { + res = PTR_ERR(pinctrl); + if (res == -EPROBE_DEFER) + return res; + + dev_warn(&pdev->dev, "No pinctrl provided\n"); + } + + dev = alloc_etherdev(sizeof(struct macb)); if (!dev) return -ENOMEM; lp = netdev_priv(dev); - lp->board_data = *board_data; + lp->pdev = pdev; + lp->dev = dev; spin_lock_init(&lp->lock); - dev->base_addr = regs->start; /* physical base address */ - lp->emac_base = ioremap(regs->start, regs->end - regs->start + 1); - if (!lp->emac_base) { + /* physical base address */ + dev->base_addr = regs->start; + lp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); + if (!lp->regs) { res = -ENOMEM; goto err_free_dev; } /* Clock */ - lp->ether_clk = clk_get(&pdev->dev, "ether_clk"); - if (IS_ERR(lp->ether_clk)) { - res = PTR_ERR(lp->ether_clk); - goto err_ioumap; + lp->pclk = devm_clk_get(&pdev->dev, "ether_clk"); + if (IS_ERR(lp->pclk)) { + res = PTR_ERR(lp->pclk); + goto err_free_dev; } - clk_enable(lp->ether_clk); + clk_enable(lp->pclk); /* Install the interrupt handler */ dev->irq = platform_get_irq(pdev, 0); - if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) { - res = -EBUSY; + res = devm_request_irq(&pdev->dev, dev->irq, at91ether_interrupt, 0, dev->name, dev); + if (res) goto err_disable_clock; - } - - /* Allocate memory for DMA Receive descriptors */ - lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL); - if (lp->dlist == NULL) { - res = -ENOMEM; - goto err_free_irq; - } ether_setup(dev); dev->netdev_ops = &at91ether_netdev_ops; - dev->ethtool_ops = &at91ether_ethtool_ops; + dev->ethtool_ops = &macb_ethtool_ops; platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); - get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */ - update_mac_address(dev); /* Program ethernet address into MAC */ - - at91_emac_write(lp, AT91_EMAC_CTL, 0); + res = at91ether_get_hwaddr_dt(lp); + if (res < 0) + macb_get_hwaddr(lp); - if (board_data->is_rmii) - at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII); - else - at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG); - - /* Detect PHY */ - if (!at91ether_phy_detect(lp)) { - printk(KERN_ERR "at91_ether: Could not detect ethernet PHY\n"); - res = -ENODEV; - goto err_free_dmamem; + res = at91ether_get_phy_mode_dt(pdev); + if (res < 0) { + if (board_data && board_data->is_rmii) + lp->phy_interface = PHY_INTERFACE_MODE_RMII; + else + lp->phy_interface = PHY_INTERFACE_MODE_MII; + } else { + lp->phy_interface = res; } - initialize_phy(lp); + macb_writel(lp, NCR, 0); + + reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG); + if (lp->phy_interface == PHY_INTERFACE_MODE_RMII) + reg |= MACB_BIT(RM9200_RMII); - lp->mii.dev = dev; /* Support for ethtool */ - lp->mii.mdio_read = mdio_read; - lp->mii.mdio_write = mdio_write; - lp->mii.phy_id = lp->phy_address; - lp->mii.phy_id_mask = 0x1f; - lp->mii.reg_num_mask = 0x1f; + macb_writel(lp, NCFGR, reg); /* Register the network interface */ res = register_netdev(dev); if (res) - goto err_free_dmamem; - - /* Determine current link speed */ - spin_lock_irq(&lp->lock); - enable_mdi(lp); - update_linkspeed(dev, 0); - disable_mdi(lp); - spin_unlock_irq(&lp->lock); - netif_carrier_off(dev); /* will be enabled in open() */ - - /* If board has no PHY IRQ, use a timer to poll the PHY */ - if (gpio_is_valid(lp->board_data.phy_irq_pin)) { - gpio_request(board_data->phy_irq_pin, "ethernet_phy"); - } else { - /* If board has no PHY IRQ, use a timer to poll the PHY */ - init_timer(&lp->check_timer); - lp->check_timer.data = (unsigned long)dev; - lp->check_timer.function = at91ether_check_link; - } + goto err_disable_clock; + + if (macb_mii_init(lp) != 0) + goto err_out_unregister_netdev; + + /* will be enabled in open() */ + netif_carrier_off(dev); + + phydev = lp->phy_dev; + netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", + phydev->drv->name, dev_name(&phydev->dev), + phydev->irq); /* Display ethernet banner */ - printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n", - dev->name, (uint) dev->base_addr, dev->irq, - at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-", - at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex", - dev->dev_addr); - if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) - printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)"); - else if (lp->phy_type == MII_LXT971A_ID) - printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name); - else if (lp->phy_type == MII_RTL8201_ID) - printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name); - else if (lp->phy_type == MII_BCM5221_ID) - printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name); - else if (lp->phy_type == MII_DP83847_ID) - printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name); - else if (lp->phy_type == MII_DP83848_ID) - printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name); - else if (lp->phy_type == MII_AC101L_ID) - printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name); - else if (lp->phy_type == MII_KS8721_ID) - printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name); - else if (lp->phy_type == MII_T78Q21x3_ID) - printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name); - else if (lp->phy_type == MII_LAN83C185_ID) - printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name); - - clk_disable(lp->ether_clk); /* Disable Peripheral clock */ + netdev_info(dev, "AT91 ethernet at 0x%08lx int=%d (%pM)\n", + dev->base_addr, dev->irq, dev->dev_addr); return 0; - -err_free_dmamem: - platform_set_drvdata(pdev, NULL); - dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); -err_free_irq: - free_irq(dev->irq, dev); +err_out_unregister_netdev: + unregister_netdev(dev); err_disable_clock: - clk_disable(lp->ether_clk); - clk_put(lp->ether_clk); -err_ioumap: - iounmap(lp->emac_base); + clk_disable(lp->pclk); err_free_dev: free_netdev(dev); return res; } -static int __devexit at91ether_remove(struct platform_device *pdev) +static int at91ether_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); - struct at91_private *lp = netdev_priv(dev); + struct macb *lp = netdev_priv(dev); - if (gpio_is_valid(lp->board_data.phy_irq_pin)) - gpio_free(lp->board_data.phy_irq_pin); + if (lp->phy_dev) + phy_disconnect(lp->phy_dev); + mdiobus_unregister(lp->mii_bus); + kfree(lp->mii_bus->irq); + mdiobus_free(lp->mii_bus); unregister_netdev(dev); - free_irq(dev->irq, dev); - dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); - clk_put(lp->ether_clk); - - platform_set_drvdata(pdev, NULL); + clk_disable(lp->pclk); free_netdev(dev); + platform_set_drvdata(pdev, NULL); + return 0; } #ifdef CONFIG_PM - static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg) { struct net_device *net_dev = platform_get_drvdata(pdev); - struct at91_private *lp = netdev_priv(net_dev); + struct macb *lp = netdev_priv(net_dev); if (netif_running(net_dev)) { - if (gpio_is_valid(lp->board_data.phy_irq_pin)) { - int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin); - disable_irq(phy_irq); - } - netif_stop_queue(net_dev); netif_device_detach(net_dev); - clk_disable(lp->ether_clk); + clk_disable(lp->pclk); } return 0; } @@ -1249,34 +493,29 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg) static int at91ether_resume(struct platform_device *pdev) { struct net_device *net_dev = platform_get_drvdata(pdev); - struct at91_private *lp = netdev_priv(net_dev); + struct macb *lp = netdev_priv(net_dev); if (netif_running(net_dev)) { - clk_enable(lp->ether_clk); + clk_enable(lp->pclk); netif_device_attach(net_dev); netif_start_queue(net_dev); - - if (gpio_is_valid(lp->board_data.phy_irq_pin)) { - int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin); - enable_irq(phy_irq); - } } return 0; } - #else #define at91ether_suspend NULL #define at91ether_resume NULL #endif static struct platform_driver at91ether_driver = { - .remove = __devexit_p(at91ether_remove), + .remove = at91ether_remove, .suspend = at91ether_suspend, .resume = at91ether_resume, .driver = { - .name = DRV_NAME, + .name = "at91_ether", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(at91ether_dt_ids), }, }; @@ -1296,4 +535,4 @@ module_exit(at91ether_exit) MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver"); MODULE_AUTHOR("Andrew Victor"); -MODULE_ALIAS("platform:" DRV_NAME); +MODULE_ALIAS("platform:at91_ether"); diff --git a/drivers/net/ethernet/cadence/at91_ether.h b/drivers/net/ethernet/cadence/at91_ether.h deleted file mode 100644 index 0ef6328fa7f8..000000000000 --- a/drivers/net/ethernet/cadence/at91_ether.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Ethernet driver for the Atmel AT91RM9200 (Thunder) - * - * Copyright (C) SAN People (Pty) Ltd - * - * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc. - * Initial version by Rick Bronson. - * - * 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 the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef AT91_ETHERNET -#define AT91_ETHERNET - - -/* Davicom 9161 PHY */ -#define MII_DM9161_ID 0x0181b880 -#define MII_DM9161A_ID 0x0181b8a0 -#define MII_DSCR_REG 16 -#define MII_DSCSR_REG 17 -#define MII_DSINTR_REG 21 - -/* Intel LXT971A PHY */ -#define MII_LXT971A_ID 0x001378E0 -#define MII_ISINTE_REG 18 -#define MII_ISINTS_REG 19 -#define MII_LEDCTRL_REG 20 - -/* Realtek RTL8201 PHY */ -#define MII_RTL8201_ID 0x00008200 - -/* Broadcom BCM5221 PHY */ -#define MII_BCM5221_ID 0x004061e0 -#define MII_BCMINTR_REG 26 - -/* National Semiconductor DP83847 */ -#define MII_DP83847_ID 0x20005c30 - -/* National Semiconductor DP83848 */ -#define MII_DP83848_ID 0x20005c90 -#define MII_DPPHYSTS_REG 16 -#define MII_DPMICR_REG 17 -#define MII_DPMISR_REG 18 - -/* Altima AC101L PHY */ -#define MII_AC101L_ID 0x00225520 - -/* Micrel KS8721 PHY */ -#define MII_KS8721_ID 0x00221610 - -/* Teridian 78Q2123/78Q2133 */ -#define MII_T78Q21x3_ID 0x000e7230 -#define MII_T78Q21INT_REG 17 - -/* SMSC LAN83C185 */ -#define MII_LAN83C185_ID 0x0007C0A0 - -/* ........................................................................ */ - -#define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */ -#define MAX_RX_DESCR 9 /* max number of receive buffers */ - -#define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */ -#define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */ - -#define EMAC_BROADCAST 0x80000000 /* broadcast address */ -#define EMAC_MULTICAST 0x40000000 /* multicast address */ -#define EMAC_UNICAST 0x20000000 /* unicast address */ - -struct rbf_t -{ - unsigned int addr; - unsigned long size; -}; - -struct recv_desc_bufs -{ - struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */ - char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */ -}; - -struct at91_private -{ - struct mii_if_info mii; /* ethtool support */ - struct macb_platform_data board_data; /* board-specific - * configuration (shared with - * macb for common data */ - void __iomem *emac_base; /* base register address */ - struct clk *ether_clk; /* clock */ - - /* PHY */ - unsigned long phy_type; /* type of PHY (PHY_ID) */ - spinlock_t lock; /* lock for MDI interface */ - short phy_media; /* media interface type */ - unsigned short phy_address; /* 5-bit MDI address of PHY (0..31) */ - struct timer_list check_timer; /* Poll link status */ - - /* Transmit */ - struct sk_buff *skb; /* holds skb until xmit interrupt completes */ - dma_addr_t skb_physaddr; /* phys addr from pci_map_single */ - int skb_length; /* saved skb length for pci_unmap_single */ - - /* Receive */ - int rxBuffIndex; /* index into receive descriptor list */ - struct recv_desc_bufs *dlist; /* descriptor list address */ - struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */ -}; - -#endif diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 033064b7b576..a9b0830fb39d 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -14,8 +14,10 @@ #include <linux/moduleparam.h> #include <linux/kernel.h> #include <linux/types.h> +#include <linux/circ_buf.h> #include <linux/slab.h> #include <linux/init.h> +#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -26,37 +28,74 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_net.h> +#include <linux/pinctrl/consumer.h> #include "macb.h" #define RX_BUFFER_SIZE 128 -#define RX_RING_SIZE 512 -#define RX_RING_BYTES (sizeof(struct dma_desc) * RX_RING_SIZE) +#define RX_RING_SIZE 512 /* must be power of 2 */ +#define RX_RING_BYTES (sizeof(struct macb_dma_desc) * RX_RING_SIZE) -/* Make the IP header word-aligned (the ethernet header is 14 bytes) */ -#define RX_OFFSET 2 +#define TX_RING_SIZE 128 /* must be power of 2 */ +#define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE) -#define TX_RING_SIZE 128 -#define DEF_TX_RING_PENDING (TX_RING_SIZE - 1) -#define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE) +/* level of occupied TX descriptors under which we wake up TX process */ +#define MACB_TX_WAKEUP_THRESH (3 * TX_RING_SIZE / 4) -#define TX_RING_GAP(bp) \ - (TX_RING_SIZE - (bp)->tx_pending) -#define TX_BUFFS_AVAIL(bp) \ - (((bp)->tx_tail <= (bp)->tx_head) ? \ - (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head : \ - (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp)) -#define NEXT_TX(n) (((n) + 1) & (TX_RING_SIZE - 1)) +#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \ + | MACB_BIT(ISR_ROVR)) +#define MACB_TX_ERR_FLAGS (MACB_BIT(ISR_TUND) \ + | MACB_BIT(ISR_RLE) \ + | MACB_BIT(TXERR)) +#define MACB_TX_INT_FLAGS (MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP)) -#define NEXT_RX(n) (((n) + 1) & (RX_RING_SIZE - 1)) +/* + * Graceful stop timeouts in us. We should allow up to + * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions) + */ +#define MACB_HALT_TIMEOUT 1230 -/* minimum number of free TX descriptors before waking up TX process */ -#define MACB_TX_WAKEUP_THRESH (TX_RING_SIZE / 4) +/* Ring buffer accessors */ +static unsigned int macb_tx_ring_wrap(unsigned int index) +{ + return index & (TX_RING_SIZE - 1); +} -#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \ - | MACB_BIT(ISR_ROVR)) +static struct macb_dma_desc *macb_tx_desc(struct macb *bp, unsigned int index) +{ + return &bp->tx_ring[macb_tx_ring_wrap(index)]; +} -static void __macb_set_hwaddr(struct macb *bp) +static struct macb_tx_skb *macb_tx_skb(struct macb *bp, unsigned int index) +{ + return &bp->tx_skb[macb_tx_ring_wrap(index)]; +} + +static dma_addr_t macb_tx_dma(struct macb *bp, unsigned int index) +{ + dma_addr_t offset; + + offset = macb_tx_ring_wrap(index) * sizeof(struct macb_dma_desc); + + return bp->tx_ring_dma + offset; +} + +static unsigned int macb_rx_ring_wrap(unsigned int index) +{ + return index & (RX_RING_SIZE - 1); +} + +static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index) +{ + return &bp->rx_ring[macb_rx_ring_wrap(index)]; +} + +static void *macb_rx_buffer(struct macb *bp, unsigned int index) +{ + return bp->rx_buffers + RX_BUFFER_SIZE * macb_rx_ring_wrap(index); +} + +void macb_set_hwaddr(struct macb *bp) { u32 bottom; u16 top; @@ -65,31 +104,58 @@ static void __macb_set_hwaddr(struct macb *bp) macb_or_gem_writel(bp, SA1B, bottom); top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4))); macb_or_gem_writel(bp, SA1T, top); + + /* Clear unused address register sets */ + macb_or_gem_writel(bp, SA2B, 0); + macb_or_gem_writel(bp, SA2T, 0); + macb_or_gem_writel(bp, SA3B, 0); + macb_or_gem_writel(bp, SA3T, 0); + macb_or_gem_writel(bp, SA4B, 0); + macb_or_gem_writel(bp, SA4T, 0); } +EXPORT_SYMBOL_GPL(macb_set_hwaddr); -static void __init macb_get_hwaddr(struct macb *bp) +void macb_get_hwaddr(struct macb *bp) { + struct macb_platform_data *pdata; u32 bottom; u16 top; u8 addr[6]; + int i; - bottom = macb_or_gem_readl(bp, SA1B); - top = macb_or_gem_readl(bp, SA1T); + pdata = bp->pdev->dev.platform_data; - addr[0] = bottom & 0xff; - addr[1] = (bottom >> 8) & 0xff; - addr[2] = (bottom >> 16) & 0xff; - addr[3] = (bottom >> 24) & 0xff; - addr[4] = top & 0xff; - addr[5] = (top >> 8) & 0xff; + /* Check all 4 address register for vaild address */ + for (i = 0; i < 4; i++) { + bottom = macb_or_gem_readl(bp, SA1B + i * 8); + top = macb_or_gem_readl(bp, SA1T + i * 8); + + if (pdata && pdata->rev_eth_addr) { + addr[5] = bottom & 0xff; + addr[4] = (bottom >> 8) & 0xff; + addr[3] = (bottom >> 16) & 0xff; + addr[2] = (bottom >> 24) & 0xff; + addr[1] = top & 0xff; + addr[0] = (top & 0xff00) >> 8; + } else { + addr[0] = bottom & 0xff; + addr[1] = (bottom >> 8) & 0xff; + addr[2] = (bottom >> 16) & 0xff; + addr[3] = (bottom >> 24) & 0xff; + addr[4] = top & 0xff; + addr[5] = (top >> 8) & 0xff; + } - if (is_valid_ether_addr(addr)) { - memcpy(bp->dev->dev_addr, addr, sizeof(addr)); - } else { - netdev_info(bp->dev, "invalid hw address, using random\n"); - eth_hw_addr_random(bp->dev); + if (is_valid_ether_addr(addr)) { + memcpy(bp->dev->dev_addr, addr, sizeof(addr)); + return; + } } + + netdev_info(bp->dev, "invalid hw address, using random\n"); + eth_hw_addr_random(bp->dev); } +EXPORT_SYMBOL_GPL(macb_get_hwaddr); static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { @@ -152,13 +218,17 @@ static void macb_handle_link_change(struct net_device *dev) reg = macb_readl(bp, NCFGR); reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); + if (macb_is_gem(bp)) + reg &= ~GEM_BIT(GBE); if (phydev->duplex) reg |= MACB_BIT(FD); if (phydev->speed == SPEED_100) reg |= MACB_BIT(SPD); + if (phydev->speed == SPEED_1000) + reg |= GEM_BIT(GBE); - macb_writel(bp, NCFGR, reg); + macb_or_gem_writel(bp, NCFGR, reg); bp->speed = phydev->speed; bp->duplex = phydev->duplex; @@ -196,7 +266,9 @@ static void macb_handle_link_change(struct net_device *dev) static int macb_mii_probe(struct net_device *dev) { struct macb *bp = netdev_priv(dev); + struct macb_platform_data *pdata; struct phy_device *phydev; + int phy_irq; int ret; phydev = phy_find_first(bp->mii_bus); @@ -205,7 +277,14 @@ static int macb_mii_probe(struct net_device *dev) return -1; } - /* TODO : add pin_irq */ + pdata = dev_get_platdata(&bp->pdev->dev); + if (pdata && gpio_is_valid(pdata->phy_irq_pin)) { + ret = devm_gpio_request(&bp->pdev->dev, pdata->phy_irq_pin, "phy int"); + if (!ret) { + phy_irq = gpio_to_irq(pdata->phy_irq_pin); + phydev->irq = (phy_irq < 0) ? PHY_POLL : phy_irq; + } + } /* attach the mac to the phy */ ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, 0, @@ -216,7 +295,10 @@ static int macb_mii_probe(struct net_device *dev) } /* mask with MAC supported features */ - phydev->supported &= PHY_BASIC_FEATURES; + if (macb_is_gem(bp)) + phydev->supported &= PHY_GBIT_FEATURES; + else + phydev->supported &= PHY_BASIC_FEATURES; phydev->advertising = phydev->supported; @@ -228,7 +310,7 @@ static int macb_mii_probe(struct net_device *dev) return 0; } -static int macb_mii_init(struct macb *bp) +int macb_mii_init(struct macb *bp) { struct macb_platform_data *pdata; int err = -ENXIO, i; @@ -284,6 +366,7 @@ err_out_free_mdiobus: err_out: return err; } +EXPORT_SYMBOL_GPL(macb_mii_init); static void macb_update_stats(struct macb *bp) { @@ -297,93 +380,148 @@ static void macb_update_stats(struct macb *bp) *p += __raw_readl(reg); } -static void macb_tx(struct macb *bp) +static int macb_halt_tx(struct macb *bp) { - unsigned int tail; - unsigned int head; - u32 status; + unsigned long halt_time, timeout; + u32 status; - status = macb_readl(bp, TSR); - macb_writel(bp, TSR, status); + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(THALT)); - netdev_dbg(bp->dev, "macb_tx status = %02lx\n", (unsigned long)status); + timeout = jiffies + usecs_to_jiffies(MACB_HALT_TIMEOUT); + do { + halt_time = jiffies; + status = macb_readl(bp, TSR); + if (!(status & MACB_BIT(TGO))) + return 0; - if (status & (MACB_BIT(UND) | MACB_BIT(TSR_RLE))) { - int i; - netdev_err(bp->dev, "TX %s, resetting buffers\n", - status & MACB_BIT(UND) ? - "underrun" : "retry limit exceeded"); + usleep_range(10, 250); + } while (time_before(halt_time, timeout)); - /* Transfer ongoing, disable transmitter, to avoid confusion */ - if (status & MACB_BIT(TGO)) - macb_writel(bp, NCR, macb_readl(bp, NCR) & ~MACB_BIT(TE)); + return -ETIMEDOUT; +} - head = bp->tx_head; +static void macb_tx_error_task(struct work_struct *work) +{ + struct macb *bp = container_of(work, struct macb, tx_error_task); + struct macb_tx_skb *tx_skb; + struct sk_buff *skb; + unsigned int tail; - /*Mark all the buffer as used to avoid sending a lost buffer*/ - for (i = 0; i < TX_RING_SIZE; i++) - bp->tx_ring[i].ctrl = MACB_BIT(TX_USED); + netdev_vdbg(bp->dev, "macb_tx_error_task: t = %u, h = %u\n", + bp->tx_tail, bp->tx_head); - /* Add wrap bit */ - bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP); + /* Make sure nobody is trying to queue up new packets */ + netif_stop_queue(bp->dev); - /* free transmit buffer in upper layer*/ - for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) { - struct ring_info *rp = &bp->tx_skb[tail]; - struct sk_buff *skb = rp->skb; + /* + * Stop transmission now + * (in case we have just queued new packets) + */ + if (macb_halt_tx(bp)) + /* Just complain for now, reinitializing TX path can be good */ + netdev_err(bp->dev, "BUG: halt tx timed out\n"); - BUG_ON(skb == NULL); + /* No need for the lock here as nobody will interrupt us anymore */ - rmb(); + /* + * Treat frames in TX queue including the ones that caused the error. + * Free transmit buffers in upper layer. + */ + for (tail = bp->tx_tail; tail != bp->tx_head; tail++) { + struct macb_dma_desc *desc; + u32 ctrl; + + desc = macb_tx_desc(bp, tail); + ctrl = desc->ctrl; + tx_skb = macb_tx_skb(bp, tail); + skb = tx_skb->skb; + + if (ctrl & MACB_BIT(TX_USED)) { + netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n", + macb_tx_ring_wrap(tail), skb->data); + bp->stats.tx_packets++; + bp->stats.tx_bytes += skb->len; + } else { + /* + * "Buffers exhausted mid-frame" errors may only happen + * if the driver is buggy, so complain loudly about those. + * Statistics are updated by hardware. + */ + if (ctrl & MACB_BIT(TX_BUF_EXHAUSTED)) + netdev_err(bp->dev, + "BUG: TX buffers exhausted mid-frame\n"); - dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len, - DMA_TO_DEVICE); - rp->skb = NULL; - dev_kfree_skb_irq(skb); + desc->ctrl = ctrl | MACB_BIT(TX_USED); } - bp->tx_head = bp->tx_tail = 0; - - /* Enable the transmitter again */ - if (status & MACB_BIT(TGO)) - macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE)); + dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len, + DMA_TO_DEVICE); + tx_skb->skb = NULL; + dev_kfree_skb(skb); } - if (!(status & MACB_BIT(COMP))) - /* - * This may happen when a buffer becomes complete - * between reading the ISR and scanning the - * descriptors. Nothing to worry about. - */ - return; + /* Make descriptor updates visible to hardware */ + wmb(); + + /* Reinitialize the TX desc queue */ + macb_writel(bp, TBQP, bp->tx_ring_dma); + /* Make TX ring reflect state of hardware */ + bp->tx_head = bp->tx_tail = 0; + + /* Now we are ready to start transmission again */ + netif_wake_queue(bp->dev); + + /* Housework before enabling TX IRQ */ + macb_writel(bp, TSR, macb_readl(bp, TSR)); + macb_writel(bp, IER, MACB_TX_INT_FLAGS); +} + +static void macb_tx_interrupt(struct macb *bp) +{ + unsigned int tail; + unsigned int head; + u32 status; + + status = macb_readl(bp, TSR); + macb_writel(bp, TSR, status); + + netdev_vdbg(bp->dev, "macb_tx_interrupt status = 0x%03lx\n", + (unsigned long)status); head = bp->tx_head; - for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) { - struct ring_info *rp = &bp->tx_skb[tail]; - struct sk_buff *skb = rp->skb; - u32 bufstat; + for (tail = bp->tx_tail; tail != head; tail++) { + struct macb_tx_skb *tx_skb; + struct sk_buff *skb; + struct macb_dma_desc *desc; + u32 ctrl; - BUG_ON(skb == NULL); + desc = macb_tx_desc(bp, tail); + /* Make hw descriptor updates visible to CPU */ rmb(); - bufstat = bp->tx_ring[tail].ctrl; - if (!(bufstat & MACB_BIT(TX_USED))) + ctrl = desc->ctrl; + + if (!(ctrl & MACB_BIT(TX_USED))) break; - netdev_dbg(bp->dev, "skb %u (data %p) TX complete\n", - tail, skb->data); - dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len, + tx_skb = macb_tx_skb(bp, tail); + skb = tx_skb->skb; + + netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n", + macb_tx_ring_wrap(tail), skb->data); + dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len, DMA_TO_DEVICE); bp->stats.tx_packets++; bp->stats.tx_bytes += skb->len; - rp->skb = NULL; + tx_skb->skb = NULL; dev_kfree_skb_irq(skb); } bp->tx_tail = tail; - if (netif_queue_stopped(bp->dev) && - TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH) + if (netif_queue_stopped(bp->dev) + && CIRC_CNT(bp->tx_head, bp->tx_tail, + TX_RING_SIZE) <= MACB_TX_WAKEUP_THRESH) netif_wake_queue(bp->dev); } @@ -392,31 +530,48 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, { unsigned int len; unsigned int frag; - unsigned int offset = 0; + unsigned int offset; struct sk_buff *skb; + struct macb_dma_desc *desc; - len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl); + desc = macb_rx_desc(bp, last_frag); + len = MACB_BFEXT(RX_FRMLEN, desc->ctrl); - netdev_dbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n", - first_frag, last_frag, len); + netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n", + macb_rx_ring_wrap(first_frag), + macb_rx_ring_wrap(last_frag), len); - skb = netdev_alloc_skb(bp->dev, len + RX_OFFSET); + /* + * The ethernet header starts NET_IP_ALIGN bytes into the + * first buffer. Since the header is 14 bytes, this makes the + * payload word-aligned. + * + * Instead of calling skb_reserve(NET_IP_ALIGN), we just copy + * the two padding bytes into the skb so that we avoid hitting + * the slowpath in memcpy(), and pull them off afterwards. + */ + skb = netdev_alloc_skb(bp->dev, len + NET_IP_ALIGN); if (!skb) { bp->stats.rx_dropped++; - for (frag = first_frag; ; frag = NEXT_RX(frag)) { - bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); + for (frag = first_frag; ; frag++) { + desc = macb_rx_desc(bp, frag); + desc->addr &= ~MACB_BIT(RX_USED); if (frag == last_frag) break; } + + /* Make descriptor updates visible to hardware */ wmb(); + return 1; } - skb_reserve(skb, RX_OFFSET); + offset = 0; + len += NET_IP_ALIGN; skb_checksum_none_assert(skb); skb_put(skb, len); - for (frag = first_frag; ; frag = NEXT_RX(frag)) { + for (frag = first_frag; ; frag++) { unsigned int frag_len = RX_BUFFER_SIZE; if (offset + frag_len > len) { @@ -424,22 +579,24 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, frag_len = len - offset; } skb_copy_to_linear_data_offset(skb, offset, - (bp->rx_buffers + - (RX_BUFFER_SIZE * frag)), - frag_len); + macb_rx_buffer(bp, frag), frag_len); offset += RX_BUFFER_SIZE; - bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); - wmb(); + desc = macb_rx_desc(bp, frag); + desc->addr &= ~MACB_BIT(RX_USED); if (frag == last_frag) break; } + /* Make descriptor updates visible to hardware */ + wmb(); + + __skb_pull(skb, NET_IP_ALIGN); skb->protocol = eth_type_trans(skb, bp->dev); bp->stats.rx_packets++; - bp->stats.rx_bytes += len; - netdev_dbg(bp->dev, "received skb of length %u, csum: %08x\n", + bp->stats.rx_bytes += skb->len; + netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n", skb->len, skb->csum); netif_receive_skb(skb); @@ -452,8 +609,12 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin, { unsigned int frag; - for (frag = begin; frag != end; frag = NEXT_RX(frag)) - bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); + for (frag = begin; frag != end; frag++) { + struct macb_dma_desc *desc = macb_rx_desc(bp, frag); + desc->addr &= ~MACB_BIT(RX_USED); + } + + /* Make descriptor updates visible to hardware */ wmb(); /* @@ -466,15 +627,18 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin, static int macb_rx(struct macb *bp, int budget) { int received = 0; - unsigned int tail = bp->rx_tail; + unsigned int tail; int first_frag = -1; - for (; budget > 0; tail = NEXT_RX(tail)) { + for (tail = bp->rx_tail; budget > 0; tail++) { + struct macb_dma_desc *desc = macb_rx_desc(bp, tail); u32 addr, ctrl; + /* Make hw descriptor updates visible to CPU */ rmb(); - addr = bp->rx_ring[tail].addr; - ctrl = bp->rx_ring[tail].ctrl; + + addr = desc->addr; + ctrl = desc->ctrl; if (!(addr & MACB_BIT(RX_USED))) break; @@ -517,7 +681,7 @@ static int macb_poll(struct napi_struct *napi, int budget) work_done = 0; - netdev_dbg(bp->dev, "poll: status = %08lx, budget = %d\n", + netdev_vdbg(bp->dev, "poll: status = %08lx, budget = %d\n", (unsigned long)status, budget); work_done = macb_rx(bp, budget); @@ -552,10 +716,12 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) while (status) { /* close possible race with dev_close */ if (unlikely(!netif_running(dev))) { - macb_writel(bp, IDR, ~0UL); + macb_writel(bp, IDR, -1); break; } + netdev_vdbg(bp->dev, "isr = 0x%08lx\n", (unsigned long)status); + if (status & MACB_RX_INT_FLAGS) { /* * There's no point taking any more interrupts @@ -567,14 +733,19 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) macb_writel(bp, IDR, MACB_RX_INT_FLAGS); if (napi_schedule_prep(&bp->napi)) { - netdev_dbg(bp->dev, "scheduling RX softirq\n"); + netdev_vdbg(bp->dev, "scheduling RX softirq\n"); __napi_schedule(&bp->napi); } } - if (status & (MACB_BIT(TCOMP) | MACB_BIT(ISR_TUND) | - MACB_BIT(ISR_RLE))) - macb_tx(bp); + if (unlikely(status & (MACB_TX_ERR_FLAGS))) { + macb_writel(bp, IDR, MACB_TX_INT_FLAGS); + schedule_work(&bp->tx_error_task); + break; + } + + if (status & MACB_BIT(TCOMP)) + macb_tx_interrupt(bp); /* * Link change detection isn't possible with RMII, so we'll @@ -626,11 +797,13 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) struct macb *bp = netdev_priv(dev); dma_addr_t mapping; unsigned int len, entry; + struct macb_dma_desc *desc; + struct macb_tx_skb *tx_skb; u32 ctrl; unsigned long flags; -#ifdef DEBUG - netdev_dbg(bp->dev, +#if defined(DEBUG) && defined(VERBOSE_DEBUG) + netdev_vdbg(bp->dev, "start_xmit: len %u head %p data %p tail %p end %p\n", skb->len, skb->head, skb->data, skb_tail_pointer(skb), skb_end_pointer(skb)); @@ -642,7 +815,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&bp->lock, flags); /* This is a hard error, log it. */ - if (TX_BUFFS_AVAIL(bp) < 1) { + if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1) { netif_stop_queue(dev); spin_unlock_irqrestore(&bp->lock, flags); netdev_err(bp->dev, "BUG! Tx Ring full when queue awake!\n"); @@ -651,13 +824,16 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } - entry = bp->tx_head; - netdev_dbg(bp->dev, "Allocated ring entry %u\n", entry); + entry = macb_tx_ring_wrap(bp->tx_head); + bp->tx_head++; + netdev_vdbg(bp->dev, "Allocated ring entry %u\n", entry); mapping = dma_map_single(&bp->pdev->dev, skb->data, len, DMA_TO_DEVICE); - bp->tx_skb[entry].skb = skb; - bp->tx_skb[entry].mapping = mapping; - netdev_dbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n", + + tx_skb = &bp->tx_skb[entry]; + tx_skb->skb = skb; + tx_skb->mapping = mapping; + netdev_vdbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n", skb->data, (unsigned long)mapping); ctrl = MACB_BF(TX_FRMLEN, len); @@ -665,18 +841,18 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) if (entry == (TX_RING_SIZE - 1)) ctrl |= MACB_BIT(TX_WRAP); - bp->tx_ring[entry].addr = mapping; - bp->tx_ring[entry].ctrl = ctrl; - wmb(); + desc = &bp->tx_ring[entry]; + desc->addr = mapping; + desc->ctrl = ctrl; - entry = NEXT_TX(entry); - bp->tx_head = entry; + /* Make newly initialized descriptor visible to hardware */ + wmb(); skb_tx_timestamp(skb); macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); - if (TX_BUFFS_AVAIL(bp) < 1) + if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1) netif_stop_queue(dev); spin_unlock_irqrestore(&bp->lock, flags); @@ -712,7 +888,7 @@ static int macb_alloc_consistent(struct macb *bp) { int size; - size = TX_RING_SIZE * sizeof(struct ring_info); + size = TX_RING_SIZE * sizeof(struct macb_tx_skb); bp->tx_skb = kmalloc(size, GFP_KERNEL); if (!bp->tx_skb) goto out_err; @@ -775,9 +951,6 @@ static void macb_init_rings(struct macb *bp) static void macb_reset_hw(struct macb *bp) { - /* Make sure we have the write buffer for ourselves */ - wmb(); - /* * Disable RX and TX (XXX: Should we halt the transmission * more gracefully?) @@ -788,11 +961,11 @@ static void macb_reset_hw(struct macb *bp) macb_writel(bp, NCR, MACB_BIT(CLRSTAT)); /* Clear all status flags */ - macb_writel(bp, TSR, ~0UL); - macb_writel(bp, RSR, ~0UL); + macb_writel(bp, TSR, -1); + macb_writel(bp, RSR, -1); /* Disable all interrupts */ - macb_writel(bp, IDR, ~0UL); + macb_writel(bp, IDR, -1); macb_readl(bp, ISR); } @@ -860,8 +1033,12 @@ static u32 macb_dbw(struct macb *bp) } /* - * Configure the receive DMA engine to use the correct receive buffer size. - * This is a configurable parameter for GEM. + * Configure the receive DMA engine + * - use the correct receive buffer size + * - set the possibility to use INCR16 bursts + * (if not supported by FIFO, it will fallback to default) + * - set both rx/tx packet buffers to full memory size + * These are configurable parameters for GEM. */ static void macb_configure_dma(struct macb *bp) { @@ -870,6 +1047,8 @@ static void macb_configure_dma(struct macb *bp) if (macb_is_gem(bp)) { dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L); dmacfg |= GEM_BF(RXBS, RX_BUFFER_SIZE / 64); + dmacfg |= GEM_BF(FBLDO, 16); + dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L); gem_writel(bp, DMACFG, dmacfg); } } @@ -879,9 +1058,10 @@ static void macb_init_hw(struct macb *bp) u32 config; macb_reset_hw(bp); - __macb_set_hwaddr(bp); + macb_set_hwaddr(bp); config = macb_mdc_clk_div(bp); + config |= MACB_BF(RBOF, NET_IP_ALIGN); /* Make eth data aligned */ config |= MACB_BIT(PAE); /* PAuse Enable */ config |= MACB_BIT(DRFCS); /* Discard Rx FCS */ config |= MACB_BIT(BIG); /* Receive oversized frames */ @@ -891,6 +1071,8 @@ static void macb_init_hw(struct macb *bp) config |= MACB_BIT(NBC); /* No BroadCast */ config |= macb_dbw(bp); macb_writel(bp, NCFGR, config); + bp->speed = SPEED_10; + bp->duplex = DUPLEX_HALF; macb_configure_dma(bp); @@ -902,13 +1084,8 @@ static void macb_init_hw(struct macb *bp) macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE)); /* Enable interrupts */ - macb_writel(bp, IER, (MACB_BIT(RCOMP) - | MACB_BIT(RXUBR) - | MACB_BIT(ISR_TUND) - | MACB_BIT(ISR_RLE) - | MACB_BIT(TXERR) - | MACB_BIT(TCOMP) - | MACB_BIT(ISR_ROVR) + macb_writel(bp, IER, (MACB_RX_INT_FLAGS + | MACB_TX_INT_FLAGS | MACB_BIT(HRESP))); } @@ -996,7 +1173,7 @@ static void macb_sethashtable(struct net_device *dev) /* * Enable/Disable promiscuous and multicast modes. */ -static void macb_set_rx_mode(struct net_device *dev) +void macb_set_rx_mode(struct net_device *dev) { unsigned long cfg; struct macb *bp = netdev_priv(dev); @@ -1028,6 +1205,7 @@ static void macb_set_rx_mode(struct net_device *dev) macb_writel(bp, NCFGR, cfg); } +EXPORT_SYMBOL_GPL(macb_set_rx_mode); static int macb_open(struct net_device *dev) { @@ -1043,9 +1221,6 @@ static int macb_open(struct net_device *dev) if (!bp->phy_dev) return -EAGAIN; - if (!is_valid_ether_addr(dev->dev_addr)) - return -EADDRNOTAVAIL; - err = macb_alloc_consistent(bp); if (err) { netdev_err(dev, "Unable to allocate DMA memory (error %d)\n", @@ -1135,7 +1310,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp) return nstat; } -static struct net_device_stats *macb_get_stats(struct net_device *dev) +struct net_device_stats *macb_get_stats(struct net_device *dev) { struct macb *bp = netdev_priv(dev); struct net_device_stats *nstat = &bp->stats; @@ -1181,6 +1356,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) return nstat; } +EXPORT_SYMBOL_GPL(macb_get_stats); static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { @@ -1204,25 +1380,55 @@ static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return phy_ethtool_sset(phydev, cmd); } -static void macb_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) +static int macb_get_regs_len(struct net_device *netdev) +{ + return MACB_GREGS_NBR * sizeof(u32); +} + +static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *p) { struct macb *bp = netdev_priv(dev); + unsigned int tail, head; + u32 *regs_buff = p; + + regs->version = (macb_readl(bp, MID) & ((1 << MACB_REV_SIZE) - 1)) + | MACB_GREGS_VERSION; + + tail = macb_tx_ring_wrap(bp->tx_tail); + head = macb_tx_ring_wrap(bp->tx_head); + + regs_buff[0] = macb_readl(bp, NCR); + regs_buff[1] = macb_or_gem_readl(bp, NCFGR); + regs_buff[2] = macb_readl(bp, NSR); + regs_buff[3] = macb_readl(bp, TSR); + regs_buff[4] = macb_readl(bp, RBQP); + regs_buff[5] = macb_readl(bp, TBQP); + regs_buff[6] = macb_readl(bp, RSR); + regs_buff[7] = macb_readl(bp, IMR); - strcpy(info->driver, bp->pdev->dev.driver->name); - strcpy(info->version, "$Revision: 1.14 $"); - strcpy(info->bus_info, dev_name(&bp->pdev->dev)); + regs_buff[8] = tail; + regs_buff[9] = head; + regs_buff[10] = macb_tx_dma(bp, tail); + regs_buff[11] = macb_tx_dma(bp, head); + + if (macb_is_gem(bp)) { + regs_buff[12] = gem_readl(bp, USRIO); + regs_buff[13] = gem_readl(bp, DMACFG); + } } -static const struct ethtool_ops macb_ethtool_ops = { +const struct ethtool_ops macb_ethtool_ops = { .get_settings = macb_get_settings, .set_settings = macb_set_settings, - .get_drvinfo = macb_get_drvinfo, + .get_regs_len = macb_get_regs_len, + .get_regs = macb_get_regs, .get_link = ethtool_op_get_link, .get_ts_info = ethtool_op_get_ts_info, }; +EXPORT_SYMBOL_GPL(macb_ethtool_ops); -static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct macb *bp = netdev_priv(dev); struct phy_device *phydev = bp->phy_dev; @@ -1235,6 +1441,7 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return phy_mii_ioctl(phydev, rq, cmd); } +EXPORT_SYMBOL_GPL(macb_ioctl); static const struct net_device_ops macb_netdev_ops = { .ndo_open = macb_open, @@ -1263,7 +1470,7 @@ static const struct of_device_id macb_dt_ids[] = { MODULE_DEVICE_TABLE(of, macb_dt_ids); -static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev) +static int macb_get_phy_mode_dt(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1273,7 +1480,7 @@ static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev) return -ENODEV; } -static int __devinit macb_get_hwaddr_dt(struct macb *bp) +static int macb_get_hwaddr_dt(struct macb *bp) { struct device_node *np = bp->pdev->dev.of_node; if (np) { @@ -1287,11 +1494,11 @@ static int __devinit macb_get_hwaddr_dt(struct macb *bp) return -ENODEV; } #else -static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev) +static int macb_get_phy_mode_dt(struct platform_device *pdev) { return -ENODEV; } -static int __devinit macb_get_hwaddr_dt(struct macb *bp) +static int macb_get_hwaddr_dt(struct macb *bp) { return -ENODEV; } @@ -1306,6 +1513,7 @@ static int __init macb_probe(struct platform_device *pdev) struct phy_device *phydev; u32 config; int err = -ENXIO; + struct pinctrl *pinctrl; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) { @@ -1313,6 +1521,15 @@ static int __init macb_probe(struct platform_device *pdev) goto err_out; } + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) { + err = PTR_ERR(pinctrl); + if (err == -EPROBE_DEFER) + goto err_out; + + dev_warn(&pdev->dev, "No pinctrl provided\n"); + } + err = -ENOMEM; dev = alloc_etherdev(sizeof(*bp)); if (!dev) @@ -1328,6 +1545,7 @@ static int __init macb_probe(struct platform_device *pdev) bp->dev = dev; spin_lock_init(&bp->lock); + INIT_WORK(&bp->tx_error_task, macb_tx_error_task); bp->pclk = clk_get(&pdev->dev, "pclk"); if (IS_ERR(bp->pclk)) { @@ -1384,7 +1602,9 @@ static int __init macb_probe(struct platform_device *pdev) bp->phy_interface = err; } - if (bp->phy_interface == PHY_INTERFACE_MODE_RMII) + if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII) + macb_or_gem_writel(bp, USRIO, GEM_BIT(RGMII)); + else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII) #if defined(CONFIG_ARCH_AT91) macb_or_gem_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN))); @@ -1398,8 +1618,6 @@ static int __init macb_probe(struct platform_device *pdev) macb_or_gem_writel(bp, USRIO, MACB_BIT(MII)); #endif - bp->tx_pending = DEF_TX_RING_PENDING; - err = register_netdev(dev); if (err) { dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 335e288f5314..570908b93578 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -10,10 +10,15 @@ #ifndef _MACB_H #define _MACB_H +#define MACB_GREGS_NBR 16 +#define MACB_GREGS_VERSION 1 + /* MACB register offsets */ #define MACB_NCR 0x0000 #define MACB_NCFGR 0x0004 #define MACB_NSR 0x0008 +#define MACB_TAR 0x000c /* AT91RM9200 only */ +#define MACB_TCR 0x0010 /* AT91RM9200 only */ #define MACB_TSR 0x0014 #define MACB_RBQP 0x0018 #define MACB_TBQP 0x001c @@ -69,6 +74,12 @@ #define GEM_HRT 0x0084 #define GEM_SA1B 0x0088 #define GEM_SA1T 0x008C +#define GEM_SA2B 0x0090 +#define GEM_SA2T 0x0094 +#define GEM_SA3B 0x0098 +#define GEM_SA3T 0x009C +#define GEM_SA4B 0x00A0 +#define GEM_SA4T 0x00A4 #define GEM_OTX 0x0100 #define GEM_DCFG1 0x0280 #define GEM_DCFG2 0x0284 @@ -133,6 +144,8 @@ #define MACB_RTY_SIZE 1 #define MACB_PAE_OFFSET 13 #define MACB_PAE_SIZE 1 +#define MACB_RM9200_RMII_OFFSET 13 /* AT91RM9200 only */ +#define MACB_RM9200_RMII_SIZE 1 /* AT91RM9200 only */ #define MACB_RBOF_OFFSET 14 #define MACB_RBOF_SIZE 2 #define MACB_RLCE_OFFSET 16 @@ -145,6 +158,8 @@ #define MACB_IRXFCS_SIZE 1 /* GEM specific NCFGR bitfields. */ +#define GEM_GBE_OFFSET 10 +#define GEM_GBE_SIZE 1 #define GEM_CLK_OFFSET 18 #define GEM_CLK_SIZE 3 #define GEM_DBW_OFFSET 21 @@ -156,8 +171,19 @@ #define GEM_DBW128 2 /* Bitfields in DMACFG. */ +#define GEM_FBLDO_OFFSET 0 +#define GEM_FBLDO_SIZE 5 +#define GEM_RXBMS_OFFSET 8 +#define GEM_RXBMS_SIZE 2 +#define GEM_TXPBMS_OFFSET 10 +#define GEM_TXPBMS_SIZE 1 +#define GEM_TXCOEN_OFFSET 11 +#define GEM_TXCOEN_SIZE 1 #define GEM_RXBS_OFFSET 16 #define GEM_RXBS_SIZE 8 +#define GEM_DDRP_OFFSET 24 +#define GEM_DDRP_SIZE 1 + /* Bitfields in NSR */ #define MACB_NSR_LINK_OFFSET 0 @@ -178,6 +204,8 @@ #define MACB_TGO_SIZE 1 #define MACB_BEX_OFFSET 4 #define MACB_BEX_SIZE 1 +#define MACB_RM9200_BNQ_OFFSET 4 /* AT91RM9200 only */ +#define MACB_RM9200_BNQ_SIZE 1 /* AT91RM9200 only */ #define MACB_COMP_OFFSET 5 #define MACB_COMP_SIZE 1 #define MACB_UND_OFFSET 6 @@ -246,6 +274,8 @@ /* Bitfields in USRIO (AT91) */ #define MACB_RMII_OFFSET 0 #define MACB_RMII_SIZE 1 +#define GEM_RGMII_OFFSET 0 /* GEM gigabit mode */ +#define GEM_RGMII_SIZE 1 #define MACB_CLKEN_OFFSET 1 #define MACB_CLKEN_SIZE 1 @@ -352,7 +382,12 @@ __v; \ }) -struct dma_desc { +/** + * struct macb_dma_desc - Hardware DMA descriptor + * @addr: DMA address of data buffer + * @ctrl: Control and status bits + */ +struct macb_dma_desc { u32 addr; u32 ctrl; }; @@ -417,7 +452,12 @@ struct dma_desc { #define MACB_TX_USED_OFFSET 31 #define MACB_TX_USED_SIZE 1 -struct ring_info { +/** + * struct macb_tx_skb - data about an skb which is being transmitted + * @skb: skb currently being transmitted + * @mapping: DMA address of the skb's data buffer + */ +struct macb_tx_skb { struct sk_buff *skb; dma_addr_t mapping; }; @@ -502,12 +542,12 @@ struct macb { void __iomem *regs; unsigned int rx_tail; - struct dma_desc *rx_ring; + struct macb_dma_desc *rx_ring; void *rx_buffers; unsigned int tx_head, tx_tail; - struct dma_desc *tx_ring; - struct ring_info *tx_skb; + struct macb_dma_desc *tx_ring; + struct macb_tx_skb *tx_skb; spinlock_t lock; struct platform_device *pdev; @@ -515,6 +555,7 @@ struct macb { struct clk *hclk; struct net_device *dev; struct napi_struct napi; + struct work_struct tx_error_task; struct net_device_stats stats; union { struct macb_stats macb; @@ -525,8 +566,6 @@ struct macb { dma_addr_t tx_ring_dma; dma_addr_t rx_buffers_dma; - unsigned int rx_pending, tx_pending; - struct mii_bus *mii_bus; struct phy_device *phy_dev; unsigned int link; @@ -534,8 +573,22 @@ struct macb { unsigned int duplex; phy_interface_t phy_interface; + + /* AT91RM9200 transmit */ + struct sk_buff *skb; /* holds skb until xmit interrupt completes */ + dma_addr_t skb_physaddr; /* phys addr from pci_map_single */ + int skb_length; /* saved skb length for pci_unmap_single */ }; +extern const struct ethtool_ops macb_ethtool_ops; + +int macb_mii_init(struct macb *bp); +int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +struct net_device_stats *macb_get_stats(struct net_device *dev); +void macb_set_rx_mode(struct net_device *dev); +void macb_set_hwaddr(struct macb *bp); +void macb_get_hwaddr(struct macb *bp); + static inline bool macb_is_gem(struct macb *bp) { return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2; diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index 16814b34d4b6..f7f02900f650 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -191,6 +191,7 @@ #define DMA_CONTROL_ST 0x00002000 /* Start/Stop Transmission */ #define DMA_CONTROL_SR 0x00000002 /* Start/Stop Receive */ #define DMA_CONTROL_DFF 0x01000000 /* Disable flush of rx frames */ +#define DMA_CONTROL_OSF 0x00000004 /* Operate on 2nd tx frame */ /* DMA Normal interrupt */ #define DMA_INTR_ENA_NIE 0x00010000 /* Normal Summary */ @@ -210,7 +211,7 @@ #define DMA_INTR_ENA_TIE 0x00000001 /* Transmit Interrupt */ #define DMA_INTR_NORMAL (DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \ - DMA_INTR_ENA_TUE) + DMA_INTR_ENA_TUE | DMA_INTR_ENA_TIE) #define DMA_INTR_ABNORMAL (DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \ DMA_INTR_ENA_RWE | DMA_INTR_ENA_RSE | \ @@ -373,6 +374,7 @@ struct xgmac_priv { struct sk_buff **tx_skbuff; unsigned int tx_head; unsigned int tx_tail; + int tx_irq_cnt; void __iomem *base; unsigned int dma_buf_sz; @@ -546,6 +548,10 @@ static int desc_get_rx_status(struct xgmac_priv *priv, struct xgmac_dma_desc *p) return -1; } + /* All frames should fit into a single buffer */ + if (!(status & RXDESC_FIRST_SEG) || !(status & RXDESC_LAST_SEG)) + return -1; + /* Check if packet has checksum already */ if ((status & RXDESC_FRAME_TYPE) && (status & RXDESC_EXT_STATUS) && !(ext_status & RXDESC_IP_PAYLOAD_MASK)) @@ -663,6 +669,7 @@ static void xgmac_rx_refill(struct xgmac_priv *priv) { struct xgmac_dma_desc *p; dma_addr_t paddr; + int bufsz = priv->dev->mtu + ETH_HLEN + ETH_FCS_LEN; while (dma_ring_space(priv->rx_head, priv->rx_tail, DMA_RX_RING_SZ) > 1) { int entry = priv->rx_head; @@ -671,13 +678,13 @@ static void xgmac_rx_refill(struct xgmac_priv *priv) p = priv->dma_rx + entry; if (priv->rx_skbuff[entry] == NULL) { - skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz); + skb = netdev_alloc_skb_ip_align(priv->dev, bufsz); if (unlikely(skb == NULL)) break; priv->rx_skbuff[entry] = skb; paddr = dma_map_single(priv->device, skb->data, - priv->dma_buf_sz, DMA_FROM_DEVICE); + bufsz, DMA_FROM_DEVICE); desc_set_buf_addr(p, paddr, priv->dma_buf_sz); } @@ -701,10 +708,10 @@ static int xgmac_dma_desc_rings_init(struct net_device *dev) unsigned int bfsize; /* Set the Buffer size according to the MTU; - * indeed, in case of jumbo we need to bump-up the buffer sizes. + * The total buffer size including any IP offset must be a multiple + * of 8 bytes. */ - bfsize = ALIGN(dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN + 64, - 64); + bfsize = ALIGN(dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN, 8); netdev_dbg(priv->dev, "mtu [%d] bfsize [%d]\n", dev->mtu, bfsize); @@ -845,9 +852,6 @@ static void xgmac_free_dma_desc_rings(struct xgmac_priv *priv) static void xgmac_tx_complete(struct xgmac_priv *priv) { int i; - void __iomem *ioaddr = priv->base; - - writel(DMA_STATUS_TU | DMA_STATUS_NIS, ioaddr + XGMAC_DMA_STATUS); while (dma_ring_cnt(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ)) { unsigned int entry = priv->tx_tail; @@ -888,7 +892,7 @@ static void xgmac_tx_complete(struct xgmac_priv *priv) } if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) > - TX_THRESH) + MAX_SKB_FRAGS) netif_wake_queue(priv->dev); } @@ -965,8 +969,7 @@ static int xgmac_hw_init(struct net_device *dev) ctrl |= XGMAC_CONTROL_IPC; writel(ctrl, ioaddr + XGMAC_CONTROL); - value = DMA_CONTROL_DFF; - writel(value, ioaddr + XGMAC_DMA_CONTROL); + writel(DMA_CONTROL_OSF, ioaddr + XGMAC_DMA_CONTROL); /* Set the HW DMA mode and the COE */ writel(XGMAC_OMR_TSF | XGMAC_OMR_RFD | XGMAC_OMR_RFA | @@ -1060,19 +1063,15 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev) struct xgmac_priv *priv = netdev_priv(dev); unsigned int entry; int i; + u32 irq_flag; int nfrags = skb_shinfo(skb)->nr_frags; struct xgmac_dma_desc *desc, *first; unsigned int desc_flags; unsigned int len; dma_addr_t paddr; - if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) < - (nfrags + 1)) { - writel(DMA_INTR_DEFAULT_MASK | DMA_INTR_ENA_TIE, - priv->base + XGMAC_DMA_INTR_ENA); - netif_stop_queue(dev); - return NETDEV_TX_BUSY; - } + priv->tx_irq_cnt = (priv->tx_irq_cnt + 1) & (DMA_TX_RING_SZ/4 - 1); + irq_flag = priv->tx_irq_cnt ? 0 : TXDESC_INTERRUPT; desc_flags = (skb->ip_summed == CHECKSUM_PARTIAL) ? TXDESC_CSUM_ALL : 0; @@ -1113,9 +1112,9 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev) /* Interrupt on completition only for the latest segment */ if (desc != first) desc_set_tx_owner(desc, desc_flags | - TXDESC_LAST_SEG | TXDESC_INTERRUPT); + TXDESC_LAST_SEG | irq_flag); else - desc_flags |= TXDESC_LAST_SEG | TXDESC_INTERRUPT; + desc_flags |= TXDESC_LAST_SEG | irq_flag; /* Set owner on first desc last to avoid race condition */ wmb(); @@ -1124,6 +1123,9 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev) priv->tx_head = dma_ring_incr(entry, DMA_TX_RING_SZ); writel(1, priv->base + XGMAC_DMA_TX_POLL); + if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) < + MAX_SKB_FRAGS) + netif_stop_queue(dev); return NETDEV_TX_OK; } @@ -1139,9 +1141,6 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit) struct sk_buff *skb; int frame_len; - writel(DMA_STATUS_RI | DMA_STATUS_NIS, - priv->base + XGMAC_DMA_STATUS); - entry = priv->rx_tail; p = priv->dma_rx + entry; if (desc_get_owner(p)) @@ -1180,8 +1179,6 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit) xgmac_rx_refill(priv); - writel(1, priv->base + XGMAC_DMA_RX_POLL); - return count; } @@ -1205,7 +1202,7 @@ static int xgmac_poll(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete(napi); - writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA); + __raw_writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA); } return work_done; } @@ -1350,7 +1347,7 @@ static irqreturn_t xgmac_pmt_interrupt(int irq, void *dev_id) struct xgmac_priv *priv = netdev_priv(dev); void __iomem *ioaddr = priv->base; - intr_status = readl(ioaddr + XGMAC_INT_STAT); + intr_status = __raw_readl(ioaddr + XGMAC_INT_STAT); if (intr_status & XGMAC_INT_STAT_PMT) { netdev_dbg(priv->dev, "received Magic frame\n"); /* clear the PMT bits 5 and 6 by reading the PMT */ @@ -1368,9 +1365,9 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id) struct xgmac_extra_stats *x = &priv->xstats; /* read the status register (CSR5) */ - intr_status = readl(priv->base + XGMAC_DMA_STATUS); - intr_status &= readl(priv->base + XGMAC_DMA_INTR_ENA); - writel(intr_status, priv->base + XGMAC_DMA_STATUS); + intr_status = __raw_readl(priv->base + XGMAC_DMA_STATUS); + intr_status &= __raw_readl(priv->base + XGMAC_DMA_INTR_ENA); + __raw_writel(intr_status, priv->base + XGMAC_DMA_STATUS); /* It displays the DMA process states (CSR5 register) */ /* ABNORMAL interrupts */ @@ -1405,8 +1402,8 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id) } /* TX/RX NORMAL interrupts */ - if (intr_status & (DMA_STATUS_RI | DMA_STATUS_TU)) { - writel(DMA_INTR_ABNORMAL, priv->base + XGMAC_DMA_INTR_ENA); + if (intr_status & (DMA_STATUS_RI | DMA_STATUS_TU | DMA_STATUS_TI)) { + __raw_writel(DMA_INTR_ABNORMAL, priv->base + XGMAC_DMA_INTR_ENA); napi_schedule(&priv->napi); } diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig index 2de50f95798f..d40c994a4f6a 100644 --- a/drivers/net/ethernet/chelsio/Kconfig +++ b/drivers/net/ethernet/chelsio/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_CHELSIO bool "Chelsio devices" default y - depends on PCI || INET + depends on PCI ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c index 1d17c92f2dda..c8fdeaae56c0 100644 --- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c +++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c @@ -974,8 +974,7 @@ static const struct net_device_ops cxgb_netdev_ops = { #endif }; -static int __devinit init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int version_printed; @@ -1332,7 +1331,7 @@ static inline void t1_sw_reset(struct pci_dev *pdev) pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 0); } -static void __devexit remove_one(struct pci_dev *pdev) +static void remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct adapter *adapter = dev->ml_priv; @@ -1361,7 +1360,7 @@ static struct pci_driver driver = { .name = DRV_NAME, .id_table = t1_pci_tbl, .probe = init_one, - .remove = __devexit_p(remove_one), + .remove = remove_one, }; static int __init t1_init_module(void) diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c index 47a84359d4e4..d84872e88171 100644 --- a/drivers/net/ethernet/chelsio/cxgb/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb/sge.c @@ -367,18 +367,6 @@ void t1_sched_set_drain_bits_per_us(struct sge *sge, unsigned int port, #endif /* 0 */ - -/* - * get_clock() implements a ns clock (see ktime_get) - */ -static inline ktime_t get_clock(void) -{ - struct timespec ts; - - ktime_get_ts(&ts); - return timespec_to_ktime(ts); -} - /* * tx_sched_init() allocates resources and does basic initialization. */ @@ -411,7 +399,7 @@ static int tx_sched_init(struct sge *sge) static inline int sched_update_avail(struct sge *sge) { struct sched *s = sge->tx_sched; - ktime_t now = get_clock(); + ktime_t now = ktime_get(); unsigned int i; long long delta_time_ns; @@ -2071,8 +2059,7 @@ static void espibug_workaround(unsigned long data) /* * Creates a t1_sge structure and returns suggested resource parameters. */ -struct sge * __devinit t1_sge_create(struct adapter *adapter, - struct sge_params *p) +struct sge *t1_sge_create(struct adapter *adapter, struct sge_params *p) { struct sge *sge = kzalloc(sizeof(*sge), GFP_KERNEL); int i; diff --git a/drivers/net/ethernet/chelsio/cxgb/subr.c b/drivers/net/ethernet/chelsio/cxgb/subr.c index 8a43c7e19701..e0a03a31e7c4 100644 --- a/drivers/net/ethernet/chelsio/cxgb/subr.c +++ b/drivers/net/ethernet/chelsio/cxgb/subr.c @@ -892,8 +892,8 @@ static void power_sequence_xpak(adapter_t* adapter) } } -int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi, - struct adapter_params *p) +int t1_get_board_rev(adapter_t *adapter, const struct board_info *bi, + struct adapter_params *p) { p->chip_version = bi->chip_term; p->is_asic = (p->chip_version != CHBT_TERM_FPGA); @@ -992,7 +992,7 @@ out_err: /* * Determine a card's PCI mode. */ -static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p) +static void get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p) { static const unsigned short speed_map[] = { 33, 66, 100, 133 }; u32 pci_mode; @@ -1028,8 +1028,8 @@ void t1_free_sw_modules(adapter_t *adapter) t1_espi_destroy(adapter->espi); } -static void __devinit init_link_config(struct link_config *lc, - const struct board_info *bi) +static void init_link_config(struct link_config *lc, + const struct board_info *bi) { lc->supported = bi->caps; lc->requested_speed = lc->speed = SPEED_INVALID; @@ -1049,8 +1049,7 @@ static void __devinit init_link_config(struct link_config *lc, * Allocate and initialize the data structures that hold the SW state of * the Terminator HW modules. */ -int __devinit t1_init_sw_modules(adapter_t *adapter, - const struct board_info *bi) +int t1_init_sw_modules(adapter_t *adapter, const struct board_info *bi) { unsigned int i; diff --git a/drivers/net/ethernet/chelsio/cxgb/tp.c b/drivers/net/ethernet/chelsio/cxgb/tp.c index 8bed4a59e65f..b146acabf982 100644 --- a/drivers/net/ethernet/chelsio/cxgb/tp.c +++ b/drivers/net/ethernet/chelsio/cxgb/tp.c @@ -55,7 +55,7 @@ void t1_tp_destroy(struct petp *tp) kfree(tp); } -struct petp *__devinit t1_tp_create(adapter_t * adapter, struct tp_params *p) +struct petp *t1_tp_create(adapter_t *adapter, struct tp_params *p) { struct petp *tp = kzalloc(sizeof(*tp), GFP_KERNEL); diff --git a/drivers/net/ethernet/chelsio/cxgb3/common.h b/drivers/net/ethernet/chelsio/cxgb3/common.h index df01b6343241..8c82248ce416 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/common.h +++ b/drivers/net/ethernet/chelsio/cxgb3/common.h @@ -42,10 +42,9 @@ #include <linux/mdio.h> #include "version.h" -#define CH_ERR(adap, fmt, ...) dev_err(&adap->pdev->dev, fmt, ## __VA_ARGS__) -#define CH_WARN(adap, fmt, ...) dev_warn(&adap->pdev->dev, fmt, ## __VA_ARGS__) -#define CH_ALERT(adap, fmt, ...) \ - dev_printk(KERN_ALERT, &adap->pdev->dev, fmt, ## __VA_ARGS__) +#define CH_ERR(adap, fmt, ...) dev_err(&adap->pdev->dev, fmt, ##__VA_ARGS__) +#define CH_WARN(adap, fmt, ...) dev_warn(&adap->pdev->dev, fmt, ##__VA_ARGS__) +#define CH_ALERT(adap, fmt, ...) dev_alert(&adap->pdev->dev, fmt, ##__VA_ARGS__) /* * More powerful macro that selectively prints messages based on msg_enable. diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index 9c9f3260344a..f15ee326d5c1 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -3078,7 +3078,7 @@ static void set_nqsets(struct adapter *adap) } } -static int __devinit cxgb_enable_msix(struct adapter *adap) +static int cxgb_enable_msix(struct adapter *adap) { struct msix_entry entries[SGE_QSETS + 1]; int vectors; @@ -3108,8 +3108,7 @@ static int __devinit cxgb_enable_msix(struct adapter *adap) return err; } -static void __devinit print_port_info(struct adapter *adap, - const struct adapter_info *ai) +static void print_port_info(struct adapter *adap, const struct adapter_info *ai) { static const char *pci_variant[] = { "PCI", "PCI-X", "PCI-X ECC", "PCI-X 266", "PCI Express" @@ -3165,7 +3164,7 @@ static const struct net_device_ops cxgb_netdev_ops = { #endif }; -static void __devinit cxgb3_init_iscsi_mac(struct net_device *dev) +static void cxgb3_init_iscsi_mac(struct net_device *dev) { struct port_info *pi = netdev_priv(dev); @@ -3176,8 +3175,7 @@ static void __devinit cxgb3_init_iscsi_mac(struct net_device *dev) #define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN) #define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \ NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA) -static int __devinit init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int version_printed; @@ -3381,7 +3379,7 @@ out: return err; } -static void __devexit remove_one(struct pci_dev *pdev) +static void remove_one(struct pci_dev *pdev) { struct adapter *adapter = pci_get_drvdata(pdev); @@ -3425,7 +3423,7 @@ static struct pci_driver driver = { .name = DRV_NAME, .id_table = cxgb3_pci_tbl, .probe = init_one, - .remove = __devexit_p(remove_one), + .remove = remove_one, .err_handler = &t3_err_handler, }; diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c index 2dbbcbb450d3..942dace361d2 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c @@ -1382,7 +1382,7 @@ static inline int adap2type(struct adapter *adapter) return type; } -void __devinit cxgb3_adapter_ofld(struct adapter *adapter) +void cxgb3_adapter_ofld(struct adapter *adapter) { struct t3cdev *tdev = &adapter->tdev; @@ -1396,7 +1396,7 @@ void __devinit cxgb3_adapter_ofld(struct adapter *adapter) register_tdev(tdev); } -void __devexit cxgb3_adapter_unofld(struct adapter *adapter) +void cxgb3_adapter_unofld(struct adapter *adapter) { struct t3cdev *tdev = &adapter->tdev; diff --git a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c index aef45d3113ba..3dee68612c9e 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c @@ -3307,7 +3307,7 @@ static void config_pcie(struct adapter *adap) G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE)); log2_width = fls(adap->params.pci.width) - 1; acklat = ack_lat[log2_width][pldsize]; - if (val & 1) /* check LOsEnable */ + if (val & PCI_EXP_LNKCTL_ASPM_L0S) /* check LOsEnable */ acklat += fst_trn_tx * 4; rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 378988b5709a..6db997c78a5f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -35,6 +35,8 @@ #ifndef __CXGB4_H__ #define __CXGB4_H__ +#include "t4_hw.h" + #include <linux/bitops.h> #include <linux/cache.h> #include <linux/interrupt.h> @@ -212,6 +214,8 @@ struct tp_err_stats { struct tp_params { unsigned int ntxchan; /* # of Tx channels */ unsigned int tre; /* log2 of core clocks per TP tick */ + unsigned short tx_modq_map; /* TX modulation scheduler queue to */ + /* channel map */ uint32_t dack_re; /* DACK timer resolution */ unsigned short tx_modq[NCHAN]; /* channel to modulation queue map */ @@ -526,6 +530,7 @@ struct adapter { struct net_device *port[MAX_NPORTS]; u8 chan_map[NCHAN]; /* channel -> port map */ + u32 filter_mode; unsigned int l2t_start; unsigned int l2t_end; struct l2t_data *l2t; @@ -545,6 +550,129 @@ struct adapter { spinlock_t stats_lock; }; +/* Defined bit width of user definable filter tuples + */ +#define ETHTYPE_BITWIDTH 16 +#define FRAG_BITWIDTH 1 +#define MACIDX_BITWIDTH 9 +#define FCOE_BITWIDTH 1 +#define IPORT_BITWIDTH 3 +#define MATCHTYPE_BITWIDTH 3 +#define PROTO_BITWIDTH 8 +#define TOS_BITWIDTH 8 +#define PF_BITWIDTH 8 +#define VF_BITWIDTH 8 +#define IVLAN_BITWIDTH 16 +#define OVLAN_BITWIDTH 16 + +/* Filter matching rules. These consist of a set of ingress packet field + * (value, mask) tuples. The associated ingress packet field matches the + * tuple when ((field & mask) == value). (Thus a wildcard "don't care" field + * rule can be constructed by specifying a tuple of (0, 0).) A filter rule + * matches an ingress packet when all of the individual individual field + * matching rules are true. + * + * Partial field masks are always valid, however, while it may be easy to + * understand their meanings for some fields (e.g. IP address to match a + * subnet), for others making sensible partial masks is less intuitive (e.g. + * MPS match type) ... + * + * Most of the following data structures are modeled on T4 capabilities. + * Drivers for earlier chips use the subsets which make sense for those chips. + * We really need to come up with a hardware-independent mechanism to + * represent hardware filter capabilities ... + */ +struct ch_filter_tuple { + /* Compressed header matching field rules. The TP_VLAN_PRI_MAP + * register selects which of these fields will participate in the + * filter match rules -- up to a maximum of 36 bits. Because + * TP_VLAN_PRI_MAP is a global register, all filters must use the same + * set of fields. + */ + uint32_t ethtype:ETHTYPE_BITWIDTH; /* Ethernet type */ + uint32_t frag:FRAG_BITWIDTH; /* IP fragmentation header */ + uint32_t ivlan_vld:1; /* inner VLAN valid */ + uint32_t ovlan_vld:1; /* outer VLAN valid */ + uint32_t pfvf_vld:1; /* PF/VF valid */ + uint32_t macidx:MACIDX_BITWIDTH; /* exact match MAC index */ + uint32_t fcoe:FCOE_BITWIDTH; /* FCoE packet */ + uint32_t iport:IPORT_BITWIDTH; /* ingress port */ + uint32_t matchtype:MATCHTYPE_BITWIDTH; /* MPS match type */ + uint32_t proto:PROTO_BITWIDTH; /* protocol type */ + uint32_t tos:TOS_BITWIDTH; /* TOS/Traffic Type */ + uint32_t pf:PF_BITWIDTH; /* PCI-E PF ID */ + uint32_t vf:VF_BITWIDTH; /* PCI-E VF ID */ + uint32_t ivlan:IVLAN_BITWIDTH; /* inner VLAN */ + uint32_t ovlan:OVLAN_BITWIDTH; /* outer VLAN */ + + /* Uncompressed header matching field rules. These are always + * available for field rules. + */ + uint8_t lip[16]; /* local IP address (IPv4 in [3:0]) */ + uint8_t fip[16]; /* foreign IP address (IPv4 in [3:0]) */ + uint16_t lport; /* local port */ + uint16_t fport; /* foreign port */ +}; + +/* A filter ioctl command. + */ +struct ch_filter_specification { + /* Administrative fields for filter. + */ + uint32_t hitcnts:1; /* count filter hits in TCB */ + uint32_t prio:1; /* filter has priority over active/server */ + + /* Fundamental filter typing. This is the one element of filter + * matching that doesn't exist as a (value, mask) tuple. + */ + uint32_t type:1; /* 0 => IPv4, 1 => IPv6 */ + + /* Packet dispatch information. Ingress packets which match the + * filter rules will be dropped, passed to the host or switched back + * out as egress packets. + */ + uint32_t action:2; /* drop, pass, switch */ + + uint32_t rpttid:1; /* report TID in RSS hash field */ + + uint32_t dirsteer:1; /* 0 => RSS, 1 => steer to iq */ + uint32_t iq:10; /* ingress queue */ + + uint32_t maskhash:1; /* dirsteer=0: store RSS hash in TCB */ + uint32_t dirsteerhash:1;/* dirsteer=1: 0 => TCB contains RSS hash */ + /* 1 => TCB contains IQ ID */ + + /* Switch proxy/rewrite fields. An ingress packet which matches a + * filter with "switch" set will be looped back out as an egress + * packet -- potentially with some Ethernet header rewriting. + */ + uint32_t eport:2; /* egress port to switch packet out */ + uint32_t newdmac:1; /* rewrite destination MAC address */ + uint32_t newsmac:1; /* rewrite source MAC address */ + uint32_t newvlan:2; /* rewrite VLAN Tag */ + uint8_t dmac[ETH_ALEN]; /* new destination MAC address */ + uint8_t smac[ETH_ALEN]; /* new source MAC address */ + uint16_t vlan; /* VLAN Tag to insert */ + + /* Filter rule value/mask pairs. + */ + struct ch_filter_tuple val; + struct ch_filter_tuple mask; +}; + +enum { + FILTER_PASS = 0, /* default */ + FILTER_DROP, + FILTER_SWITCH +}; + +enum { + VLAN_NOCHANGE = 0, /* default */ + VLAN_REMOVE, + VLAN_INSERT, + VLAN_REWRITE +}; + static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) { return readl(adap->regs + reg_addr); @@ -701,6 +829,12 @@ static inline int t4_wr_mbox_ns(struct adapter *adap, int mbox, const void *cmd, void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, unsigned int data_reg, const u32 *vals, unsigned int nregs, unsigned int start_idx); +void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, + unsigned int data_reg, u32 *vals, unsigned int nregs, + unsigned int start_idx); + +struct fw_filter_wr; + void t4_intr_enable(struct adapter *adapter); void t4_intr_disable(struct adapter *adapter); int t4_slow_intr_handler(struct adapter *adapter); @@ -737,6 +871,8 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4, void t4_load_mtus(struct adapter *adap, const unsigned short *mtus, const unsigned short *alpha, const unsigned short *beta); +void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid); + void t4_wol_magic_enable(struct adapter *adap, unsigned int port, const u8 *addr); int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index c1cde11b0c6d..c306df7d4568 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -175,6 +175,30 @@ enum { MIN_FL_ENTRIES = 16 }; +/* Host shadow copy of ingress filter entry. This is in host native format + * and doesn't match the ordering or bit order, etc. of the hardware of the + * firmware command. The use of bit-field structure elements is purely to + * remind ourselves of the field size limitations and save memory in the case + * where the filter table is large. + */ +struct filter_entry { + /* Administrative fields for filter. + */ + u32 valid:1; /* filter allocated and valid */ + u32 locked:1; /* filter is administratively locked */ + + u32 pending:1; /* filter action is pending firmware reply */ + u32 smtidx:8; /* Source MAC Table index for smac */ + struct l2t_entry *l2t; /* Layer Two Table entry for dmac */ + + /* The filter itself. Most of this is a straight copy of information + * provided by the extended ioctl(). Some fields are translated to + * internal forms -- for instance the Ingress Queue ID passed in from + * the ioctl() is translated into the Absolute Ingress Queue ID. + */ + struct ch_filter_specification fs; +}; + #define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \ NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\ NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) @@ -325,6 +349,9 @@ enum { static unsigned int tp_vlan_pri_map = TP_VLAN_PRI_MAP_DEFAULT; +module_param(tp_vlan_pri_map, uint, 0644); +MODULE_PARM_DESC(tp_vlan_pri_map, "global compressed filter configuration"); + static struct dentry *cxgb4_debugfs_root; static LIST_HEAD(adapter_list); @@ -506,8 +533,67 @@ static int link_start(struct net_device *dev) return ret; } -/* - * Response queue handler for the FW event queue. +/* Clear a filter and release any of its resources that we own. This also + * clears the filter's "pending" status. + */ +static void clear_filter(struct adapter *adap, struct filter_entry *f) +{ + /* If the new or old filter have loopback rewriteing rules then we'll + * need to free any existing Layer Two Table (L2T) entries of the old + * filter rule. The firmware will handle freeing up any Source MAC + * Table (SMT) entries used for rewriting Source MAC Addresses in + * loopback rules. + */ + if (f->l2t) + cxgb4_l2t_release(f->l2t); + + /* The zeroing of the filter rule below clears the filter valid, + * pending, locked flags, l2t pointer, etc. so it's all we need for + * this operation. + */ + memset(f, 0, sizeof(*f)); +} + +/* Handle a filter write/deletion reply. + */ +static void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl) +{ + unsigned int idx = GET_TID(rpl); + unsigned int nidx = idx - adap->tids.ftid_base; + unsigned int ret; + struct filter_entry *f; + + if (idx >= adap->tids.ftid_base && nidx < + (adap->tids.nftids + adap->tids.nsftids)) { + idx = nidx; + ret = GET_TCB_COOKIE(rpl->cookie); + f = &adap->tids.ftid_tab[idx]; + + if (ret == FW_FILTER_WR_FLT_DELETED) { + /* Clear the filter when we get confirmation from the + * hardware that the filter has been deleted. + */ + clear_filter(adap, f); + } else if (ret == FW_FILTER_WR_SMT_TBL_FULL) { + dev_err(adap->pdev_dev, "filter %u setup failed due to full SMT\n", + idx); + clear_filter(adap, f); + } else if (ret == FW_FILTER_WR_FLT_ADDED) { + f->smtidx = (be64_to_cpu(rpl->oldval) >> 24) & 0xff; + f->pending = 0; /* asynchronous setup completed */ + f->valid = 1; + } else { + /* Something went wrong. Issue a warning about the + * problem and clear everything out. + */ + dev_err(adap->pdev_dev, "filter %u setup failed with error %u\n", + idx, ret); + clear_filter(adap, f); + } + } +} + +/* Response queue handler for the FW event queue. */ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, const struct pkt_gl *gl) @@ -542,6 +628,10 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, const struct cpl_l2t_write_rpl *p = (void *)rsp; do_l2t_write_rpl(q->adap, p); + } else if (opcode == CPL_SET_TCB_RPL) { + const struct cpl_set_tcb_rpl *p = (void *)rsp; + + filter_rpl(q->adap, p); } else dev_err(q->adap->pdev_dev, "unexpected CPL %#x on FW event queue\n", opcode); @@ -983,6 +1073,148 @@ static void t4_free_mem(void *addr) kfree(addr); } +/* Send a Work Request to write the filter at a specified index. We construct + * a Firmware Filter Work Request to have the work done and put the indicated + * filter into "pending" mode which will prevent any further actions against + * it till we get a reply from the firmware on the completion status of the + * request. + */ +static int set_filter_wr(struct adapter *adapter, int fidx) +{ + struct filter_entry *f = &adapter->tids.ftid_tab[fidx]; + struct sk_buff *skb; + struct fw_filter_wr *fwr; + unsigned int ftid; + + /* If the new filter requires loopback Destination MAC and/or VLAN + * rewriting then we need to allocate a Layer 2 Table (L2T) entry for + * the filter. + */ + if (f->fs.newdmac || f->fs.newvlan) { + /* allocate L2T entry for new filter */ + f->l2t = t4_l2t_alloc_switching(adapter->l2t); + if (f->l2t == NULL) + return -EAGAIN; + if (t4_l2t_set_switching(adapter, f->l2t, f->fs.vlan, + f->fs.eport, f->fs.dmac)) { + cxgb4_l2t_release(f->l2t); + f->l2t = NULL; + return -ENOMEM; + } + } + + ftid = adapter->tids.ftid_base + fidx; + + skb = alloc_skb(sizeof(*fwr), GFP_KERNEL | __GFP_NOFAIL); + fwr = (struct fw_filter_wr *)__skb_put(skb, sizeof(*fwr)); + memset(fwr, 0, sizeof(*fwr)); + + /* It would be nice to put most of the following in t4_hw.c but most + * of the work is translating the cxgbtool ch_filter_specification + * into the Work Request and the definition of that structure is + * currently in cxgbtool.h which isn't appropriate to pull into the + * common code. We may eventually try to come up with a more neutral + * filter specification structure but for now it's easiest to simply + * put this fairly direct code in line ... + */ + fwr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR)); + fwr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*fwr)/16)); + fwr->tid_to_iq = + htonl(V_FW_FILTER_WR_TID(ftid) | + V_FW_FILTER_WR_RQTYPE(f->fs.type) | + V_FW_FILTER_WR_NOREPLY(0) | + V_FW_FILTER_WR_IQ(f->fs.iq)); + fwr->del_filter_to_l2tix = + htonl(V_FW_FILTER_WR_RPTTID(f->fs.rpttid) | + V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) | + V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) | + V_FW_FILTER_WR_MASKHASH(f->fs.maskhash) | + V_FW_FILTER_WR_DIRSTEERHASH(f->fs.dirsteerhash) | + V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) | + V_FW_FILTER_WR_DMAC(f->fs.newdmac) | + V_FW_FILTER_WR_SMAC(f->fs.newsmac) | + V_FW_FILTER_WR_INSVLAN(f->fs.newvlan == VLAN_INSERT || + f->fs.newvlan == VLAN_REWRITE) | + V_FW_FILTER_WR_RMVLAN(f->fs.newvlan == VLAN_REMOVE || + f->fs.newvlan == VLAN_REWRITE) | + V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) | + V_FW_FILTER_WR_TXCHAN(f->fs.eport) | + V_FW_FILTER_WR_PRIO(f->fs.prio) | + V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0)); + fwr->ethtype = htons(f->fs.val.ethtype); + fwr->ethtypem = htons(f->fs.mask.ethtype); + fwr->frag_to_ovlan_vldm = + (V_FW_FILTER_WR_FRAG(f->fs.val.frag) | + V_FW_FILTER_WR_FRAGM(f->fs.mask.frag) | + V_FW_FILTER_WR_IVLAN_VLD(f->fs.val.ivlan_vld) | + V_FW_FILTER_WR_OVLAN_VLD(f->fs.val.ovlan_vld) | + V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld) | + V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld)); + fwr->smac_sel = 0; + fwr->rx_chan_rx_rpl_iq = + htons(V_FW_FILTER_WR_RX_CHAN(0) | + V_FW_FILTER_WR_RX_RPL_IQ(adapter->sge.fw_evtq.abs_id)); + fwr->maci_to_matchtypem = + htonl(V_FW_FILTER_WR_MACI(f->fs.val.macidx) | + V_FW_FILTER_WR_MACIM(f->fs.mask.macidx) | + V_FW_FILTER_WR_FCOE(f->fs.val.fcoe) | + V_FW_FILTER_WR_FCOEM(f->fs.mask.fcoe) | + V_FW_FILTER_WR_PORT(f->fs.val.iport) | + V_FW_FILTER_WR_PORTM(f->fs.mask.iport) | + V_FW_FILTER_WR_MATCHTYPE(f->fs.val.matchtype) | + V_FW_FILTER_WR_MATCHTYPEM(f->fs.mask.matchtype)); + fwr->ptcl = f->fs.val.proto; + fwr->ptclm = f->fs.mask.proto; + fwr->ttyp = f->fs.val.tos; + fwr->ttypm = f->fs.mask.tos; + fwr->ivlan = htons(f->fs.val.ivlan); + fwr->ivlanm = htons(f->fs.mask.ivlan); + fwr->ovlan = htons(f->fs.val.ovlan); + fwr->ovlanm = htons(f->fs.mask.ovlan); + memcpy(fwr->lip, f->fs.val.lip, sizeof(fwr->lip)); + memcpy(fwr->lipm, f->fs.mask.lip, sizeof(fwr->lipm)); + memcpy(fwr->fip, f->fs.val.fip, sizeof(fwr->fip)); + memcpy(fwr->fipm, f->fs.mask.fip, sizeof(fwr->fipm)); + fwr->lp = htons(f->fs.val.lport); + fwr->lpm = htons(f->fs.mask.lport); + fwr->fp = htons(f->fs.val.fport); + fwr->fpm = htons(f->fs.mask.fport); + if (f->fs.newsmac) + memcpy(fwr->sma, f->fs.smac, sizeof(fwr->sma)); + + /* Mark the filter as "pending" and ship off the Filter Work Request. + * When we get the Work Request Reply we'll clear the pending status. + */ + f->pending = 1; + set_wr_txq(skb, CPL_PRIORITY_CONTROL, f->fs.val.iport & 0x3); + t4_ofld_send(adapter, skb); + return 0; +} + +/* Delete the filter at a specified index. + */ +static int del_filter_wr(struct adapter *adapter, int fidx) +{ + struct filter_entry *f = &adapter->tids.ftid_tab[fidx]; + struct sk_buff *skb; + struct fw_filter_wr *fwr; + unsigned int len, ftid; + + len = sizeof(*fwr); + ftid = adapter->tids.ftid_base + fidx; + + skb = alloc_skb(len, GFP_KERNEL | __GFP_NOFAIL); + fwr = (struct fw_filter_wr *)__skb_put(skb, len); + t4_mk_filtdelwr(ftid, fwr, adapter->sge.fw_evtq.abs_id); + + /* Mark the filter as "pending" and ship off the Filter Work Request. + * When we get the Work Request Reply we'll clear the pending status. + */ + f->pending = 1; + t4_mgmt_tx(adapter, skb); + return 0; +} + static inline int is_offload(const struct adapter *adap) { return adap->params.offload; @@ -1762,9 +1994,20 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) { const struct port_info *pi = netdev_priv(dev); struct adapter *adap = pi->adapter; - - return set_rxq_intr_params(adap, &adap->sge.ethrxq[pi->first_qset].rspq, - c->rx_coalesce_usecs, c->rx_max_coalesced_frames); + struct sge_rspq *q; + int i; + int r = 0; + + for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) { + q = &adap->sge.ethrxq[i].rspq; + r = set_rxq_intr_params(adap, q, c->rx_coalesce_usecs, + c->rx_max_coalesced_frames); + if (r) { + dev_err(&dev->dev, "failed to set coalesce %d\n", r); + break; + } + } + return r; } static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) @@ -2148,8 +2391,8 @@ static const struct file_operations mem_debugfs_fops = { .llseek = default_llseek, }; -static void __devinit add_debugfs_mem(struct adapter *adap, const char *name, - unsigned int idx, unsigned int size_mb) +static void add_debugfs_mem(struct adapter *adap, const char *name, + unsigned int idx, unsigned int size_mb) { struct dentry *de; @@ -2159,7 +2402,7 @@ static void __devinit add_debugfs_mem(struct adapter *adap, const char *name, de->d_inode->i_size = size_mb << 20; } -static int __devinit setup_debugfs(struct adapter *adap) +static int setup_debugfs(struct adapter *adap) { int i; @@ -2195,7 +2438,7 @@ int cxgb4_alloc_atid(struct tid_info *t, void *data) if (t->afree) { union aopen_entry *p = t->afree; - atid = p - t->atid_tab; + atid = (p - t->atid_tab) + t->atid_base; t->afree = p->next; p->data = data; t->atids_in_use++; @@ -2210,7 +2453,7 @@ EXPORT_SYMBOL(cxgb4_alloc_atid); */ void cxgb4_free_atid(struct tid_info *t, unsigned int atid) { - union aopen_entry *p = &t->atid_tab[atid]; + union aopen_entry *p = &t->atid_tab[atid - t->atid_base]; spin_lock_bh(&t->atid_lock); p->next = t->afree; @@ -2249,8 +2492,34 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data) } EXPORT_SYMBOL(cxgb4_alloc_stid); -/* - * Release a server TID. +/* Allocate a server filter TID and set it to the supplied value. + */ +int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data) +{ + int stid; + + spin_lock_bh(&t->stid_lock); + if (family == PF_INET) { + stid = find_next_zero_bit(t->stid_bmap, + t->nstids + t->nsftids, t->nstids); + if (stid < (t->nstids + t->nsftids)) + __set_bit(stid, t->stid_bmap); + else + stid = -1; + } else { + stid = -1; + } + if (stid >= 0) { + t->stid_tab[stid].data = data; + stid += t->stid_base; + t->stids_in_use++; + } + spin_unlock_bh(&t->stid_lock); + return stid; +} +EXPORT_SYMBOL(cxgb4_alloc_sftid); + +/* Release a server TID. */ void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family) { @@ -2362,18 +2631,26 @@ EXPORT_SYMBOL(cxgb4_remove_tid); static int tid_init(struct tid_info *t) { size_t size; + unsigned int stid_bmap_size; unsigned int natids = t->natids; - size = t->ntids * sizeof(*t->tid_tab) + natids * sizeof(*t->atid_tab) + + stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids); + size = t->ntids * sizeof(*t->tid_tab) + + natids * sizeof(*t->atid_tab) + t->nstids * sizeof(*t->stid_tab) + - BITS_TO_LONGS(t->nstids) * sizeof(long); + t->nsftids * sizeof(*t->stid_tab) + + stid_bmap_size * sizeof(long) + + t->nftids * sizeof(*t->ftid_tab) + + t->nsftids * sizeof(*t->ftid_tab); + t->tid_tab = t4_alloc_mem(size); if (!t->tid_tab) return -ENOMEM; t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids]; t->stid_tab = (struct serv_entry *)&t->atid_tab[natids]; - t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids]; + t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids + t->nsftids]; + t->ftid_tab = (struct filter_entry *)&t->stid_bmap[stid_bmap_size]; spin_lock_init(&t->stid_lock); spin_lock_init(&t->atid_lock); @@ -2388,7 +2665,7 @@ static int tid_init(struct tid_info *t) t->atid_tab[natids - 1].next = &t->atid_tab[natids]; t->afree = t->atid_tab; } - bitmap_zero(t->stid_bmap, t->nstids); + bitmap_zero(t->stid_bmap, t->nstids + t->nsftids); return 0; } @@ -2404,7 +2681,8 @@ static int tid_init(struct tid_info *t) * Returns <0 on error and one of the %NET_XMIT_* values on success. */ int cxgb4_create_server(const struct net_device *dev, unsigned int stid, - __be32 sip, __be16 sport, unsigned int queue) + __be32 sip, __be16 sport, __be16 vlan, + unsigned int queue) { unsigned int chan; struct sk_buff *skb; @@ -2750,6 +3028,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld) { void *handle; struct cxgb4_lld_info lli; + unsigned short i; lli.pdev = adap->pdev; lli.l2t = adap->l2t; @@ -2776,10 +3055,16 @@ static void uld_attach(struct adapter *adap, unsigned int uld) lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET( t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >> (adap->fn * 4)); + lli.filt_mode = adap->filter_mode; + /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */ + for (i = 0; i < NCHAN; i++) + lli.tx_modq[i] = i; lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS); lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL); lli.fw_vers = adap->params.fw_vers; lli.dbfifo_int_thresh = dbfifo_int_thresh; + lli.sge_pktshift = adap->sge.pktshift; + lli.enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN; handle = ulds[uld].add(&lli); if (IS_ERR(handle)) { @@ -2999,6 +3284,126 @@ static int cxgb_close(struct net_device *dev) return t4_enable_vi(adapter, adapter->fn, pi->viid, false, false); } +/* Return an error number if the indicated filter isn't writable ... + */ +static int writable_filter(struct filter_entry *f) +{ + if (f->locked) + return -EPERM; + if (f->pending) + return -EBUSY; + + return 0; +} + +/* Delete the filter at the specified index (if valid). The checks for all + * the common problems with doing this like the filter being locked, currently + * pending in another operation, etc. + */ +static int delete_filter(struct adapter *adapter, unsigned int fidx) +{ + struct filter_entry *f; + int ret; + + if (fidx >= adapter->tids.nftids + adapter->tids.nsftids) + return -EINVAL; + + f = &adapter->tids.ftid_tab[fidx]; + ret = writable_filter(f); + if (ret) + return ret; + if (f->valid) + return del_filter_wr(adapter, fidx); + + return 0; +} + +int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid, + __be32 sip, __be16 sport, __be16 vlan, + unsigned int queue, unsigned char port, unsigned char mask) +{ + int ret; + struct filter_entry *f; + struct adapter *adap; + int i; + u8 *val; + + adap = netdev2adap(dev); + + /* Adjust stid to correct filter index */ + stid -= adap->tids.nstids; + stid += adap->tids.nftids; + + /* Check to make sure the filter requested is writable ... + */ + f = &adap->tids.ftid_tab[stid]; + ret = writable_filter(f); + if (ret) + return ret; + + /* Clear out any old resources being used by the filter before + * we start constructing the new filter. + */ + if (f->valid) + clear_filter(adap, f); + + /* Clear out filter specifications */ + memset(&f->fs, 0, sizeof(struct ch_filter_specification)); + f->fs.val.lport = cpu_to_be16(sport); + f->fs.mask.lport = ~0; + val = (u8 *)&sip; + if ((val[0] | val[1] | val[2] | val[3]) != 0) { + for (i = 0; i < 4; i++) { + f->fs.val.lip[i] = val[i]; + f->fs.mask.lip[i] = ~0; + } + if (adap->filter_mode & F_PORT) { + f->fs.val.iport = port; + f->fs.mask.iport = mask; + } + } + + f->fs.dirsteer = 1; + f->fs.iq = queue; + /* Mark filter as locked */ + f->locked = 1; + f->fs.rpttid = 1; + + ret = set_filter_wr(adap, stid); + if (ret) { + clear_filter(adap, f); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(cxgb4_create_server_filter); + +int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid, + unsigned int queue, bool ipv6) +{ + int ret; + struct filter_entry *f; + struct adapter *adap; + + adap = netdev2adap(dev); + + /* Adjust stid to correct filter index */ + stid -= adap->tids.nstids; + stid += adap->tids.nftids; + + f = &adap->tids.ftid_tab[stid]; + /* Unlock the filter */ + f->locked = 0; + + ret = delete_filter(adap, stid); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(cxgb4_remove_server_filter); + static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev, struct rtnl_link_stats64 *ns) { @@ -3203,7 +3608,7 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c) memset(c, 0, sizeof(*c)); c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | FW_CMD_REQUEST | FW_CMD_READ); - c->retval_len16 = htonl(FW_LEN16(*c)); + c->cfvalid_to_len16 = htonl(FW_LEN16(*c)); ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), c); if (ret < 0) return ret; @@ -3245,6 +3650,34 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c) v = t4_read_reg(adap, TP_PIO_DATA); t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR); + /* first 4 Tx modulation queues point to consecutive Tx channels */ + adap->params.tp.tx_modq_map = 0xE4; + t4_write_reg(adap, A_TP_TX_MOD_QUEUE_REQ_MAP, + V_TX_MOD_QUEUE_REQ_MAP(adap->params.tp.tx_modq_map)); + + /* associate each Tx modulation queue with consecutive Tx channels */ + v = 0x84218421; + t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, + &v, 1, A_TP_TX_SCHED_HDR); + t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, + &v, 1, A_TP_TX_SCHED_FIFO); + t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, + &v, 1, A_TP_TX_SCHED_PCMD); + +#define T4_TX_MODQ_10G_WEIGHT_DEFAULT 16 /* in KB units */ + if (is_offload(adap)) { + t4_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, + V_TX_MODQ_WEIGHT0(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | + V_TX_MODQ_WEIGHT1(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | + V_TX_MODQ_WEIGHT2(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | + V_TX_MODQ_WEIGHT3(T4_TX_MODQ_10G_WEIGHT_DEFAULT)); + t4_write_reg(adap, A_TP_TX_MOD_CHANNEL_WEIGHT, + V_TX_MODQ_WEIGHT0(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | + V_TX_MODQ_WEIGHT1(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | + V_TX_MODQ_WEIGHT2(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | + V_TX_MODQ_WEIGHT3(T4_TX_MODQ_10G_WEIGHT_DEFAULT)); + } + /* get basic stuff going */ return t4_early_init(adap, adap->fn); } @@ -3397,7 +3830,7 @@ static int adap_init0_config(struct adapter *adapter, int reset) htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | FW_CMD_REQUEST | FW_CMD_READ); - caps_cmd.retval_len16 = + caps_cmd.cfvalid_to_len16 = htonl(FW_CAPS_CONFIG_CMD_CFVALID | FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) | FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) | @@ -3416,23 +3849,13 @@ static int adap_init0_config(struct adapter *adapter, int reset) finicsum, cfcsum); /* - * If we're a pure NIC driver then disable all offloading facilities. - * This will allow the firmware to optimize aspects of the hardware - * configuration which will result in improved performance. - */ - caps_cmd.ofldcaps = 0; - caps_cmd.iscsicaps = 0; - caps_cmd.rdmacaps = 0; - caps_cmd.fcoecaps = 0; - - /* * And now tell the firmware to use the configuration we just loaded. */ caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | FW_CMD_REQUEST | FW_CMD_WRITE); - caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd)); + caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), NULL); if (ret < 0) @@ -3507,7 +3930,7 @@ static int adap_init0_no_config(struct adapter *adapter, int reset) memset(&caps_cmd, 0, sizeof(caps_cmd)); caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | FW_CMD_REQUEST | FW_CMD_READ); - caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd)); + caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), &caps_cmd); if (ret < 0) @@ -3939,7 +4362,7 @@ static int adap_init0(struct adapter *adap) memset(&caps_cmd, 0, sizeof(caps_cmd)); caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | FW_CMD_REQUEST | FW_CMD_READ); - caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd)); + caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd), &caps_cmd); if (ret < 0) @@ -4045,6 +4468,10 @@ static int adap_init0(struct adapter *adap) for (j = 0; j < NCHAN; j++) adap->params.tp.tx_modq[j] = j; + t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, + &adap->filter_mode, 1, + TP_VLAN_PRI_MAP); + adap->flags |= FW_OK; return 0; @@ -4183,7 +4610,7 @@ static inline void init_rspq(struct sge_rspq *q, u8 timer_idx, u8 pkt_cnt_idx, * of ports we found and the number of available CPUs. Most settings can be * modified by the admin prior to actual use. */ -static void __devinit cfg_queues(struct adapter *adap) +static void cfg_queues(struct adapter *adap) { struct sge *s = &adap->sge; int i, q10g = 0, n10g = 0, qidx = 0; @@ -4267,7 +4694,7 @@ static void __devinit cfg_queues(struct adapter *adap) * Reduce the number of Ethernet queues across all ports to at most n. * n provides at least one queue per port. */ -static void __devinit reduce_ethqs(struct adapter *adap, int n) +static void reduce_ethqs(struct adapter *adap, int n) { int i; struct port_info *pi; @@ -4294,7 +4721,7 @@ static void __devinit reduce_ethqs(struct adapter *adap, int n) /* 2 MSI-X vectors needed for the FW queue and non-data interrupts */ #define EXTRA_VECS 2 -static int __devinit enable_msix(struct adapter *adap) +static int enable_msix(struct adapter *adap) { int ofld_need = 0; int i, err, want, need; @@ -4343,7 +4770,7 @@ static int __devinit enable_msix(struct adapter *adap) #undef EXTRA_VECS -static int __devinit init_rss(struct adapter *adap) +static int init_rss(struct adapter *adap) { unsigned int i, j; @@ -4359,7 +4786,7 @@ static int __devinit init_rss(struct adapter *adap) return 0; } -static void __devinit print_port_info(const struct net_device *dev) +static void print_port_info(const struct net_device *dev) { static const char *base[] = { "R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4", @@ -4396,7 +4823,7 @@ static void __devinit print_port_info(const struct net_device *dev) adap->params.vpd.sn, adap->params.vpd.ec); } -static void __devinit enable_pcie_relaxed_ordering(struct pci_dev *dev) +static void enable_pcie_relaxed_ordering(struct pci_dev *dev) { pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN); } @@ -4429,8 +4856,7 @@ static void free_some_resources(struct adapter *adapter) #define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \ NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA) -static int __devinit init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int func, i, err; struct port_info *pi; @@ -4650,7 +5076,7 @@ sriov: return err; } -static void __devexit remove_one(struct pci_dev *pdev) +static void remove_one(struct pci_dev *pdev) { struct adapter *adapter = pci_get_drvdata(pdev); @@ -4672,6 +5098,17 @@ static void __devexit remove_one(struct pci_dev *pdev) if (adapter->debugfs_root) debugfs_remove_recursive(adapter->debugfs_root); + /* If we allocated filters, free up state associated with any + * valid filters ... + */ + if (adapter->tids.ftid_tab) { + struct filter_entry *f = &adapter->tids.ftid_tab[0]; + for (i = 0; i < (adapter->tids.nftids + + adapter->tids.nsftids); i++, f++) + if (f->valid) + clear_filter(adapter, f); + } + if (adapter->flags & FULL_INIT_DONE) cxgb_down(adapter); @@ -4690,7 +5127,7 @@ static struct pci_driver cxgb4_driver = { .name = KBUILD_MODNAME, .id_table = cxgb4_pci_tbl, .probe = init_one, - .remove = __devexit_p(remove_one), + .remove = remove_one, .err_handler = &cxgb4_eeh, }; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 39bec73ff87c..e2bbc7f3e2de 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -38,6 +38,7 @@ #include <linux/cache.h> #include <linux/spinlock.h> #include <linux/skbuff.h> +#include <linux/inetdevice.h> #include <linux/atomic.h> /* CPL message priority levels */ @@ -97,7 +98,9 @@ struct tid_info { union aopen_entry *atid_tab; unsigned int natids; + unsigned int atid_base; + struct filter_entry *ftid_tab; unsigned int nftids; unsigned int ftid_base; unsigned int aftid_base; @@ -129,7 +132,7 @@ static inline void *lookup_atid(const struct tid_info *t, unsigned int atid) static inline void *lookup_stid(const struct tid_info *t, unsigned int stid) { stid -= t->stid_base; - return stid < t->nstids ? t->stid_tab[stid].data : NULL; + return stid < (t->nstids + t->nsftids) ? t->stid_tab[stid].data : NULL; } static inline void cxgb4_insert_tid(struct tid_info *t, void *data, @@ -141,6 +144,7 @@ static inline void cxgb4_insert_tid(struct tid_info *t, void *data, int cxgb4_alloc_atid(struct tid_info *t, void *data); int cxgb4_alloc_stid(struct tid_info *t, int family, void *data); +int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data); void cxgb4_free_atid(struct tid_info *t, unsigned int atid); void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family); void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid); @@ -148,8 +152,14 @@ void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid); struct in6_addr; int cxgb4_create_server(const struct net_device *dev, unsigned int stid, - __be32 sip, __be16 sport, unsigned int queue); - + __be32 sip, __be16 sport, __be16 vlan, + unsigned int queue); +int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid, + __be32 sip, __be16 sport, __be16 vlan, + unsigned int queue, + unsigned char port, unsigned char mask); +int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid, + unsigned int queue, bool ipv6); static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue) { skb_set_queue_mapping(skb, (queue << 1) | prio); @@ -221,9 +231,16 @@ struct cxgb4_lld_info { unsigned int iscsi_iolen; /* iSCSI max I/O length */ unsigned short udb_density; /* # of user DB/page */ unsigned short ucq_density; /* # of user CQs/page */ + unsigned short filt_mode; /* filter optional components */ + unsigned short tx_modq[NCHAN]; /* maps each tx channel to a */ + /* scheduler queue */ void __iomem *gts_reg; /* address of GTS register */ void __iomem *db_reg; /* address of kernel doorbell */ int dbfifo_int_thresh; /* doorbell fifo int threshold */ + unsigned int sge_pktshift; /* Padding between CPL and */ + /* packet data */ + bool enable_fw_ofld_conn; /* Enable connection through fw */ + /* WR */ }; struct cxgb4_uld_info { diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c index 6ac77a62f361..29878098101e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c +++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c @@ -484,6 +484,38 @@ void t4_l2t_update(struct adapter *adap, struct neighbour *neigh) handle_failed_resolution(adap, arpq); } +/* Allocate an L2T entry for use by a switching rule. Such need to be + * explicitly freed and while busy they are not on any hash chain, so normal + * address resolution updates do not see them. + */ +struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d) +{ + struct l2t_entry *e; + + write_lock_bh(&d->lock); + e = alloc_l2e(d); + if (e) { + spin_lock(&e->lock); /* avoid race with t4_l2t_free */ + e->state = L2T_STATE_SWITCHING; + atomic_set(&e->refcnt, 1); + spin_unlock(&e->lock); + } + write_unlock_bh(&d->lock); + return e; +} + +/* Sets/updates the contents of a switching L2T entry that has been allocated + * with an earlier call to @t4_l2t_alloc_switching. + */ +int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan, + u8 port, u8 *eth_addr) +{ + e->vlan = vlan; + e->lport = port; + memcpy(e->dmac, eth_addr, ETH_ALEN); + return write_l2e(adap, e, 0); +} + struct l2t_data *t4_init_l2t(void) { int i; diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.h b/drivers/net/ethernet/chelsio/cxgb4/l2t.h index 02b31d0c6410..108c0f1fce1c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/l2t.h +++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.h @@ -100,6 +100,9 @@ struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh, unsigned int priority); void t4_l2t_update(struct adapter *adap, struct neighbour *neigh); +struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d); +int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan, + u8 port, u8 *eth_addr); struct l2t_data *t4_init_l2t(void); void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl); diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 3ecc087d732d..fe9a2ea3588b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -508,7 +508,7 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q) { if (q->pend_cred >= 8) { wmb(); - t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO | + t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO(1) | QID(q->cntxt_id) | PIDX(q->pend_cred / 8)); q->pend_cred &= 7; } @@ -2082,10 +2082,10 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, goto fl_nomem; flsz = fl->size / 8 + s->stat_len / sizeof(struct tx_desc); - c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN | + c.iqns_to_fl0congen = htonl(FW_IQ_CMD_FL0PACKEN(1) | FW_IQ_CMD_FL0FETCHRO(1) | FW_IQ_CMD_FL0DATARO(1) | - FW_IQ_CMD_FL0PADEN); + FW_IQ_CMD_FL0PADEN(1)); c.fl0dcaen_to_fl0cidxfthresh = htons(FW_IQ_CMD_FL0FBMIN(2) | FW_IQ_CMD_FL0FBMAX(3)); c.fl0size = htons(flsz); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 32eec15fe4c2..22f3af5166bf 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -109,7 +109,7 @@ void t4_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask, * Reads registers that are accessed indirectly through an address/data * register pair. */ -static void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, +void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, unsigned int data_reg, u32 *vals, unsigned int nregs, unsigned int start_idx) { @@ -648,12 +648,12 @@ static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont, if (!byte_cnt || byte_cnt > 4) return -EINVAL; - if (t4_read_reg(adapter, SF_OP) & BUSY) + if (t4_read_reg(adapter, SF_OP) & SF_BUSY) return -EBUSY; cont = cont ? SF_CONT : 0; lock = lock ? SF_LOCK : 0; t4_write_reg(adapter, SF_OP, lock | cont | BYTECNT(byte_cnt - 1)); - ret = t4_wait_op_done(adapter, SF_OP, BUSY, 0, SF_ATTEMPTS, 5); + ret = t4_wait_op_done(adapter, SF_OP, SF_BUSY, 0, SF_ATTEMPTS, 5); if (!ret) *valp = t4_read_reg(adapter, SF_DATA); return ret; @@ -676,14 +676,14 @@ static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont, { if (!byte_cnt || byte_cnt > 4) return -EINVAL; - if (t4_read_reg(adapter, SF_OP) & BUSY) + if (t4_read_reg(adapter, SF_OP) & SF_BUSY) return -EBUSY; cont = cont ? SF_CONT : 0; lock = lock ? SF_LOCK : 0; t4_write_reg(adapter, SF_DATA, val); t4_write_reg(adapter, SF_OP, lock | cont | BYTECNT(byte_cnt - 1) | OP_WR); - return t4_wait_op_done(adapter, SF_OP, BUSY, 0, SF_ATTEMPTS, 5); + return t4_wait_op_done(adapter, SF_OP, SF_BUSY, 0, SF_ATTEMPTS, 5); } /** @@ -2003,7 +2003,7 @@ void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr, * * Initialize the congestion control parameters. */ -static void __devinit init_cong_ctrl(unsigned short *a, unsigned short *b) +static void init_cong_ctrl(unsigned short *a, unsigned short *b) { a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1; a[9] = 2; @@ -2252,14 +2252,14 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, t4_write_reg(adap, EPIO_REG(DATA0), mask0); t4_write_reg(adap, EPIO_REG(OP), ADDRESS(i) | EPIOWR); t4_read_reg(adap, EPIO_REG(OP)); /* flush */ - if (t4_read_reg(adap, EPIO_REG(OP)) & BUSY) + if (t4_read_reg(adap, EPIO_REG(OP)) & SF_BUSY) return -ETIMEDOUT; /* write CRC */ t4_write_reg(adap, EPIO_REG(DATA0), crc); t4_write_reg(adap, EPIO_REG(OP), ADDRESS(i + 32) | EPIOWR); t4_read_reg(adap, EPIO_REG(OP)); /* flush */ - if (t4_read_reg(adap, EPIO_REG(OP)) & BUSY) + if (t4_read_reg(adap, EPIO_REG(OP)) & SF_BUSY) return -ETIMEDOUT; } #undef EPIO_REG @@ -2268,6 +2268,26 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, return 0; } +/* t4_mk_filtdelwr - create a delete filter WR + * @ftid: the filter ID + * @wr: the filter work request to populate + * @qid: ingress queue to receive the delete notification + * + * Creates a filter work request to delete the supplied filter. If @qid is + * negative the delete notification is suppressed. + */ +void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid) +{ + memset(wr, 0, sizeof(*wr)); + wr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR)); + wr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*wr) / 16)); + wr->tid_to_iq = htonl(V_FW_FILTER_WR_TID(ftid) | + V_FW_FILTER_WR_NOREPLY(qid < 0)); + wr->del_filter_to_l2tix = htonl(F_FW_FILTER_WR_DEL_FILTER); + if (qid >= 0) + wr->rx_chan_rx_rpl_iq = htons(V_FW_FILTER_WR_RX_RPL_IQ(qid)); +} + #define INIT_CMD(var, cmd, rd_wr) do { \ (var).op_to_write = htonl(FW_CMD_OP(FW_##cmd##_CMD) | \ FW_CMD_REQUEST | FW_CMD_##rd_wr); \ @@ -2405,7 +2425,7 @@ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox, retry: memset(&c, 0, sizeof(c)); INIT_CMD(c, HELLO, WRITE); - c.err_to_mbasyncnot = htonl( + c.err_to_clearinit = htonl( FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) | FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) | FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox : @@ -2426,7 +2446,7 @@ retry: return ret; } - v = ntohl(c.err_to_mbasyncnot); + v = ntohl(c.err_to_clearinit); master_mbox = FW_HELLO_CMD_MBMASTER_GET(v); if (state) { if (v & FW_HELLO_CMD_ERR) @@ -2519,6 +2539,7 @@ int t4_fw_bye(struct adapter *adap, unsigned int mbox) { struct fw_bye_cmd c; + memset(&c, 0, sizeof(c)); INIT_CMD(c, BYE, WRITE); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -2535,6 +2556,7 @@ int t4_early_init(struct adapter *adap, unsigned int mbox) { struct fw_initialize_cmd c; + memset(&c, 0, sizeof(c)); INIT_CMD(c, INITIALIZE, WRITE); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -2551,6 +2573,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset) { struct fw_reset_cmd c; + memset(&c, 0, sizeof(c)); INIT_CMD(c, RESET, WRITE); c.val = htonl(reset); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); @@ -2771,7 +2794,7 @@ int t4_fw_config_file(struct adapter *adap, unsigned int mbox, htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | FW_CMD_REQUEST | FW_CMD_READ); - caps_cmd.retval_len16 = + caps_cmd.cfvalid_to_len16 = htonl(FW_CAPS_CONFIG_CMD_CFVALID | FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) | FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) | @@ -2794,7 +2817,7 @@ int t4_fw_config_file(struct adapter *adap, unsigned int mbox, htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | FW_CMD_REQUEST | FW_CMD_WRITE); - caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd)); + caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); return t4_wr_mbox(adap, mbox, &caps_cmd, sizeof(caps_cmd), NULL); } @@ -2828,7 +2851,7 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size, HOSTPAGESIZEPF7(sge_hps)); t4_set_reg_field(adap, SGE_CONTROL, - INGPADBOUNDARY(INGPADBOUNDARY_MASK) | + INGPADBOUNDARY_MASK | EGRSTATUSPAGESIZE_MASK, INGPADBOUNDARY(fl_align_log - 5) | EGRSTATUSPAGESIZE(stat_len != 64)); @@ -3278,6 +3301,7 @@ int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid, { struct fw_vi_enable_cmd c; + memset(&c, 0, sizeof(c)); c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST | FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid)); c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED | FW_LEN16(c)); @@ -3436,8 +3460,7 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl) return 0; } -static void __devinit get_pci_mode(struct adapter *adapter, - struct pci_params *p) +static void get_pci_mode(struct adapter *adapter, struct pci_params *p) { u16 val; @@ -3456,8 +3479,7 @@ static void __devinit get_pci_mode(struct adapter *adapter, * Initializes the SW state maintained for each link, including the link's * capabilities and default speed/flow-control/autonegotiation settings. */ -static void __devinit init_link_config(struct link_config *lc, - unsigned int caps) +static void init_link_config(struct link_config *lc, unsigned int caps) { lc->supported = caps; lc->requested_speed = 0; @@ -3481,7 +3503,7 @@ int t4_wait_dev_ready(struct adapter *adap) return t4_read_reg(adap, PL_WHOAMI) != 0xffffffff ? 0 : -EIO; } -static int __devinit get_flash_params(struct adapter *adap) +static int get_flash_params(struct adapter *adap) { int ret; u32 info; @@ -3517,7 +3539,7 @@ static int __devinit get_flash_params(struct adapter *adap) * values for some adapter tunables, take PHYs out of reset, and * initialize the MDIO interface. */ -int __devinit t4_prep_adapter(struct adapter *adapter) +int t4_prep_adapter(struct adapter *adapter) { int ret; @@ -3545,7 +3567,7 @@ int __devinit t4_prep_adapter(struct adapter *adapter) return 0; } -int __devinit t4_port_init(struct adapter *adap, int mbox, int pf, int vf) +int t4_port_init(struct adapter *adap, int mbox, int pf, int vf) { u8 addr[6]; int ret, i, j = 0; diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h index eb71b8250b91..261d17703adc 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h @@ -193,8 +193,24 @@ struct work_request_hdr { __be64 wr_lo; }; +/* wr_hi fields */ +#define S_WR_OP 24 +#define V_WR_OP(x) ((__u64)(x) << S_WR_OP) + #define WR_HDR struct work_request_hdr wr +/* option 0 fields */ +#define S_MSS_IDX 60 +#define M_MSS_IDX 0xF +#define V_MSS_IDX(x) ((__u64)(x) << S_MSS_IDX) +#define G_MSS_IDX(x) (((x) >> S_MSS_IDX) & M_MSS_IDX) + +/* option 2 fields */ +#define S_RSS_QUEUE 0 +#define M_RSS_QUEUE 0x3FF +#define V_RSS_QUEUE(x) ((x) << S_RSS_QUEUE) +#define G_RSS_QUEUE(x) (((x) >> S_RSS_QUEUE) & M_RSS_QUEUE) + struct cpl_pass_open_req { WR_HDR; union opcode_tid ot; @@ -204,12 +220,14 @@ struct cpl_pass_open_req { __be32 peer_ip; __be64 opt0; #define TX_CHAN(x) ((x) << 2) +#define NO_CONG(x) ((x) << 4) #define DELACK(x) ((x) << 5) #define ULP_MODE(x) ((x) << 8) #define RCV_BUFSIZ(x) ((x) << 12) #define DSCP(x) ((x) << 22) #define SMAC_SEL(x) ((u64)(x) << 28) #define L2T_IDX(x) ((u64)(x) << 36) +#define TCAM_BYPASS(x) ((u64)(x) << 48) #define NAGLE(x) ((u64)(x) << 49) #define WND_SCALE(x) ((u64)(x) << 50) #define KEEP_ALIVE(x) ((u64)(x) << 54) @@ -247,8 +265,10 @@ struct cpl_pass_accept_rpl { #define RSS_QUEUE_VALID (1 << 10) #define RX_COALESCE_VALID(x) ((x) << 11) #define RX_COALESCE(x) ((x) << 12) +#define PACE(x) ((x) << 16) #define TX_QUEUE(x) ((x) << 23) #define RX_CHANNEL(x) ((x) << 26) +#define CCTRL_ECN(x) ((x) << 27) #define WND_SCALE_EN(x) ((x) << 28) #define TSTAMPS_EN(x) ((x) << 29) #define SACK_EN(x) ((x) << 30) @@ -292,6 +312,9 @@ struct cpl_pass_establish { union opcode_tid ot; __be32 rsvd; __be32 tos_stid; +#define PASS_OPEN_TID(x) ((x) << 0) +#define PASS_OPEN_TOS(x) ((x) << 24) +#define GET_PASS_OPEN_TID(x) (((x) >> 0) & 0xFFFFFF) #define GET_POPEN_TID(x) ((x) & 0xffffff) #define GET_POPEN_TOS(x) (((x) >> 24) & 0xff) __be16 mac_idx; @@ -332,6 +355,7 @@ struct cpl_set_tcb_field { __be16 word_cookie; #define TCB_WORD(x) ((x) << 0) #define TCB_COOKIE(x) ((x) << 5) +#define GET_TCB_COOKIE(x) (((x) >> 5) & 7) __be64 mask; __be64 val; }; @@ -536,6 +560,37 @@ struct cpl_rx_pkt { __be16 err_vec; }; +/* rx_pkt.l2info fields */ +#define S_RX_ETHHDR_LEN 0 +#define M_RX_ETHHDR_LEN 0x1F +#define V_RX_ETHHDR_LEN(x) ((x) << S_RX_ETHHDR_LEN) +#define G_RX_ETHHDR_LEN(x) (((x) >> S_RX_ETHHDR_LEN) & M_RX_ETHHDR_LEN) + +#define S_RX_MACIDX 8 +#define M_RX_MACIDX 0x1FF +#define V_RX_MACIDX(x) ((x) << S_RX_MACIDX) +#define G_RX_MACIDX(x) (((x) >> S_RX_MACIDX) & M_RX_MACIDX) + +#define S_RXF_SYN 21 +#define V_RXF_SYN(x) ((x) << S_RXF_SYN) +#define F_RXF_SYN V_RXF_SYN(1U) + +#define S_RX_CHAN 28 +#define M_RX_CHAN 0xF +#define V_RX_CHAN(x) ((x) << S_RX_CHAN) +#define G_RX_CHAN(x) (((x) >> S_RX_CHAN) & M_RX_CHAN) + +/* rx_pkt.hdr_len fields */ +#define S_RX_TCPHDR_LEN 0 +#define M_RX_TCPHDR_LEN 0x3F +#define V_RX_TCPHDR_LEN(x) ((x) << S_RX_TCPHDR_LEN) +#define G_RX_TCPHDR_LEN(x) (((x) >> S_RX_TCPHDR_LEN) & M_RX_TCPHDR_LEN) + +#define S_RX_IPHDR_LEN 6 +#define M_RX_IPHDR_LEN 0x3FF +#define V_RX_IPHDR_LEN(x) ((x) << S_RX_IPHDR_LEN) +#define G_RX_IPHDR_LEN(x) (((x) >> S_RX_IPHDR_LEN) & M_RX_IPHDR_LEN) + struct cpl_trace_pkt { u8 opcode; u8 intf; @@ -634,6 +689,17 @@ struct cpl_fw6_msg { /* cpl_fw6_msg.type values */ enum { FW6_TYPE_CMD_RPL = 0, + FW6_TYPE_WR_RPL = 1, + FW6_TYPE_CQE = 2, + FW6_TYPE_OFLD_CONNECTION_WR_RPL = 3, +}; + +struct cpl_fw6_msg_ofld_connection_wr_rpl { + __u64 cookie; + __be32 tid; /* or atid in case of active failure */ + __u8 t_state; + __u8 retval; + __u8 rsvd[2]; }; enum { @@ -658,6 +724,7 @@ struct ulptx_sgl { __be32 cmd_nsge; #define ULPTX_CMD(x) ((x) << 24) #define ULPTX_NSGE(x) ((x) << 0) +#define ULPTX_MORE (1U << 23) __be32 len0; __be64 addr0; struct ulptx_sge_pair sge[0]; diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h index a1a8b57200f6..83ec5f7844ac 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h @@ -67,7 +67,7 @@ #define QID_MASK 0xffff8000U #define QID_SHIFT 15 #define QID(x) ((x) << QID_SHIFT) -#define DBPRIO 0x00004000U +#define DBPRIO(x) ((x) << 14) #define PIDX_MASK 0x00003fffU #define PIDX_SHIFT 0 #define PIDX(x) ((x) << PIDX_SHIFT) @@ -193,6 +193,12 @@ #define SGE_FL_BUFFER_SIZE1 0x1048 #define SGE_FL_BUFFER_SIZE2 0x104c #define SGE_FL_BUFFER_SIZE3 0x1050 +#define SGE_FL_BUFFER_SIZE4 0x1054 +#define SGE_FL_BUFFER_SIZE5 0x1058 +#define SGE_FL_BUFFER_SIZE6 0x105c +#define SGE_FL_BUFFER_SIZE7 0x1060 +#define SGE_FL_BUFFER_SIZE8 0x1064 + #define SGE_INGRESS_RX_THRESHOLD 0x10a0 #define THRESHOLD_0_MASK 0x3f000000U #define THRESHOLD_0_SHIFT 24 @@ -217,6 +223,17 @@ #define EGRTHRESHOLD(x) ((x) << EGRTHRESHOLDshift) #define EGRTHRESHOLD_GET(x) (((x) & EGRTHRESHOLD_MASK) >> EGRTHRESHOLDshift) +#define SGE_DBFIFO_STATUS 0x10a4 +#define HP_INT_THRESH_SHIFT 28 +#define HP_INT_THRESH_MASK 0xfU +#define HP_INT_THRESH(x) ((x) << HP_INT_THRESH_SHIFT) +#define LP_INT_THRESH_SHIFT 12 +#define LP_INT_THRESH_MASK 0xfU +#define LP_INT_THRESH(x) ((x) << LP_INT_THRESH_SHIFT) + +#define SGE_DOORBELL_CONTROL 0x10a8 +#define ENABLE_DROP (1 << 13) + #define SGE_TIMER_VALUE_0_AND_1 0x10b8 #define TIMERVALUE0_MASK 0xffff0000U #define TIMERVALUE0_SHIFT 16 @@ -277,6 +294,10 @@ #define A_SGE_CTXT_CMD 0x11fc #define A_SGE_DBQ_CTXT_BADDR 0x1084 +#define PCIE_PF_CFG 0x40 +#define AIVEC(x) ((x) << 4) +#define AIVEC_MASK 0x3ffU + #define PCIE_PF_CLI 0x44 #define PCIE_INT_CAUSE 0x3004 #define UNXSPLCPLERR 0x20000000U @@ -322,6 +343,13 @@ #define PCIE_MEM_ACCESS_OFFSET 0x306c #define PCIE_FW 0x30b8 +#define PCIE_FW_ERR 0x80000000U +#define PCIE_FW_INIT 0x40000000U +#define PCIE_FW_HALT 0x20000000U +#define PCIE_FW_MASTER_VLD 0x00008000U +#define PCIE_FW_MASTER(x) ((x) << 12) +#define PCIE_FW_MASTER_MASK 0x7 +#define PCIE_FW_MASTER_GET(x) (((x) >> 12) & PCIE_FW_MASTER_MASK) #define PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS 0x5908 #define RNPP 0x80000000U @@ -432,6 +460,9 @@ #define MBOWNER(x) ((x) << MBOWNER_SHIFT) #define MBOWNER_GET(x) (((x) & MBOWNER_MASK) >> MBOWNER_SHIFT) +#define CIM_PF_HOST_INT_ENABLE 0x288 +#define MBMSGRDYINTEN(x) ((x) << 19) + #define CIM_PF_HOST_INT_CAUSE 0x28c #define MBMSGRDYINT 0x00080000U @@ -922,7 +953,7 @@ #define SF_DATA 0x193f8 #define SF_OP 0x193fc -#define BUSY 0x80000000U +#define SF_BUSY 0x80000000U #define SF_LOCK 0x00000010U #define SF_CONT 0x00000008U #define BYTECNT_MASK 0x00000006U @@ -981,6 +1012,7 @@ #define I2CM 0x00000002U #define CIM 0x00000001U +#define PL_INT_ENABLE 0x19410 #define PL_INT_MAP0 0x19414 #define PL_RST 0x19428 #define PIORST 0x00000002U @@ -1032,4 +1064,41 @@ #define ADDRESS(x) ((x) << ADDRESS_SHIFT) #define XGMAC_PORT_INT_CAUSE 0x10dc + +#define A_TP_TX_MOD_QUEUE_REQ_MAP 0x7e28 + +#define A_TP_TX_MOD_CHANNEL_WEIGHT 0x7e34 + +#define S_TX_MOD_QUEUE_REQ_MAP 0 +#define M_TX_MOD_QUEUE_REQ_MAP 0xffffU +#define V_TX_MOD_QUEUE_REQ_MAP(x) ((x) << S_TX_MOD_QUEUE_REQ_MAP) + +#define A_TP_TX_MOD_QUEUE_WEIGHT0 0x7e30 + +#define S_TX_MODQ_WEIGHT3 24 +#define M_TX_MODQ_WEIGHT3 0xffU +#define V_TX_MODQ_WEIGHT3(x) ((x) << S_TX_MODQ_WEIGHT3) + +#define S_TX_MODQ_WEIGHT2 16 +#define M_TX_MODQ_WEIGHT2 0xffU +#define V_TX_MODQ_WEIGHT2(x) ((x) << S_TX_MODQ_WEIGHT2) + +#define S_TX_MODQ_WEIGHT1 8 +#define M_TX_MODQ_WEIGHT1 0xffU +#define V_TX_MODQ_WEIGHT1(x) ((x) << S_TX_MODQ_WEIGHT1) + +#define S_TX_MODQ_WEIGHT0 0 +#define M_TX_MODQ_WEIGHT0 0xffU +#define V_TX_MODQ_WEIGHT0(x) ((x) << S_TX_MODQ_WEIGHT0) + +#define A_TP_TX_SCHED_HDR 0x23 + +#define A_TP_TX_SCHED_FIFO 0x24 + +#define A_TP_TX_SCHED_PCMD 0x25 + +#define S_PORT 1 +#define V_PORT(x) ((x) << S_PORT) +#define F_PORT V_PORT(1U) + #endif /* __T4_REGS_H */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index a6364632b490..a0dcccd846c9 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -35,6 +35,45 @@ #ifndef _T4FW_INTERFACE_H_ #define _T4FW_INTERFACE_H_ +enum fw_retval { + FW_SUCCESS = 0, /* completed sucessfully */ + FW_EPERM = 1, /* operation not permitted */ + FW_ENOENT = 2, /* no such file or directory */ + FW_EIO = 5, /* input/output error; hw bad */ + FW_ENOEXEC = 8, /* exec format error; inv microcode */ + FW_EAGAIN = 11, /* try again */ + FW_ENOMEM = 12, /* out of memory */ + FW_EFAULT = 14, /* bad address; fw bad */ + FW_EBUSY = 16, /* resource busy */ + FW_EEXIST = 17, /* file exists */ + FW_EINVAL = 22, /* invalid argument */ + FW_ENOSPC = 28, /* no space left on device */ + FW_ENOSYS = 38, /* functionality not implemented */ + FW_EPROTO = 71, /* protocol error */ + FW_EADDRINUSE = 98, /* address already in use */ + FW_EADDRNOTAVAIL = 99, /* cannot assigned requested address */ + FW_ENETDOWN = 100, /* network is down */ + FW_ENETUNREACH = 101, /* network is unreachable */ + FW_ENOBUFS = 105, /* no buffer space available */ + FW_ETIMEDOUT = 110, /* timeout */ + FW_EINPROGRESS = 115, /* fw internal */ + FW_SCSI_ABORT_REQUESTED = 128, /* */ + FW_SCSI_ABORT_TIMEDOUT = 129, /* */ + FW_SCSI_ABORTED = 130, /* */ + FW_SCSI_CLOSE_REQUESTED = 131, /* */ + FW_ERR_LINK_DOWN = 132, /* */ + FW_RDEV_NOT_READY = 133, /* */ + FW_ERR_RDEV_LOST = 134, /* */ + FW_ERR_RDEV_LOGO = 135, /* */ + FW_FCOE_NO_XCHG = 136, /* */ + FW_SCSI_RSP_ERR = 137, /* */ + FW_ERR_RDEV_IMPL_LOGO = 138, /* */ + FW_SCSI_UNDER_FLOW_ERR = 139, /* */ + FW_SCSI_OVER_FLOW_ERR = 140, /* */ + FW_SCSI_DDP_ERR = 141, /* DDP error*/ + FW_SCSI_TASK_ERR = 142, /* No SCSI tasks available */ +}; + #define FW_T4VF_SGE_BASE_ADDR 0x0000 #define FW_T4VF_MPS_BASE_ADDR 0x0100 #define FW_T4VF_PL_BASE_ADDR 0x0200 @@ -46,6 +85,7 @@ enum fw_wr_opcodes { FW_ULPTX_WR = 0x04, FW_TP_WR = 0x05, FW_ETH_TX_PKT_WR = 0x08, + FW_OFLD_CONNECTION_WR = 0x2f, FW_FLOWC_WR = 0x0a, FW_OFLD_TX_DATA_WR = 0x0b, FW_CMD_WR = 0x10, @@ -68,6 +108,7 @@ struct fw_wr_hdr { }; #define FW_WR_OP(x) ((x) << 24) +#define FW_WR_OP_GET(x) (((x) >> 24) & 0xff) #define FW_WR_ATOMIC(x) ((x) << 23) #define FW_WR_FLUSH(x) ((x) << 22) #define FW_WR_COMPL(x) ((x) << 21) @@ -80,6 +121,282 @@ struct fw_wr_hdr { #define FW_WR_LEN16(x) ((x) << 0) #define HW_TPL_FR_MT_PR_IV_P_FC 0X32B +#define HW_TPL_FR_MT_PR_OV_P_FC 0X327 + +/* filter wr reply code in cookie in CPL_SET_TCB_RPL */ +enum fw_filter_wr_cookie { + FW_FILTER_WR_SUCCESS, + FW_FILTER_WR_FLT_ADDED, + FW_FILTER_WR_FLT_DELETED, + FW_FILTER_WR_SMT_TBL_FULL, + FW_FILTER_WR_EINVAL, +}; + +struct fw_filter_wr { + __be32 op_pkd; + __be32 len16_pkd; + __be64 r3; + __be32 tid_to_iq; + __be32 del_filter_to_l2tix; + __be16 ethtype; + __be16 ethtypem; + __u8 frag_to_ovlan_vldm; + __u8 smac_sel; + __be16 rx_chan_rx_rpl_iq; + __be32 maci_to_matchtypem; + __u8 ptcl; + __u8 ptclm; + __u8 ttyp; + __u8 ttypm; + __be16 ivlan; + __be16 ivlanm; + __be16 ovlan; + __be16 ovlanm; + __u8 lip[16]; + __u8 lipm[16]; + __u8 fip[16]; + __u8 fipm[16]; + __be16 lp; + __be16 lpm; + __be16 fp; + __be16 fpm; + __be16 r7; + __u8 sma[6]; +}; + +#define S_FW_FILTER_WR_TID 12 +#define M_FW_FILTER_WR_TID 0xfffff +#define V_FW_FILTER_WR_TID(x) ((x) << S_FW_FILTER_WR_TID) +#define G_FW_FILTER_WR_TID(x) \ + (((x) >> S_FW_FILTER_WR_TID) & M_FW_FILTER_WR_TID) + +#define S_FW_FILTER_WR_RQTYPE 11 +#define M_FW_FILTER_WR_RQTYPE 0x1 +#define V_FW_FILTER_WR_RQTYPE(x) ((x) << S_FW_FILTER_WR_RQTYPE) +#define G_FW_FILTER_WR_RQTYPE(x) \ + (((x) >> S_FW_FILTER_WR_RQTYPE) & M_FW_FILTER_WR_RQTYPE) +#define F_FW_FILTER_WR_RQTYPE V_FW_FILTER_WR_RQTYPE(1U) + +#define S_FW_FILTER_WR_NOREPLY 10 +#define M_FW_FILTER_WR_NOREPLY 0x1 +#define V_FW_FILTER_WR_NOREPLY(x) ((x) << S_FW_FILTER_WR_NOREPLY) +#define G_FW_FILTER_WR_NOREPLY(x) \ + (((x) >> S_FW_FILTER_WR_NOREPLY) & M_FW_FILTER_WR_NOREPLY) +#define F_FW_FILTER_WR_NOREPLY V_FW_FILTER_WR_NOREPLY(1U) + +#define S_FW_FILTER_WR_IQ 0 +#define M_FW_FILTER_WR_IQ 0x3ff +#define V_FW_FILTER_WR_IQ(x) ((x) << S_FW_FILTER_WR_IQ) +#define G_FW_FILTER_WR_IQ(x) \ + (((x) >> S_FW_FILTER_WR_IQ) & M_FW_FILTER_WR_IQ) + +#define S_FW_FILTER_WR_DEL_FILTER 31 +#define M_FW_FILTER_WR_DEL_FILTER 0x1 +#define V_FW_FILTER_WR_DEL_FILTER(x) ((x) << S_FW_FILTER_WR_DEL_FILTER) +#define G_FW_FILTER_WR_DEL_FILTER(x) \ + (((x) >> S_FW_FILTER_WR_DEL_FILTER) & M_FW_FILTER_WR_DEL_FILTER) +#define F_FW_FILTER_WR_DEL_FILTER V_FW_FILTER_WR_DEL_FILTER(1U) + +#define S_FW_FILTER_WR_RPTTID 25 +#define M_FW_FILTER_WR_RPTTID 0x1 +#define V_FW_FILTER_WR_RPTTID(x) ((x) << S_FW_FILTER_WR_RPTTID) +#define G_FW_FILTER_WR_RPTTID(x) \ + (((x) >> S_FW_FILTER_WR_RPTTID) & M_FW_FILTER_WR_RPTTID) +#define F_FW_FILTER_WR_RPTTID V_FW_FILTER_WR_RPTTID(1U) + +#define S_FW_FILTER_WR_DROP 24 +#define M_FW_FILTER_WR_DROP 0x1 +#define V_FW_FILTER_WR_DROP(x) ((x) << S_FW_FILTER_WR_DROP) +#define G_FW_FILTER_WR_DROP(x) \ + (((x) >> S_FW_FILTER_WR_DROP) & M_FW_FILTER_WR_DROP) +#define F_FW_FILTER_WR_DROP V_FW_FILTER_WR_DROP(1U) + +#define S_FW_FILTER_WR_DIRSTEER 23 +#define M_FW_FILTER_WR_DIRSTEER 0x1 +#define V_FW_FILTER_WR_DIRSTEER(x) ((x) << S_FW_FILTER_WR_DIRSTEER) +#define G_FW_FILTER_WR_DIRSTEER(x) \ + (((x) >> S_FW_FILTER_WR_DIRSTEER) & M_FW_FILTER_WR_DIRSTEER) +#define F_FW_FILTER_WR_DIRSTEER V_FW_FILTER_WR_DIRSTEER(1U) + +#define S_FW_FILTER_WR_MASKHASH 22 +#define M_FW_FILTER_WR_MASKHASH 0x1 +#define V_FW_FILTER_WR_MASKHASH(x) ((x) << S_FW_FILTER_WR_MASKHASH) +#define G_FW_FILTER_WR_MASKHASH(x) \ + (((x) >> S_FW_FILTER_WR_MASKHASH) & M_FW_FILTER_WR_MASKHASH) +#define F_FW_FILTER_WR_MASKHASH V_FW_FILTER_WR_MASKHASH(1U) + +#define S_FW_FILTER_WR_DIRSTEERHASH 21 +#define M_FW_FILTER_WR_DIRSTEERHASH 0x1 +#define V_FW_FILTER_WR_DIRSTEERHASH(x) ((x) << S_FW_FILTER_WR_DIRSTEERHASH) +#define G_FW_FILTER_WR_DIRSTEERHASH(x) \ + (((x) >> S_FW_FILTER_WR_DIRSTEERHASH) & M_FW_FILTER_WR_DIRSTEERHASH) +#define F_FW_FILTER_WR_DIRSTEERHASH V_FW_FILTER_WR_DIRSTEERHASH(1U) + +#define S_FW_FILTER_WR_LPBK 20 +#define M_FW_FILTER_WR_LPBK 0x1 +#define V_FW_FILTER_WR_LPBK(x) ((x) << S_FW_FILTER_WR_LPBK) +#define G_FW_FILTER_WR_LPBK(x) \ + (((x) >> S_FW_FILTER_WR_LPBK) & M_FW_FILTER_WR_LPBK) +#define F_FW_FILTER_WR_LPBK V_FW_FILTER_WR_LPBK(1U) + +#define S_FW_FILTER_WR_DMAC 19 +#define M_FW_FILTER_WR_DMAC 0x1 +#define V_FW_FILTER_WR_DMAC(x) ((x) << S_FW_FILTER_WR_DMAC) +#define G_FW_FILTER_WR_DMAC(x) \ + (((x) >> S_FW_FILTER_WR_DMAC) & M_FW_FILTER_WR_DMAC) +#define F_FW_FILTER_WR_DMAC V_FW_FILTER_WR_DMAC(1U) + +#define S_FW_FILTER_WR_SMAC 18 +#define M_FW_FILTER_WR_SMAC 0x1 +#define V_FW_FILTER_WR_SMAC(x) ((x) << S_FW_FILTER_WR_SMAC) +#define G_FW_FILTER_WR_SMAC(x) \ + (((x) >> S_FW_FILTER_WR_SMAC) & M_FW_FILTER_WR_SMAC) +#define F_FW_FILTER_WR_SMAC V_FW_FILTER_WR_SMAC(1U) + +#define S_FW_FILTER_WR_INSVLAN 17 +#define M_FW_FILTER_WR_INSVLAN 0x1 +#define V_FW_FILTER_WR_INSVLAN(x) ((x) << S_FW_FILTER_WR_INSVLAN) +#define G_FW_FILTER_WR_INSVLAN(x) \ + (((x) >> S_FW_FILTER_WR_INSVLAN) & M_FW_FILTER_WR_INSVLAN) +#define F_FW_FILTER_WR_INSVLAN V_FW_FILTER_WR_INSVLAN(1U) + +#define S_FW_FILTER_WR_RMVLAN 16 +#define M_FW_FILTER_WR_RMVLAN 0x1 +#define V_FW_FILTER_WR_RMVLAN(x) ((x) << S_FW_FILTER_WR_RMVLAN) +#define G_FW_FILTER_WR_RMVLAN(x) \ + (((x) >> S_FW_FILTER_WR_RMVLAN) & M_FW_FILTER_WR_RMVLAN) +#define F_FW_FILTER_WR_RMVLAN V_FW_FILTER_WR_RMVLAN(1U) + +#define S_FW_FILTER_WR_HITCNTS 15 +#define M_FW_FILTER_WR_HITCNTS 0x1 +#define V_FW_FILTER_WR_HITCNTS(x) ((x) << S_FW_FILTER_WR_HITCNTS) +#define G_FW_FILTER_WR_HITCNTS(x) \ + (((x) >> S_FW_FILTER_WR_HITCNTS) & M_FW_FILTER_WR_HITCNTS) +#define F_FW_FILTER_WR_HITCNTS V_FW_FILTER_WR_HITCNTS(1U) + +#define S_FW_FILTER_WR_TXCHAN 13 +#define M_FW_FILTER_WR_TXCHAN 0x3 +#define V_FW_FILTER_WR_TXCHAN(x) ((x) << S_FW_FILTER_WR_TXCHAN) +#define G_FW_FILTER_WR_TXCHAN(x) \ + (((x) >> S_FW_FILTER_WR_TXCHAN) & M_FW_FILTER_WR_TXCHAN) + +#define S_FW_FILTER_WR_PRIO 12 +#define M_FW_FILTER_WR_PRIO 0x1 +#define V_FW_FILTER_WR_PRIO(x) ((x) << S_FW_FILTER_WR_PRIO) +#define G_FW_FILTER_WR_PRIO(x) \ + (((x) >> S_FW_FILTER_WR_PRIO) & M_FW_FILTER_WR_PRIO) +#define F_FW_FILTER_WR_PRIO V_FW_FILTER_WR_PRIO(1U) + +#define S_FW_FILTER_WR_L2TIX 0 +#define M_FW_FILTER_WR_L2TIX 0xfff +#define V_FW_FILTER_WR_L2TIX(x) ((x) << S_FW_FILTER_WR_L2TIX) +#define G_FW_FILTER_WR_L2TIX(x) \ + (((x) >> S_FW_FILTER_WR_L2TIX) & M_FW_FILTER_WR_L2TIX) + +#define S_FW_FILTER_WR_FRAG 7 +#define M_FW_FILTER_WR_FRAG 0x1 +#define V_FW_FILTER_WR_FRAG(x) ((x) << S_FW_FILTER_WR_FRAG) +#define G_FW_FILTER_WR_FRAG(x) \ + (((x) >> S_FW_FILTER_WR_FRAG) & M_FW_FILTER_WR_FRAG) +#define F_FW_FILTER_WR_FRAG V_FW_FILTER_WR_FRAG(1U) + +#define S_FW_FILTER_WR_FRAGM 6 +#define M_FW_FILTER_WR_FRAGM 0x1 +#define V_FW_FILTER_WR_FRAGM(x) ((x) << S_FW_FILTER_WR_FRAGM) +#define G_FW_FILTER_WR_FRAGM(x) \ + (((x) >> S_FW_FILTER_WR_FRAGM) & M_FW_FILTER_WR_FRAGM) +#define F_FW_FILTER_WR_FRAGM V_FW_FILTER_WR_FRAGM(1U) + +#define S_FW_FILTER_WR_IVLAN_VLD 5 +#define M_FW_FILTER_WR_IVLAN_VLD 0x1 +#define V_FW_FILTER_WR_IVLAN_VLD(x) ((x) << S_FW_FILTER_WR_IVLAN_VLD) +#define G_FW_FILTER_WR_IVLAN_VLD(x) \ + (((x) >> S_FW_FILTER_WR_IVLAN_VLD) & M_FW_FILTER_WR_IVLAN_VLD) +#define F_FW_FILTER_WR_IVLAN_VLD V_FW_FILTER_WR_IVLAN_VLD(1U) + +#define S_FW_FILTER_WR_OVLAN_VLD 4 +#define M_FW_FILTER_WR_OVLAN_VLD 0x1 +#define V_FW_FILTER_WR_OVLAN_VLD(x) ((x) << S_FW_FILTER_WR_OVLAN_VLD) +#define G_FW_FILTER_WR_OVLAN_VLD(x) \ + (((x) >> S_FW_FILTER_WR_OVLAN_VLD) & M_FW_FILTER_WR_OVLAN_VLD) +#define F_FW_FILTER_WR_OVLAN_VLD V_FW_FILTER_WR_OVLAN_VLD(1U) + +#define S_FW_FILTER_WR_IVLAN_VLDM 3 +#define M_FW_FILTER_WR_IVLAN_VLDM 0x1 +#define V_FW_FILTER_WR_IVLAN_VLDM(x) ((x) << S_FW_FILTER_WR_IVLAN_VLDM) +#define G_FW_FILTER_WR_IVLAN_VLDM(x) \ + (((x) >> S_FW_FILTER_WR_IVLAN_VLDM) & M_FW_FILTER_WR_IVLAN_VLDM) +#define F_FW_FILTER_WR_IVLAN_VLDM V_FW_FILTER_WR_IVLAN_VLDM(1U) + +#define S_FW_FILTER_WR_OVLAN_VLDM 2 +#define M_FW_FILTER_WR_OVLAN_VLDM 0x1 +#define V_FW_FILTER_WR_OVLAN_VLDM(x) ((x) << S_FW_FILTER_WR_OVLAN_VLDM) +#define G_FW_FILTER_WR_OVLAN_VLDM(x) \ + (((x) >> S_FW_FILTER_WR_OVLAN_VLDM) & M_FW_FILTER_WR_OVLAN_VLDM) +#define F_FW_FILTER_WR_OVLAN_VLDM V_FW_FILTER_WR_OVLAN_VLDM(1U) + +#define S_FW_FILTER_WR_RX_CHAN 15 +#define M_FW_FILTER_WR_RX_CHAN 0x1 +#define V_FW_FILTER_WR_RX_CHAN(x) ((x) << S_FW_FILTER_WR_RX_CHAN) +#define G_FW_FILTER_WR_RX_CHAN(x) \ + (((x) >> S_FW_FILTER_WR_RX_CHAN) & M_FW_FILTER_WR_RX_CHAN) +#define F_FW_FILTER_WR_RX_CHAN V_FW_FILTER_WR_RX_CHAN(1U) + +#define S_FW_FILTER_WR_RX_RPL_IQ 0 +#define M_FW_FILTER_WR_RX_RPL_IQ 0x3ff +#define V_FW_FILTER_WR_RX_RPL_IQ(x) ((x) << S_FW_FILTER_WR_RX_RPL_IQ) +#define G_FW_FILTER_WR_RX_RPL_IQ(x) \ + (((x) >> S_FW_FILTER_WR_RX_RPL_IQ) & M_FW_FILTER_WR_RX_RPL_IQ) + +#define S_FW_FILTER_WR_MACI 23 +#define M_FW_FILTER_WR_MACI 0x1ff +#define V_FW_FILTER_WR_MACI(x) ((x) << S_FW_FILTER_WR_MACI) +#define G_FW_FILTER_WR_MACI(x) \ + (((x) >> S_FW_FILTER_WR_MACI) & M_FW_FILTER_WR_MACI) + +#define S_FW_FILTER_WR_MACIM 14 +#define M_FW_FILTER_WR_MACIM 0x1ff +#define V_FW_FILTER_WR_MACIM(x) ((x) << S_FW_FILTER_WR_MACIM) +#define G_FW_FILTER_WR_MACIM(x) \ + (((x) >> S_FW_FILTER_WR_MACIM) & M_FW_FILTER_WR_MACIM) + +#define S_FW_FILTER_WR_FCOE 13 +#define M_FW_FILTER_WR_FCOE 0x1 +#define V_FW_FILTER_WR_FCOE(x) ((x) << S_FW_FILTER_WR_FCOE) +#define G_FW_FILTER_WR_FCOE(x) \ + (((x) >> S_FW_FILTER_WR_FCOE) & M_FW_FILTER_WR_FCOE) +#define F_FW_FILTER_WR_FCOE V_FW_FILTER_WR_FCOE(1U) + +#define S_FW_FILTER_WR_FCOEM 12 +#define M_FW_FILTER_WR_FCOEM 0x1 +#define V_FW_FILTER_WR_FCOEM(x) ((x) << S_FW_FILTER_WR_FCOEM) +#define G_FW_FILTER_WR_FCOEM(x) \ + (((x) >> S_FW_FILTER_WR_FCOEM) & M_FW_FILTER_WR_FCOEM) +#define F_FW_FILTER_WR_FCOEM V_FW_FILTER_WR_FCOEM(1U) + +#define S_FW_FILTER_WR_PORT 9 +#define M_FW_FILTER_WR_PORT 0x7 +#define V_FW_FILTER_WR_PORT(x) ((x) << S_FW_FILTER_WR_PORT) +#define G_FW_FILTER_WR_PORT(x) \ + (((x) >> S_FW_FILTER_WR_PORT) & M_FW_FILTER_WR_PORT) + +#define S_FW_FILTER_WR_PORTM 6 +#define M_FW_FILTER_WR_PORTM 0x7 +#define V_FW_FILTER_WR_PORTM(x) ((x) << S_FW_FILTER_WR_PORTM) +#define G_FW_FILTER_WR_PORTM(x) \ + (((x) >> S_FW_FILTER_WR_PORTM) & M_FW_FILTER_WR_PORTM) + +#define S_FW_FILTER_WR_MATCHTYPE 3 +#define M_FW_FILTER_WR_MATCHTYPE 0x7 +#define V_FW_FILTER_WR_MATCHTYPE(x) ((x) << S_FW_FILTER_WR_MATCHTYPE) +#define G_FW_FILTER_WR_MATCHTYPE(x) \ + (((x) >> S_FW_FILTER_WR_MATCHTYPE) & M_FW_FILTER_WR_MATCHTYPE) + +#define S_FW_FILTER_WR_MATCHTYPEM 0 +#define M_FW_FILTER_WR_MATCHTYPEM 0x7 +#define V_FW_FILTER_WR_MATCHTYPEM(x) ((x) << S_FW_FILTER_WR_MATCHTYPEM) +#define G_FW_FILTER_WR_MATCHTYPEM(x) \ + (((x) >> S_FW_FILTER_WR_MATCHTYPEM) & M_FW_FILTER_WR_MATCHTYPEM) struct fw_ulptx_wr { __be32 op_to_compl; @@ -99,6 +416,108 @@ struct fw_eth_tx_pkt_wr { __be64 r3; }; +struct fw_ofld_connection_wr { + __be32 op_compl; + __be32 len16_pkd; + __u64 cookie; + __be64 r2; + __be64 r3; + struct fw_ofld_connection_le { + __be32 version_cpl; + __be32 filter; + __be32 r1; + __be16 lport; + __be16 pport; + union fw_ofld_connection_leip { + struct fw_ofld_connection_le_ipv4 { + __be32 pip; + __be32 lip; + __be64 r0; + __be64 r1; + __be64 r2; + } ipv4; + struct fw_ofld_connection_le_ipv6 { + __be64 pip_hi; + __be64 pip_lo; + __be64 lip_hi; + __be64 lip_lo; + } ipv6; + } u; + } le; + struct fw_ofld_connection_tcb { + __be32 t_state_to_astid; + __be16 cplrxdataack_cplpassacceptrpl; + __be16 rcv_adv; + __be32 rcv_nxt; + __be32 tx_max; + __be64 opt0; + __be32 opt2; + __be32 r1; + __be64 r2; + __be64 r3; + } tcb; +}; + +#define S_FW_OFLD_CONNECTION_WR_VERSION 31 +#define M_FW_OFLD_CONNECTION_WR_VERSION 0x1 +#define V_FW_OFLD_CONNECTION_WR_VERSION(x) \ + ((x) << S_FW_OFLD_CONNECTION_WR_VERSION) +#define G_FW_OFLD_CONNECTION_WR_VERSION(x) \ + (((x) >> S_FW_OFLD_CONNECTION_WR_VERSION) & \ + M_FW_OFLD_CONNECTION_WR_VERSION) +#define F_FW_OFLD_CONNECTION_WR_VERSION \ + V_FW_OFLD_CONNECTION_WR_VERSION(1U) + +#define S_FW_OFLD_CONNECTION_WR_CPL 30 +#define M_FW_OFLD_CONNECTION_WR_CPL 0x1 +#define V_FW_OFLD_CONNECTION_WR_CPL(x) ((x) << S_FW_OFLD_CONNECTION_WR_CPL) +#define G_FW_OFLD_CONNECTION_WR_CPL(x) \ + (((x) >> S_FW_OFLD_CONNECTION_WR_CPL) & M_FW_OFLD_CONNECTION_WR_CPL) +#define F_FW_OFLD_CONNECTION_WR_CPL V_FW_OFLD_CONNECTION_WR_CPL(1U) + +#define S_FW_OFLD_CONNECTION_WR_T_STATE 28 +#define M_FW_OFLD_CONNECTION_WR_T_STATE 0xf +#define V_FW_OFLD_CONNECTION_WR_T_STATE(x) \ + ((x) << S_FW_OFLD_CONNECTION_WR_T_STATE) +#define G_FW_OFLD_CONNECTION_WR_T_STATE(x) \ + (((x) >> S_FW_OFLD_CONNECTION_WR_T_STATE) & \ + M_FW_OFLD_CONNECTION_WR_T_STATE) + +#define S_FW_OFLD_CONNECTION_WR_RCV_SCALE 24 +#define M_FW_OFLD_CONNECTION_WR_RCV_SCALE 0xf +#define V_FW_OFLD_CONNECTION_WR_RCV_SCALE(x) \ + ((x) << S_FW_OFLD_CONNECTION_WR_RCV_SCALE) +#define G_FW_OFLD_CONNECTION_WR_RCV_SCALE(x) \ + (((x) >> S_FW_OFLD_CONNECTION_WR_RCV_SCALE) & \ + M_FW_OFLD_CONNECTION_WR_RCV_SCALE) + +#define S_FW_OFLD_CONNECTION_WR_ASTID 0 +#define M_FW_OFLD_CONNECTION_WR_ASTID 0xffffff +#define V_FW_OFLD_CONNECTION_WR_ASTID(x) \ + ((x) << S_FW_OFLD_CONNECTION_WR_ASTID) +#define G_FW_OFLD_CONNECTION_WR_ASTID(x) \ + (((x) >> S_FW_OFLD_CONNECTION_WR_ASTID) & M_FW_OFLD_CONNECTION_WR_ASTID) + +#define S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK 15 +#define M_FW_OFLD_CONNECTION_WR_CPLRXDATAACK 0x1 +#define V_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(x) \ + ((x) << S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) +#define G_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(x) \ + (((x) >> S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) & \ + M_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) +#define F_FW_OFLD_CONNECTION_WR_CPLRXDATAACK \ + V_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(1U) + +#define S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL 14 +#define M_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL 0x1 +#define V_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(x) \ + ((x) << S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) +#define G_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(x) \ + (((x) >> S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) & \ + M_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) +#define F_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL \ + V_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(1U) + enum fw_flowc_mnem { FW_FLOWC_MNEM_PFNVFN, /* PFN [15:8] VFN [7:0] */ FW_FLOWC_MNEM_CH, @@ -222,6 +641,7 @@ struct fw_cmd_hdr { #define FW_CMD_OP(x) ((x) << 24) #define FW_CMD_OP_GET(x) (((x) >> 24) & 0xff) #define FW_CMD_REQUEST (1U << 23) +#define FW_CMD_REQUEST_GET(x) (((x) >> 23) & 0x1) #define FW_CMD_READ (1U << 22) #define FW_CMD_WRITE (1U << 21) #define FW_CMD_EXEC (1U << 20) @@ -229,6 +649,7 @@ struct fw_cmd_hdr { #define FW_CMD_RETVAL(x) ((x) << 8) #define FW_CMD_RETVAL_GET(x) (((x) >> 8) & 0xff) #define FW_CMD_LEN16(x) ((x) << 0) +#define FW_LEN16(fw_struct) FW_CMD_LEN16(sizeof(fw_struct) / 16) enum fw_ldst_addrspc { FW_LDST_ADDRSPC_FIRMWARE = 0x0001, @@ -241,7 +662,8 @@ enum fw_ldst_addrspc { FW_LDST_ADDRSPC_TP_MIB = 0x0012, FW_LDST_ADDRSPC_MDIO = 0x0018, FW_LDST_ADDRSPC_MPS = 0x0020, - FW_LDST_ADDRSPC_FUNC = 0x0028 + FW_LDST_ADDRSPC_FUNC = 0x0028, + FW_LDST_ADDRSPC_FUNC_PCIE = 0x0029, }; enum fw_ldst_mps_fid { @@ -303,6 +725,16 @@ struct fw_ldst_cmd { __be64 data0; __be64 data1; } func; + struct fw_ldst_pcie { + u8 ctrl_to_fn; + u8 bnum; + u8 r; + u8 ext_r; + u8 select_naccess; + u8 pcie_fn; + __be16 nset_pkd; + __be32 data[12]; + } pcie; } u; }; @@ -312,6 +744,9 @@ struct fw_ldst_cmd { #define FW_LDST_CMD_FID(x) ((x) << 15) #define FW_LDST_CMD_CTL(x) ((x) << 0) #define FW_LDST_CMD_RPLCPF(x) ((x) << 0) +#define FW_LDST_CMD_LC (1U << 4) +#define FW_LDST_CMD_NACCESS(x) ((x) << 0) +#define FW_LDST_CMD_FN(x) ((x) << 0) struct fw_reset_cmd { __be32 op_to_write; @@ -333,7 +768,7 @@ enum fw_hellow_cmd { struct fw_hello_cmd { __be32 op_to_write; __be32 retval_len16; - __be32 err_to_mbasyncnot; + __be32 err_to_clearinit; #define FW_HELLO_CMD_ERR (1U << 31) #define FW_HELLO_CMD_INIT (1U << 30) #define FW_HELLO_CMD_MASTERDIS(x) ((x) << 29) @@ -343,6 +778,7 @@ struct fw_hello_cmd { #define FW_HELLO_CMD_MBMASTER(x) ((x) << FW_HELLO_CMD_MBMASTER_SHIFT) #define FW_HELLO_CMD_MBMASTER_GET(x) \ (((x) >> FW_HELLO_CMD_MBMASTER_SHIFT) & FW_HELLO_CMD_MBMASTER_MASK) +#define FW_HELLO_CMD_MBASYNCNOTINT(x) ((x) << 23) #define FW_HELLO_CMD_MBASYNCNOT(x) ((x) << 20) #define FW_HELLO_CMD_STAGE(x) ((x) << 17) #define FW_HELLO_CMD_CLEARINIT (1U << 16) @@ -428,6 +864,7 @@ enum fw_caps_config_iscsi { enum fw_caps_config_fcoe { FW_CAPS_CONFIG_FCOE_INITIATOR = 0x00000001, FW_CAPS_CONFIG_FCOE_TARGET = 0x00000002, + FW_CAPS_CONFIG_FCOE_CTRL_OFLD = 0x00000004, }; enum fw_memtype_cf { @@ -440,7 +877,7 @@ enum fw_memtype_cf { struct fw_caps_config_cmd { __be32 op_to_write; - __be32 retval_len16; + __be32 cfvalid_to_len16; __be32 r2; __be32 hwmbitmap; __be16 nbmcaps; @@ -701,8 +1138,8 @@ struct fw_iq_cmd { #define FW_IQ_CMD_FL0FETCHRO(x) ((x) << 6) #define FW_IQ_CMD_FL0HOSTFCMODE(x) ((x) << 4) #define FW_IQ_CMD_FL0CPRIO(x) ((x) << 3) -#define FW_IQ_CMD_FL0PADEN (1U << 2) -#define FW_IQ_CMD_FL0PACKEN (1U << 1) +#define FW_IQ_CMD_FL0PADEN(x) ((x) << 2) +#define FW_IQ_CMD_FL0PACKEN(x) ((x) << 1) #define FW_IQ_CMD_FL0CONGEN (1U << 0) #define FW_IQ_CMD_FL0DCAEN(x) ((x) << 15) @@ -1190,6 +1627,14 @@ enum fw_port_dcb_cfg_rc { FW_PORT_DCB_CFG_ERROR = 0x1 }; +enum fw_port_dcb_type { + FW_PORT_DCB_TYPE_PGID = 0x00, + FW_PORT_DCB_TYPE_PGRATE = 0x01, + FW_PORT_DCB_TYPE_PRIORATE = 0x02, + FW_PORT_DCB_TYPE_PFC = 0x03, + FW_PORT_DCB_TYPE_APP_ID = 0x04, +}; + struct fw_port_cmd { __be32 op_to_portid; __be32 action_to_len16; @@ -1257,6 +1702,7 @@ struct fw_port_cmd { #define FW_PORT_CMD_TXIPG(x) ((x) << 19) #define FW_PORT_CMD_LSTATUS (1U << 31) +#define FW_PORT_CMD_LSTATUS_GET(x) (((x) >> 31) & 0x1) #define FW_PORT_CMD_LSPEED(x) ((x) << 24) #define FW_PORT_CMD_LSPEED_GET(x) (((x) >> 24) & 0x3f) #define FW_PORT_CMD_TXPAUSE (1U << 23) @@ -1305,6 +1751,9 @@ enum fw_port_module_type { FW_PORT_MOD_TYPE_TWINAX_PASSIVE, FW_PORT_MOD_TYPE_TWINAX_ACTIVE, FW_PORT_MOD_TYPE_LRM, + FW_PORT_MOD_TYPE_ERROR = FW_PORT_CMD_MODTYPE_MASK - 3, + FW_PORT_MOD_TYPE_UNKNOWN = FW_PORT_CMD_MODTYPE_MASK - 2, + FW_PORT_MOD_TYPE_NOTSUPPORTED = FW_PORT_CMD_MODTYPE_MASK - 1, FW_PORT_MOD_TYPE_NONE = FW_PORT_CMD_MODTYPE_MASK }; diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 9dad56101e23..0188df705719 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -2023,7 +2023,7 @@ static struct cxgb4vf_debugfs_entry debugfs_files[] = { * Set up out /sys/kernel/debug/cxgb4vf sub-nodes. We assume that the * directory (debugfs_root) has already been set up. */ -static int __devinit setup_debugfs(struct adapter *adapter) +static int setup_debugfs(struct adapter *adapter) { int i; @@ -2064,7 +2064,7 @@ static void cleanup_debugfs(struct adapter *adapter) * adapter parameters we're going to be using and initialize basic adapter * hardware support. */ -static int __devinit adap_init0(struct adapter *adapter) +static int adap_init0(struct adapter *adapter) { struct vf_resources *vfres = &adapter->params.vfres; struct sge_params *sge_params = &adapter->params.sge; @@ -2266,7 +2266,7 @@ static inline void init_rspq(struct sge_rspq *rspq, u8 timer_idx, * be modified by the admin via ethtool and cxgbtool prior to the adapter * being brought up for the first time. */ -static void __devinit cfg_queues(struct adapter *adapter) +static void cfg_queues(struct adapter *adapter) { struct sge *s = &adapter->sge; int q10g, n10g, qidx, pidx, qs; @@ -2361,7 +2361,7 @@ static void __devinit cfg_queues(struct adapter *adapter) * Reduce the number of Ethernet queues across all ports to at most n. * n provides at least one queue per port. */ -static void __devinit reduce_ethqs(struct adapter *adapter, int n) +static void reduce_ethqs(struct adapter *adapter, int n) { int i; struct port_info *pi; @@ -2400,7 +2400,7 @@ static void __devinit reduce_ethqs(struct adapter *adapter, int n) * for our "extras". Note that this process may lower the maximum number of * allowed Queue Sets ... */ -static int __devinit enable_msix(struct adapter *adapter) +static int enable_msix(struct adapter *adapter) { int i, err, want, need; struct msix_entry entries[MSIX_ENTRIES]; @@ -2462,8 +2462,8 @@ static const struct net_device_ops cxgb4vf_netdev_ops = { * state needed to manage the device. This routine is called "init_one" in * the PF Driver ... */ -static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int cxgb4vf_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { static int version_printed; @@ -2769,7 +2769,7 @@ err_disable_device: * "probe" routine and quiesce the device (disable interrupts, etc.). (Note * that this is called "remove_one" in the PF Driver.) */ -static void __devexit cxgb4vf_pci_remove(struct pci_dev *pdev) +static void cxgb4vf_pci_remove(struct pci_dev *pdev) { struct adapter *adapter = pci_get_drvdata(pdev); @@ -2835,7 +2835,7 @@ static void __devexit cxgb4vf_pci_remove(struct pci_dev *pdev) * "Shutdown" quiesce the device, stopping Ingress Packet and Interrupt * delivery. */ -static void __devexit cxgb4vf_pci_shutdown(struct pci_dev *pdev) +static void cxgb4vf_pci_shutdown(struct pci_dev *pdev) { struct adapter *adapter; int pidx; @@ -2905,8 +2905,8 @@ static struct pci_driver cxgb4vf_driver = { .name = KBUILD_MODNAME, .id_table = cxgb4vf_pci_tbl, .probe = cxgb4vf_pci_probe, - .remove = __devexit_p(cxgb4vf_pci_remove), - .shutdown = __devexit_p(cxgb4vf_pci_shutdown), + .remove = cxgb4vf_pci_remove, + .shutdown = cxgb4vf_pci_shutdown, }; /* diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index f16745f4b36b..92170d50d9d8 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c @@ -536,7 +536,7 @@ static inline void ring_fl_db(struct adapter *adapter, struct sge_fl *fl) if (fl->pend_cred >= FL_PER_EQ_UNIT) { wmb(); t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL, - DBPRIO | + DBPRIO(1) | QID(fl->cntxt_id) | PIDX(fl->pend_cred / FL_PER_EQ_UNIT)); fl->pend_cred %= FL_PER_EQ_UNIT; @@ -952,7 +952,7 @@ static inline void ring_tx_db(struct adapter *adapter, struct sge_txq *tq, * Warn if we write doorbells with the wrong priority and write * descriptors before telling HW. */ - WARN_ON((QID(tq->cntxt_id) | PIDX(n)) & DBPRIO); + WARN_ON((QID(tq->cntxt_id) | PIDX(n)) & DBPRIO(1)); wmb(); t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL, QID(tq->cntxt_id) | PIDX(n)); @@ -2126,8 +2126,8 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq, cmd.iqns_to_fl0congen = cpu_to_be32( FW_IQ_CMD_FL0HOSTFCMODE(SGE_HOSTFCMODE_NONE) | - FW_IQ_CMD_FL0PACKEN | - FW_IQ_CMD_FL0PADEN); + FW_IQ_CMD_FL0PACKEN(1) | + FW_IQ_CMD_FL0PADEN(1)); cmd.fl0dcaen_to_fl0cidxfthresh = cpu_to_be16( FW_IQ_CMD_FL0FBMIN(SGE_FETCHBURSTMIN_64B) | diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h index a65c80aed1f2..283f9d0d37fd 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h @@ -232,8 +232,8 @@ static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd, return t4vf_wr_mbox_core(adapter, cmd, size, rpl, false); } -int __devinit t4vf_wait_dev_ready(struct adapter *); -int __devinit t4vf_port_init(struct adapter *, int); +int t4vf_wait_dev_ready(struct adapter *); +int t4vf_port_init(struct adapter *, int); int t4vf_fw_reset(struct adapter *); int t4vf_query_params(struct adapter *, unsigned int, const u32 *, u32 *); diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c index fe3fd3dad6f7..7127c7b9efde 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c @@ -46,7 +46,7 @@ * returning a value other than all 1's). Return an error if it doesn't * become ready ... */ -int __devinit t4vf_wait_dev_ready(struct adapter *adapter) +int t4vf_wait_dev_ready(struct adapter *adapter) { const u32 whoami = T4VF_PL_BASE_ADDR + PL_VF_WHOAMI; const u32 notready1 = 0xffffffff; @@ -253,8 +253,7 @@ static int hash_mac_addr(const u8 *addr) * Initializes the SW state maintained for each link, including the link's * capabilities and default speed/flow-control/autonegotiation settings. */ -static void __devinit init_link_config(struct link_config *lc, - unsigned int caps) +static void init_link_config(struct link_config *lc, unsigned int caps) { lc->supported = caps; lc->requested_speed = 0; @@ -275,7 +274,7 @@ static void __devinit init_link_config(struct link_config *lc, * @adapter: the adapter * @pidx: the adapter port index */ -int __devinit t4vf_port_init(struct adapter *adapter, int pidx) +int t4vf_port_init(struct adapter *adapter, int pidx) { struct port_info *pi = adap2pinfo(adapter, pidx); struct fw_vi_cmd vi_cmd, vi_rpl; diff --git a/drivers/net/ethernet/cisco/Kconfig b/drivers/net/ethernet/cisco/Kconfig index 94606f7ee13a..1c7b884e3371 100644 --- a/drivers/net/ethernet/cisco/Kconfig +++ b/drivers/net/ethernet/cisco/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_CISCO bool "Cisco devices" default y - depends on PCI && INET + depends on PCI ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from diff --git a/drivers/net/ethernet/cisco/enic/Kconfig b/drivers/net/ethernet/cisco/enic/Kconfig index 9cc706a6cffd..b63f8d8a4261 100644 --- a/drivers/net/ethernet/cisco/enic/Kconfig +++ b/drivers/net/ethernet/cisco/enic/Kconfig @@ -4,6 +4,6 @@ config ENIC tristate "Cisco VIC Ethernet NIC Support" - depends on PCI && INET + depends on PCI ---help--- This enables the support for the Cisco VIC Ethernet card. diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index ad1468b3ab91..64866ff1aea0 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -2275,8 +2275,7 @@ static void enic_iounmap(struct enic *enic) iounmap(enic->bar[i].vaddr); } -static int __devinit enic_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct device *dev = &pdev->dev; struct net_device *netdev; @@ -2552,7 +2551,7 @@ err_out_free_netdev: return err; } -static void __devexit enic_remove(struct pci_dev *pdev) +static void enic_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -2584,7 +2583,7 @@ static struct pci_driver enic_driver = { .name = DRV_NAME, .id_table = enic_id_table, .probe = enic_probe, - .remove = __devexit_p(enic_remove), + .remove = enic_remove, }; static int __init enic_init_module(void) diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 36499d5edd95..c73472c369cd 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -193,35 +193,35 @@ iow(board_info_t * db, int reg, int value) static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count) { - writesb(reg, data, count); + iowrite8_rep(reg, data, count); } static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count) { - writesw(reg, data, (count+1) >> 1); + iowrite16_rep(reg, data, (count+1) >> 1); } static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count) { - writesl(reg, data, (count+3) >> 2); + iowrite32_rep(reg, data, (count+3) >> 2); } /* input block from chip to memory */ static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count) { - readsb(reg, data, count); + ioread8_rep(reg, data, count); } static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count) { - readsw(reg, data, (count+1) >> 1); + ioread16_rep(reg, data, (count+1) >> 1); } static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count) { - readsl(reg, data, (count+3) >> 2); + ioread32_rep(reg, data, (count+3) >> 2); } /* dump block from chip to null */ @@ -1359,7 +1359,7 @@ static const struct net_device_ops dm9000_netdev_ops = { /* * Search DM9000 board, allocate space and register it */ -static int __devinit +static int dm9000_probe(struct platform_device *pdev) { struct dm9000_plat_data *pdata = pdev->dev.platform_data; @@ -1661,7 +1661,7 @@ static const struct dev_pm_ops dm9000_drv_pm_ops = { .resume = dm9000_drv_resume, }; -static int __devexit +static int dm9000_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); @@ -1683,7 +1683,7 @@ static struct platform_driver dm9000_driver = { .pm = &dm9000_drv_pm_ops, }, .probe = dm9000_probe, - .remove = __devexit_p(dm9000_drv_remove), + .remove = dm9000_drv_remove, }; static int __init diff --git a/drivers/net/ethernet/dec/ewrk3.c b/drivers/net/ethernet/dec/ewrk3.c index 17ae8c619680..9f992b95eddc 100644 --- a/drivers/net/ethernet/dec/ewrk3.c +++ b/drivers/net/ethernet/dec/ewrk3.c @@ -1910,9 +1910,8 @@ static struct net_device *ewrk3_devs[MAX_NUM_EWRK3S]; static int ndevs; static int io[MAX_NUM_EWRK3S+1] = { 0x300, 0, }; -/* '21' below should really be 'MAX_NUM_EWRK3S' */ module_param_array(io, int, NULL, 0); -module_param_array(irq, int, NULL, 0); +module_param_array(irq, byte, NULL, 0); MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)"); MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)"); diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c index 77335853ac36..eaab73cf27ca 100644 --- a/drivers/net/ethernet/dec/tulip/de2104x.c +++ b/drivers/net/ethernet/dec/tulip/de2104x.c @@ -1700,7 +1700,7 @@ static const struct ethtool_ops de_ethtool_ops = { .get_regs = de_get_regs, }; -static void __devinit de21040_get_mac_address (struct de_private *de) +static void de21040_get_mac_address(struct de_private *de) { unsigned i; @@ -1721,7 +1721,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de) } } -static void __devinit de21040_get_media_info(struct de_private *de) +static void de21040_get_media_info(struct de_private *de) { unsigned int i; @@ -1748,7 +1748,8 @@ static void __devinit de21040_get_media_info(struct de_private *de) } /* Note: this routine returns extra data bits for size detection. */ -static unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, int addr_len) +static unsigned tulip_read_eeprom(void __iomem *regs, int location, + int addr_len) { int i; unsigned retval = 0; @@ -1783,7 +1784,7 @@ static unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, in return retval; } -static void __devinit de21041_get_srom_info (struct de_private *de) +static void de21041_get_srom_info(struct de_private *de) { unsigned i, sa_offset = 0, ofs; u8 ee_data[DE_EEPROM_SIZE + 6] = {}; @@ -1961,8 +1962,7 @@ static const struct net_device_ops de_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit de_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int de_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; struct de_private *de; @@ -2099,7 +2099,7 @@ err_out_free: return rc; } -static void __devexit de_remove_one (struct pci_dev *pdev) +static void de_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct de_private *de = netdev_priv(dev); @@ -2184,7 +2184,7 @@ static struct pci_driver de_driver = { .name = DRV_NAME, .id_table = de_pci_tbl, .probe = de_init_one, - .remove = __devexit_p(de_remove_one), + .remove = de_remove_one, #ifdef CONFIG_PM .suspend = de_suspend, .resume = de_resume, diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c index f879e9224846..4c830030fb06 100644 --- a/drivers/net/ethernet/dec/tulip/de4x5.c +++ b/drivers/net/ethernet/dec/tulip/de4x5.c @@ -479,7 +479,7 @@ #include "de4x5.h" -static const char version[] __devinitconst = +static const char version[] = KERN_INFO "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n"; #define c_char const char @@ -1092,7 +1092,7 @@ static const struct net_device_ops de4x5_netdev_ops = { }; -static int __devinit +static int de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) { char name[DE4X5_NAME_LENGTH + 1]; @@ -2077,7 +2077,7 @@ static int __init de4x5_eisa_probe (struct device *gendev) return status; } -static int __devexit de4x5_eisa_remove (struct device *device) +static int de4x5_eisa_remove(struct device *device) { struct net_device *dev; u_long iobase; @@ -2104,7 +2104,7 @@ static struct eisa_driver de4x5_eisa_driver = { .driver = { .name = "de4x5", .probe = de4x5_eisa_probe, - .remove = __devexit_p (de4x5_eisa_remove), + .remove = de4x5_eisa_remove, } }; MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids); @@ -2118,7 +2118,7 @@ MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids); ** DECchips, we can find the base SROM irrespective of the BIOS scan direction. ** For single port cards this is a time waster... */ -static void __devinit +static void srom_search(struct net_device *dev, struct pci_dev *pdev) { u_char pb; @@ -2192,8 +2192,8 @@ srom_search(struct net_device *dev, struct pci_dev *pdev) ** kernels use the V0.535[n] drivers. */ -static int __devinit de4x5_pci_probe (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int de4x5_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { u_char pb, pbus = 0, dev_num, dnum = 0, timer; u_short vendor, status; @@ -2314,7 +2314,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev, return error; } -static void __devexit de4x5_pci_remove (struct pci_dev *pdev) +static void de4x5_pci_remove(struct pci_dev *pdev) { struct net_device *dev; u_long iobase; @@ -2344,7 +2344,7 @@ static struct pci_driver de4x5_pci_driver = { .name = "de4x5", .id_table = de4x5_pci_tbl, .probe = de4x5_pci_probe, - .remove = __devexit_p (de4x5_pci_remove), + .remove = de4x5_pci_remove, }; #endif diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c index d23755ea9bc7..83139307861c 100644 --- a/drivers/net/ethernet/dec/tulip/dmfe.c +++ b/drivers/net/ethernet/dec/tulip/dmfe.c @@ -291,8 +291,8 @@ enum dmfe_CR6_bits { }; /* Global variable declaration ----------------------------- */ -static int __devinitdata printed_version; -static const char version[] __devinitconst = +static int printed_version; +static const char version[] = "Davicom DM9xxx net driver, version " DRV_VERSION " (" DRV_RELDATE ")"; static int dmfe_debug; @@ -367,8 +367,7 @@ static const struct net_device_ops netdev_ops = { * Search DM910X board ,allocate space and register it */ -static int __devinit dmfe_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int dmfe_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct dmfe_board_info *db; /* board information structure */ struct net_device *dev; @@ -531,7 +530,7 @@ err_out_free: } -static void __devexit dmfe_remove_one (struct pci_dev *pdev) +static void dmfe_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct dmfe_board_info *db = netdev_priv(dev); @@ -2187,7 +2186,7 @@ static struct pci_driver dmfe_driver = { .name = "dmfe", .id_table = dmfe_pci_tbl, .probe = dmfe_init_one, - .remove = __devexit_p(dmfe_remove_one), + .remove = dmfe_remove_one, .suspend = dmfe_suspend, .resume = dmfe_resume }; diff --git a/drivers/net/ethernet/dec/tulip/eeprom.c b/drivers/net/ethernet/dec/tulip/eeprom.c index 44f7e8e82d85..df5a892fb49c 100644 --- a/drivers/net/ethernet/dec/tulip/eeprom.c +++ b/drivers/net/ethernet/dec/tulip/eeprom.c @@ -26,7 +26,7 @@ */ /* Known cards that have old-style EEPROMs. */ -static struct eeprom_fixup eeprom_fixups[] __devinitdata = { +static struct eeprom_fixup eeprom_fixups[] = { {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c, 0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }}, {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f, @@ -79,7 +79,7 @@ static struct eeprom_fixup eeprom_fixups[] __devinitdata = { {NULL}}; -static const char *const block_name[] __devinitconst = { +static const char *const block_name[] = { "21140 non-MII", "21140 MII PHY", "21142 Serial PHY", @@ -102,7 +102,7 @@ static const char *const block_name[] __devinitconst = { * #ifdef __hppa__ should completely optimize this function away for * non-parisc hardware. */ -static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp) +static void tulip_build_fake_mediatable(struct tulip_private *tp) { #ifdef CONFIG_GSC if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) { @@ -140,7 +140,7 @@ static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp) #endif } -void __devinit tulip_parse_eeprom(struct net_device *dev) +void tulip_parse_eeprom(struct net_device *dev) { /* dev is not registered at this point, so logging messages can't @@ -339,7 +339,7 @@ subsequent_board: #define EE_READ_CMD (6) /* Note: this routine returns extra data bits for size detection. */ -int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len) +int tulip_read_eeprom(struct net_device *dev, int location, int addr_len) { int i; unsigned retval = 0; diff --git a/drivers/net/ethernet/dec/tulip/media.c b/drivers/net/ethernet/dec/tulip/media.c index ae937c6749e7..93a4afaa09f1 100644 --- a/drivers/net/ethernet/dec/tulip/media.c +++ b/drivers/net/ethernet/dec/tulip/media.c @@ -447,7 +447,7 @@ int tulip_check_duplex(struct net_device *dev) return 0; } -void __devinit tulip_find_mii (struct net_device *dev, int board_idx) +void tulip_find_mii(struct net_device *dev, int board_idx) { struct tulip_private *tp = netdev_priv(dev); int phyn, phy_idx = 0; diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c index 885700a19978..1e9443d9fb57 100644 --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c @@ -37,7 +37,7 @@ #include <asm/prom.h> #endif -static char version[] __devinitdata = +static char version[] = "Linux Tulip driver version " DRV_VERSION " (" DRV_RELDATE ")\n"; /* A few user-configurable values. */ @@ -1191,8 +1191,7 @@ static void set_rx_mode(struct net_device *dev) } #ifdef CONFIG_TULIP_MWI -static void __devinit tulip_mwi_config (struct pci_dev *pdev, - struct net_device *dev) +static void tulip_mwi_config(struct pci_dev *pdev, struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); u8 cache; @@ -1301,8 +1300,7 @@ DEFINE_PCI_DEVICE_TABLE(early_486_chipsets) = { { }, }; -static int __devinit tulip_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct tulip_private *tp; /* See note below on the multiport cards. */ @@ -1927,7 +1925,7 @@ static int tulip_resume(struct pci_dev *pdev) #endif /* CONFIG_PM */ -static void __devexit tulip_remove_one (struct pci_dev *pdev) +static void tulip_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); struct tulip_private *tp; @@ -1974,7 +1972,7 @@ static struct pci_driver tulip_driver = { .name = DRV_NAME, .id_table = tulip_pci_tbl, .probe = tulip_init_one, - .remove = __devexit_p(tulip_remove_one), + .remove = tulip_remove_one, #ifdef CONFIG_PM .suspend = tulip_suspend, .resume = tulip_resume, diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c index 75d45f8a37dc..93845afe1cea 100644 --- a/drivers/net/ethernet/dec/tulip/uli526x.c +++ b/drivers/net/ethernet/dec/tulip/uli526x.c @@ -204,8 +204,8 @@ enum uli526x_CR6_bits { }; /* Global variable declaration ----------------------------- */ -static int __devinitdata printed_version; -static const char version[] __devinitconst = +static int printed_version; +static const char version[] = "ULi M5261/M5263 net driver, version " DRV_VERSION " (" DRV_RELDATE ")"; static int uli526x_debug; @@ -281,8 +281,8 @@ static const struct net_device_ops netdev_ops = { * Search ULI526X board, allocate space and register it */ -static int __devinit uli526x_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int uli526x_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct uli526x_board_info *db; /* board information structure */ struct net_device *dev; @@ -436,7 +436,7 @@ err_out_free: } -static void __devexit uli526x_remove_one (struct pci_dev *pdev) +static void uli526x_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct uli526x_board_info *db = netdev_priv(dev); @@ -1788,7 +1788,7 @@ static struct pci_driver uli526x_driver = { .name = "uli526x", .id_table = uli526x_pci_tbl, .probe = uli526x_init_one, - .remove = __devexit_p(uli526x_remove_one), + .remove = uli526x_remove_one, .suspend = uli526x_suspend, .resume = uli526x_resume, }; diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c index 7c1ec4d7920b..c7b04ecf5b49 100644 --- a/drivers/net/ethernet/dec/tulip/winbond-840.c +++ b/drivers/net/ethernet/dec/tulip/winbond-840.c @@ -236,7 +236,7 @@ struct pci_id_info { int drv_flags; /* Driver use, intended as capability flags. */ }; -static const struct pci_id_info pci_id_tbl[] __devinitconst = { +static const struct pci_id_info pci_id_tbl[] = { { /* Sometime a Level-One switch card. */ "Winbond W89c840", CanHaveMII | HasBrokenTx | FDXOnNoMII}, { "Winbond W89c840", CanHaveMII | HasBrokenTx}, @@ -358,8 +358,7 @@ static const struct net_device_ops netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit w840_probe1 (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int w840_probe1(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; struct netdev_private *np; @@ -1532,7 +1531,7 @@ static int netdev_close(struct net_device *dev) return 0; } -static void __devexit w840_remove1 (struct pci_dev *pdev) +static void w840_remove1(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -1647,7 +1646,7 @@ static struct pci_driver w840_driver = { .name = DRV_NAME, .id_table = w840_pci_tbl, .probe = w840_probe1, - .remove = __devexit_p(w840_remove1), + .remove = w840_remove1, #ifdef CONFIG_PM .suspend = w840_suspend, .resume = w840_resume, diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c index 138bf83bc98e..88feced9a629 100644 --- a/drivers/net/ethernet/dec/tulip/xircom_cb.c +++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c @@ -148,7 +148,7 @@ static struct pci_driver xircom_ops = { .name = "xircom_cb", .id_table = xircom_pci_table, .probe = xircom_probe, - .remove = __devexit_p(xircom_remove), + .remove = xircom_remove, }; @@ -190,7 +190,7 @@ static const struct net_device_ops netdev_ops = { first two packets that get send, and pump hates that. */ -static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id) +static int xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct device *d = &pdev->dev; struct net_device *dev = NULL; @@ -312,7 +312,7 @@ err_disable: Interrupts and such are already stopped in the "ifconfig ethX down" code. */ -static void __devexit xircom_remove(struct pci_dev *pdev) +static void xircom_remove(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct xircom_private *card = netdev_priv(dev); diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c index a059f0c27e28..1d342d37915c 100644 --- a/drivers/net/ethernet/dlink/dl2k.c +++ b/drivers/net/ethernet/dlink/dl2k.c @@ -23,7 +23,7 @@ #define dr16(reg) ioread16(ioaddr + (reg)) #define dr8(reg) ioread8(ioaddr + (reg)) -static char version[] __devinitdata = +static char version[] = KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n"; #define MAX_UNITS 8 static int mtu[MAX_UNITS]; @@ -110,7 +110,7 @@ static const struct net_device_ops netdev_ops = { .ndo_change_mtu = change_mtu, }; -static int __devinit +static int rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; @@ -1727,7 +1727,7 @@ rio_close (struct net_device *dev) return 0; } -static void __devexit +static void rio_remove1 (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); @@ -1755,24 +1755,10 @@ static struct pci_driver rio_driver = { .name = "dl2k", .id_table = rio_pci_tbl, .probe = rio_probe1, - .remove = __devexit_p(rio_remove1), + .remove = rio_remove1, }; -static int __init -rio_init (void) -{ - return pci_register_driver(&rio_driver); -} - -static void __exit -rio_exit (void) -{ - pci_unregister_driver (&rio_driver); -} - -module_init (rio_init); -module_exit (rio_exit); - +module_pci_driver(rio_driver); /* Compile command: diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c index 3b83588e51f6..28fc11b2f1ea 100644 --- a/drivers/net/ethernet/dlink/sundance.c +++ b/drivers/net/ethernet/dlink/sundance.c @@ -102,7 +102,7 @@ static char *media[MAX_UNITS]; #include <linux/mii.h> /* These identify the driver base version and may not be removed. */ -static const char version[] __devinitconst = +static const char version[] = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n"; @@ -218,7 +218,7 @@ enum { struct pci_id_info { const char *name; }; -static const struct pci_id_info pci_id_tbl[] __devinitconst = { +static const struct pci_id_info pci_id_tbl[] = { {"D-Link DFE-550TX FAST Ethernet Adapter"}, {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"}, {"D-Link DFE-580TX 4 port Server Adapter"}, @@ -259,6 +259,7 @@ enum alta_offsets { EECtrl = 0x36, FlashAddr = 0x40, FlashData = 0x44, + WakeEvent = 0x45, TxStatus = 0x46, TxFrameId = 0x47, DownCounter = 0x18, @@ -333,6 +334,14 @@ enum mac_ctrl1_bits { RxEnable=0x0800, RxDisable=0x1000, RxEnabled=0x2000, }; +/* Bits in WakeEvent register. */ +enum wake_event_bits { + WakePktEnable = 0x01, + MagicPktEnable = 0x02, + LinkEventEnable = 0x04, + WolEnable = 0x80, +}; + /* The Rx and Tx buffer descriptors. */ /* Note that using only 32 bit fields simplifies conversion to big-endian architectures. */ @@ -392,6 +401,7 @@ struct netdev_private { unsigned int default_port:4; /* Last dev->if_port value. */ unsigned int an_enable:1; unsigned int speed; + unsigned int wol_enabled:1; /* Wake on LAN enabled */ struct tasklet_struct rx_tasklet; struct tasklet_struct tx_tasklet; int budget; @@ -472,8 +482,8 @@ static const struct net_device_ops netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit sundance_probe1 (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int sundance_probe1(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct net_device *dev; struct netdev_private *np; @@ -701,7 +711,7 @@ static int change_mtu(struct net_device *dev, int new_mtu) #define eeprom_delay(ee_addr) ioread32(ee_addr) /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */ -static int __devinit eeprom_read(void __iomem *ioaddr, int location) +static int eeprom_read(void __iomem *ioaddr, int location) { int boguscnt = 10000; /* Typical 1900 ticks. */ iowrite16(0x0200 | (location & 0xff), ioaddr + EECtrl); @@ -829,7 +839,7 @@ static int netdev_open(struct net_device *dev) unsigned long flags; int i; - /* Do we need to reset the chip??? */ + sundance_reset(dev, 0x00ff << 16); i = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev); if (i) @@ -877,6 +887,10 @@ static int netdev_open(struct net_device *dev) iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); + /* Disable Wol */ + iowrite8(ioread8(ioaddr + WakeEvent) | 0x00, ioaddr + WakeEvent); + np->wol_enabled = 0; + if (netif_msg_ifup(np)) printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x " "MAC Control %x, %4.4x %4.4x.\n", @@ -1715,6 +1729,60 @@ static void get_ethtool_stats(struct net_device *dev, data[i++] = np->xstats.rx_mcasts; } +#ifdef CONFIG_PM + +static void sundance_get_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; + u8 wol_bits; + + wol->wolopts = 0; + + wol->supported = (WAKE_PHY | WAKE_MAGIC); + if (!np->wol_enabled) + return; + + wol_bits = ioread8(ioaddr + WakeEvent); + if (wol_bits & MagicPktEnable) + wol->wolopts |= WAKE_MAGIC; + if (wol_bits & LinkEventEnable) + wol->wolopts |= WAKE_PHY; +} + +static int sundance_set_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; + u8 wol_bits; + + if (!device_can_wakeup(&np->pci_dev->dev)) + return -EOPNOTSUPP; + + np->wol_enabled = !!(wol->wolopts); + wol_bits = ioread8(ioaddr + WakeEvent); + wol_bits &= ~(WakePktEnable | MagicPktEnable | + LinkEventEnable | WolEnable); + + if (np->wol_enabled) { + if (wol->wolopts & WAKE_MAGIC) + wol_bits |= (MagicPktEnable | WolEnable); + if (wol->wolopts & WAKE_PHY) + wol_bits |= (LinkEventEnable | WolEnable); + } + iowrite8(wol_bits, ioaddr + WakeEvent); + + device_set_wakeup_enable(&np->pci_dev->dev, np->wol_enabled); + + return 0; +} +#else +#define sundance_get_wol NULL +#define sundance_set_wol NULL +#endif /* CONFIG_PM */ + static const struct ethtool_ops ethtool_ops = { .begin = check_if_running, .get_drvinfo = get_drvinfo, @@ -1722,6 +1790,8 @@ static const struct ethtool_ops ethtool_ops = { .set_settings = set_settings, .nway_reset = nway_reset, .get_link = get_link, + .get_wol = sundance_get_wol, + .set_wol = sundance_set_wol, .get_msglevel = get_msglevel, .set_msglevel = set_msglevel, .get_strings = get_strings, @@ -1844,7 +1914,7 @@ static int netdev_close(struct net_device *dev) return 0; } -static void __devexit sundance_remove1 (struct pci_dev *pdev) +static void sundance_remove1(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -1867,6 +1937,8 @@ static void __devexit sundance_remove1 (struct pci_dev *pdev) static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pci_dev); + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; if (!netif_running(dev)) return 0; @@ -1875,6 +1947,12 @@ static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state) netif_device_detach(dev); pci_save_state(pci_dev); + if (np->wol_enabled) { + iowrite8(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode); + iowrite16(RxEnable, ioaddr + MACCtrl1); + } + pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), + np->wol_enabled); pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); return 0; @@ -1890,6 +1968,7 @@ static int sundance_resume(struct pci_dev *pci_dev) pci_set_power_state(pci_dev, PCI_D0); pci_restore_state(pci_dev); + pci_enable_wake(pci_dev, PCI_D0, 0); err = netdev_open(dev); if (err) { @@ -1910,7 +1989,7 @@ static struct pci_driver sundance_driver = { .name = DRV_NAME, .id_table = sundance_pci_tbl, .probe = sundance_probe1, - .remove = __devexit_p(sundance_remove1), + .remove = sundance_remove1, #ifdef CONFIG_PM .suspend = sundance_suspend, .resume = sundance_resume, diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c index 290b26f868c9..2c177b329c8b 100644 --- a/drivers/net/ethernet/dnet.c +++ b/drivers/net/ethernet/dnet.c @@ -72,7 +72,7 @@ static void __dnet_set_hwaddr(struct dnet *bp) dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp); } -static void __devinit dnet_get_hwaddr(struct dnet *bp) +static void dnet_get_hwaddr(struct dnet *bp) { u16 tmp; u8 addr[6]; @@ -664,9 +664,6 @@ static int dnet_open(struct net_device *dev) if (!bp->phy_dev) return -EAGAIN; - if (!is_valid_ether_addr(dev->dev_addr)) - return -EADDRNOTAVAIL; - napi_enable(&bp->napi); dnet_init_hw(bp); @@ -829,7 +826,7 @@ static const struct net_device_ops dnet_netdev_ops = { .ndo_change_mtu = eth_change_mtu, }; -static int __devinit dnet_probe(struct platform_device *pdev) +static int dnet_probe(struct platform_device *pdev) { struct resource *res; struct net_device *dev; @@ -945,7 +942,7 @@ err_out: return err; } -static int __devexit dnet_remove(struct platform_device *pdev) +static int dnet_remove(struct platform_device *pdev) { struct net_device *dev; @@ -971,7 +968,7 @@ static int __devexit dnet_remove(struct platform_device *pdev) static struct platform_driver dnet_driver = { .probe = dnet_probe, - .remove = __devexit_p(dnet_remove), + .remove = dnet_remove, .driver = { .name = "dnet", }, diff --git a/drivers/net/ethernet/emulex/Kconfig b/drivers/net/ethernet/emulex/Kconfig index 7a28a6433944..1b8d638c6cb1 100644 --- a/drivers/net/ethernet/emulex/Kconfig +++ b/drivers/net/ethernet/emulex/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_EMULEX bool "Emulex devices" default y - depends on PCI && INET + depends on PCI ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from diff --git a/drivers/net/ethernet/emulex/benet/Kconfig b/drivers/net/ethernet/emulex/benet/Kconfig index 804db04a2bd0..231129dd1764 100644 --- a/drivers/net/ethernet/emulex/benet/Kconfig +++ b/drivers/net/ethernet/emulex/benet/Kconfig @@ -1,6 +1,6 @@ config BE2NET tristate "ServerEngines' 10Gbps NIC - BladeEngine" - depends on PCI && INET + depends on PCI ---help--- This driver implements the NIC functionality for ServerEngines' 10Gbps network adapter - BladeEngine. diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index cf4c05bdf5fe..4eba17b83ba8 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -34,7 +34,7 @@ #include "be_hw.h" #include "be_roce.h" -#define DRV_VER "4.4.31.0u" +#define DRV_VER "4.4.161.0u" #define DRV_NAME "be2net" #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" @@ -53,6 +53,7 @@ #define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */ #define OC_DEVICE_ID4 0xe228 /* Device id for VF in Lancer */ #define OC_DEVICE_ID5 0x720 /* Device Id for Skyhawk cards */ +#define OC_DEVICE_ID6 0x728 /* Device id for VF in SkyHawk */ #define OC_SUBSYS_DEVICE_ID1 0xE602 #define OC_SUBSYS_DEVICE_ID2 0xE642 #define OC_SUBSYS_DEVICE_ID3 0xE612 @@ -71,6 +72,7 @@ static inline char *nic_name(struct pci_dev *pdev) case BE_DEVICE_ID2: return BE3_NAME; case OC_DEVICE_ID5: + case OC_DEVICE_ID6: return OC_NAME_SH; default: return BE_NAME; @@ -188,6 +190,7 @@ struct be_eq_obj { u8 idx; /* array index */ u16 tx_budget; + u16 spurious_intr; struct napi_struct napi; struct be_adapter *adapter; } ____cacheline_aligned_in_smp; @@ -346,7 +349,6 @@ struct be_adapter { struct pci_dev *pdev; struct net_device *netdev; - u8 __iomem *csr; u8 __iomem *db; /* Door Bell */ struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ @@ -374,11 +376,8 @@ struct be_adapter { struct be_rx_obj rx_obj[MAX_RX_QS]; u32 big_page_size; /* Compounded page size shared by rx wrbs */ - u8 eq_next_idx; struct be_drv_stats drv_stats; - u16 vlans_added; - u16 max_vlans; /* Number of vlans supported */ u8 vlan_tag[VLAN_N_VID]; u8 vlan_prio_bmap; /* Available Priority BitMap */ u16 recommended_prio; /* Recommended Priority */ @@ -391,6 +390,7 @@ struct be_adapter { struct delayed_work func_recovery_work; u32 flags; + u32 cmd_privileges; /* Ethtool knobs and info */ char fw_ver[FW_VER_LEN]; int if_handle; /* Used to configure filtering */ @@ -408,10 +408,8 @@ struct be_adapter { u32 rx_fc; /* Rx flow control */ u32 tx_fc; /* Tx flow control */ bool stats_cmd_sent; - u8 generation; /* BladeEngine ASIC generation */ u32 if_type; struct { - u8 __iomem *base; /* Door Bell */ u32 size; u32 total_size; u64 io_addr; @@ -434,10 +432,18 @@ struct be_adapter { struct phy_info phy; u8 wol_cap; bool wol; - u32 max_pmac_cnt; /* Max secondary UC MACs programmable */ u32 uc_macs; /* Count of secondary UC MAC programmed */ u32 msg_enable; int be_get_temp_freq; + u16 max_mcast_mac; + u16 max_tx_queues; + u16 max_rss_queues; + u16 max_rx_queues; + u16 max_pmac_cnt; + u16 max_vlans; + u16 max_event_queues; + u32 if_cap_flags; + u8 pf_number; }; #define be_physfn(adapter) (!adapter->virtfn) @@ -448,21 +454,25 @@ struct be_adapter { for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \ i++, vf_cfg++) -/* BladeEngine Generation numbers */ -#define BE_GEN2 2 -#define BE_GEN3 3 - #define ON 1 #define OFF 0 -#define lancer_chip(adapter) ((adapter->pdev->device == OC_DEVICE_ID3) || \ - (adapter->pdev->device == OC_DEVICE_ID4)) -#define skyhawk_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID5) +#define lancer_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID3 || \ + adapter->pdev->device == OC_DEVICE_ID4) + +#define skyhawk_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID5 || \ + adapter->pdev->device == OC_DEVICE_ID6) + +#define BE3_chip(adapter) (adapter->pdev->device == BE_DEVICE_ID2 || \ + adapter->pdev->device == OC_DEVICE_ID2) +#define BE2_chip(adapter) (adapter->pdev->device == BE_DEVICE_ID1 || \ + adapter->pdev->device == OC_DEVICE_ID1) -#define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \ - adapter->sli_family == SKYHAWK_SLI_FAMILY) && \ - (adapter->function_mode & RDMA_ENABLED)) +#define BEx_chip(adapter) (BE3_chip(adapter) || BE2_chip(adapter)) + +#define be_roce_supported(adapter) (skyhawk_chip(adapter) && \ + (adapter->function_mode & RDMA_ENABLED)) extern const struct ethtool_ops be_ethtool_ops; @@ -607,7 +617,7 @@ static inline bool be_error(struct be_adapter *adapter) return adapter->eeh_error || adapter->hw_error || adapter->fw_timeout; } -static inline bool be_crit_error(struct be_adapter *adapter) +static inline bool be_hw_error(struct be_adapter *adapter) { return adapter->eeh_error || adapter->hw_error; } @@ -637,12 +647,6 @@ static inline bool be_is_wol_excluded(struct be_adapter *adapter) } } -static inline bool be_type_2_3(struct be_adapter *adapter) -{ - return (adapter->if_type == SLI_INTF_TYPE_2 || - adapter->if_type == SLI_INTF_TYPE_3) ? true : false; -} - extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped); extern void be_link_status_update(struct be_adapter *adapter, u8 link_status); diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index af60bb26e330..8a250c38fb82 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -19,6 +19,55 @@ #include "be.h" #include "be_cmds.h" +static struct be_cmd_priv_map cmd_priv_map[] = { + { + OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, + CMD_SUBSYSTEM_ETH, + BE_PRIV_LNKMGMT | BE_PRIV_VHADM | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_COMMON_GET_FLOW_CONTROL, + CMD_SUBSYSTEM_COMMON, + BE_PRIV_LNKQUERY | BE_PRIV_VHADM | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_COMMON_SET_FLOW_CONTROL, + CMD_SUBSYSTEM_COMMON, + BE_PRIV_LNKMGMT | BE_PRIV_VHADM | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_ETH_GET_PPORT_STATS, + CMD_SUBSYSTEM_ETH, + BE_PRIV_LNKMGMT | BE_PRIV_VHADM | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_COMMON_GET_PHY_DETAILS, + CMD_SUBSYSTEM_COMMON, + BE_PRIV_LNKMGMT | BE_PRIV_VHADM | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + } +}; + +static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode, + u8 subsystem) +{ + int i; + int num_entries = sizeof(cmd_priv_map)/sizeof(struct be_cmd_priv_map); + u32 cmd_privileges = adapter->cmd_privileges; + + for (i = 0; i < num_entries; i++) + if (opcode == cmd_priv_map[i].opcode && + subsystem == cmd_priv_map[i].subsystem) + if (!(cmd_privileges & cmd_priv_map[i].priv_mask)) + return false; + + return true; +} + static inline void *embedded_payload(struct be_mcc_wrb *wrb) { return wrb->payload.embedded_payload; @@ -249,7 +298,12 @@ void be_async_mcc_enable(struct be_adapter *adapter) void be_async_mcc_disable(struct be_adapter *adapter) { + spin_lock_bh(&adapter->mcc_cq_lock); + adapter->mcc_obj.rearm_cq = false; + be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0); + + spin_unlock_bh(&adapter->mcc_cq_lock); } int be_process_mcc(struct be_adapter *adapter) @@ -419,14 +473,13 @@ static int be_mbox_notify_wait(struct be_adapter *adapter) static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage) { u32 sem; + u32 reg = skyhawk_chip(adapter) ? SLIPORT_SEMAPHORE_OFFSET_SH : + SLIPORT_SEMAPHORE_OFFSET_BE; - if (lancer_chip(adapter)) - sem = ioread32(adapter->db + MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET); - else - sem = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET); + pci_read_config_dword(adapter->pdev, reg, &sem); + *stage = sem & POST_STAGE_MASK; - *stage = sem & EP_SEMAPHORE_POST_STAGE_MASK; - if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK) + if ((sem >> POST_ERR_SHIFT) & POST_ERR_MASK) return -1; else return 0; @@ -452,10 +505,33 @@ int lancer_wait_ready(struct be_adapter *adapter) return status; } +static bool lancer_provisioning_error(struct be_adapter *adapter) +{ + u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; + sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); + if (sliport_status & SLIPORT_STATUS_ERR_MASK) { + sliport_err1 = ioread32(adapter->db + + SLIPORT_ERROR1_OFFSET); + sliport_err2 = ioread32(adapter->db + + SLIPORT_ERROR2_OFFSET); + + if (sliport_err1 == SLIPORT_ERROR_NO_RESOURCE1 && + sliport_err2 == SLIPORT_ERROR_NO_RESOURCE2) + return true; + } + return false; +} + int lancer_test_and_set_rdy_state(struct be_adapter *adapter) { int status; u32 sliport_status, err, reset_needed; + bool resource_error; + + resource_error = lancer_provisioning_error(adapter); + if (resource_error) + return -1; + status = lancer_wait_ready(adapter); if (!status) { sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); @@ -477,6 +553,14 @@ int lancer_test_and_set_rdy_state(struct be_adapter *adapter) status = -1; } } + /* Stop error recovery if error is not recoverable. + * No resource error is temporary errors and will go away + * when PF provisions resources. + */ + resource_error = lancer_provisioning_error(adapter); + if (status == -1 && !resource_error) + adapter->eeh_error = true; + return status; } @@ -601,6 +685,9 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) struct be_queue_info *mccq = &adapter->mcc_obj.q; struct be_mcc_wrb *wrb; + if (!mccq->created) + return NULL; + if (atomic_read(&mccq->used) >= mccq->len) { dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n"); return NULL; @@ -1155,8 +1242,7 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, req->id = cpu_to_le16(q->id); status = be_mbox_notify_wait(adapter); - if (!status) - q->created = false; + q->created = false; mutex_unlock(&adapter->mbox_lock); return status; @@ -1183,8 +1269,7 @@ int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) req->id = cpu_to_le16(q->id); status = be_mcc_notify_wait(adapter); - if (!status) - q->created = false; + q->created = false; err: spin_unlock_bh(&adapter->mcc_lock); @@ -1281,7 +1366,8 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb, nonemb_cmd); - if (adapter->generation == BE_GEN3) + /* version 1 of the cmd is not supported only by BE2 */ + if (!BE2_chip(adapter)) hdr->version = 1; be_mcc_notify(adapter); @@ -1301,6 +1387,10 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, struct lancer_cmd_req_pport_stats *req; int status = 0; + if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS, + CMD_SUBSYSTEM_ETH)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -1367,7 +1457,8 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, 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)) + /* version 1 of the cmd is not supported only by BE2 */ + if (!BE2_chip(adapter)) req->hdr.version = 1; req->hdr.domain = dom; @@ -1658,9 +1749,9 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) /* Reset mcast promisc mode if already set by setting mask * and not setting flags field */ - if (!lancer_chip(adapter) || be_physfn(adapter)) - req->if_flags_mask |= - cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS); + req->if_flags_mask |= + cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS & + adapter->if_cap_flags); req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev)); netdev_for_each_mc_addr(ha, adapter->netdev) @@ -1680,6 +1771,10 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) struct be_cmd_req_set_flow_control *req; int status; + if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL, + CMD_SUBSYSTEM_COMMON)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -1709,6 +1804,10 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) struct be_cmd_req_get_flow_control *req; int status; + if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL, + CMD_SUBSYSTEM_COMMON)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -2067,7 +2166,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, int offset) { struct be_mcc_wrb *wrb; - struct be_cmd_write_flashrom *req; + struct be_cmd_read_flash_crc *req; int status; spin_lock_bh(&adapter->mcc_lock); @@ -2080,7 +2179,8 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, req = embedded_payload(wrb); be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, - OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL); + OPCODE_COMMON_READ_FLASHROM, sizeof(*req), + wrb, NULL); req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT); req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); @@ -2089,7 +2189,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, status = be_mcc_notify_wait(adapter); if (!status) - memcpy(flashed_crc, req->params.data_buf, 4); + memcpy(flashed_crc, req->crc, 4); err: spin_unlock_bh(&adapter->mcc_lock); @@ -2275,6 +2375,10 @@ int be_cmd_get_phy_info(struct be_adapter *adapter) struct be_dma_mem cmd; int status; + if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS, + CMD_SUBSYSTEM_COMMON)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -2434,6 +2538,42 @@ err: return status; } +/* Get privilege(s) for a function */ +int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, + u32 domain) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_fn_privileges *req; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = embedded_payload(wrb); + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req), + wrb, NULL); + + req->hdr.domain = domain; + + status = be_mcc_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_get_fn_privileges *resp = + embedded_payload(wrb); + *privilege = le32_to_cpu(resp->privilege_mask); + } + +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} + /* Uses synchronous MCCQ */ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, bool *pmac_id_active, u32 *pmac_id, u8 domain) @@ -2651,6 +2791,10 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) int payload_len = sizeof(*req); struct be_dma_mem cmd; + if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, + CMD_SUBSYSTEM_ETH)) + return -EPERM; + memset(&cmd, 0, sizeof(struct be_dma_mem)); cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1); cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, @@ -2792,6 +2936,240 @@ err: return status; } +static struct be_nic_resource_desc *be_get_nic_desc(u8 *buf, u32 desc_count, + u32 max_buf_size) +{ + struct be_nic_resource_desc *desc = (struct be_nic_resource_desc *)buf; + int i; + + for (i = 0; i < desc_count; i++) { + desc->desc_len = RESOURCE_DESC_SIZE; + if (((void *)desc + desc->desc_len) > + (void *)(buf + max_buf_size)) { + desc = NULL; + break; + } + + if (desc->desc_type == NIC_RESOURCE_DESC_TYPE_ID) + break; + + desc = (void *)desc + desc->desc_len; + } + + if (!desc || i == MAX_RESOURCE_DESC) + return NULL; + + return desc; +} + +/* Uses Mbox */ +int be_cmd_get_func_config(struct be_adapter *adapter) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_func_config *req; + int status; + struct be_dma_mem cmd; + + memset(&cmd, 0, sizeof(struct be_dma_mem)); + cmd.size = sizeof(struct be_cmd_resp_get_func_config); + cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, + &cmd.dma); + if (!cmd.va) { + dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); + return -ENOMEM; + } + if (mutex_lock_interruptible(&adapter->mbox_lock)) + return -1; + + wrb = wrb_from_mbox(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = cmd.va; + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FUNC_CONFIG, + cmd.size, wrb, &cmd); + + status = be_mbox_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_get_func_config *resp = cmd.va; + u32 desc_count = le32_to_cpu(resp->desc_count); + struct be_nic_resource_desc *desc; + + desc = be_get_nic_desc(resp->func_param, desc_count, + sizeof(resp->func_param)); + if (!desc) { + status = -EINVAL; + goto err; + } + + adapter->pf_number = desc->pf_num; + adapter->max_pmac_cnt = le16_to_cpu(desc->unicast_mac_count); + adapter->max_vlans = le16_to_cpu(desc->vlan_count); + adapter->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count); + adapter->max_tx_queues = le16_to_cpu(desc->txq_count); + adapter->max_rss_queues = le16_to_cpu(desc->rssq_count); + adapter->max_rx_queues = le16_to_cpu(desc->rq_count); + + adapter->max_event_queues = le16_to_cpu(desc->eq_count); + adapter->if_cap_flags = le32_to_cpu(desc->cap_flags); + } +err: + mutex_unlock(&adapter->mbox_lock); + pci_free_consistent(adapter->pdev, cmd.size, + cmd.va, cmd.dma); + return status; +} + + /* Uses sync mcc */ +int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags, + u8 domain) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_profile_config *req; + int status; + struct be_dma_mem cmd; + + memset(&cmd, 0, sizeof(struct be_dma_mem)); + cmd.size = sizeof(struct be_cmd_resp_get_profile_config); + cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, + &cmd.dma); + if (!cmd.va) { + dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); + return -ENOMEM; + } + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = cmd.va; + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_PROFILE_CONFIG, + cmd.size, wrb, &cmd); + + req->type = ACTIVE_PROFILE_TYPE; + req->hdr.domain = domain; + + status = be_mcc_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_get_profile_config *resp = cmd.va; + u32 desc_count = le32_to_cpu(resp->desc_count); + struct be_nic_resource_desc *desc; + + desc = be_get_nic_desc(resp->func_param, desc_count, + sizeof(resp->func_param)); + + if (!desc) { + status = -EINVAL; + goto err; + } + *cap_flags = le32_to_cpu(desc->cap_flags); + } +err: + spin_unlock_bh(&adapter->mcc_lock); + pci_free_consistent(adapter->pdev, cmd.size, + cmd.va, cmd.dma); + return status; +} + +/* Uses sync mcc */ +int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps, + u8 domain) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_set_profile_config *req; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = embedded_payload(wrb); + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_PROFILE_CONFIG, sizeof(*req), + wrb, NULL); + + req->hdr.domain = domain; + req->desc_count = cpu_to_le32(1); + + req->nic_desc.desc_type = NIC_RESOURCE_DESC_TYPE_ID; + req->nic_desc.desc_len = RESOURCE_DESC_SIZE; + req->nic_desc.flags = (1 << QUN) | (1 << IMM) | (1 << NOSV); + req->nic_desc.pf_num = adapter->pf_number; + req->nic_desc.vf_num = domain; + + /* Mark fields invalid */ + req->nic_desc.unicast_mac_count = 0xFFFF; + req->nic_desc.mcc_count = 0xFFFF; + req->nic_desc.vlan_count = 0xFFFF; + req->nic_desc.mcast_mac_count = 0xFFFF; + req->nic_desc.txq_count = 0xFFFF; + req->nic_desc.rq_count = 0xFFFF; + req->nic_desc.rssq_count = 0xFFFF; + req->nic_desc.lro_count = 0xFFFF; + req->nic_desc.cq_count = 0xFFFF; + req->nic_desc.toe_conn_count = 0xFFFF; + req->nic_desc.eq_count = 0xFFFF; + req->nic_desc.link_param = 0xFF; + req->nic_desc.bw_min = 0xFFFFFFFF; + req->nic_desc.acpi_params = 0xFF; + req->nic_desc.wol_param = 0x0F; + + /* Change BW */ + req->nic_desc.bw_min = cpu_to_le32(bps); + req->nic_desc.bw_max = cpu_to_le32(bps); + status = be_mcc_notify_wait(adapter); +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} + +/* Uses sync mcc */ +int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_enable_disable_vf *req; + int status; + + if (!lancer_chip(adapter)) + return 0; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = embedded_payload(wrb); + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req), + wrb, NULL); + + req->hdr.domain = domain; + req->enable = 1; + status = be_mcc_notify_wait(adapter); +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} + int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, int wrb_payload_size, u16 *cmd_status, u16 *ext_status) { diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 0936e21e3cff..d6552e19ffee 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -196,9 +196,14 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_GET_MAC_LIST 147 #define OPCODE_COMMON_SET_MAC_LIST 148 #define OPCODE_COMMON_GET_HSW_CONFIG 152 +#define OPCODE_COMMON_GET_FUNC_CONFIG 160 +#define OPCODE_COMMON_GET_PROFILE_CONFIG 164 +#define OPCODE_COMMON_SET_PROFILE_CONFIG 165 #define OPCODE_COMMON_SET_HSW_CONFIG 153 +#define OPCODE_COMMON_GET_FN_PRIVILEGES 170 #define OPCODE_COMMON_READ_OBJECT 171 #define OPCODE_COMMON_WRITE_OBJECT 172 +#define OPCODE_COMMON_ENABLE_DISABLE_VF 196 #define OPCODE_ETH_RSS_CONFIG 1 #define OPCODE_ETH_ACPI_CONFIG 2 @@ -1151,14 +1156,22 @@ struct flashrom_params { u32 op_type; u32 data_buf_size; u32 offset; - u8 data_buf[4]; }; struct be_cmd_write_flashrom { struct be_cmd_req_hdr hdr; struct flashrom_params params; -}; + u8 data_buf[32768]; + u8 rsvd[4]; +} __packed; +/* cmd to read flash crc */ +struct be_cmd_read_flash_crc { + struct be_cmd_req_hdr hdr; + struct flashrom_params params; + u8 crc[4]; + u8 rsvd[4]; +}; /**************** Lancer Firmware Flash ************/ struct amap_lancer_write_obj_context { u8 write_length[24]; @@ -1429,6 +1442,41 @@ struct be_cmd_resp_set_func_cap { u8 rsvd[212]; }; +/*********************** Function Privileges ***********************/ +enum { + BE_PRIV_DEFAULT = 0x1, + BE_PRIV_LNKQUERY = 0x2, + BE_PRIV_LNKSTATS = 0x4, + BE_PRIV_LNKMGMT = 0x8, + BE_PRIV_LNKDIAG = 0x10, + BE_PRIV_UTILQUERY = 0x20, + BE_PRIV_FILTMGMT = 0x40, + BE_PRIV_IFACEMGMT = 0x80, + BE_PRIV_VHADM = 0x100, + BE_PRIV_DEVCFG = 0x200, + BE_PRIV_DEVSEC = 0x400 +}; +#define MAX_PRIVILEGES (BE_PRIV_VHADM | BE_PRIV_DEVCFG | \ + BE_PRIV_DEVSEC) +#define MIN_PRIVILEGES BE_PRIV_DEFAULT + +struct be_cmd_priv_map { + u8 opcode; + u8 subsystem; + u32 priv_mask; +}; + +struct be_cmd_req_get_fn_privileges { + struct be_cmd_req_hdr hdr; + u32 rsvd; +}; + +struct be_cmd_resp_get_fn_privileges { + struct be_cmd_resp_hdr hdr; + u32 privilege_mask; +}; + + /******************** GET/SET_MACLIST **************************/ #define BE_MAX_MAC 64 struct be_cmd_req_get_mac_list { @@ -1608,33 +1656,6 @@ struct be_cmd_resp_get_stats_v1 { struct be_hw_stats_v1 hw_stats; }; -static inline void *hw_stats_from_cmd(struct be_adapter *adapter) -{ - if (adapter->generation == BE_GEN3) { - struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va; - - return &cmd->hw_stats; - } else { - struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va; - - return &cmd->hw_stats; - } -} - -static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter) -{ - if (adapter->generation == BE_GEN3) { - struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter); - - return &hw_stats->erx; - } else { - struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter); - - return &hw_stats->erx; - } -} - - /************** get fat capabilites *******************/ #define MAX_MODULES 27 #define MAX_MODES 4 @@ -1684,6 +1705,96 @@ struct be_cmd_req_set_ext_fat_caps { struct be_fat_conf_params set_params; }; +#define RESOURCE_DESC_SIZE 72 +#define NIC_RESOURCE_DESC_TYPE_ID 0x41 +#define MAX_RESOURCE_DESC 4 + +/* QOS unit number */ +#define QUN 4 +/* Immediate */ +#define IMM 6 +/* No save */ +#define NOSV 7 + +struct be_nic_resource_desc { + u8 desc_type; + u8 desc_len; + u8 rsvd1; + u8 flags; + u8 vf_num; + u8 rsvd2; + u8 pf_num; + u8 rsvd3; + u16 unicast_mac_count; + u8 rsvd4[6]; + u16 mcc_count; + u16 vlan_count; + u16 mcast_mac_count; + u16 txq_count; + u16 rq_count; + u16 rssq_count; + u16 lro_count; + u16 cq_count; + u16 toe_conn_count; + u16 eq_count; + u32 rsvd5; + u32 cap_flags; + u8 link_param; + u8 rsvd6[3]; + u32 bw_min; + u32 bw_max; + u8 acpi_params; + u8 wol_param; + u16 rsvd7; + u32 rsvd8[3]; +}; + +struct be_cmd_req_get_func_config { + struct be_cmd_req_hdr hdr; +}; + +struct be_cmd_resp_get_func_config { + struct be_cmd_req_hdr hdr; + u32 desc_count; + u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE]; +}; + +#define ACTIVE_PROFILE_TYPE 0x2 +struct be_cmd_req_get_profile_config { + struct be_cmd_req_hdr hdr; + u8 rsvd; + u8 type; + u16 rsvd1; +}; + +struct be_cmd_resp_get_profile_config { + struct be_cmd_req_hdr hdr; + u32 desc_count; + u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE]; +}; + +struct be_cmd_req_set_profile_config { + struct be_cmd_req_hdr hdr; + u32 rsvd; + u32 desc_count; + struct be_nic_resource_desc nic_desc; +}; + +struct be_cmd_resp_set_profile_config { + struct be_cmd_req_hdr hdr; +}; + +struct be_cmd_enable_disable_vf { + struct be_cmd_req_hdr hdr; + u8 enable; + u8 rsvd[3]; +}; + +static inline bool check_privilege(struct be_adapter *adapter, u32 flags) +{ + return flags & adapter->cmd_privileges ? true : false; +} + extern int be_pci_fnum_get(struct be_adapter *adapter); extern int be_fw_wait_ready(struct be_adapter *adapter); extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, @@ -1780,6 +1891,8 @@ extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter); 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_fn_privileges(struct be_adapter *adapter, + u32 *privilege, u32 domain); extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, bool *pmac_id_active, u32 *pmac_id, u8 domain); @@ -1798,4 +1911,10 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, extern int lancer_wait_ready(struct be_adapter *adapter); extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter); extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name); +extern int be_cmd_get_func_config(struct be_adapter *adapter); +extern int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags, + u8 domain); +extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps, + u8 domain); +extern int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain); diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 8e6fb0ba6aa9..00454a10f88d 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -261,6 +261,9 @@ be_get_reg_len(struct net_device *netdev) struct be_adapter *adapter = netdev_priv(netdev); u32 log_size = 0; + if (!check_privilege(adapter, MAX_PRIVILEGES)) + return 0; + if (be_physfn(adapter)) { if (lancer_chip(adapter)) log_size = lancer_cmd_get_file_len(adapter, @@ -525,6 +528,10 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) u8 link_status; u16 link_speed = 0; int status; + u32 auto_speeds; + u32 fixed_speeds; + u32 dac_cable_len; + u16 interface_type; if (adapter->phy.link_speed < 0) { status = be_cmd_link_status_query(adapter, &link_speed, @@ -534,39 +541,46 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ethtool_cmd_speed_set(ecmd, link_speed); status = be_cmd_get_phy_info(adapter); - if (status) - return status; - - ecmd->supported = - convert_to_et_setting(adapter->phy.interface_type, - adapter->phy.auto_speeds_supported | - adapter->phy.fixed_speeds_supported); - ecmd->advertising = - convert_to_et_setting(adapter->phy.interface_type, - adapter->phy.auto_speeds_supported); - - ecmd->port = be_get_port_type(adapter->phy.interface_type, - adapter->phy.dac_cable_len); - - if (adapter->phy.auto_speeds_supported) { - ecmd->supported |= SUPPORTED_Autoneg; - ecmd->autoneg = AUTONEG_ENABLE; - ecmd->advertising |= ADVERTISED_Autoneg; - } + if (!status) { + interface_type = adapter->phy.interface_type; + auto_speeds = adapter->phy.auto_speeds_supported; + fixed_speeds = adapter->phy.fixed_speeds_supported; + dac_cable_len = adapter->phy.dac_cable_len; + + ecmd->supported = + convert_to_et_setting(interface_type, + auto_speeds | + fixed_speeds); + ecmd->advertising = + convert_to_et_setting(interface_type, + auto_speeds); + + ecmd->port = be_get_port_type(interface_type, + dac_cable_len); + + if (adapter->phy.auto_speeds_supported) { + ecmd->supported |= SUPPORTED_Autoneg; + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->advertising |= ADVERTISED_Autoneg; + } - if (be_pause_supported(adapter)) { ecmd->supported |= SUPPORTED_Pause; - ecmd->advertising |= ADVERTISED_Pause; - } - - switch (adapter->phy.interface_type) { - case PHY_TYPE_KR_10GB: - case PHY_TYPE_KX4_10GB: - ecmd->transceiver = XCVR_INTERNAL; - break; - default: - ecmd->transceiver = XCVR_EXTERNAL; - break; + if (be_pause_supported(adapter)) + ecmd->advertising |= ADVERTISED_Pause; + + switch (adapter->phy.interface_type) { + case PHY_TYPE_KR_10GB: + case PHY_TYPE_KX4_10GB: + ecmd->transceiver = XCVR_INTERNAL; + break; + default: + ecmd->transceiver = XCVR_EXTERNAL; + break; + } + } else { + ecmd->port = PORT_OTHER; + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->transceiver = XCVR_DUMMY1; } /* Save for future use */ @@ -787,6 +801,10 @@ static int be_get_eeprom_len(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); + + if (!check_privilege(adapter, MAX_PRIVILEGES)) + return 0; + if (lancer_chip(adapter)) { if (be_physfn(adapter)) return lancer_cmd_get_file_len(adapter, diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h index b755f7061dce..541d4530d5bf 100644 --- a/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/drivers/net/ethernet/emulex/benet/be_hw.h @@ -31,12 +31,12 @@ #define MPU_EP_CONTROL 0 -/********** MPU semphore ******************/ -#define MPU_EP_SEMAPHORE_OFFSET 0xac -#define MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET 0x400 -#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF -#define EP_SEMAPHORE_POST_ERR_MASK 0x1 -#define EP_SEMAPHORE_POST_ERR_SHIFT 31 +/********** MPU semphore: used for SH & BE *************/ +#define SLIPORT_SEMAPHORE_OFFSET_BE 0x7c +#define SLIPORT_SEMAPHORE_OFFSET_SH 0x94 +#define POST_STAGE_MASK 0x0000FFFF +#define POST_ERR_MASK 0x1 +#define POST_ERR_SHIFT 31 /* MPU semphore POST stage values */ #define POST_STAGE_AWAITING_HOST_RDY 0x1 /* FW awaiting goahead from host */ @@ -59,6 +59,9 @@ #define PHYSDEV_CONTROL_FW_RESET_MASK 0x00000002 #define PHYSDEV_CONTROL_INP_MASK 0x40000000 +#define SLIPORT_ERROR_NO_RESOURCE1 0x2 +#define SLIPORT_ERROR_NO_RESOURCE2 0x9 + /********* Memory BAR register ************/ #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt @@ -102,11 +105,6 @@ #define SLI_INTF_TYPE_2 2 #define SLI_INTF_TYPE_3 3 -/* SLI family */ -#define BE_SLI_FAMILY 0x0 -#define LANCER_A0_SLI_FAMILY 0xA -#define SKYHAWK_SLI_FAMILY 0x2 - /********* ISR0 Register offset **********/ #define CEV_ISR0_OFFSET 0xC18 #define CEV_ISR_SIZE 4 diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index d1b6cc587639..5c995700e534 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -44,6 +44,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)}, { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID4)}, { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID5)}, + { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID6)}, { 0 } }; MODULE_DEVICE_TABLE(pci, be_dev_ids); @@ -237,23 +238,46 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) int status = 0; u8 current_mac[ETH_ALEN]; u32 pmac_id = adapter->pmac_id[0]; + bool active_mac = true; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - status = be_cmd_mac_addr_query(adapter, current_mac, false, - adapter->if_handle, 0); + /* For BE VF, MAC address is already activated by PF. + * Hence only operation left is updating netdev->devaddr. + * Update it if user is passing the same MAC which was used + * during configuring VF MAC from PF(Hypervisor). + */ + if (!lancer_chip(adapter) && !be_physfn(adapter)) { + status = be_cmd_mac_addr_query(adapter, current_mac, + false, adapter->if_handle, 0); + if (!status && !memcmp(current_mac, addr->sa_data, ETH_ALEN)) + goto done; + else + goto err; + } + + if (!memcmp(addr->sa_data, netdev->dev_addr, ETH_ALEN)) + goto done; + + /* For Lancer check if any MAC is active. + * If active, get its mac id. + */ + if (lancer_chip(adapter) && !be_physfn(adapter)) + be_cmd_get_mac_from_list(adapter, current_mac, &active_mac, + &pmac_id, 0); + + status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data, + adapter->if_handle, + &adapter->pmac_id[0], 0); + if (status) goto err; - if (memcmp(addr->sa_data, current_mac, ETH_ALEN)) { - status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data, - adapter->if_handle, &adapter->pmac_id[0], 0); - if (status) - goto err; - - be_cmd_pmac_del(adapter, adapter->if_handle, pmac_id, 0); - } + if (active_mac) + be_cmd_pmac_del(adapter, adapter->if_handle, + pmac_id, 0); +done: memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); return 0; err: @@ -261,7 +285,35 @@ err: return status; } -static void populate_be2_stats(struct be_adapter *adapter) +/* BE2 supports only v0 cmd */ +static void *hw_stats_from_cmd(struct be_adapter *adapter) +{ + if (BE2_chip(adapter)) { + struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va; + + return &cmd->hw_stats; + } else { + struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va; + + return &cmd->hw_stats; + } +} + +/* BE2 supports only v0 cmd */ +static void *be_erx_stats_from_cmd(struct be_adapter *adapter) +{ + if (BE2_chip(adapter)) { + struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter); + + return &hw_stats->erx; + } else { + struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter); + + return &hw_stats->erx; + } +} + +static void populate_be_v0_stats(struct be_adapter *adapter) { struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter); struct be_pmem_stats *pmem_sts = &hw_stats->pmem; @@ -310,7 +362,7 @@ static void populate_be2_stats(struct be_adapter *adapter) adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops; } -static void populate_be3_stats(struct be_adapter *adapter) +static void populate_be_v1_stats(struct be_adapter *adapter) { struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter); struct be_pmem_stats *pmem_sts = &hw_stats->pmem; @@ -412,28 +464,25 @@ void be_parse_stats(struct be_adapter *adapter) struct be_rx_obj *rxo; int i; - if (adapter->generation == BE_GEN3) { - if (lancer_chip(adapter)) - populate_lancer_stats(adapter); - else - populate_be3_stats(adapter); + if (lancer_chip(adapter)) { + populate_lancer_stats(adapter); } else { - populate_be2_stats(adapter); - } - - if (lancer_chip(adapter)) - goto done; + if (BE2_chip(adapter)) + populate_be_v0_stats(adapter); + else + /* for BE3 and Skyhawk */ + populate_be_v1_stats(adapter); - /* as erx_v1 is longer than v0, ok to use v1 defn for v0 access */ - for_all_rx_queues(adapter, rxo, i) { - /* below erx HW counter can actually wrap around after - * 65535. Driver accumulates a 32-bit value - */ - accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags, - (u16)erx->rx_drops_no_fragments[rxo->q.id]); + /* as erx_v1 is longer than v0, ok to use v1 for v0 access */ + for_all_rx_queues(adapter, rxo, i) { + /* below erx HW counter can actually wrap around after + * 65535. Driver accumulates a 32-bit value + */ + accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags, + (u16)erx->rx_drops_no_fragments \ + [rxo->q.id]); + } } -done: - return; } static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev, @@ -597,16 +646,6 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, hdr, skb_shinfo(skb)->gso_size); if (skb_is_gso_v6(skb) && !lancer_chip(adapter)) AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1); - if (lancer_chip(adapter) && adapter->sli_family == - LANCER_A0_SLI_FAMILY) { - AMAP_SET_BITS(struct amap_eth_hdr_wrb, ipcs, hdr, 1); - if (is_tcp_pkt(skb)) - AMAP_SET_BITS(struct amap_eth_hdr_wrb, - tcpcs, hdr, 1); - else if (is_udp_pkt(skb)) - AMAP_SET_BITS(struct amap_eth_hdr_wrb, - udpcs, hdr, 1); - } } else if (skb->ip_summed == CHECKSUM_PARTIAL) { if (is_tcp_pkt(skb)) AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1); @@ -856,11 +895,15 @@ static int be_vlan_add_vid(struct net_device *netdev, u16 vid) struct be_adapter *adapter = netdev_priv(netdev); int status = 0; - if (!be_physfn(adapter)) { + if (!lancer_chip(adapter) && !be_physfn(adapter)) { status = -EINVAL; goto ret; } + /* Packets with VID 0 are always received by Lancer by default */ + if (lancer_chip(adapter) && vid == 0) + goto ret; + adapter->vlan_tag[vid] = 1; if (adapter->vlans_added <= (adapter->max_vlans + 1)) status = be_vid_config(adapter); @@ -878,11 +921,15 @@ static int be_vlan_rem_vid(struct net_device *netdev, u16 vid) struct be_adapter *adapter = netdev_priv(netdev); int status = 0; - if (!be_physfn(adapter)) { + if (!lancer_chip(adapter) && !be_physfn(adapter)) { status = -EINVAL; goto ret; } + /* Packets with VID 0 are always received by Lancer by default */ + if (lancer_chip(adapter) && vid == 0) + goto ret; + adapter->vlan_tag[vid] = 0; if (adapter->vlans_added <= adapter->max_vlans) status = be_vid_config(adapter); @@ -917,7 +964,7 @@ static void be_set_rx_mode(struct net_device *netdev) /* Enable multicast promisc if num configured exceeds what we support */ if (netdev->flags & IFF_ALLMULTI || - netdev_mc_count(netdev) > BE_MAX_MC) { + netdev_mc_count(netdev) > adapter->max_mcast_mac) { be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); goto done; } @@ -962,6 +1009,9 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) struct be_adapter *adapter = netdev_priv(netdev); struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; int status; + bool active_mac = false; + u32 pmac_id; + u8 old_mac[ETH_ALEN]; if (!sriov_enabled(adapter)) return -EPERM; @@ -970,6 +1020,12 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) return -EINVAL; if (lancer_chip(adapter)) { + status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac, + &pmac_id, vf + 1); + if (!status && active_mac) + be_cmd_pmac_del(adapter, vf_cfg->if_handle, + pmac_id, vf + 1); + status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1); } else { status = be_cmd_pmac_del(adapter, vf_cfg->if_handle, @@ -1062,7 +1118,10 @@ static int be_set_vf_tx_rate(struct net_device *netdev, return -EINVAL; } - status = be_cmd_set_qos(adapter, rate / 10, vf + 1); + if (lancer_chip(adapter)) + status = be_cmd_set_profile_config(adapter, rate / 10, vf + 1); + else + status = be_cmd_set_qos(adapter, rate / 10, vf + 1); if (status) dev_err(&adapter->pdev->dev, @@ -1616,24 +1675,6 @@ static inline int events_get(struct be_eq_obj *eqo) return num; } -static int event_handle(struct be_eq_obj *eqo) -{ - bool rearm = false; - int num = events_get(eqo); - - /* Deal with any spurious interrupts that come without events */ - if (!num) - rearm = true; - - if (num || msix_enabled(eqo->adapter)) - be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num); - - if (num) - napi_schedule(&eqo->napi); - - return num; -} - /* Leaves the EQ is disarmed state */ static void be_eq_clean(struct be_eq_obj *eqo) { @@ -1648,15 +1689,41 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo) struct be_queue_info *rxq = &rxo->q; struct be_queue_info *rx_cq = &rxo->cq; struct be_rx_compl_info *rxcp; + struct be_adapter *adapter = rxo->adapter; + int flush_wait = 0; u16 tail; - /* First cleanup pending rx completions */ - while ((rxcp = be_rx_compl_get(rxo)) != NULL) { - be_rx_compl_discard(rxo, rxcp); - be_cq_notify(rxo->adapter, rx_cq->id, false, 1); + /* Consume pending rx completions. + * Wait for the flush completion (identified by zero num_rcvd) + * to arrive. Notify CQ even when there are no more CQ entries + * for HW to flush partially coalesced CQ entries. + * In Lancer, there is no need to wait for flush compl. + */ + for (;;) { + rxcp = be_rx_compl_get(rxo); + if (rxcp == NULL) { + if (lancer_chip(adapter)) + break; + + if (flush_wait++ > 10 || be_hw_error(adapter)) { + dev_warn(&adapter->pdev->dev, + "did not receive flush compl\n"); + break; + } + be_cq_notify(adapter, rx_cq->id, true, 0); + mdelay(1); + } else { + be_rx_compl_discard(rxo, rxcp); + be_cq_notify(adapter, rx_cq->id, true, 1); + if (rxcp->num_rcvd == 0) + break; + } } - /* Then free posted rx buffer that were not used */ + /* After cleanup, leave the CQ in unarmed state */ + be_cq_notify(adapter, rx_cq->id, false, 0); + + /* Then free posted rx buffers that were not used */ tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len; for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) { page_info = get_rx_page_info(rxo, tail); @@ -1837,12 +1904,13 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) static int be_num_txqs_want(struct be_adapter *adapter) { - if (sriov_want(adapter) || be_is_mc(adapter) || - lancer_chip(adapter) || !be_physfn(adapter) || - adapter->generation == BE_GEN2) + if ((!lancer_chip(adapter) && sriov_want(adapter)) || + be_is_mc(adapter) || + (!lancer_chip(adapter) && !be_physfn(adapter)) || + BE2_chip(adapter)) return 1; else - return MAX_TX_QS; + return adapter->max_tx_queues; } static int be_tx_cqs_create(struct be_adapter *adapter) @@ -1954,12 +2022,31 @@ static int be_rx_cqs_create(struct be_adapter *adapter) static irqreturn_t be_intx(int irq, void *dev) { - struct be_adapter *adapter = dev; - int num_evts; + struct be_eq_obj *eqo = dev; + struct be_adapter *adapter = eqo->adapter; + int num_evts = 0; + + /* IRQ is not expected when NAPI is scheduled as the EQ + * will not be armed. + * But, this can happen on Lancer INTx where it takes + * a while to de-assert INTx or in BE2 where occasionaly + * an interrupt may be raised even when EQ is unarmed. + * If NAPI is already scheduled, then counting & notifying + * events will orphan them. + */ + if (napi_schedule_prep(&eqo->napi)) { + num_evts = events_get(eqo); + __napi_schedule(&eqo->napi); + if (num_evts) + eqo->spurious_intr = 0; + } + be_eq_notify(adapter, eqo->q.id, false, true, num_evts); - /* With INTx only one EQ is used */ - num_evts = event_handle(&adapter->eq_obj[0]); - if (num_evts) + /* Return IRQ_HANDLED only for the the first spurious intr + * after a valid intr to stop the kernel from branding + * this irq as a bad one! + */ + if (num_evts || eqo->spurious_intr++ == 0) return IRQ_HANDLED; else return IRQ_NONE; @@ -1969,7 +2056,8 @@ static irqreturn_t be_msix(int irq, void *dev) { struct be_eq_obj *eqo = dev; - event_handle(eqo); + be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0); + napi_schedule(&eqo->napi); return IRQ_HANDLED; } @@ -2065,9 +2153,11 @@ int be_poll(struct napi_struct *napi, int budget) { struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi); struct be_adapter *adapter = eqo->adapter; - int max_work = 0, work, i; + int max_work = 0, work, i, num_evts; bool tx_done; + num_evts = events_get(eqo); + /* Process all TXQs serviced by this EQ */ for (i = eqo->idx; i < adapter->num_tx_qs; i += adapter->num_evt_qs) { tx_done = be_process_tx(adapter, &adapter->tx_obj[i], @@ -2090,10 +2180,10 @@ int be_poll(struct napi_struct *napi, int budget) if (max_work < budget) { napi_complete(napi); - be_eq_notify(adapter, eqo->q.id, true, false, 0); + be_eq_notify(adapter, eqo->q.id, true, false, num_evts); } else { /* As we'll continue in polling mode, count and clear events */ - be_eq_notify(adapter, eqo->q.id, false, false, events_get(eqo)); + be_eq_notify(adapter, eqo->q.id, false, false, num_evts); } return max_work; } @@ -2104,7 +2194,7 @@ void be_detect_error(struct be_adapter *adapter) u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; u32 i; - if (be_crit_error(adapter)) + if (be_hw_error(adapter)) return; if (lancer_chip(adapter)) { @@ -2177,9 +2267,11 @@ static void be_msix_disable(struct be_adapter *adapter) static uint be_num_rss_want(struct be_adapter *adapter) { u32 num = 0; + if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && - !sriov_want(adapter) && be_physfn(adapter)) { - num = (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; + (lancer_chip(adapter) || + (!sriov_want(adapter) && be_physfn(adapter)))) { + num = adapter->max_rss_queues; num = min_t(u32, num, (u32)netif_get_num_default_rss_queues()); } return num; @@ -2277,10 +2369,10 @@ static int be_irq_register(struct be_adapter *adapter) return status; } - /* INTx */ + /* INTx: only the first EQ is used */ netdev->irq = adapter->pdev->irq; status = request_irq(netdev->irq, be_intx, IRQF_SHARED, netdev->name, - adapter); + &adapter->eq_obj[0]); if (status) { dev_err(&adapter->pdev->dev, "INTx request IRQ failed - err %d\n", status); @@ -2302,7 +2394,7 @@ static void be_irq_unregister(struct be_adapter *adapter) /* INTx */ if (!msix_enabled(adapter)) { - free_irq(netdev->irq, adapter); + free_irq(netdev->irq, &adapter->eq_obj[0]); goto done; } @@ -2343,13 +2435,22 @@ static int be_close(struct net_device *netdev) be_roce_dev_close(adapter); - be_async_mcc_disable(adapter); - if (!lancer_chip(adapter)) be_intr_set(adapter, false); - for_all_evt_queues(adapter, eqo, i) { + for_all_evt_queues(adapter, eqo, i) napi_disable(&eqo->napi); + + be_async_mcc_disable(adapter); + + /* Wait for all pending tx completions to arrive so that + * all tx skbs are freed. + */ + be_tx_compl_clean(adapter); + + be_rx_qs_destroy(adapter); + + for_all_evt_queues(adapter, eqo, i) { if (msix_enabled(adapter)) synchronize_irq(be_msix_vec_get(adapter, eqo)); else @@ -2359,12 +2460,6 @@ static int be_close(struct net_device *netdev) be_irq_unregister(adapter); - /* Wait for all pending tx completions to arrive so that - * all tx skbs are freed. - */ - be_tx_compl_clean(adapter); - - be_rx_qs_destroy(adapter); return 0; } @@ -2579,10 +2674,30 @@ static int be_clear(struct be_adapter *adapter) be_tx_queues_destroy(adapter); be_evt_queues_destroy(adapter); + kfree(adapter->pmac_id); + adapter->pmac_id = NULL; + be_msix_disable(adapter); return 0; } +static void be_get_vf_if_cap_flags(struct be_adapter *adapter, + u32 *cap_flags, u8 domain) +{ + bool profile_present = false; + int status; + + if (lancer_chip(adapter)) { + status = be_cmd_get_profile_config(adapter, cap_flags, domain); + if (!status) + profile_present = true; + } + + if (!profile_present) + *cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST; +} + static int be_vf_setup_init(struct be_adapter *adapter) { struct be_vf_cfg *vf_cfg; @@ -2634,9 +2749,13 @@ static int be_vf_setup(struct be_adapter *adapter) if (status) goto err; - cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | - BE_IF_FLAGS_MULTICAST; for_all_vfs(adapter, vf_cfg, vf) { + be_get_vf_if_cap_flags(adapter, &cap_flags, vf + 1); + + en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED | + BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST); + status = be_cmd_if_create(adapter, cap_flags, en_flags, &vf_cfg->if_handle, vf + 1); if (status) @@ -2661,6 +2780,8 @@ static int be_vf_setup(struct be_adapter *adapter) if (status) goto err; vf_cfg->def_vid = def_vlan; + + be_cmd_enable_vf(adapter, vf + 1); } return 0; err: @@ -2674,7 +2795,10 @@ static void be_setup_init(struct be_adapter *adapter) adapter->if_handle = -1; adapter->be3_native = false; adapter->promiscuous = false; - adapter->eq_next_idx = 0; + if (be_physfn(adapter)) + adapter->cmd_privileges = MAX_PRIVILEGES; + else + adapter->cmd_privileges = MIN_PRIVILEGES; } static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle, @@ -2712,12 +2836,93 @@ static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle, return status; } +static void be_get_resources(struct be_adapter *adapter) +{ + int status; + bool profile_present = false; + + if (lancer_chip(adapter)) { + status = be_cmd_get_func_config(adapter); + + if (!status) + profile_present = true; + } + + if (profile_present) { + /* Sanity fixes for Lancer */ + adapter->max_pmac_cnt = min_t(u16, adapter->max_pmac_cnt, + BE_UC_PMAC_COUNT); + adapter->max_vlans = min_t(u16, adapter->max_vlans, + BE_NUM_VLANS_SUPPORTED); + adapter->max_mcast_mac = min_t(u16, adapter->max_mcast_mac, + BE_MAX_MC); + adapter->max_tx_queues = min_t(u16, adapter->max_tx_queues, + MAX_TX_QS); + adapter->max_rss_queues = min_t(u16, adapter->max_rss_queues, + BE3_MAX_RSS_QS); + adapter->max_event_queues = min_t(u16, + adapter->max_event_queues, + BE3_MAX_RSS_QS); + + if (adapter->max_rss_queues && + adapter->max_rss_queues == adapter->max_rx_queues) + adapter->max_rss_queues -= 1; + + if (adapter->max_event_queues < adapter->max_rss_queues) + adapter->max_rss_queues = adapter->max_event_queues; + + } else { + if (be_physfn(adapter)) + adapter->max_pmac_cnt = BE_UC_PMAC_COUNT; + else + adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT; + + if (adapter->function_mode & FLEX10_MODE) + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8; + else + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; + + adapter->max_mcast_mac = BE_MAX_MC; + adapter->max_tx_queues = MAX_TX_QS; + adapter->max_rss_queues = (adapter->be3_native) ? + BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; + adapter->max_event_queues = BE3_MAX_RSS_QS; + + adapter->if_cap_flags = BE_IF_FLAGS_UNTAGGED | + BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST | + BE_IF_FLAGS_PASS_L3L4_ERRORS | + BE_IF_FLAGS_MCAST_PROMISCUOUS | + BE_IF_FLAGS_VLAN_PROMISCUOUS | + BE_IF_FLAGS_PROMISCUOUS; + + if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) + adapter->if_cap_flags |= BE_IF_FLAGS_RSS; + } +} + /* Routine to query per function resource limits */ static int be_get_config(struct be_adapter *adapter) { - int pos; + int pos, status; u16 dev_num_vfs; + status = be_cmd_query_fw_cfg(adapter, &adapter->port_num, + &adapter->function_mode, + &adapter->function_caps); + if (status) + goto err; + + be_get_resources(adapter); + + /* primary mac needs 1 pmac entry */ + adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1, + sizeof(u32), GFP_KERNEL); + if (!adapter->pmac_id) { + status = -ENOMEM; + goto err; + } + pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV); if (pos) { pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF, @@ -2726,13 +2931,14 @@ static int be_get_config(struct be_adapter *adapter) dev_num_vfs = min_t(u16, dev_num_vfs, MAX_VFS); adapter->dev_num_vfs = dev_num_vfs; } - return 0; +err: + return status; } static int be_setup(struct be_adapter *adapter) { struct device *dev = &adapter->pdev->dev; - u32 cap_flags, en_flags; + u32 en_flags; u32 tx_fc, rx_fc; int status; u8 mac[ETH_ALEN]; @@ -2740,9 +2946,12 @@ static int be_setup(struct be_adapter *adapter) be_setup_init(adapter); - be_get_config(adapter); + if (!lancer_chip(adapter)) + be_cmd_req_native_mode(adapter); - be_cmd_req_native_mode(adapter); + status = be_get_config(adapter); + if (status) + goto err; be_msix_enable(adapter); @@ -2762,24 +2971,22 @@ static int be_setup(struct be_adapter *adapter) if (status) goto err; + be_cmd_get_fn_privileges(adapter, &adapter->cmd_privileges, 0); + /* In UMC mode FW does not return right privileges. + * Override with correct privilege equivalent to PF. + */ + if (be_is_mc(adapter)) + adapter->cmd_privileges = MAX_PRIVILEGES; + en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS; - cap_flags = en_flags | BE_IF_FLAGS_MCAST_PROMISCUOUS | - BE_IF_FLAGS_VLAN_PROMISCUOUS | BE_IF_FLAGS_PROMISCUOUS; - if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) { - cap_flags |= BE_IF_FLAGS_RSS; + if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) en_flags |= BE_IF_FLAGS_RSS; - } - if (lancer_chip(adapter) && !be_physfn(adapter)) { - en_flags = BE_IF_FLAGS_UNTAGGED | - BE_IF_FLAGS_BROADCAST | - BE_IF_FLAGS_MULTICAST; - cap_flags = en_flags; - } + en_flags = en_flags & adapter->if_cap_flags; - status = be_cmd_if_create(adapter, cap_flags, en_flags, + status = be_cmd_if_create(adapter, adapter->if_cap_flags, en_flags, &adapter->if_handle, 0); if (status != 0) goto err; @@ -2827,8 +3034,8 @@ static int be_setup(struct be_adapter *adapter) dev_warn(dev, "device doesn't support SRIOV\n"); } - be_cmd_get_phy_info(adapter); - if (be_pause_supported(adapter)) + status = be_cmd_get_phy_info(adapter); + if (!status && be_pause_supported(adapter)) adapter->phy.fc_autoneg = 1; schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); @@ -2846,8 +3053,10 @@ static void be_netpoll(struct net_device *netdev) struct be_eq_obj *eqo; int i; - for_all_evt_queues(adapter, eqo, i) - event_handle(eqo); + for_all_evt_queues(adapter, eqo, i) { + be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0); + napi_schedule(&eqo->napi); + } return; } @@ -2895,7 +3104,7 @@ static bool is_comp_in_ufi(struct be_adapter *adapter, int i = 0, img_type = 0; struct flash_section_info_g2 *fsec_g2 = NULL; - if (adapter->generation != BE_GEN3) + if (BE2_chip(adapter)) fsec_g2 = (struct flash_section_info_g2 *)fsec; for (i = 0; i < MAX_FLASH_COMP; i++) { @@ -2928,7 +3137,49 @@ struct flash_section_info *get_fsec_info(struct be_adapter *adapter, return NULL; } -static int be_flash_data(struct be_adapter *adapter, +static int be_flash(struct be_adapter *adapter, const u8 *img, + struct be_dma_mem *flash_cmd, int optype, int img_size) +{ + u32 total_bytes = 0, flash_op, num_bytes = 0; + int status = 0; + struct be_cmd_write_flashrom *req = flash_cmd->va; + + total_bytes = img_size; + while (total_bytes) { + num_bytes = min_t(u32, 32*1024, total_bytes); + + total_bytes -= num_bytes; + + if (!total_bytes) { + if (optype == OPTYPE_PHY_FW) + flash_op = FLASHROM_OPER_PHY_FLASH; + else + flash_op = FLASHROM_OPER_FLASH; + } else { + if (optype == OPTYPE_PHY_FW) + flash_op = FLASHROM_OPER_PHY_SAVE; + else + flash_op = FLASHROM_OPER_SAVE; + } + + memcpy(req->data_buf, img, num_bytes); + img += num_bytes; + status = be_cmd_write_flashrom(adapter, flash_cmd, optype, + flash_op, num_bytes); + if (status) { + if (status == ILLEGAL_IOCTL_REQ && + optype == OPTYPE_PHY_FW) + break; + dev_err(&adapter->pdev->dev, + "cmd to write to flash rom failed.\n"); + return status; + } + } + return 0; +} + +/* For BE2 and BE3 */ +static int be_flash_BEx(struct be_adapter *adapter, const struct firmware *fw, struct be_dma_mem *flash_cmd, int num_of_images) @@ -2936,12 +3187,9 @@ static int be_flash_data(struct be_adapter *adapter, { int status = 0, i, filehdr_size = 0; int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); - u32 total_bytes = 0, flash_op; - int num_bytes; const u8 *p = fw->data; - struct be_cmd_write_flashrom *req = flash_cmd->va; const struct flash_comp *pflashcomp; - int num_comp, hdr_size; + int num_comp, redboot; struct flash_section_info *fsec = NULL; struct flash_comp gen3_flash_types[] = { @@ -2986,7 +3234,7 @@ static int be_flash_data(struct be_adapter *adapter, FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_FCoE} }; - if (adapter->generation == BE_GEN3) { + if (BE3_chip(adapter)) { pflashcomp = gen3_flash_types; filehdr_size = sizeof(struct flash_file_hdr_g3); num_comp = ARRAY_SIZE(gen3_flash_types); @@ -2995,6 +3243,7 @@ static int be_flash_data(struct be_adapter *adapter, filehdr_size = sizeof(struct flash_file_hdr_g2); num_comp = ARRAY_SIZE(gen2_flash_types); } + /* Get flash section info*/ fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); if (!fsec) { @@ -3010,70 +3259,105 @@ static int be_flash_data(struct be_adapter *adapter, memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) continue; - if (pflashcomp[i].optype == OPTYPE_PHY_FW) { - if (!phy_flashing_required(adapter)) + if (pflashcomp[i].optype == OPTYPE_PHY_FW && + !phy_flashing_required(adapter)) continue; - } - - hdr_size = filehdr_size + - (num_of_images * sizeof(struct image_hdr)); - if ((pflashcomp[i].optype == OPTYPE_REDBOOT) && - (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset, - pflashcomp[i].size, hdr_size))) - continue; + if (pflashcomp[i].optype == OPTYPE_REDBOOT) { + redboot = be_flash_redboot(adapter, fw->data, + pflashcomp[i].offset, pflashcomp[i].size, + filehdr_size + img_hdrs_size); + if (!redboot) + continue; + } - /* Flash the component */ p = fw->data; p += filehdr_size + pflashcomp[i].offset + img_hdrs_size; if (p + pflashcomp[i].size > fw->data + fw->size) return -1; - total_bytes = pflashcomp[i].size; - while (total_bytes) { - if (total_bytes > 32*1024) - num_bytes = 32*1024; - else - num_bytes = total_bytes; - total_bytes -= num_bytes; - if (!total_bytes) { - if (pflashcomp[i].optype == OPTYPE_PHY_FW) - flash_op = FLASHROM_OPER_PHY_FLASH; - else - flash_op = FLASHROM_OPER_FLASH; - } else { - if (pflashcomp[i].optype == OPTYPE_PHY_FW) - flash_op = FLASHROM_OPER_PHY_SAVE; - else - flash_op = FLASHROM_OPER_SAVE; - } - memcpy(req->params.data_buf, p, num_bytes); - p += num_bytes; - status = be_cmd_write_flashrom(adapter, flash_cmd, - pflashcomp[i].optype, flash_op, num_bytes); - if (status) { - if ((status == ILLEGAL_IOCTL_REQ) && - (pflashcomp[i].optype == - OPTYPE_PHY_FW)) - break; - dev_err(&adapter->pdev->dev, - "cmd to write to flash rom failed.\n"); - return -1; - } + + status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype, + pflashcomp[i].size); + if (status) { + dev_err(&adapter->pdev->dev, + "Flashing section type %d failed.\n", + pflashcomp[i].img_type); + return status; } } return 0; } -static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr) +static int be_flash_skyhawk(struct be_adapter *adapter, + const struct firmware *fw, + struct be_dma_mem *flash_cmd, int num_of_images) { - if (fhdr == NULL) - return 0; - if (fhdr->build[0] == '3') - return BE_GEN3; - else if (fhdr->build[0] == '2') - return BE_GEN2; - else - return 0; + int status = 0, i, filehdr_size = 0; + int img_offset, img_size, img_optype, redboot; + int img_hdrs_size = num_of_images * sizeof(struct image_hdr); + const u8 *p = fw->data; + struct flash_section_info *fsec = NULL; + + filehdr_size = sizeof(struct flash_file_hdr_g3); + fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); + if (!fsec) { + dev_err(&adapter->pdev->dev, + "Invalid Cookie. UFI corrupted ?\n"); + return -1; + } + + for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) { + img_offset = le32_to_cpu(fsec->fsec_entry[i].offset); + img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size); + + switch (le32_to_cpu(fsec->fsec_entry[i].type)) { + case IMAGE_FIRMWARE_iSCSI: + img_optype = OPTYPE_ISCSI_ACTIVE; + break; + case IMAGE_BOOT_CODE: + img_optype = OPTYPE_REDBOOT; + break; + case IMAGE_OPTION_ROM_ISCSI: + img_optype = OPTYPE_BIOS; + break; + case IMAGE_OPTION_ROM_PXE: + img_optype = OPTYPE_PXE_BIOS; + break; + case IMAGE_OPTION_ROM_FCoE: + img_optype = OPTYPE_FCOE_BIOS; + break; + case IMAGE_FIRMWARE_BACKUP_iSCSI: + img_optype = OPTYPE_ISCSI_BACKUP; + break; + case IMAGE_NCSI: + img_optype = OPTYPE_NCSI_FW; + break; + default: + continue; + } + + if (img_optype == OPTYPE_REDBOOT) { + redboot = be_flash_redboot(adapter, fw->data, + img_offset, img_size, + filehdr_size + img_hdrs_size); + if (!redboot) + continue; + } + + p = fw->data; + p += filehdr_size + img_offset + img_hdrs_size; + if (p + img_size > fw->data + fw->size) + return -1; + + status = be_flash(adapter, p, flash_cmd, img_optype, img_size); + if (status) { + dev_err(&adapter->pdev->dev, + "Flashing section type %d failed.\n", + fsec->fsec_entry[i].type); + return status; + } + } + return 0; } static int lancer_wait_idle(struct be_adapter *adapter) @@ -3207,6 +3491,28 @@ lancer_fw_exit: return status; } +#define UFI_TYPE2 2 +#define UFI_TYPE3 3 +#define UFI_TYPE4 4 +static int be_get_ufi_type(struct be_adapter *adapter, + struct flash_file_hdr_g2 *fhdr) +{ + if (fhdr == NULL) + goto be_get_ufi_exit; + + if (skyhawk_chip(adapter) && fhdr->build[0] == '4') + return UFI_TYPE4; + else if (BE3_chip(adapter) && fhdr->build[0] == '3') + return UFI_TYPE3; + else if (BE2_chip(adapter) && fhdr->build[0] == '2') + return UFI_TYPE2; + +be_get_ufi_exit: + dev_err(&adapter->pdev->dev, + "UFI and Interface are not compatible for flashing\n"); + return -1; +} + static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) { struct flash_file_hdr_g2 *fhdr; @@ -3214,12 +3520,9 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) struct image_hdr *img_hdr_ptr = NULL; struct be_dma_mem flash_cmd; const u8 *p; - int status = 0, i = 0, num_imgs = 0; - - p = fw->data; - fhdr = (struct flash_file_hdr_g2 *) p; + int status = 0, i = 0, num_imgs = 0, ufi_type = 0; - flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; + flash_cmd.size = sizeof(struct be_cmd_write_flashrom); flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, &flash_cmd.dma, GFP_KERNEL); if (!flash_cmd.va) { @@ -3229,27 +3532,32 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) goto be_fw_exit; } - if ((adapter->generation == BE_GEN3) && - (get_ufigen_type(fhdr) == BE_GEN3)) { - fhdr3 = (struct flash_file_hdr_g3 *) fw->data; - num_imgs = le32_to_cpu(fhdr3->num_imgs); - for (i = 0; i < num_imgs; i++) { - img_hdr_ptr = (struct image_hdr *) (fw->data + - (sizeof(struct flash_file_hdr_g3) + - i * sizeof(struct image_hdr))); - if (le32_to_cpu(img_hdr_ptr->imageid) == 1) - status = be_flash_data(adapter, fw, &flash_cmd, - num_imgs); + p = fw->data; + fhdr = (struct flash_file_hdr_g2 *)p; + + ufi_type = be_get_ufi_type(adapter, fhdr); + + fhdr3 = (struct flash_file_hdr_g3 *)fw->data; + num_imgs = le32_to_cpu(fhdr3->num_imgs); + for (i = 0; i < num_imgs; i++) { + img_hdr_ptr = (struct image_hdr *)(fw->data + + (sizeof(struct flash_file_hdr_g3) + + i * sizeof(struct image_hdr))); + if (le32_to_cpu(img_hdr_ptr->imageid) == 1) { + if (ufi_type == UFI_TYPE4) + status = be_flash_skyhawk(adapter, fw, + &flash_cmd, num_imgs); + else if (ufi_type == UFI_TYPE3) + status = be_flash_BEx(adapter, fw, &flash_cmd, + num_imgs); } - } else if ((adapter->generation == BE_GEN2) && - (get_ufigen_type(fhdr) == BE_GEN2)) { - status = be_flash_data(adapter, fw, &flash_cmd, 0); - } else { - dev_err(&adapter->pdev->dev, - "UFI and Interface are not compatible for flashing\n"); - status = -1; } + if (ufi_type == UFI_TYPE2) + status = be_flash_BEx(adapter, fw, &flash_cmd, 0); + else if (ufi_type == -1) + status = -1; + dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma); if (status) { @@ -3344,80 +3652,47 @@ static void be_netdev_init(struct net_device *netdev) static void be_unmap_pci_bars(struct be_adapter *adapter) { - if (adapter->csr) - iounmap(adapter->csr); if (adapter->db) - iounmap(adapter->db); - if (adapter->roce_db.base) - pci_iounmap(adapter->pdev, adapter->roce_db.base); + pci_iounmap(adapter->pdev, adapter->db); } -static int lancer_roce_map_pci_bars(struct be_adapter *adapter) +static int db_bar(struct be_adapter *adapter) { - struct pci_dev *pdev = adapter->pdev; - u8 __iomem *addr; - - addr = pci_iomap(pdev, 2, 0); - if (addr == NULL) - return -ENOMEM; + if (lancer_chip(adapter) || !be_physfn(adapter)) + return 0; + else + return 4; +} - adapter->roce_db.base = addr; - adapter->roce_db.io_addr = pci_resource_start(pdev, 2); - adapter->roce_db.size = 8192; - adapter->roce_db.total_size = pci_resource_len(pdev, 2); +static int be_roce_map_pci_bars(struct be_adapter *adapter) +{ + if (skyhawk_chip(adapter)) { + adapter->roce_db.size = 4096; + adapter->roce_db.io_addr = pci_resource_start(adapter->pdev, + db_bar(adapter)); + adapter->roce_db.total_size = pci_resource_len(adapter->pdev, + db_bar(adapter)); + } return 0; } static int be_map_pci_bars(struct be_adapter *adapter) { u8 __iomem *addr; - int db_reg; - - if (lancer_chip(adapter)) { - if (be_type_2_3(adapter)) { - addr = ioremap_nocache( - pci_resource_start(adapter->pdev, 0), - pci_resource_len(adapter->pdev, 0)); - if (addr == NULL) - return -ENOMEM; - adapter->db = addr; - } - if (adapter->if_type == SLI_INTF_TYPE_3) { - if (lancer_roce_map_pci_bars(adapter)) - goto pci_map_err; - } - return 0; - } + u32 sli_intf; - if (be_physfn(adapter)) { - addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2), - pci_resource_len(adapter->pdev, 2)); - if (addr == NULL) - return -ENOMEM; - adapter->csr = addr; - } + pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); + adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> + SLI_INTF_IF_TYPE_SHIFT; - if (adapter->generation == BE_GEN2) { - db_reg = 4; - } else { - if (be_physfn(adapter)) - db_reg = 4; - else - db_reg = 0; - } - addr = ioremap_nocache(pci_resource_start(adapter->pdev, db_reg), - pci_resource_len(adapter->pdev, db_reg)); + addr = pci_iomap(adapter->pdev, db_bar(adapter), 0); if (addr == NULL) goto pci_map_err; adapter->db = addr; - if (adapter->sli_family == SKYHAWK_SLI_FAMILY) { - adapter->roce_db.size = 4096; - adapter->roce_db.io_addr = - pci_resource_start(adapter->pdev, db_reg); - adapter->roce_db.total_size = - pci_resource_len(adapter->pdev, db_reg); - } + + be_roce_map_pci_bars(adapter); return 0; + pci_map_err: be_unmap_pci_bars(adapter); return -ENOMEM; @@ -3437,7 +3712,6 @@ static void be_ctrl_cleanup(struct be_adapter *adapter) if (mem->va) dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va, mem->dma); - kfree(adapter->pmac_id); } static int be_ctrl_init(struct be_adapter *adapter) @@ -3445,8 +3719,14 @@ static int be_ctrl_init(struct be_adapter *adapter) struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced; struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem; struct be_dma_mem *rx_filter = &adapter->rx_filter; + u32 sli_intf; int status; + pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); + adapter->sli_family = (sli_intf & SLI_INTF_FAMILY_MASK) >> + SLI_INTF_FAMILY_SHIFT; + adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; + status = be_map_pci_bars(adapter); if (status) goto done; @@ -3473,13 +3753,6 @@ static int be_ctrl_init(struct be_adapter *adapter) goto free_mbox; } memset(rx_filter->va, 0, rx_filter->size); - - /* primary mac needs 1 pmac entry */ - adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1, - sizeof(*adapter->pmac_id), GFP_KERNEL); - if (!adapter->pmac_id) - return -ENOMEM; - mutex_init(&adapter->mbox_lock); spin_lock_init(&adapter->mcc_lock); spin_lock_init(&adapter->mcc_cq_lock); @@ -3512,14 +3785,14 @@ static int be_stats_init(struct be_adapter *adapter) { struct be_dma_mem *cmd = &adapter->stats_cmd; - if (adapter->generation == BE_GEN2) { + if (lancer_chip(adapter)) + cmd->size = sizeof(struct lancer_cmd_req_pport_stats); + else if (BE2_chip(adapter)) cmd->size = sizeof(struct be_cmd_req_get_stats_v0); - } else { - if (lancer_chip(adapter)) - cmd->size = sizeof(struct lancer_cmd_req_pport_stats); - else - cmd->size = sizeof(struct be_cmd_req_get_stats_v1); - } + else + /* BE3 and Skyhawk */ + cmd->size = sizeof(struct be_cmd_req_get_stats_v1); + cmd->va = dma_alloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma, GFP_KERNEL); if (cmd->va == NULL) @@ -3528,7 +3801,7 @@ static int be_stats_init(struct be_adapter *adapter) return 0; } -static void __devexit be_remove(struct pci_dev *pdev) +static void be_remove(struct pci_dev *pdev) { struct be_adapter *adapter = pci_get_drvdata(pdev); @@ -3573,6 +3846,9 @@ u32 be_get_fw_log_level(struct be_adapter *adapter) u32 level = 0; int j; + if (lancer_chip(adapter)) + return 0; + memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size, @@ -3598,26 +3874,12 @@ u32 be_get_fw_log_level(struct be_adapter *adapter) err: return level; } + static int be_get_initial_config(struct be_adapter *adapter) { int status; u32 level; - status = be_cmd_query_fw_cfg(adapter, &adapter->port_num, - &adapter->function_mode, &adapter->function_caps); - if (status) - return status; - - if (adapter->function_mode & FLEX10_MODE) - adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8; - else - adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; - - if (be_physfn(adapter)) - adapter->max_pmac_cnt = BE_UC_PMAC_COUNT; - else - adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT; - status = be_cmd_get_cntl_attributes(adapter); if (status) return status; @@ -3642,55 +3904,6 @@ static int be_get_initial_config(struct be_adapter *adapter) return 0; } -static int be_dev_type_check(struct be_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - u32 sli_intf = 0, if_type; - - switch (pdev->device) { - case BE_DEVICE_ID1: - case OC_DEVICE_ID1: - adapter->generation = BE_GEN2; - break; - case BE_DEVICE_ID2: - case OC_DEVICE_ID2: - adapter->generation = BE_GEN3; - break; - case OC_DEVICE_ID3: - case OC_DEVICE_ID4: - pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf); - adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> - SLI_INTF_IF_TYPE_SHIFT; - if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> - SLI_INTF_IF_TYPE_SHIFT; - if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) || - !be_type_2_3(adapter)) { - dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n"); - return -EINVAL; - } - adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >> - SLI_INTF_FAMILY_SHIFT); - adapter->generation = BE_GEN3; - break; - case OC_DEVICE_ID5: - pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf); - if ((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) { - dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n"); - return -EINVAL; - } - adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >> - SLI_INTF_FAMILY_SHIFT); - adapter->generation = BE_GEN3; - break; - default: - adapter->generation = 0; - } - - pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); - adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; - return 0; -} - static int lancer_recover_func(struct be_adapter *adapter) { int status; @@ -3721,8 +3934,9 @@ static int lancer_recover_func(struct be_adapter *adapter) "Adapter SLIPORT recovery succeeded\n"); return 0; err: - dev_err(&adapter->pdev->dev, - "Adapter SLIPORT recovery failed\n"); + if (adapter->eeh_error) + dev_err(&adapter->pdev->dev, + "Adapter SLIPORT recovery failed\n"); return status; } @@ -3820,8 +4034,7 @@ static inline char *func_name(struct be_adapter *adapter) return be_physfn(adapter) ? "PF" : "VF"; } -static int __devinit be_probe(struct pci_dev *pdev, - const struct pci_device_id *pdev_id) +static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) { int status = 0; struct be_adapter *adapter; @@ -3845,11 +4058,6 @@ static int __devinit be_probe(struct pci_dev *pdev, adapter = netdev_priv(netdev); adapter->pdev = pdev; pci_set_drvdata(pdev, adapter); - - status = be_dev_type_check(adapter); - if (status) - goto free_netdev; - adapter->netdev = netdev; SET_NETDEV_DEV(netdev, &pdev->dev); @@ -4023,9 +4231,6 @@ static void be_shutdown(struct pci_dev *pdev) netif_device_detach(adapter->netdev); - if (adapter->wol) - be_setup_wol(adapter, true); - be_cmd_reset_function(adapter); pci_disable_device(pdev); @@ -4061,9 +4266,13 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, /* The error could cause the FW to trigger a flash debug dump. * Resetting the card while flash dump is in progress - * can cause it not to recover; wait for it to finish + * can cause it not to recover; wait for it to finish. + * Wait only for first function as it is needed only once per + * adapter. */ - ssleep(30); + if (pdev->devfn == 0) + ssleep(30); + return PCI_ERS_RESULT_NEED_RESET; } diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c index deecc44b3617..55d32aa0a093 100644 --- a/drivers/net/ethernet/emulex/benet/be_roce.c +++ b/drivers/net/ethernet/emulex/benet/be_roce.c @@ -47,10 +47,7 @@ static void _be_roce_dev_add(struct be_adapter *adapter) dev_info.dpp_unmapped_len = 0; } dev_info.pdev = adapter->pdev; - if (adapter->sli_family == SKYHAWK_SLI_FAMILY) - dev_info.db = adapter->db; - else - dev_info.db = adapter->roce_db.base; + dev_info.db = adapter->db; dev_info.unmapped_db = adapter->roce_db.io_addr; dev_info.db_page_size = adapter->roce_db.size; dev_info.db_total_size = adapter->roce_db.total_size; diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 94b7bfcdb24e..8db1c06008de 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -665,7 +665,7 @@ static void ethoc_mdio_poll(struct net_device *dev) { } -static int __devinit ethoc_mdio_probe(struct net_device *dev) +static int ethoc_mdio_probe(struct net_device *dev) { struct ethoc *priv = netdev_priv(dev); struct phy_device *phy; @@ -905,7 +905,7 @@ static const struct net_device_ops ethoc_netdev_ops = { * ethoc_probe - initialize OpenCores ethernet MAC * pdev: platform device */ -static int __devinit ethoc_probe(struct platform_device *pdev) +static int ethoc_probe(struct platform_device *pdev) { struct net_device *netdev = NULL; struct resource *res = NULL; @@ -1143,7 +1143,7 @@ out: * ethoc_remove - shutdown OpenCores ethernet MAC * @pdev: platform device */ -static int __devexit ethoc_remove(struct platform_device *pdev) +static int ethoc_remove(struct platform_device *pdev) { struct net_device *netdev = platform_get_drvdata(pdev); struct ethoc *priv = netdev_priv(netdev); @@ -1190,7 +1190,7 @@ MODULE_DEVICE_TABLE(of, ethoc_match); static struct platform_driver ethoc_driver = { .probe = ethoc_probe, - .remove = __devexit_p(ethoc_remove), + .remove = ethoc_remove, .suspend = ethoc_suspend, .resume = ethoc_resume, .driver = { diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c index 0e4a0ac86aa8..c706b7a9397e 100644 --- a/drivers/net/ethernet/fealnx.c +++ b/drivers/net/ethernet/fealnx.c @@ -92,7 +92,7 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; #include <asm/byteorder.h> /* These identify the driver base version and may not be removed. */ -static const char version[] __devinitconst = +static const char version[] = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n"; @@ -150,7 +150,7 @@ struct chip_info { int flags; }; -static const struct chip_info skel_netdrv_tbl[] __devinitconst = { +static const struct chip_info skel_netdrv_tbl[] = { { "100/10M Ethernet PCI Adapter", HAS_MII_XCVR }, { "100/10M Ethernet PCI Adapter", HAS_CHIP_XCVR }, { "1000/100/10M Ethernet PCI Adapter", HAS_MII_XCVR }, @@ -477,8 +477,8 @@ static const struct net_device_ops netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit fealnx_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int fealnx_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct netdev_private *np; int i, option, err, irq; @@ -684,7 +684,7 @@ err_out_res: } -static void __devexit fealnx_remove_one(struct pci_dev *pdev) +static void fealnx_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -1950,7 +1950,7 @@ static struct pci_driver fealnx_driver = { .name = "fealnx", .id_table = fealnx_pci_tbl, .probe = fealnx_init_one, - .remove = __devexit_p(fealnx_remove_one), + .remove = fealnx_remove_one, }; static int __init fealnx_init(void) diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index feff51664dcf..ec490d741fc0 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -92,4 +92,12 @@ config GIANFAR This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx, and MPC86xx family of chips, and the FEC on the 8540. +config FEC_PTP + bool "PTP Hardware Clock (PHC)" + depends on FEC && ARCH_MXC && !SOC_IMX25 && !SOC_IMX27 && !SOC_IMX35 && !SOC_IMX5 + select PTP_1588_CLOCK + --help--- + Say Y here if you want to use PTP Hardware Clock (PHC) in the + driver. Only the basic clock operations have been implemented. + endif # NET_VENDOR_FREESCALE diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile index 3d1839afff65..d4d19b3d00ae 100644 --- a/drivers/net/ethernet/freescale/Makefile +++ b/drivers/net/ethernet/freescale/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_FEC) += fec.o +obj-$(CONFIG_FEC_PTP) += fec_ptp.o obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y) obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index fffd20528b5d..0704bcab178a 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c @@ -140,21 +140,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); #endif #endif /* CONFIG_M5272 */ -/* The number of Tx and Rx buffers. These are allocated from the page - * pool. The code may assume these are power of two, so it it best - * to keep them that size. - * We don't need to allocate pages for the transmitter. We just use - * the skbuffer directly. - */ -#define FEC_ENET_RX_PAGES 8 -#define FEC_ENET_RX_FRSIZE 2048 -#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) -#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) -#define FEC_ENET_TX_FRSIZE 2048 -#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE) -#define TX_RING_SIZE 16 /* Must be power of two */ -#define TX_RING_MOD_MASK 15 /* for this to work */ - #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE) #error "FEC: descriptor ring size constants too large" #endif @@ -179,9 +164,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); #define PKT_MINBUF_SIZE 64 #define PKT_MAXBLR_SIZE 1520 -/* This device has up to three irqs on some platforms */ -#define FEC_IRQ_NUM 3 - /* * The 5270/5271/5280/5282/532x RX control register also contains maximum frame * size bits. Other FEC hardware does not, so we need to take that into @@ -194,61 +176,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); #define OPT_FRAME_SIZE 0 #endif -/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and - * tx_bd_base always point to the base of the buffer descriptors. The - * cur_rx and cur_tx point to the currently available buffer. - * The dirty_tx tracks the current buffer that is being sent by the - * controller. The cur_tx and dirty_tx are equal under both completely - * empty and completely full conditions. The empty/ready indicator in - * the buffer descriptor determines the actual condition. - */ -struct fec_enet_private { - /* Hardware registers of the FEC device */ - void __iomem *hwp; - - struct net_device *netdev; - - struct clk *clk_ipg; - struct clk *clk_ahb; - - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ - unsigned char *tx_bounce[TX_RING_SIZE]; - struct sk_buff* tx_skbuff[TX_RING_SIZE]; - struct sk_buff* rx_skbuff[RX_RING_SIZE]; - ushort skb_cur; - ushort skb_dirty; - - /* CPM dual port RAM relative addresses */ - dma_addr_t bd_dma; - /* Address of Rx and Tx buffers */ - struct bufdesc *rx_bd_base; - struct bufdesc *tx_bd_base; - /* The next free ring entry */ - struct bufdesc *cur_rx, *cur_tx; - /* The ring entries to be free()ed */ - struct bufdesc *dirty_tx; - - uint tx_full; - /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ - spinlock_t hw_lock; - - struct platform_device *pdev; - - int opened; - int dev_id; - - /* Phylib and MDIO interface */ - struct mii_bus *mii_bus; - struct phy_device *phy_dev; - int mii_timeout; - uint phy_speed; - phy_interface_t phy_interface; - int link; - int full_duplex; - struct completion mdio_done; - int irq[FEC_IRQ_NUM]; -}; - /* FEC MII MMFR bits definition */ #define FEC_MMFR_ST (1 << 30) #define FEC_MMFR_OP_READ (2 << 28) @@ -353,6 +280,17 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | BD_ENET_TX_LAST | BD_ENET_TX_TC); bdp->cbd_sc = status; +#ifdef CONFIG_FEC_PTP + bdp->cbd_bdu = 0; + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && + fep->hwts_tx_en)) { + bdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT); + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + } else { + + bdp->cbd_esc = BD_ENET_TX_INT; + } +#endif /* Trigger transmission start */ writel(0, fep->hwp + FEC_X_DES_ACTIVE); @@ -510,10 +448,17 @@ fec_restart(struct net_device *ndev, int duplex) writel(1 << 8, fep->hwp + FEC_X_WMRK); } +#ifdef CONFIG_FEC_PTP + ecntl |= (1 << 4); +#endif + /* And last, enable the transmit and receive processing */ writel(ecntl, fep->hwp + FEC_ECNTRL); writel(0, fep->hwp + FEC_R_DES_ACTIVE); +#ifdef CONFIG_FEC_PTP + fec_ptp_start_cyclecounter(ndev); +#endif /* Enable interrupts we wish to service */ writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); } @@ -599,6 +544,19 @@ fec_enet_tx(struct net_device *ndev) ndev->stats.tx_packets++; } +#ifdef CONFIG_FEC_PTP + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { + struct skb_shared_hwtstamps shhwtstamps; + unsigned long flags; + + memset(&shhwtstamps, 0, sizeof(shhwtstamps)); + spin_lock_irqsave(&fep->tmreg_lock, flags); + shhwtstamps.hwtstamp = ns_to_ktime( + timecounter_cyc2time(&fep->tc, bdp->ts)); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + skb_tstamp_tx(skb, &shhwtstamps); + } +#endif if (status & BD_ENET_TX_READY) printk("HEY! Enet xmit interrupt and TX_READY.\n"); @@ -725,6 +683,21 @@ fec_enet_rx(struct net_device *ndev) skb_put(skb, pkt_len - 4); /* Make room */ skb_copy_to_linear_data(skb, data, pkt_len - 4); skb->protocol = eth_type_trans(skb, ndev); +#ifdef CONFIG_FEC_PTP + /* Get receive timestamp from the skb */ + if (fep->hwts_rx_en) { + struct skb_shared_hwtstamps *shhwtstamps = + skb_hwtstamps(skb); + unsigned long flags; + + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); + + spin_lock_irqsave(&fep->tmreg_lock, flags); + shhwtstamps->hwtstamp = ns_to_ktime( + timecounter_cyc2time(&fep->tc, bdp->ts)); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + } +#endif if (!skb_defer_rx_timestamp(skb)) netif_rx(skb); } @@ -739,6 +712,12 @@ rx_processing_done: status |= BD_ENET_RX_EMPTY; bdp->cbd_sc = status; +#ifdef CONFIG_FEC_PTP + bdp->cbd_esc = BD_ENET_RX_INT; + bdp->cbd_prot = 0; + bdp->cbd_bdu = 0; +#endif + /* Update BD pointer to next entry */ if (status & BD_ENET_RX_WRAP) bdp = fep->rx_bd_base; @@ -1178,6 +1157,10 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) if (!phydev) return -ENODEV; +#ifdef CONFIG_FEC_PTP + if (cmd == SIOCSHWTSTAMP) + return fec_ptp_ioctl(ndev, rq, cmd); +#endif return phy_mii_ioctl(phydev, rq, cmd); } @@ -1224,6 +1207,9 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); bdp->cbd_sc = BD_ENET_RX_EMPTY; +#ifdef CONFIG_FEC_PTP + bdp->cbd_esc = BD_ENET_RX_INT; +#endif bdp++; } @@ -1237,6 +1223,10 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) bdp->cbd_sc = 0; bdp->cbd_bufaddr = 0; + +#ifdef CONFIG_FEC_PTP + bdp->cbd_esc = BD_ENET_RX_INT; +#endif bdp++; } @@ -1494,7 +1484,7 @@ static int fec_enet_init(struct net_device *ndev) } #ifdef CONFIG_OF -static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev) +static int fec_get_phy_mode_dt(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1504,7 +1494,7 @@ static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev) return -ENODEV; } -static void __devinit fec_reset_phy(struct platform_device *pdev) +static void fec_reset_phy(struct platform_device *pdev) { int err, phy_reset; int msec = 1; @@ -1543,7 +1533,7 @@ static inline void fec_reset_phy(struct platform_device *pdev) } #endif /* CONFIG_OF */ -static int __devinit +static int fec_probe(struct platform_device *pdev) { struct fec_enet_private *fep; @@ -1638,9 +1628,19 @@ fec_probe(struct platform_device *pdev) goto failed_clk; } +#ifdef CONFIG_FEC_PTP + fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp"); + if (IS_ERR(fep->clk_ptp)) { + ret = PTR_ERR(fep->clk_ptp); + goto failed_clk; + } +#endif + clk_prepare_enable(fep->clk_ahb); clk_prepare_enable(fep->clk_ipg); - +#ifdef CONFIG_FEC_PTP + clk_prepare_enable(fep->clk_ptp); +#endif reg_phy = devm_regulator_get(&pdev->dev, "phy"); if (!IS_ERR(reg_phy)) { ret = regulator_enable(reg_phy); @@ -1668,6 +1668,10 @@ fec_probe(struct platform_device *pdev) if (ret) goto failed_register; +#ifdef CONFIG_FEC_PTP + fec_ptp_init(ndev, pdev); +#endif + return 0; failed_register: @@ -1677,6 +1681,9 @@ failed_init: failed_regulator: clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ipg); +#ifdef CONFIG_FEC_PTP + clk_disable_unprepare(fep->clk_ptp); +#endif failed_pin: failed_clk: for (i = 0; i < FEC_IRQ_NUM; i++) { @@ -1694,7 +1701,7 @@ failed_alloc_etherdev: return ret; } -static int __devexit +static int fec_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); @@ -1709,6 +1716,12 @@ fec_drv_remove(struct platform_device *pdev) if (irq > 0) free_irq(irq, ndev); } +#ifdef CONFIG_FEC_PTP + del_timer_sync(&fep->time_keep); + clk_disable_unprepare(fep->clk_ptp); + if (fep->ptp_clock) + ptp_clock_unregister(fep->ptp_clock); +#endif clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ipg); iounmap(fep->hwp); @@ -1777,7 +1790,7 @@ static struct platform_driver fec_driver = { }, .id_table = fec_devtype, .probe = fec_probe, - .remove = __devexit_p(fec_drv_remove), + .remove = fec_drv_remove, }; module_platform_driver(fec_driver); diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 8408c627b195..c5a3bc1475c7 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -13,6 +13,12 @@ #define FEC_H /****************************************************************************/ +#ifdef CONFIG_FEC_PTP +#include <linux/clocksource.h> +#include <linux/net_tstamp.h> +#include <linux/ptp_clock_kernel.h> +#endif + #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ defined(CONFIG_M520x) || defined(CONFIG_M532x) || \ defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) @@ -88,6 +94,13 @@ struct bufdesc { unsigned short cbd_datlen; /* Data length */ unsigned short cbd_sc; /* Control and status info */ unsigned long cbd_bufaddr; /* Buffer address */ +#ifdef CONFIG_FEC_PTP + unsigned long cbd_esc; + unsigned long cbd_prot; + unsigned long cbd_bdu; + unsigned long ts; + unsigned short res0[4]; +#endif }; #else struct bufdesc { @@ -147,6 +160,112 @@ struct bufdesc { #define BD_ENET_TX_CSL ((ushort)0x0001) #define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */ +/*enhanced buffer desciptor control/status used by Ethernet transmit*/ +#define BD_ENET_TX_INT 0x40000000 +#define BD_ENET_TX_TS 0x20000000 + + +/* This device has up to three irqs on some platforms */ +#define FEC_IRQ_NUM 3 + +/* The number of Tx and Rx buffers. These are allocated from the page + * pool. The code may assume these are power of two, so it it best + * to keep them that size. + * We don't need to allocate pages for the transmitter. We just use + * the skbuffer directly. + */ + +#define FEC_ENET_RX_PAGES 8 +#define FEC_ENET_RX_FRSIZE 2048 +#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) +#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) +#define FEC_ENET_TX_FRSIZE 2048 +#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE) +#define TX_RING_SIZE 16 /* Must be power of two */ +#define TX_RING_MOD_MASK 15 /* for this to work */ + +#define BD_ENET_RX_INT 0x00800000 +#define BD_ENET_RX_PTP ((ushort)0x0400) + +/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and + * tx_bd_base always point to the base of the buffer descriptors. The + * cur_rx and cur_tx point to the currently available buffer. + * The dirty_tx tracks the current buffer that is being sent by the + * controller. The cur_tx and dirty_tx are equal under both completely + * empty and completely full conditions. The empty/ready indicator in + * the buffer descriptor determines the actual condition. + */ +struct fec_enet_private { + /* Hardware registers of the FEC device */ + void __iomem *hwp; + + struct net_device *netdev; + + struct clk *clk_ipg; + struct clk *clk_ahb; +#ifdef CONFIG_FEC_PTP + struct clk *clk_ptp; +#endif + + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + unsigned char *tx_bounce[TX_RING_SIZE]; + struct sk_buff *tx_skbuff[TX_RING_SIZE]; + struct sk_buff *rx_skbuff[RX_RING_SIZE]; + ushort skb_cur; + ushort skb_dirty; + + /* CPM dual port RAM relative addresses */ + dma_addr_t bd_dma; + /* Address of Rx and Tx buffers */ + struct bufdesc *rx_bd_base; + struct bufdesc *tx_bd_base; + /* The next free ring entry */ + struct bufdesc *cur_rx, *cur_tx; + /* The ring entries to be free()ed */ + struct bufdesc *dirty_tx; + + uint tx_full; + /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ + spinlock_t hw_lock; + + struct platform_device *pdev; + + int opened; + int dev_id; + + /* Phylib and MDIO interface */ + struct mii_bus *mii_bus; + struct phy_device *phy_dev; + int mii_timeout; + uint phy_speed; + phy_interface_t phy_interface; + int link; + int full_duplex; + struct completion mdio_done; + int irq[FEC_IRQ_NUM]; + +#ifdef CONFIG_FEC_PTP + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_caps; + unsigned long last_overflow_check; + spinlock_t tmreg_lock; + struct cyclecounter cc; + struct timecounter tc; + int rx_hwtstamp_filter; + u32 base_incval; + u32 cycle_speed; + int hwts_rx_en; + int hwts_tx_en; + struct timer_list time_keep; +#endif + +}; + +#ifdef CONFIG_FEC_PTP +void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev); +void fec_ptp_start_cyclecounter(struct net_device *ndev); +int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd); +#endif /****************************************************************************/ #endif /* FEC_H */ diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index 2933d08b036e..817d081d2cd8 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c @@ -845,7 +845,7 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = { /* OF Driver */ /* ======================================================================== */ -static int __devinit mpc52xx_fec_probe(struct platform_device *op) +static int mpc52xx_fec_probe(struct platform_device *op) { int rv; struct net_device *ndev; diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c new file mode 100644 index 000000000000..c40526c78c20 --- /dev/null +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -0,0 +1,383 @@ +/* + * Fast Ethernet Controller (ENET) PTP driver for MX6x. + * + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * + * 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. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/ptrace.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> +#include <linux/bitops.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/phy.h> +#include <linux/fec.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_gpio.h> +#include <linux/of_net.h> + +#include "fec.h" + +/* FEC 1588 register bits */ +#define FEC_T_CTRL_SLAVE 0x00002000 +#define FEC_T_CTRL_CAPTURE 0x00000800 +#define FEC_T_CTRL_RESTART 0x00000200 +#define FEC_T_CTRL_PERIOD_RST 0x00000030 +#define FEC_T_CTRL_PERIOD_EN 0x00000010 +#define FEC_T_CTRL_ENABLE 0x00000001 + +#define FEC_T_INC_MASK 0x0000007f +#define FEC_T_INC_OFFSET 0 +#define FEC_T_INC_CORR_MASK 0x00007f00 +#define FEC_T_INC_CORR_OFFSET 8 + +#define FEC_ATIME_CTRL 0x400 +#define FEC_ATIME 0x404 +#define FEC_ATIME_EVT_OFFSET 0x408 +#define FEC_ATIME_EVT_PERIOD 0x40c +#define FEC_ATIME_CORR 0x410 +#define FEC_ATIME_INC 0x414 +#define FEC_TS_TIMESTAMP 0x418 + +#define FEC_CC_MULT (1 << 31) +/** + * fec_ptp_read - read raw cycle counter (to be used by time counter) + * @cc: the cyclecounter structure + * + * this function reads the cyclecounter registers and is called by the + * cyclecounter structure used to construct a ns counter from the + * arbitrary fixed point registers + */ +static cycle_t fec_ptp_read(const struct cyclecounter *cc) +{ + struct fec_enet_private *fep = + container_of(cc, struct fec_enet_private, cc); + u32 tempval; + + tempval = readl(fep->hwp + FEC_ATIME_CTRL); + tempval |= FEC_T_CTRL_CAPTURE; + writel(tempval, fep->hwp + FEC_ATIME_CTRL); + + return readl(fep->hwp + FEC_ATIME); +} + +/** + * fec_ptp_start_cyclecounter - create the cycle counter from hw + * @ndev: network device + * + * this function initializes the timecounter and cyclecounter + * structures for use in generated a ns counter from the arbitrary + * fixed point cycles registers in the hardware. + */ +void fec_ptp_start_cyclecounter(struct net_device *ndev) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + unsigned long flags; + int inc; + + inc = 1000000000 / clk_get_rate(fep->clk_ptp); + + /* grab the ptp lock */ + spin_lock_irqsave(&fep->tmreg_lock, flags); + + /* 1ns counter */ + writel(inc << FEC_T_INC_OFFSET, fep->hwp + FEC_ATIME_INC); + + /* use free running count */ + writel(0, fep->hwp + FEC_ATIME_EVT_PERIOD); + + writel(FEC_T_CTRL_ENABLE, fep->hwp + FEC_ATIME_CTRL); + + memset(&fep->cc, 0, sizeof(fep->cc)); + fep->cc.read = fec_ptp_read; + fep->cc.mask = CLOCKSOURCE_MASK(32); + fep->cc.shift = 31; + fep->cc.mult = FEC_CC_MULT; + + /* reset the ns time counter */ + timecounter_init(&fep->tc, &fep->cc, ktime_to_ns(ktime_get_real())); + + spin_unlock_irqrestore(&fep->tmreg_lock, flags); +} + +/** + * fec_ptp_adjfreq - adjust ptp cycle frequency + * @ptp: the ptp clock structure + * @ppb: parts per billion adjustment from base + * + * Adjust the frequency of the ptp cycle counter by the + * indicated ppb from the base frequency. + * + * Because ENET hardware frequency adjust is complex, + * using software method to do that. + */ +static int fec_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) +{ + u64 diff; + unsigned long flags; + int neg_adj = 0; + u32 mult = FEC_CC_MULT; + + struct fec_enet_private *fep = + container_of(ptp, struct fec_enet_private, ptp_caps); + + if (ppb < 0) { + ppb = -ppb; + neg_adj = 1; + } + + diff = mult; + diff *= ppb; + diff = div_u64(diff, 1000000000ULL); + + spin_lock_irqsave(&fep->tmreg_lock, flags); + /* + * dummy read to set cycle_last in tc to now. + * So use adjusted mult to calculate when next call + * timercounter_read. + */ + timecounter_read(&fep->tc); + + fep->cc.mult = neg_adj ? mult - diff : mult + diff; + + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + + return 0; +} + +/** + * fec_ptp_adjtime + * @ptp: the ptp clock structure + * @delta: offset to adjust the cycle counter by + * + * adjust the timer by resetting the timecounter structure. + */ +static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + struct fec_enet_private *fep = + container_of(ptp, struct fec_enet_private, ptp_caps); + unsigned long flags; + u64 now; + + spin_lock_irqsave(&fep->tmreg_lock, flags); + + now = timecounter_read(&fep->tc); + now += delta; + + /* reset the timecounter */ + timecounter_init(&fep->tc, &fep->cc, now); + + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + + return 0; +} + +/** + * fec_ptp_gettime + * @ptp: the ptp clock structure + * @ts: timespec structure to hold the current time value + * + * read the timecounter and return the correct value on ns, + * after converting it into a struct timespec. + */ +static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts) +{ + struct fec_enet_private *adapter = + container_of(ptp, struct fec_enet_private, ptp_caps); + u64 ns; + u32 remainder; + unsigned long flags; + + spin_lock_irqsave(&adapter->tmreg_lock, flags); + ns = timecounter_read(&adapter->tc); + spin_unlock_irqrestore(&adapter->tmreg_lock, flags); + + ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder); + ts->tv_nsec = remainder; + + return 0; +} + +/** + * fec_ptp_settime + * @ptp: the ptp clock structure + * @ts: the timespec containing the new time for the cycle counter + * + * reset the timecounter to use a new base value instead of the kernel + * wall timer value. + */ +static int fec_ptp_settime(struct ptp_clock_info *ptp, + const struct timespec *ts) +{ + struct fec_enet_private *fep = + container_of(ptp, struct fec_enet_private, ptp_caps); + + u64 ns; + unsigned long flags; + + ns = ts->tv_sec * 1000000000ULL; + ns += ts->tv_nsec; + + spin_lock_irqsave(&fep->tmreg_lock, flags); + timecounter_init(&fep->tc, &fep->cc, ns); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + return 0; +} + +/** + * fec_ptp_enable + * @ptp: the ptp clock structure + * @rq: the requested feature to change + * @on: whether to enable or disable the feature + * + */ +static int fec_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + return -EOPNOTSUPP; +} + +/** + * fec_ptp_hwtstamp_ioctl - control hardware time stamping + * @ndev: pointer to net_device + * @ifreq: ioctl data + * @cmd: particular ioctl requested + */ +int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + + struct hwtstamp_config config; + + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) + return -EFAULT; + + /* reserved for future extensions */ + if (config.flags) + return -EINVAL; + + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: + fep->hwts_tx_en = 0; + break; + case HWTSTAMP_TX_ON: + fep->hwts_tx_en = 1; + break; + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + if (fep->hwts_rx_en) + fep->hwts_rx_en = 0; + config.rx_filter = HWTSTAMP_FILTER_NONE; + break; + + default: + /* + * register RXMTRL must be set in order to do V1 packets, + * therefore it is not possible to time stamp both V1 Sync and + * Delay_Req messages and hardware does not support + * timestamping all packets => return error + */ + fep->hwts_rx_en = 1; + config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + } + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + -EFAULT : 0; +} + +/** + * fec_time_keep - call timecounter_read every second to avoid timer overrun + * because ENET just support 32bit counter, will timeout in 4s + */ +static void fec_time_keep(unsigned long _data) +{ + struct fec_enet_private *fep = (struct fec_enet_private *)_data; + u64 ns; + unsigned long flags; + + spin_lock_irqsave(&fep->tmreg_lock, flags); + ns = timecounter_read(&fep->tc); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + + mod_timer(&fep->time_keep, jiffies + HZ); +} + +/** + * fec_ptp_init + * @ndev: The FEC network adapter + * + * This function performs the required steps for enabling ptp + * support. If ptp support has already been loaded it simply calls the + * cyclecounter init routine and exits. + */ + +void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + + fep->ptp_caps.owner = THIS_MODULE; + snprintf(fep->ptp_caps.name, 16, "fec ptp"); + + fep->ptp_caps.max_adj = 250000000; + fep->ptp_caps.n_alarm = 0; + fep->ptp_caps.n_ext_ts = 0; + fep->ptp_caps.n_per_out = 0; + fep->ptp_caps.pps = 0; + fep->ptp_caps.adjfreq = fec_ptp_adjfreq; + fep->ptp_caps.adjtime = fec_ptp_adjtime; + fep->ptp_caps.gettime = fec_ptp_gettime; + fep->ptp_caps.settime = fec_ptp_settime; + fep->ptp_caps.enable = fec_ptp_enable; + + spin_lock_init(&fep->tmreg_lock); + + fec_ptp_start_cyclecounter(ndev); + + init_timer(&fep->time_keep); + fep->time_keep.data = (unsigned long)fep; + fep->time_keep.function = fec_time_keep; + fep->time_keep.expires = jiffies + HZ; + add_timer(&fep->time_keep); + + fep->ptp_clock = ptp_clock_register(&fep->ptp_caps, &pdev->dev); + if (IS_ERR(fep->ptp_clock)) { + fep->ptp_clock = NULL; + pr_err("ptp_clock_register failed\n"); + } else { + pr_info("registered PHC device on %s\n", ndev->name); + } +} 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 2b7633f766d9..e9879c5af7ba 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -1004,7 +1004,7 @@ static const struct net_device_ops fs_enet_netdev_ops = { }; static struct of_device_id fs_enet_match[]; -static int __devinit fs_enet_probe(struct platform_device *ofdev) +static int fs_enet_probe(struct platform_device *ofdev) { const struct of_device_id *match; struct net_device *ndev; diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c index 151453309401..2bafbd37c247 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c @@ -108,8 +108,7 @@ static struct mdiobb_ops bb_ops = { .get_mdio_data = mdio_read, }; -static int __devinit fs_mii_bitbang_init(struct mii_bus *bus, - struct device_node *np) +static int fs_mii_bitbang_init(struct mii_bus *bus, struct device_node *np) { struct resource res; const u32 *data; @@ -150,7 +149,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus, return 0; } -static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) +static int fs_enet_mdio_probe(struct platform_device *ofdev) { struct mii_bus *new_bus; struct bb_info *bitbang; diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c index cdf702a59485..18e8ef203736 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c @@ -102,7 +102,7 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus) } static struct of_device_id fs_enet_mdio_fec_match[]; -static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev) +static int fs_enet_mdio_probe(struct platform_device *ofdev) { const struct of_device_id *match; struct resource res; diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 1d03dcdd5e56..bffb2edd6858 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -210,7 +210,7 @@ static int gfar_init_bds(struct net_device *ndev) skb = gfar_new_skb(ndev); if (!skb) { netdev_err(ndev, "Can't allocate RX buffers\n"); - goto err_rxalloc_fail; + return -ENOMEM; } rx_queue->rx_skbuff[j] = skb; @@ -223,10 +223,6 @@ static int gfar_init_bds(struct net_device *ndev) } return 0; - -err_rxalloc_fail: - free_skb_resources(priv); - return -ENOMEM; } static int gfar_alloc_skb_resources(struct net_device *ndev) @@ -1353,10 +1349,17 @@ static int gfar_restore(struct device *dev) struct gfar_private *priv = dev_get_drvdata(dev); struct net_device *ndev = priv->ndev; - if (!netif_running(ndev)) + if (!netif_running(ndev)) { + netif_device_attach(ndev); + return 0; + } + + if (gfar_init_bds(ndev)) { + free_skb_resources(priv); + return -ENOMEM; + } - gfar_init_bds(ndev); init_registers(ndev); gfar_set_mac_address(ndev); gfar_init_mac(ndev); @@ -1709,6 +1712,7 @@ static void free_skb_tx_queue(struct gfar_priv_tx_q *tx_queue) tx_queue->tx_skbuff[i] = NULL; } kfree(tx_queue->tx_skbuff); + tx_queue->tx_skbuff = NULL; } static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue) @@ -1732,6 +1736,7 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue) rxbdp++; } kfree(rx_queue->rx_skbuff); + rx_queue->rx_skbuff = NULL; } /* If there are any tx skbs or rx skbs still around, free them. diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c index 1afb5ea2a984..418068b941b1 100644 --- a/drivers/net/ethernet/freescale/xgmac_mdio.c +++ b/drivers/net/ethernet/freescale/xgmac_mdio.c @@ -189,7 +189,7 @@ static int xgmac_mdio_reset(struct mii_bus *bus) return ret; } -static int __devinit xgmac_mdio_probe(struct platform_device *pdev) +static int xgmac_mdio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct mii_bus *bus; @@ -240,7 +240,7 @@ err_ioremap: return ret; } -static int __devexit xgmac_mdio_remove(struct platform_device *pdev) +static int xgmac_mdio_remove(struct platform_device *pdev) { struct mii_bus *bus = dev_get_drvdata(&pdev->dev); diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c index 3f4391bede81..e3c7c697fc45 100644 --- a/drivers/net/ethernet/hp/hp100.c +++ b/drivers/net/ethernet/hp/hp100.c @@ -308,7 +308,7 @@ static void wait(void) * Read board id and convert to string. * Effectively same code as decode_eisa_sig */ -static __devinit const char *hp100_read_id(int ioaddr) +static const char *hp100_read_id(int ioaddr) { int i; static char str[HP100_SIG_LEN]; @@ -447,8 +447,8 @@ static const struct net_device_ops hp100_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit hp100_probe1(struct net_device *dev, int ioaddr, - u_char bus, struct pci_dev *pci_dev) +static int hp100_probe1(struct net_device *dev, int ioaddr, u_char bus, + struct pci_dev *pci_dev) { int i; int err = -ENODEV; @@ -2866,7 +2866,7 @@ static int __init hp100_eisa_probe (struct device *gendev) return err; } -static int __devexit hp100_eisa_remove (struct device *gendev) +static int hp100_eisa_remove(struct device *gendev) { struct net_device *dev = dev_get_drvdata(gendev); cleanup_dev(dev); @@ -2878,14 +2878,14 @@ static struct eisa_driver hp100_eisa_driver = { .driver = { .name = "hp100", .probe = hp100_eisa_probe, - .remove = __devexit_p (hp100_eisa_remove), + .remove = hp100_eisa_remove, } }; #endif #ifdef CONFIG_PCI -static int __devinit hp100_pci_probe (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int hp100_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct net_device *dev; int ioaddr; @@ -2937,7 +2937,7 @@ static int __devinit hp100_pci_probe (struct pci_dev *pdev, return err; } -static void __devexit hp100_pci_remove (struct pci_dev *pdev) +static void hp100_pci_remove(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -2950,7 +2950,7 @@ static struct pci_driver hp100_pci_driver = { .name = "hp100", .id_table = hp100_pci_tbl, .probe = hp100_pci_probe, - .remove = __devexit_p(hp100_pci_remove), + .remove = hp100_pci_remove, }; #endif diff --git a/drivers/net/ethernet/i825xx/ether1.c b/drivers/net/ethernet/i825xx/ether1.c index 067db3f13e91..5d353c660068 100644 --- a/drivers/net/ethernet/i825xx/ether1.c +++ b/drivers/net/ethernet/i825xx/ether1.c @@ -72,7 +72,7 @@ static void ether1_timeout(struct net_device *dev); /* ------------------------------------------------------------------------- */ -static char version[] __devinitdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n"; +static char version[] = "ether1 ethernet driver (c) 2000 Russell King v1.07\n"; #define BUS_16 16 #define BUS_8 8 @@ -250,7 +250,7 @@ ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsig } while (thislen); } -static int __devinit +static int ether1_ramtest(struct net_device *dev, unsigned char byte) { unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL); @@ -304,7 +304,7 @@ ether1_reset (struct net_device *dev) return BUS_16; } -static int __devinit +static int ether1_init_2(struct net_device *dev) { int i; @@ -638,12 +638,6 @@ ether1_txalloc (struct net_device *dev, int size) static int ether1_open (struct net_device *dev) { - if (!is_valid_ether_addr(dev->dev_addr)) { - printk(KERN_WARNING "%s: invalid ethernet MAC address\n", - dev->name); - return -EINVAL; - } - if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev)) return -EAGAIN; @@ -972,7 +966,7 @@ ether1_setmulticastlist (struct net_device *dev) /* ------------------------------------------------------------------------- */ -static void __devinit ether1_banner(void) +static void ether1_banner(void) { static unsigned int version_printed = 0; @@ -991,7 +985,7 @@ static const struct net_device_ops ether1_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, }; -static int __devinit +static int ether1_probe(struct expansion_card *ec, const struct ecard_id *id) { struct net_device *dev; @@ -1052,7 +1046,7 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id) return ret; } -static void __devexit ether1_remove(struct expansion_card *ec) +static void ether1_remove(struct expansion_card *ec) { struct net_device *dev = ecard_get_drvdata(ec); @@ -1070,7 +1064,7 @@ static const struct ecard_id ether1_ids[] = { static struct ecard_driver ether1_driver = { .probe = ether1_probe, - .remove = __devexit_p(ether1_remove), + .remove = ether1_remove, .id_table = ether1_ids, .drv = { .name = "ether1", diff --git a/drivers/net/ethernet/i825xx/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c index 6eba352c52e0..f42f1b707733 100644 --- a/drivers/net/ethernet/i825xx/lasi_82596.c +++ b/drivers/net/ethernet/i825xx/lasi_82596.c @@ -150,7 +150,7 @@ static void mpu_port(struct net_device *dev, int c, dma_addr_t x) #define LAN_PROM_ADDR 0xF0810000 -static int __devinit +static int lan_init_chip(struct parisc_device *dev) { struct net_device *netdevice; @@ -195,7 +195,7 @@ lan_init_chip(struct parisc_device *dev) return retval; } -static int __devexit lan_remove_chip (struct parisc_device *pdev) +static int lan_remove_chip(struct parisc_device *pdev) { struct net_device *dev = parisc_get_drvdata(pdev); struct i596_private *lp = netdev_priv(dev); @@ -219,10 +219,10 @@ static struct parisc_driver lan_driver = { .name = "lasi_82596", .id_table = lan_tbl, .probe = lan_init_chip, - .remove = __devexit_p(lan_remove_chip), + .remove = lan_remove_chip, }; -static int __devinit lasi_82596_init(void) +static int lasi_82596_init(void) { printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n"); return register_parisc_driver(&lan_driver); diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c index 3efbd8dbb63d..f045ea4dc514 100644 --- a/drivers/net/ethernet/i825xx/lib82596.c +++ b/drivers/net/ethernet/i825xx/lib82596.c @@ -1048,7 +1048,7 @@ static const struct net_device_ops i596_netdev_ops = { #endif }; -static int __devinit i82596_probe(struct net_device *dev) +static int i82596_probe(struct net_device *dev) { int i; struct i596_private *lp = netdev_priv(dev); diff --git a/drivers/net/ethernet/i825xx/sni_82596.c b/drivers/net/ethernet/i825xx/sni_82596.c index 6b2a88817473..4ceae9a30274 100644 --- a/drivers/net/ethernet/i825xx/sni_82596.c +++ b/drivers/net/ethernet/i825xx/sni_82596.c @@ -75,7 +75,7 @@ static void mpu_port(struct net_device *dev, int c, dma_addr_t x) } -static int __devinit sni_82596_probe(struct platform_device *dev) +static int sni_82596_probe(struct platform_device *dev) { struct net_device *netdevice; struct i596_private *lp; @@ -147,7 +147,7 @@ probe_failed_free_mpu: return retval; } -static int __devexit sni_82596_driver_remove(struct platform_device *pdev) +static int sni_82596_driver_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct i596_private *lp = netdev_priv(dev); @@ -163,14 +163,14 @@ static int __devexit sni_82596_driver_remove(struct platform_device *pdev) static struct platform_driver sni_82596_driver = { .probe = sni_82596_probe, - .remove = __devexit_p(sni_82596_driver_remove), + .remove = sni_82596_driver_remove, .driver = { .name = sni_82596_string, .owner = THIS_MODULE, }, }; -static int __devinit sni_82596_init(void) +static int sni_82596_init(void) { printk(KERN_INFO SNI_82596_DRIVER_VERSION "\n"); return platform_driver_register(&sni_82596_driver); diff --git a/drivers/net/ethernet/ibm/Kconfig b/drivers/net/ethernet/ibm/Kconfig index b9773d229192..6529d31595a7 100644 --- a/drivers/net/ethernet/ibm/Kconfig +++ b/drivers/net/ethernet/ibm/Kconfig @@ -6,7 +6,7 @@ config NET_VENDOR_IBM bool "IBM devices" default y depends on MCA || PPC_PSERIES || PPC_PSERIES || PPC_DCR || \ - (IBMEBUS && INET && SPARSEMEM) + (IBMEBUS && SPARSEMEM) ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from @@ -33,8 +33,7 @@ source "drivers/net/ethernet/ibm/emac/Kconfig" config EHEA tristate "eHEA Ethernet support" - depends on IBMEBUS && INET && SPARSEMEM - select INET_LRO + depends on IBMEBUS && SPARSEMEM ---help--- This driver supports the IBM pSeries eHEA ethernet adapter. diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index f4d2da0db1b1..19b64de7124b 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -98,10 +98,10 @@ static struct ehea_fw_handle_array ehea_fw_handles; static struct ehea_bcmc_reg_array ehea_bcmc_regs; -static int __devinit ehea_probe_adapter(struct platform_device *dev, - const struct of_device_id *id); +static int ehea_probe_adapter(struct platform_device *dev, + const struct of_device_id *id); -static int __devexit ehea_remove(struct platform_device *dev); +static int ehea_remove(struct platform_device *dev); static struct of_device_id ehea_device_table[] = { { @@ -2909,7 +2909,7 @@ static ssize_t ehea_show_port_id(struct device *dev, static DEVICE_ATTR(log_port_id, S_IRUSR | S_IRGRP | S_IROTH, ehea_show_port_id, NULL); -static void __devinit logical_port_release(struct device *dev) +static void logical_port_release(struct device *dev) { struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev); of_node_put(port->ofdev.dev.of_node); @@ -3028,7 +3028,7 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, ehea_set_ethtool_ops(dev); dev->hw_features = NETIF_F_SG | NETIF_F_TSO - | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_LRO; + | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX; dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER @@ -3257,8 +3257,8 @@ static void ehea_remove_device_sysfs(struct platform_device *dev) device_remove_file(&dev->dev, &dev_attr_remove_port); } -static int __devinit ehea_probe_adapter(struct platform_device *dev, - const struct of_device_id *id) +static int ehea_probe_adapter(struct platform_device *dev, + const struct of_device_id *id) { struct ehea_adapter *adapter; const u64 *adapter_handle; @@ -3364,7 +3364,7 @@ out: return ret; } -static int __devexit ehea_remove(struct platform_device *dev) +static int ehea_remove(struct platform_device *dev) { struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev); int i; diff --git a/drivers/net/ethernet/ibm/ehea/ehea_phyp.h b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h index 8364815c32ff..99b6c2a38dbf 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_phyp.h +++ b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h @@ -39,26 +39,6 @@ * hcp_* - structures, variables and functions releated to Hypervisor Calls */ -static inline u32 get_longbusy_msecs(int long_busy_ret_code) -{ - switch (long_busy_ret_code) { - case H_LONG_BUSY_ORDER_1_MSEC: - return 1; - case H_LONG_BUSY_ORDER_10_MSEC: - return 10; - case H_LONG_BUSY_ORDER_100_MSEC: - return 100; - case H_LONG_BUSY_ORDER_1_SEC: - return 1000; - case H_LONG_BUSY_ORDER_10_SEC: - return 10000; - case H_LONG_BUSY_ORDER_100_SEC: - return 100000; - default: - return 1; - } -} - /* Number of pages which can be registered at once by H_REGISTER_HEA_RPAGES */ #define EHEA_MAX_RPAGE 512 diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index a0fe6e3fce61..256bdb8e1994 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -2261,8 +2261,8 @@ struct emac_depentry { #define EMAC_DEP_PREV_IDX 5 #define EMAC_DEP_COUNT 6 -static int __devinit emac_check_deps(struct emac_instance *dev, - struct emac_depentry *deps) +static int emac_check_deps(struct emac_instance *dev, + struct emac_depentry *deps) { int i, there = 0; struct device_node *np; @@ -2314,8 +2314,8 @@ static void emac_put_deps(struct emac_instance *dev) of_dev_put(dev->tah_dev); } -static int __devinit emac_of_bus_notify(struct notifier_block *nb, - unsigned long action, void *data) +static int emac_of_bus_notify(struct notifier_block *nb, unsigned long action, + void *data) { /* We are only intereted in device addition */ if (action == BUS_NOTIFY_BOUND_DRIVER) @@ -2323,11 +2323,11 @@ static int __devinit emac_of_bus_notify(struct notifier_block *nb, return 0; } -static struct notifier_block emac_of_bus_notifier __devinitdata = { +static struct notifier_block emac_of_bus_notifier = { .notifier_call = emac_of_bus_notify }; -static int __devinit emac_wait_deps(struct emac_instance *dev) +static int emac_wait_deps(struct emac_instance *dev) { struct emac_depentry deps[EMAC_DEP_COUNT]; int i, err; @@ -2367,8 +2367,8 @@ static int __devinit emac_wait_deps(struct emac_instance *dev) return err; } -static int __devinit emac_read_uint_prop(struct device_node *np, const char *name, - u32 *val, int fatal) +static int emac_read_uint_prop(struct device_node *np, const char *name, + u32 *val, int fatal) { int len; const u32 *prop = of_get_property(np, name, &len); @@ -2382,7 +2382,7 @@ static int __devinit emac_read_uint_prop(struct device_node *np, const char *nam return 0; } -static int __devinit emac_init_phy(struct emac_instance *dev) +static int emac_init_phy(struct emac_instance *dev) { struct device_node *np = dev->ofdev->dev.of_node; struct net_device *ndev = dev->ndev; @@ -2518,7 +2518,7 @@ static int __devinit emac_init_phy(struct emac_instance *dev) return 0; } -static int __devinit emac_init_config(struct emac_instance *dev) +static int emac_init_config(struct emac_instance *dev) { struct device_node *np = dev->ofdev->dev.of_node; const void *p; @@ -2703,7 +2703,7 @@ static const struct net_device_ops emac_gige_netdev_ops = { .ndo_change_mtu = emac_change_mtu, }; -static int __devinit emac_probe(struct platform_device *ofdev) +static int emac_probe(struct platform_device *ofdev) { struct net_device *ndev; struct emac_instance *dev; @@ -2930,7 +2930,7 @@ static int __devinit emac_probe(struct platform_device *ofdev) return err; } -static int __devexit emac_remove(struct platform_device *ofdev) +static int emac_remove(struct platform_device *ofdev) { struct emac_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c index 479e43e2f1ef..50ea12bfb579 100644 --- a/drivers/net/ethernet/ibm/emac/mal.c +++ b/drivers/net/ethernet/ibm/emac/mal.c @@ -33,8 +33,7 @@ static int mal_count; -int __devinit mal_register_commac(struct mal_instance *mal, - struct mal_commac *commac) +int mal_register_commac(struct mal_instance *mal, struct mal_commac *commac) { unsigned long flags; @@ -517,7 +516,7 @@ void *mal_dump_regs(struct mal_instance *mal, void *buf) return regs + 1; } -static int __devinit mal_probe(struct platform_device *ofdev) +static int mal_probe(struct platform_device *ofdev) { struct mal_instance *mal; int err = 0, i, bd_size; @@ -729,7 +728,7 @@ static int __devinit mal_probe(struct platform_device *ofdev) return err; } -static int __devexit mal_remove(struct platform_device *ofdev) +static int mal_remove(struct platform_device *ofdev) { struct mal_instance *mal = dev_get_drvdata(&ofdev->dev); @@ -738,13 +737,11 @@ static int __devexit mal_remove(struct platform_device *ofdev) /* Synchronize with scheduled polling */ napi_disable(&mal->napi); - if (!list_empty(&mal->list)) { + if (!list_empty(&mal->list)) /* This is *very* bad */ - printk(KERN_EMERG + WARN(1, KERN_EMERG "mal%d: commac list is not empty on remove!\n", mal->index); - WARN_ON(1); - } dev_set_drvdata(&ofdev->dev, NULL); diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c index d3123282e18e..39251765b55d 100644 --- a/drivers/net/ethernet/ibm/emac/rgmii.c +++ b/drivers/net/ethernet/ibm/emac/rgmii.c @@ -93,7 +93,7 @@ static inline u32 rgmii_mode_mask(int mode, int input) } } -int __devinit rgmii_attach(struct platform_device *ofdev, int input, int mode) +int rgmii_attach(struct platform_device *ofdev, int input, int mode) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct rgmii_regs __iomem *p = dev->base; @@ -228,7 +228,7 @@ void *rgmii_dump_regs(struct platform_device *ofdev, void *buf) } -static int __devinit rgmii_probe(struct platform_device *ofdev) +static int rgmii_probe(struct platform_device *ofdev) { struct device_node *np = ofdev->dev.of_node; struct rgmii_instance *dev; @@ -289,7 +289,7 @@ static int __devinit rgmii_probe(struct platform_device *ofdev) return rc; } -static int __devexit rgmii_remove(struct platform_device *ofdev) +static int rgmii_remove(struct platform_device *ofdev) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ethernet/ibm/emac/tah.c b/drivers/net/ethernet/ibm/emac/tah.c index 872912ef518d..795f1393e2b6 100644 --- a/drivers/net/ethernet/ibm/emac/tah.c +++ b/drivers/net/ethernet/ibm/emac/tah.c @@ -23,7 +23,7 @@ #include "emac.h" #include "core.h" -int __devinit tah_attach(struct platform_device *ofdev, int channel) +int tah_attach(struct platform_device *ofdev, int channel) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); @@ -87,7 +87,7 @@ void *tah_dump_regs(struct platform_device *ofdev, void *buf) return regs + 1; } -static int __devinit tah_probe(struct platform_device *ofdev) +static int tah_probe(struct platform_device *ofdev) { struct device_node *np = ofdev->dev.of_node; struct tah_instance *dev; @@ -135,7 +135,7 @@ static int __devinit tah_probe(struct platform_device *ofdev) return rc; } -static int __devexit tah_remove(struct platform_device *ofdev) +static int tah_remove(struct platform_device *ofdev) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c index 415e9b4d5408..f91202f42125 100644 --- a/drivers/net/ethernet/ibm/emac/zmii.c +++ b/drivers/net/ethernet/ibm/emac/zmii.c @@ -82,7 +82,7 @@ static inline u32 zmii_mode_mask(int mode, int input) } } -int __devinit zmii_attach(struct platform_device *ofdev, int input, int *mode) +int zmii_attach(struct platform_device *ofdev, int input, int *mode) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct zmii_regs __iomem *p = dev->base; @@ -231,7 +231,7 @@ void *zmii_dump_regs(struct platform_device *ofdev, void *buf) return regs + 1; } -static int __devinit zmii_probe(struct platform_device *ofdev) +static int zmii_probe(struct platform_device *ofdev) { struct device_node *np = ofdev->dev.of_node; struct zmii_instance *dev; @@ -282,7 +282,7 @@ static int __devinit zmii_probe(struct platform_device *ofdev) return rc; } -static int __devexit zmii_remove(struct platform_device *ofdev) +static int zmii_remove(struct platform_device *ofdev) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index b68d28a130e6..f2fdbb79837e 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -1324,8 +1324,7 @@ static const struct net_device_ops ibmveth_netdev_ops = { #endif }; -static int __devinit ibmveth_probe(struct vio_dev *dev, - const struct vio_device_id *id) +static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) { int rc, i; struct net_device *netdev; @@ -1426,7 +1425,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, return 0; } -static int __devexit ibmveth_remove(struct vio_dev *dev) +static int ibmveth_remove(struct vio_dev *dev) { struct net_device *netdev = dev_get_drvdata(&dev->dev); struct ibmveth_adapter *adapter = netdev_priv(netdev); @@ -1593,7 +1592,7 @@ static int ibmveth_resume(struct device *dev) return 0; } -static struct vio_device_id ibmveth_device_table[] __devinitdata = { +static struct vio_device_id ibmveth_device_table[] = { { "network", "IBM,l-lan"}, { "", "" } }; diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c index 1b563bb959c2..068d78151658 100644 --- a/drivers/net/ethernet/icplus/ipg.c +++ b/drivers/net/ethernet/icplus/ipg.c @@ -2167,7 +2167,7 @@ static const struct ethtool_ops ipg_ethtool_ops = { .nway_reset = ipg_nway_reset, }; -static void __devexit ipg_remove(struct pci_dev *pdev) +static void ipg_remove(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct ipg_nic_private *sp = netdev_priv(dev); @@ -2199,8 +2199,7 @@ static const struct net_device_ops ipg_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit ipg_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int ipg_probe(struct pci_dev *pdev, const struct pci_device_id *id) { unsigned int i = id->driver_data; struct ipg_nic_private *sp; @@ -2296,7 +2295,7 @@ static struct pci_driver ipg_pci_driver = { .name = IPG_DRIVER_NAME, .id_table = ipg_pci_tbl, .probe = ipg_probe, - .remove = __devexit_p(ipg_remove), + .remove = ipg_remove, }; static int __init ipg_init_module(void) diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 0cafe4fe9406..ddee4060948a 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -93,6 +93,7 @@ config E1000E config IGB tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support" depends on PCI + select PTP_1588_CLOCK ---help--- This driver supports Intel(R) 82575/82576 gigabit ethernet family of adapters. For more information on how to identify your adapter, go @@ -120,19 +121,6 @@ config IGB_DCA driver. DCA is a method for warming the CPU cache before data is used, with the intent of lessening the impact of cache misses. -config IGB_PTP - bool "PTP Hardware Clock (PHC)" - default n - depends on IGB && EXPERIMENTAL - select PPS - select PTP_1588_CLOCK - ---help--- - Say Y here if you want to use PTP Hardware Clock (PHC) in the - driver. Only the basic clock operations have been implemented. - - Every timestamp and clock read operations must consult the - overflow counter to form a correct time value. - config IGBVF tristate "Intel(R) 82576 Virtual Function Ethernet support" depends on PCI @@ -178,8 +166,9 @@ config IXGB config IXGBE tristate "Intel(R) 10GbE PCI Express adapters support" - depends on PCI && INET + depends on PCI select MDIO + select PTP_1588_CLOCK ---help--- This driver supports Intel(R) 10GbE PCI Express family of adapters. For more information on how to identify your adapter, go @@ -222,19 +211,6 @@ config IXGBE_DCB If unsure, say N. -config IXGBE_PTP - bool "PTP Clock Support" - default n - depends on IXGBE && EXPERIMENTAL - select PPS - select PTP_1588_CLOCK - ---help--- - Say Y here if you want support for 1588 Timestamping with a - PHC device, using the PTP 1588 Clock support. This is - required to enable timestamping support for the device. - - If unsure, say N. - config IXGBEVF tristate "Intel(R) 82599 Virtual Function Ethernet support" depends on PCI_MSI diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 29ce9bd27f94..a59f0779e1c3 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -2829,8 +2829,7 @@ static const struct net_device_ops e100_netdev_ops = { .ndo_set_features = e100_set_features, }; -static int __devinit e100_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct nic *nic; @@ -2981,7 +2980,7 @@ err_out_free_dev: return err; } -static void __devexit e100_remove(struct pci_dev *pdev) +static void e100_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -3167,7 +3166,7 @@ static struct pci_driver e100_driver = { .name = DRV_NAME, .id_table = e100_id_table, .probe = e100_probe, - .remove = __devexit_p(e100_remove), + .remove = e100_remove, #ifdef CONFIG_PM /* Power Management hooks */ .suspend = e100_suspend, diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.c b/drivers/net/ethernet/intel/e1000/e1000_hw.c index 3d6839528761..8fedd2451538 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_hw.c +++ b/drivers/net/ethernet/intel/e1000/e1000_hw.c @@ -107,6 +107,7 @@ u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = { }; static DEFINE_SPINLOCK(e1000_eeprom_lock); +static DEFINE_SPINLOCK(e1000_phy_lock); /** * e1000_set_phy_type - Set the phy type member in the hw struct. @@ -2830,19 +2831,25 @@ static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw) s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data) { u32 ret_val; + unsigned long flags; e_dbg("e1000_read_phy_reg"); + spin_lock_irqsave(&e1000_phy_lock, flags); + if ((hw->phy_type == e1000_phy_igp) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, (u16) reg_addr); - if (ret_val) + if (ret_val) { + spin_unlock_irqrestore(&e1000_phy_lock, flags); return ret_val; + } } ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, phy_data); + spin_unlock_irqrestore(&e1000_phy_lock, flags); return ret_val; } @@ -2965,19 +2972,25 @@ static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data) { u32 ret_val; + unsigned long flags; e_dbg("e1000_write_phy_reg"); + spin_lock_irqsave(&e1000_phy_lock, flags); + if ((hw->phy_type == e1000_phy_igp) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, (u16) reg_addr); - if (ret_val) + if (ret_val) { + spin_unlock_irqrestore(&e1000_phy_lock, flags); return ret_val; + } } ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, phy_data); + spin_unlock_irqrestore(&e1000_phy_lock, flags); return ret_val; } diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 222bfaff4622..294da56b824c 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -111,7 +111,7 @@ void e1000_update_stats(struct e1000_adapter *adapter); static int e1000_init_module(void); static void e1000_exit_module(void); static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent); -static void __devexit e1000_remove(struct pci_dev *pdev); +static void e1000_remove(struct pci_dev *pdev); static int e1000_alloc_queues(struct e1000_adapter *adapter); static int e1000_sw_init(struct e1000_adapter *adapter); static int e1000_open(struct net_device *netdev); @@ -202,7 +202,7 @@ static struct pci_driver e1000_driver = { .name = e1000_driver_name, .id_table = e1000_pci_tbl, .probe = e1000_probe, - .remove = __devexit_p(e1000_remove), + .remove = e1000_remove, #ifdef CONFIG_PM /* Power Management Hooks */ .suspend = e1000_suspend, @@ -938,8 +938,7 @@ static int e1000_init_hw_struct(struct e1000_adapter *adapter, * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. **/ -static int __devinit e1000_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct e1000_adapter *adapter; @@ -1273,7 +1272,7 @@ err_pci_reg: * memory. **/ -static void __devexit e1000_remove(struct pci_dev *pdev) +static void e1000_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev_priv(netdev); @@ -1309,7 +1308,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev) * e1000_init_hw_struct MUST be called before this function **/ -static int __devinit e1000_sw_init(struct e1000_adapter *adapter) +static int e1000_sw_init(struct e1000_adapter *adapter) { adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; @@ -1340,7 +1339,7 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) * number of queues at compile-time. **/ -static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter) +static int e1000_alloc_queues(struct e1000_adapter *adapter) { adapter->tx_ring = kcalloc(adapter->num_tx_queues, sizeof(struct e1000_tx_ring), GFP_KERNEL); diff --git a/drivers/net/ethernet/intel/e1000/e1000_param.c b/drivers/net/ethernet/intel/e1000/e1000_param.c index 1301eba8b57a..750fc0194f37 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_param.c +++ b/drivers/net/ethernet/intel/e1000/e1000_param.c @@ -45,7 +45,7 @@ #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } #define E1000_PARAM(X, desc) \ - static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ + static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ static unsigned int num_##X; \ module_param_array_named(X, X, int, &num_##X, 0); \ MODULE_PARM_DESC(X, desc); @@ -205,9 +205,9 @@ struct e1000_option { } arg; }; -static int __devinit e1000_validate_option(unsigned int *value, - const struct e1000_option *opt, - struct e1000_adapter *adapter) +static int e1000_validate_option(unsigned int *value, + const struct e1000_option *opt, + struct e1000_adapter *adapter) { if (*value == OPTION_UNSET) { *value = opt->def; @@ -268,7 +268,7 @@ static void e1000_check_copper_options(struct e1000_adapter *adapter); * in a variable in the adapter structure. **/ -void __devinit e1000_check_options(struct e1000_adapter *adapter) +void e1000_check_options(struct e1000_adapter *adapter) { struct e1000_option opt; int bd = adapter->bd_number; @@ -534,7 +534,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) * Handles speed and duplex options on fiber adapters **/ -static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter) +static void e1000_check_fiber_options(struct e1000_adapter *adapter) { int bd = adapter->bd_number; if (num_Speed > bd) { @@ -560,7 +560,7 @@ static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter) * Handles speed and duplex options on copper adapters **/ -static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) +static void e1000_check_copper_options(struct e1000_adapter *adapter) { struct e1000_option opt; unsigned int speed, dplx, an; diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c index 4dd18a1f45d2..e73c2c355993 100644 --- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c +++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c @@ -26,8 +26,7 @@ *******************************************************************************/ -/* - * 80003ES2LAN Gigabit Ethernet Controller (Copper) +/* 80003ES2LAN Gigabit Ethernet Controller (Copper) * 80003ES2LAN Gigabit Ethernet Controller (Serdes) */ @@ -80,7 +79,8 @@ 1 = 50-80M 2 = 80-110M 3 = 110-140M - 4 = >140M */ + 4 = >140M + */ /* Kumeran Mode Control Register (Page 193, Register 16) */ #define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 @@ -95,8 +95,7 @@ /* In-Band Control Register (Page 194, Register 18) */ #define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */ -/* - * A table for the GG82563 cable length where the range is defined +/* A table for the GG82563 cable length where the range is defined * with a lower bound at "index" and the upper bound at * "index + 5". */ @@ -183,8 +182,7 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> E1000_EECD_SIZE_EX_SHIFT); - /* - * Added to a constant, "size" becomes the left-shift value + /* Added to a constant, "size" becomes the left-shift value * for setting word_size. */ size += NVM_WORD_SIZE_BASE_SHIFT; @@ -375,8 +373,7 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) if (!(swfw_sync & (fwmask | swmask))) break; - /* - * Firmware currently using resource (fwmask) + /* Firmware currently using resource (fwmask) * or other software thread using resource (swmask) */ e1000e_put_hw_semaphore(hw); @@ -442,8 +439,7 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { page_select = GG82563_PHY_PAGE_SELECT; } else { - /* - * Use Alternative Page Select register to access + /* Use Alternative Page Select register to access * registers 30 and 31 */ page_select = GG82563_PHY_PAGE_SELECT_ALT; @@ -457,8 +453,7 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, } if (hw->dev_spec.e80003es2lan.mdic_wa_enable) { - /* - * The "ready" bit in the MDIC register may be incorrectly set + /* The "ready" bit in the MDIC register may be incorrectly set * before the device has completed the "Page Select" MDI * transaction. So we wait 200us after each MDI command... */ @@ -513,8 +508,7 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { page_select = GG82563_PHY_PAGE_SELECT; } else { - /* - * Use Alternative Page Select register to access + /* Use Alternative Page Select register to access * registers 30 and 31 */ page_select = GG82563_PHY_PAGE_SELECT_ALT; @@ -528,8 +522,7 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, } if (hw->dev_spec.e80003es2lan.mdic_wa_enable) { - /* - * The "ready" bit in the MDIC register may be incorrectly set + /* The "ready" bit in the MDIC register may be incorrectly set * before the device has completed the "Page Select" MDI * transaction. So we wait 200us after each MDI command... */ @@ -618,8 +611,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) u16 phy_data; bool link; - /* - * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI + /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI * forced whenever speed and duplex are forced. */ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); @@ -657,8 +649,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) return ret_val; if (!link) { - /* - * We didn't get link. + /* We didn't get link. * Reset the DSP and cross our fingers. */ ret_val = e1000e_phy_reset_dsp(hw); @@ -677,8 +668,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Resetting the phy means we need to verify the TX_CLK corresponds + /* Resetting the phy means we need to verify the TX_CLK corresponds * to the link speed. 10Mbps -> 2.5MHz, else 25MHz. */ phy_data &= ~GG82563_MSCR_TX_CLK_MASK; @@ -687,8 +677,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) else phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25; - /* - * In addition, we must re-enable CRS on Tx for both half and full + /* In addition, we must re-enable CRS on Tx for both half and full * duplex. */ phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; @@ -766,8 +755,7 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) s32 ret_val; u16 kum_reg_data; - /* - * Prevent the PCI-E bus from sticking if there is no TLP connection + /* Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000e_disable_pcie_master(hw); @@ -899,8 +887,7 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) hw->dev_spec.e80003es2lan.mdic_wa_enable = false; } - /* - * Clear all of the statistics registers (clear on read). It is + /* Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. @@ -945,8 +932,7 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw) reg |= (1 << 28); ew32(TARC(1), reg); - /* - * Disable IPv6 extension header parsing because some malformed + /* Disable IPv6 extension header parsing because some malformed * IPv6 headers can hang the Rx. */ reg = er32(RFCTL); @@ -979,8 +965,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Options: + /* Options: * MDI/MDI-X = 0 (default) * 0 - Auto for all speeds * 1 - MDI mode @@ -1006,8 +991,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) break; } - /* - * Options: + /* Options: * disable_polarity_correction = 0 (default) * Automatic Correction for Reversed Cable Polarity * 0 - Disabled @@ -1065,8 +1049,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Do not init these registers when the HW is in IAMT mode, since the + /* Do not init these registers when the HW is in IAMT mode, since the * firmware will have already initialized them. We only initialize * them if the HW is not in IAMT mode. */ @@ -1087,8 +1070,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) return ret_val; } - /* - * Workaround: Disable padding in Kumeran interface in the MAC + /* Workaround: Disable padding in Kumeran interface in the MAC * and in the PHY to avoid CRC errors. */ ret_val = e1e_rphy(hw, GG82563_PHY_INBAND_CTRL, &data); @@ -1121,8 +1103,7 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); ew32(CTRL, ctrl); - /* - * Set the mac to wait the maximum time between each + /* Set the mac to wait the maximum time between each * iteration and increase the max iterations when * polling the phy; this fixes erroneous timeouts at 10Mbps. */ @@ -1352,8 +1333,7 @@ static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw) { s32 ret_val = 0; - /* - * If there's an alternate MAC address place it in RAR0 + /* If there's an alternate MAC address place it in RAR0 * so that it will override the Si installed default perm * address. */ diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index c98586408005..c77d010d5c59 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -26,8 +26,7 @@ *******************************************************************************/ -/* - * 82571EB Gigabit Ethernet Controller +/* 82571EB Gigabit Ethernet Controller * 82571EB Gigabit Ethernet Controller (Copper) * 82571EB Gigabit Ethernet Controller (Fiber) * 82571EB Dual Port Gigabit Mezzanine Adapter @@ -191,8 +190,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) if (((eecd >> 15) & 0x3) == 0x3) { nvm->type = e1000_nvm_flash_hw; nvm->word_size = 2048; - /* - * Autonomous Flash update bit must be cleared due + /* Autonomous Flash update bit must be cleared due * to Flash update issue. */ eecd &= ~E1000_EECD_AUPDEN; @@ -204,8 +202,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) nvm->type = e1000_nvm_eeprom_spi; size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> E1000_EECD_SIZE_EX_SHIFT); - /* - * Added to a constant, "size" becomes the left-shift value + /* Added to a constant, "size" becomes the left-shift value * for setting word_size. */ size += NVM_WORD_SIZE_BASE_SHIFT; @@ -291,8 +288,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) /* FWSM register */ mac->has_fwsm = true; - /* - * ARC supported; valid only if manageability features are + /* ARC supported; valid only if manageability features are * enabled. */ mac->arc_subsystem_valid = !!(er32(FWSM) & @@ -314,8 +310,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) break; } - /* - * Ensure that the inter-port SWSM.SMBI lock bit is clear before + /* Ensure that the inter-port SWSM.SMBI lock bit is clear before * first NVM or PHY access. This should be done for single-port * devices, and for one port only on dual-port devices so that * for those devices we can still use the SMBI lock to synchronize @@ -352,11 +347,8 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) ew32(SWSM, swsm & ~E1000_SWSM_SMBI); } - /* - * Initialize device specific counter of SMBI acquisition - * timeouts. - */ - hw->dev_spec.e82571.smb_counter = 0; + /* Initialize device specific counter of SMBI acquisition timeouts. */ + hw->dev_spec.e82571.smb_counter = 0; return 0; } @@ -445,8 +437,7 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_82571: case e1000_82572: - /* - * The 82571 firmware may still be configuring the PHY. + /* The 82571 firmware may still be configuring the PHY. * In this case, we cannot access the PHY until the * configuration is done. So we explicitly set the * PHY ID. @@ -492,8 +483,7 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) s32 fw_timeout = hw->nvm.word_size + 1; s32 i = 0; - /* - * If we have timedout 3 times on trying to acquire + /* If we have timedout 3 times on trying to acquire * the inter-port SMBI semaphore, there is old code * operating on the other port, and it is not * releasing SMBI. Modify the number of times that @@ -787,8 +777,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * If our nvm is an EEPROM, then we're done + /* If our nvm is an EEPROM, then we're done * otherwise, commit the checksum to the flash NVM. */ if (hw->nvm.type != e1000_nvm_flash_hw) @@ -806,8 +795,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) /* Reset the firmware if using STM opcode. */ if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) { - /* - * The enabling of and the actual reset must be done + /* The enabling of and the actual reset must be done * in two write cycles. */ ew32(HICR, E1000_HICR_FW_RESET_ENABLE); @@ -867,8 +855,7 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, u32 i, eewr = 0; s32 ret_val = 0; - /* - * A check for invalid values: offset too large, too many words, + /* 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)) || @@ -957,8 +944,7 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) } else { data &= ~IGP02E1000_PM_D0_LPLU; ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. @@ -1002,8 +988,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) u32 ctrl, ctrl_ext, eecd, tctl; s32 ret_val; - /* - * Prevent the PCI-E bus from sticking if there is no TLP connection + /* Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000e_disable_pcie_master(hw); @@ -1021,8 +1006,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) usleep_range(10000, 20000); - /* - * Must acquire the MDIO ownership before MAC reset. + /* Must acquire the MDIO ownership before MAC reset. * Ownership defaults to firmware after a reset. */ switch (hw->mac.type) { @@ -1067,8 +1051,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) /* We don't want to continue accessing MAC registers. */ return ret_val; - /* - * Phy configuration from NVM just starts after EECD_AUTO_RD is set. + /* Phy configuration from NVM just starts after EECD_AUTO_RD is set. * Need to wait for Phy configuration completion before accessing * NVM and Phy. */ @@ -1076,8 +1059,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_82571: case e1000_82572: - /* - * REQ and GNT bits need to be cleared when using AUTO_RD + /* REQ and GNT bits need to be cleared when using AUTO_RD * to access the EEPROM. */ eecd = er32(EECD); @@ -1138,8 +1120,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw) e_dbg("Initializing the IEEE VLAN\n"); mac->ops.clear_vfta(hw); - /* Setup the receive address. */ - /* + /* Setup the receive address. * If, however, a locally administered address was assigned to the * 82571, we must reserve a RAR for it to work around an issue where * resetting one port will reload the MAC on the other port. @@ -1183,8 +1164,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw) break; } - /* - * Clear all of the statistics registers (clear on read). It is + /* Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. @@ -1281,8 +1261,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) ew32(PBA_ECC, reg); } - /* - * Workaround for hardware errata. + /* Workaround for hardware errata. * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572 */ if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) { @@ -1291,8 +1270,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) ew32(CTRL_EXT, reg); } - /* - * Disable IPv6 extension header parsing because some malformed + /* Disable IPv6 extension header parsing because some malformed * IPv6 headers can hang the Rx. */ if (hw->mac.type <= e1000_82573) { @@ -1309,8 +1287,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) reg |= (1 << 22); ew32(GCR, reg); - /* - * Workaround for hardware errata. + /* Workaround for hardware errata. * apply workaround for hardware errata documented in errata * docs Fixes issue where some error prone or unreliable PCIe * completions are occurring, particularly with ASPM enabled. @@ -1344,8 +1321,7 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw) case e1000_82574: case e1000_82583: if (hw->mng_cookie.vlan_id != 0) { - /* - * The VFTA is a 4096b bit-field, each identifying + /* The VFTA is a 4096b bit-field, each identifying * a single VLAN ID. The following operations * determine which 32b entry (i.e. offset) into the * array we want to set the VLAN ID (i.e. bit) of @@ -1362,8 +1338,7 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw) break; } for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - /* - * If the offset we want to clear is the same offset of the + /* If the offset we want to clear is the same offset of the * manageability VLAN ID, then clear all bits except that of * the manageability unit. */ @@ -1401,8 +1376,7 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw) ctrl = hw->mac.ledctl_mode2; if (!(E1000_STATUS_LU & er32(STATUS))) { - /* - * If no link, then turn LED on by setting the invert bit + /* If no link, then turn LED on by setting the invert bit * for each LED that's "on" (0x0E) in ledctl_mode2. */ for (i = 0; i < 4; i++) @@ -1427,8 +1401,7 @@ bool e1000_check_phy_82574(struct e1000_hw *hw) u16 receive_errors = 0; s32 ret_val = 0; - /* - * Read PHY Receive Error counter first, if its is max - all F's then + /* Read PHY Receive Error counter first, if its is max - all F's then * read the Base1000T status register If both are max then PHY is hung. */ ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors); @@ -1458,8 +1431,7 @@ bool e1000_check_phy_82574(struct e1000_hw *hw) **/ static s32 e1000_setup_link_82571(struct e1000_hw *hw) { - /* - * 82573 does not have a word in the NVM to determine + /* 82573 does not have a word in the NVM to determine * the default flow control setting, so we explicitly * set it to full. */ @@ -1526,8 +1498,7 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_82571: case e1000_82572: - /* - * If SerDes loopback mode is entered, there is no form + /* If SerDes loopback mode is entered, there is no form * of reset to take the adapter out of that mode. So we * have to explicitly take the adapter out of loopback * mode. This prevents drivers from twiddling their thumbs @@ -1584,8 +1555,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) switch (mac->serdes_link_state) { case e1000_serdes_link_autoneg_complete: if (!(status & E1000_STATUS_LU)) { - /* - * We have lost link, retry autoneg before + /* We have lost link, retry autoneg before * reporting link failure */ mac->serdes_link_state = @@ -1598,8 +1568,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) break; case e1000_serdes_link_forced_up: - /* - * If we are receiving /C/ ordered sets, re-enable + /* If we are receiving /C/ ordered sets, re-enable * auto-negotiation in the TXCW register and disable * forced link in the Device Control register in an * attempt to auto-negotiate with our link partner. @@ -1619,8 +1588,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) case e1000_serdes_link_autoneg_progress: if (rxcw & E1000_RXCW_C) { - /* - * We received /C/ ordered sets, meaning the + /* We received /C/ ordered sets, meaning the * link partner has autonegotiated, and we can * trust the Link Up (LU) status bit. */ @@ -1636,8 +1604,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) e_dbg("AN_PROG -> DOWN\n"); } } else { - /* - * The link partner did not autoneg. + /* The link partner did not autoneg. * Force link up and full duplex, and change * state to forced. */ @@ -1660,8 +1627,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) case e1000_serdes_link_down: default: - /* - * The link was down but the receiver has now gained + /* The link was down but the receiver has now gained * valid sync, so lets see if we can bring the link * up. */ @@ -1679,8 +1645,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) mac->serdes_link_state = e1000_serdes_link_down; e_dbg("ANYSTATE -> DOWN\n"); } else { - /* - * Check several times, if SYNCH bit and CONFIG + /* Check several times, if SYNCH bit and CONFIG * bit both are consistently 1 then simply ignore * the IV bit and restart Autoneg */ @@ -1780,8 +1745,7 @@ void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state) /* If workaround is activated... */ if (state) - /* - * Hold a copy of the LAA in RAR[14] This is done so that + /* Hold a copy of the LAA in RAR[14] This is done so that * between the time RAR[0] gets clobbered and the time it * gets fixed, the actual LAA is in one of the RARs and no * incoming packets directed to this port are dropped. @@ -1810,8 +1774,7 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) if (nvm->type != e1000_nvm_flash_hw) return 0; - /* - * Check bit 4 of word 10h. If it is 0, firmware is done updating + /* Check bit 4 of word 10h. If it is 0, firmware is done updating * 10h-12h. Checksum may need to be fixed. */ ret_val = e1000_read_nvm(hw, 0x10, 1, &data); @@ -1819,8 +1782,7 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) return ret_val; if (!(data & 0x10)) { - /* - * Read 0x23 and check bit 15. This bit is a 1 + /* Read 0x23 and check bit 15. This bit is a 1 * when the checksum has already been fixed. If * the checksum is still wrong and this bit is a * 1, we need to return bad checksum. Otherwise, @@ -1852,8 +1814,7 @@ static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw) if (hw->mac.type == e1000_82571) { s32 ret_val = 0; - /* - * If there's an alternate MAC address place it in RAR0 + /* If there's an alternate MAC address place it in RAR0 * so that it will override the Si installed default perm * address. */ diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h index 76edbc1be33b..02a12b69555f 100644 --- a/drivers/net/ethernet/intel/e1000e/defines.h +++ b/drivers/net/ethernet/intel/e1000e/defines.h @@ -185,8 +185,7 @@ #define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ #define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ -/* - * Use byte values for the following shift parameters +/* Use byte values for the following shift parameters * Usage: * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & * E1000_PSRCTL_BSIZE0_MASK) | @@ -242,8 +241,7 @@ #define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ #define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ -/* - * Bit definitions for the Management Data IO (MDIO) and Management Data +/* Bit definitions for the Management Data IO (MDIO) and Management Data * Clock (MDC) pins in the Device Control Register. */ @@ -424,8 +422,7 @@ #define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */ #define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 for ECC */ -/* - * This defines the bits that are set in the Interrupt Mask +/* This defines the bits that are set in the Interrupt Mask * Set/Read Register. Each bit is documented below: * o RXT0 = Receiver Timer Interrupt (ring 0) * o TXDW = Transmit Descriptor Written Back @@ -475,8 +472,7 @@ /* 802.1q VLAN Packet Size */ #define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ -/* Receive Address */ -/* +/* Receive Address * Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. * Technically, we have 16 spots. However, we reserve one of these spots @@ -723,8 +719,7 @@ #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ #define MAX_PHY_MULTI_PAGE_REG 0xF -/* Bit definitions for valid PHY IDs. */ -/* +/* Bit definitions for valid PHY IDs. * I = Integrated * E = External */ @@ -762,8 +757,7 @@ #define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* Auto crossover enabled all speeds */ #define M88E1000_PSCR_AUTO_X_MODE 0x0060 -/* - * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold) +/* 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold) * 0=Normal 10BASE-T Rx Threshold */ #define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ @@ -779,14 +773,12 @@ #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 -/* - * Number of times we will attempt to autonegotiate before downshifting if we +/* Number of times we will attempt to autonegotiate before downshifting if we * are the master */ #define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 -/* - * Number of times we will attempt to autonegotiate before downshifting if we +/* Number of times we will attempt to autonegotiate before downshifting if we * are the slave */ #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 @@ -808,8 +800,7 @@ #define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ ((reg) & MAX_PHY_REG_ADDRESS)) -/* - * Bits... +/* Bits... * 15-5: page * 4-0: register offset */ diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index 04668b47a1df..6782a2eea1bc 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -161,8 +161,7 @@ struct e1000_info; /* Time to wait before putting the device into D3 if there's no link (in ms). */ #define LINK_TIMEOUT 100 -/* - * Count for polling __E1000_RESET condition every 10-20msec. +/* Count for polling __E1000_RESET condition every 10-20msec. * Experimentation has shown the reset can take approximately 210msec. */ #define E1000_CHECK_RESET_COUNT 25 @@ -172,8 +171,7 @@ struct e1000_info; #define BURST_RDTR 0x20 #define BURST_RADV 0x20 -/* - * in the case of WTHRESH, it appears at least the 82571/2 hardware +/* in the case of WTHRESH, it appears at least the 82571/2 hardware * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when * WTHRESH=4, so a setting of 5 gives the most efficient bus * utilization but to avoid possible Tx stalls, set it to 1 @@ -214,8 +212,7 @@ struct e1000_ps_page { u64 dma; /* must be u64 - written to hw */ }; -/* - * wrappers around a pointer to a socket buffer, +/* wrappers around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer */ struct e1000_buffer { @@ -305,9 +302,7 @@ struct e1000_adapter { u16 tx_itr; u16 rx_itr; - /* - * Tx - */ + /* Tx */ struct e1000_ring *tx_ring /* One per active queue */ ____cacheline_aligned_in_smp; u32 tx_fifo_limit; @@ -340,9 +335,7 @@ struct e1000_adapter { u32 tx_fifo_size; u32 tx_dma_failed; - /* - * Rx - */ + /* Rx */ 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, diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index c11ac2756667..f95bc6ee1c22 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -214,7 +214,8 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) mac->autoneg = 0; /* Make sure dplx is at most 1 bit and lsb of speed is not set - * for the switch() below to work */ + * for the switch() below to work + */ if ((spd & 1) || (dplx & ~1)) goto err_inval; @@ -263,8 +264,7 @@ static int e1000_set_settings(struct net_device *netdev, struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - /* - * When SoL/IDER sessions are active, autoneg/speed/duplex + /* When SoL/IDER sessions are active, autoneg/speed/duplex * cannot be changed */ if (hw->phy.ops.check_reset_block && @@ -273,8 +273,7 @@ static int e1000_set_settings(struct net_device *netdev, return -EINVAL; } - /* - * MDI setting is only allowed when autoneg enabled because + /* MDI setting is only allowed when autoneg enabled because * some hardware doesn't allow MDI setting when speed or * duplex is forced. */ @@ -316,8 +315,7 @@ static int e1000_set_settings(struct net_device *netdev, /* MDI-X => 2; MDI => 1; Auto => 3 */ if (ecmd->eth_tp_mdix_ctrl) { - /* - * fix up the value for auto (3 => 0) as zero is mapped + /* fix up the value for auto (3 => 0) as zero is mapped * internally to auto */ if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) @@ -454,8 +452,8 @@ static void e1000_get_regs(struct net_device *netdev, regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ /* ethtool doesn't use anything past this point, so all this - * code is likely legacy junk for apps that may or may not - * exist */ + * code is likely legacy junk for apps that may or may not exist + */ if (hw->phy.type == e1000_phy_m88) { e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); regs_buff[13] = (u32)phy_data; /* cable length */ @@ -598,8 +596,7 @@ static int e1000_set_eeprom(struct net_device *netdev, if (ret_val) goto out; - /* - * Update the checksum over the first part of the EEPROM if needed + /* Update the checksum over the first part of the EEPROM if needed * and flush shadow RAM for applicable controllers */ if ((first_word <= NVM_CHECKSUM_REG) || @@ -623,8 +620,7 @@ static void e1000_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->version, e1000e_driver_version, sizeof(drvinfo->version)); - /* - * EEPROM image version # is reported as firmware version # for + /* EEPROM image version # is reported as firmware version # for * PCI-E controllers */ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), @@ -708,8 +704,7 @@ static int e1000_set_ringparam(struct net_device *netdev, e1000e_down(adapter); - /* - * We can't just free everything and then setup again, because the + /* 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... */ @@ -813,8 +808,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) u32 mask; u32 wlock_mac = 0; - /* - * The status register is Read Only, so a write should fail. + /* The status register is Read Only, so a write should fail. * Some bits that get toggled are ignored. */ switch (mac->type) { @@ -996,8 +990,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) } if (!shared_int) { - /* - * Disable the interrupt to be reported in + /* Disable the interrupt to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was posted to the bus, the @@ -1015,8 +1008,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) } } - /* - * Enable the interrupt to be reported in + /* Enable the interrupt to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was not posted to the bus, the @@ -1034,8 +1026,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) } if (!shared_int) { - /* - * Disable the other interrupts to be reported in + /* Disable the other interrupts to be reported in * the cause register and then force the other * interrupts and see if any get posted. If * an interrupt was posted to the bus, the @@ -1378,8 +1369,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) hw->phy.type == e1000_phy_m88) { ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ } else { - /* - * Set the ILOS bit on the fiber Nic if half duplex link is + /* Set the ILOS bit on the fiber Nic if half duplex link is * detected. */ if ((er32(STATUS) & E1000_STATUS_FD) == 0) @@ -1388,8 +1378,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) ew32(CTRL, ctrl_reg); - /* - * Disable the receiver on the PHY so when a cable is plugged in, the + /* Disable the receiver on the PHY so when a cable is plugged in, the * PHY does not begin to autoneg when a cable is reconnected to the NIC. */ if (hw->phy.type == e1000_phy_m88) @@ -1408,8 +1397,7 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) /* special requirements for 82571/82572 fiber adapters */ - /* - * jump through hoops to make sure link is up because serdes + /* jump through hoops to make sure link is up because serdes * link is hardwired up */ ctrl |= E1000_CTRL_SLU; @@ -1429,8 +1417,7 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) ew32(CTRL, ctrl); } - /* - * special write to serdes control register to enable SerDes analog + /* special write to serdes control register to enable SerDes analog * loopback */ #define E1000_SERDES_LB_ON 0x410 @@ -1448,8 +1435,7 @@ static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter) u32 ctrlext = er32(CTRL_EXT); u32 ctrl = er32(CTRL); - /* - * save CTRL_EXT to restore later, reuse an empty variable (unused + /* save CTRL_EXT to restore later, reuse an empty variable (unused * on mac_type 80003es2lan) */ adapter->tx_fifo_head = ctrlext; @@ -1585,8 +1571,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter) ew32(RDT(0), rx_ring->count - 1); - /* - * Calculate the loop count based on the largest descriptor ring + /* Calculate the loop count based on the largest descriptor ring * The idea is to wrap the largest ring a number of times using 64 * send/receive pairs during each loop */ @@ -1627,8 +1612,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter) l++; if (l == rx_ring->count) l = 0; - /* - * time + 20 msecs (200 msecs on 2.4) is more than + /* time + 20 msecs (200 msecs on 2.4) is more than * enough time to complete the receives, if it's * exceeded, break and error off */ @@ -1649,10 +1633,7 @@ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) { struct e1000_hw *hw = &adapter->hw; - /* - * PHY loopback cannot be performed if SoL/IDER - * sessions are active - */ + /* PHY loopback cannot be performed if SoL/IDER sessions are active */ if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) { e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); @@ -1686,8 +1667,7 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) int i = 0; hw->mac.serdes_has_link = false; - /* - * On some blade server designs, link establishment + /* On some blade server designs, link establishment * could take as long as 2-3 minutes */ do { @@ -1701,8 +1681,7 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) } else { hw->mac.ops.check_for_link(hw); if (hw->mac.autoneg) - /* - * On some Phy/switch combinations, link establishment + /* On some Phy/switch combinations, link establishment * can take a few seconds more than expected. */ msleep(5000); diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h index d37bfd96c987..cf217777586c 100644 --- a/drivers/net/ethernet/intel/e1000e/hw.h +++ b/drivers/net/ethernet/intel/e1000e/hw.h @@ -85,8 +85,7 @@ enum e1e_registers { E1000_FCRTL = 0x02160, /* Flow Control Receive Threshold Low - RW */ E1000_FCRTH = 0x02168, /* Flow Control Receive Threshold High - RW */ E1000_PSRCTL = 0x02170, /* Packet Split Receive Control - RW */ -/* - * Convenience macros +/* Convenience macros * * Note: "_n" is the queue number of the register to be written to. * @@ -800,8 +799,7 @@ struct e1000_mac_operations { s32 (*read_mac_addr)(struct e1000_hw *); }; -/* - * When to use various PHY register access functions: +/* When to use various PHY register access functions: * * Func Caller * Function Does Does When to use diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index e3a7b07df629..976336547607 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -26,8 +26,7 @@ *******************************************************************************/ -/* - * 82562G 10/100 Network Connection +/* 82562G 10/100 Network Connection * 82562G-2 10/100 Network Connection * 82562GT 10/100 Network Connection * 82562GT-2 10/100 Network Connection @@ -354,8 +353,7 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) return true; } - /* - * In case the PHY needs to be in mdio slow mode, + /* In case the PHY needs to be in mdio slow mode, * set slow mode and try to get the PHY id again. */ hw->phy.ops.release(hw); @@ -386,8 +384,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) return ret_val; } - /* - * The MAC-PHY interconnect may be in SMBus mode. If the PHY is + /* The MAC-PHY interconnect may be in SMBus mode. If the PHY is * inaccessible and resetting the PHY is not blocked, toggle the * LANPHYPC Value bit to force the interconnect to PCIe mode. */ @@ -396,8 +393,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) if (e1000_phy_is_accessible_pchlan(hw)) break; - /* - * Before toggling LANPHYPC, see if PHY is accessible by + /* Before toggling LANPHYPC, see if PHY is accessible by * forcing MAC to SMBus mode first. */ mac_reg = er32(CTRL_EXT); @@ -406,8 +402,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) /* fall-through */ case e1000_pch2lan: - /* - * Gate automatic PHY configuration by hardware on + /* Gate automatic PHY configuration by hardware on * non-managed 82579 */ if ((hw->mac.type == e1000_pch2lan) && @@ -474,8 +469,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) hw->phy.ops.release(hw); - /* - * Reset the PHY before any access to it. Doing so, ensures + /* 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. @@ -536,8 +530,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) /* fall-through */ case e1000_pch2lan: case e1000_pch_lpt: - /* - * In case the PHY needs to be in mdio slow mode, + /* In case the PHY needs to be in mdio slow mode, * set slow mode and try to get the PHY id again. */ ret_val = e1000_set_mdio_slow_mode_hv(hw); @@ -593,8 +586,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; - /* - * We may need to do this twice - once for IGP and if that fails, + /* We may need to do this twice - once for IGP and if that fails, * we'll set BM func pointers and try again */ ret_val = e1000e_determine_phy_address(hw); @@ -679,8 +671,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) gfpreg = er32flash(ICH_FLASH_GFPREG); - /* - * sector_X_addr is a "sector"-aligned address (4096 bytes) + /* sector_X_addr is a "sector"-aligned address (4096 bytes) * Add 1 to sector_end_addr since this sector is included in * the overall size. */ @@ -690,8 +681,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) /* flash_base_addr is byte-aligned */ nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; - /* - * find total size of the NVM, then cut in half since the total + /* find total size of the NVM, then cut in half since the total * size represents two separate NVM banks. */ nvm->flash_bank_size = (sector_end_addr - sector_base_addr) @@ -788,8 +778,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) if (mac->type == e1000_ich8lan) e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); - /* - * Gate automatic PHY configuration by hardware on managed + /* Gate automatic PHY configuration by hardware on managed * 82579 and i217 */ if ((mac->type == e1000_pch2lan || mac->type == e1000_pch_lpt) && @@ -840,8 +829,7 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw) goto release; e1e_rphy_locked(hw, I82579_EMI_DATA, &dev_spec->eee_lp_ability); - /* - * EEE is not supported in 100Half, so ignore partner's EEE + /* EEE is not supported in 100Half, so ignore partner's EEE * in 100 ability if full-duplex is not advertised. */ e1e_rphy_locked(hw, PHY_LP_ABILITY, &phy_reg); @@ -869,8 +857,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) bool link; u16 phy_reg; - /* - * We only want to go out to the PHY registers to see if Auto-Neg + /* We only want to go out to the PHY registers to see if Auto-Neg * has completed and/or if our link status has changed. The * get_link_status flag is set upon receiving a Link Status * Change or Rx Sequence Error interrupt. @@ -878,8 +865,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (!mac->get_link_status) return 0; - /* - * First we want to see if the MII Status Register reports + /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. */ @@ -914,8 +900,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) return ret_val; } - /* - * Workaround for PCHx parts in half-duplex: + /* Workaround for PCHx parts in half-duplex: * Set the number of preambles removed from the packet * when it is passed from the PHY to the MAC to prevent * the MAC from misinterpreting the packet type. @@ -932,8 +917,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) break; } - /* - * Check if there was DownShift, must be checked + /* Check if there was DownShift, must be checked * immediately after link-up */ e1000e_check_downshift(hw); @@ -943,22 +927,19 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * If we are forcing speed/duplex, then we simply return since + /* If we are forcing speed/duplex, then we simply return since * we have already determined whether we have link or not. */ if (!mac->autoneg) return -E1000_ERR_CONFIG; - /* - * Auto-Neg is enabled. Auto Speed Detection takes care + /* Auto-Neg is enabled. Auto Speed Detection takes care * of MAC speed/duplex configuration. So we only need to * configure Collision Distance in the MAC. */ mac->ops.config_collision_dist(hw); - /* - * Configure Flow Control now that Auto-Neg has completed. + /* Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. @@ -1000,8 +981,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) if (rc) return rc; - /* - * Disable Jumbo Frame support on parts with Intel 10/100 PHY or + /* Disable Jumbo Frame support on parts with Intel 10/100 PHY or * on parts with MACsec enabled in NVM (reflected in CTRL_EXT). */ if ((adapter->hw.phy.type == e1000_phy_ife) || @@ -1191,8 +1171,7 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) { u32 rar_low, rar_high; - /* - * HW expects these in little endian so we reverse the byte order + /* 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] | @@ -1256,8 +1235,7 @@ static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) u32 rar_low, rar_high; u32 wlock_mac; - /* - * HW expects these in little endian so we reverse the byte order + /* 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) | @@ -1277,8 +1255,7 @@ static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) return; } - /* - * The manageability engine (ME) can lock certain SHRAR registers that + /* The manageability engine (ME) can lock certain SHRAR registers that * it is using - those registers are unavailable for use. */ if (index < hw->mac.rar_entry_count) { @@ -1387,8 +1364,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) s32 ret_val = 0; u16 word_addr, reg_data, reg_addr, phy_page = 0; - /* - * Initialize the PHY from the NVM on ICH platforms. This + /* Initialize the PHY from the NVM on ICH platforms. This * is needed due to an issue where the NVM configuration is * not properly autoloaded after power transitions. * Therefore, after each PHY reset, we will load the @@ -1422,8 +1398,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) if (!(data & sw_cfg_mask)) goto release; - /* - * Make sure HW does not configure LCD from PHY + /* Make sure HW does not configure LCD from PHY * extended configuration before SW configuration */ data = er32(EXTCNF_CTRL); @@ -1443,8 +1418,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) if (((hw->mac.type == e1000_pchlan) && !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) || (hw->mac.type > e1000_pchlan)) { - /* - * HW configures the SMBus address and LEDs when the + /* HW configures the SMBus address and LEDs when the * OEM and LCD Write Enable bits are set in the NVM. * When both NVM bits are cleared, SW will configure * them instead. @@ -1748,8 +1722,7 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) } if (hw->phy.type == e1000_phy_82578) { - /* - * Return registers to default by doing a soft reset then + /* Return registers to default by doing a soft reset then * writing 0x3140 to the control register. */ if (hw->phy.revision < 2) { @@ -1769,8 +1742,7 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Configure the K1 Si workaround during phy reset assuming there is + /* Configure the K1 Si workaround during phy reset assuming there is * link so that it disables K1 if link is in 1Gbps. */ ret_val = e1000_k1_gig_workaround_hv(hw, true); @@ -1853,8 +1825,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) return ret_val; if (enable) { - /* - * Write Rx addresses (rar_entry_count for RAL/H, +4 for + /* Write Rx addresses (rar_entry_count for RAL/H, +4 for * SHRAL/H) and initial CRC values to the MAC */ for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { @@ -2131,8 +2102,7 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) udelay(100); } while ((!data) && --loop); - /* - * If basic configuration is incomplete before the above loop + /* If basic configuration is incomplete before the above loop * count reaches 0, loading the configuration from NVM will * leave the PHY in a bad state possibly resulting in no link. */ @@ -2299,8 +2269,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) if (phy->type != e1000_phy_igp_3) return 0; - /* - * Call gig speed drop workaround on LPLU before accessing + /* Call gig speed drop workaround on LPLU before accessing * any PHY registers */ if (hw->mac.type == e1000_ich8lan) @@ -2319,8 +2288,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) if (phy->type != e1000_phy_igp_3) return 0; - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. @@ -2382,8 +2350,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) if (phy->type != e1000_phy_igp_3) return 0; - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. @@ -2420,8 +2387,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) if (phy->type != e1000_phy_igp_3) return 0; - /* - * Call gig speed drop workaround on LPLU before accessing + /* Call gig speed drop workaround on LPLU before accessing * any PHY registers */ if (hw->mac.type == e1000_ich8lan) @@ -2589,8 +2555,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); - /* - * Either we should have a hardware SPI cycle in progress + /* Either we should have a hardware SPI cycle in progress * bit to check against, in order to start a new cycle or * FDONE bit should be changed in the hardware so that it * is 1 after hardware reset, which can then be used as an @@ -2599,8 +2564,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) */ if (!hsfsts.hsf_status.flcinprog) { - /* - * There is no cycle running at present, + /* There is no cycle running at present, * so we can start a cycle. * Begin by setting Flash Cycle Done. */ @@ -2610,8 +2574,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) } else { s32 i; - /* - * Otherwise poll for sometime so the current + /* Otherwise poll for sometime so the current * cycle has a chance to end before giving up. */ for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { @@ -2623,8 +2586,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) udelay(1); } if (!ret_val) { - /* - * Successful in waiting for previous cycle to timeout, + /* Successful in waiting for previous cycle to timeout, * now set the Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; @@ -2753,8 +2715,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, ret_val = e1000_flash_cycle_ich8lan(hw, ICH_FLASH_READ_COMMAND_TIMEOUT); - /* - * Check if FCERR is set to 1, if set to 1, clear it + /* Check if FCERR is set to 1, if set to 1, clear it * and try the whole sequence a few more times, else * read in (shift in) the Flash Data0, the order is * least significant byte first msb to lsb @@ -2767,8 +2728,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, *data = (u16)(flash_data & 0x0000FFFF); break; } else { - /* - * If we've gotten here, then things are probably + /* If we've gotten here, then things are probably * completely hosed, but if the error condition is * detected, it won't hurt to give it another try... * ICH_FLASH_CYCLE_REPEAT_COUNT times. @@ -2849,8 +2809,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) nvm->ops.acquire(hw); - /* - * We're writing to the opposite bank so if we're on bank 1, + /* We're writing to the opposite bank so if we're on bank 1, * write to bank 0 etc. We also need to erase the segment that * is going to be written */ @@ -2875,8 +2834,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) } for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) { - /* - * Determine whether to write the value stored + /* Determine whether to write the value stored * in the other NVM bank or a modified value stored * in the shadow RAM */ @@ -2890,8 +2848,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) break; } - /* - * If the word is 0x13, then make sure the signature bits + /* If the word is 0x13, then make sure the signature bits * (15:14) are 11b until the commit has completed. * This will allow us to write 10b which indicates the * signature is valid. We want to do this after the write @@ -2920,8 +2877,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) break; } - /* - * Don't bother writing the segment valid bits if sector + /* Don't bother writing the segment valid bits if sector * programming failed. */ if (ret_val) { @@ -2930,8 +2886,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) goto release; } - /* - * Finally validate the new segment by setting bit 15:14 + /* Finally validate the new segment by setting bit 15:14 * to 10b in word 0x13 , this can be done without an * erase as well since these bits are 11 to start with * and we need to change bit 14 to 0b @@ -2948,8 +2903,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) if (ret_val) goto release; - /* - * And invalidate the previously valid segment by setting + /* And invalidate the previously valid segment by setting * its signature word (0x13) high_byte to 0b. This can be * done without an erase because flash erase sets all bits * to 1's. We can write 1's to 0's without an erase @@ -2968,8 +2922,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) release: nvm->ops.release(hw); - /* - * Reload the EEPROM, or else modifications will not appear + /* Reload the EEPROM, or else modifications will not appear * until after the next adapter reset. */ if (!ret_val) { @@ -2997,8 +2950,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) s32 ret_val; u16 data; - /* - * Read 0x19 and check bit 6. If this bit is 0, the checksum + /* Read 0x19 and check bit 6. If this bit is 0, the checksum * needs to be fixed. This bit is an indication that the NVM * was prepared by OEM software and did not calculate the * checksum...a likely scenario. @@ -3048,8 +3000,7 @@ void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw) pr0.range.wpe = true; ew32flash(ICH_FLASH_PR0, pr0.regval); - /* - * Lock down a subset of GbE Flash Control Registers, e.g. + /* Lock down a subset of GbE Flash Control Registers, e.g. * PR0 to prevent the write-protection from being lifted. * Once FLOCKDN is set, the registers protected by it cannot * be written until FLOCKDN is cleared by a hardware reset. @@ -3109,8 +3060,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, ew32flash(ICH_FLASH_FDATA0, flash_data); - /* - * check if FCERR is set to 1 , if set to 1, clear it + /* check if FCERR is set to 1 , if set to 1, clear it * and try the whole sequence a few more times else done */ ret_val = e1000_flash_cycle_ich8lan(hw, @@ -3118,8 +3068,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, if (!ret_val) break; - /* - * If we're here, then things are most likely + /* If we're here, then things are most likely * completely hosed, but if the error condition * is detected, it won't hurt to give it another * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. @@ -3207,8 +3156,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - /* - * Determine HW Sector size: Read BERASE bits of hw flash status + /* Determine HW Sector size: Read BERASE bits of hw flash status * register * 00: The Hw sector is 256 bytes, hence we need to erase 16 * consecutive sectors. The start index for the nth Hw sector @@ -3253,16 +3201,14 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) if (ret_val) return ret_val; - /* - * Write a value 11 (block Erase) in Flash + /* Write a value 11 (block Erase) in Flash * Cycle field in hw flash control */ hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - /* - * Write the last 24 bits of an index within the + /* Write the last 24 bits of an index within the * block into Flash Linear address field in Flash * Address. */ @@ -3274,8 +3220,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) if (!ret_val) break; - /* - * Check if FCERR is set to 1. If 1, + /* Check if FCERR is set to 1. If 1, * clear it and try the whole sequence * a few more times else Done */ @@ -3403,8 +3348,7 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) ret_val = e1000e_get_bus_info_pcie(hw); - /* - * ICH devices are "PCI Express"-ish. They have + /* ICH devices are "PCI Express"-ish. They have * a configuration space, but do not contain * PCI Express Capability registers, so bus width * must be hardcoded. @@ -3429,8 +3373,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) u32 ctrl, reg; s32 ret_val; - /* - * Prevent the PCI-E bus from sticking if there is no TLP connection + /* Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000e_disable_pcie_master(hw); @@ -3440,8 +3383,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) e_dbg("Masking off all interrupts\n"); ew32(IMC, 0xffffffff); - /* - * Disable the Transmit and Receive units. Then delay to allow + /* Disable the Transmit and Receive units. Then delay to allow * any pending transactions to complete before we hit the MAC * with the global reset. */ @@ -3474,15 +3416,13 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ctrl = er32(CTRL); if (!hw->phy.ops.check_reset_block(hw)) { - /* - * Full-chip reset requires MAC and PHY reset at the same + /* Full-chip reset requires MAC and PHY reset at the same * time to make sure the interface between MAC and the * external PHY is reset. */ ctrl |= E1000_CTRL_PHY_RST; - /* - * Gate automatic PHY configuration by hardware on + /* Gate automatic PHY configuration by hardware on * non-managed 82579 */ if ((hw->mac.type == e1000_pch2lan) && @@ -3516,8 +3456,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) return ret_val; } - /* - * For PCH, this write will make sure that any noise + /* For PCH, this write will make sure that any noise * will be detected as a CRC error and be dropped rather than show up * as a bad packet to the DMA engine. */ @@ -3569,8 +3508,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - /* - * The 82578 Rx buffer will stall if wakeup is enabled in host and + /* The 82578 Rx buffer will stall if wakeup is enabled in host and * the ME. Disable wakeup by clearing the host wakeup bit. * Reset the phy after disabling host wakeup to reset the Rx buffer. */ @@ -3600,8 +3538,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) E1000_TXDCTL_MAX_TX_DESC_PREFETCH; ew32(TXDCTL(1), txdctl); - /* - * ICH8 has opposite polarity of no_snoop bits. + /* ICH8 has opposite polarity of no_snoop bits. * By default, we should use snoop behavior. */ if (mac->type == e1000_ich8lan) @@ -3614,8 +3551,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) ctrl_ext |= E1000_CTRL_EXT_RO_DIS; ew32(CTRL_EXT, ctrl_ext); - /* - * Clear all of the statistics registers (clear on read). It is + /* Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. @@ -3676,15 +3612,13 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) ew32(STATUS, reg); } - /* - * work-around descriptor data corruption issue during nfs v2 udp + /* work-around descriptor data corruption issue during nfs v2 udp * traffic, just disable the nfs filtering capability */ reg = er32(RFCTL); reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); - /* - * Disable IPv6 extension header parsing because some malformed + /* Disable IPv6 extension header parsing because some malformed * IPv6 headers can hang the Rx. */ if (hw->mac.type == e1000_ich8lan) @@ -3709,8 +3643,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) if (hw->phy.ops.check_reset_block(hw)) return 0; - /* - * ICH parts do not have a word in the NVM to determine + /* ICH parts do not have a word in the NVM to determine * the default flow control setting, so we explicitly * set it to full. */ @@ -3722,8 +3655,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) hw->fc.requested_mode = e1000_fc_full; } - /* - * Save off the requested flow control mode for use later. Depending + /* Save off the requested flow control mode for use later. Depending * on the link partner's capabilities, we may or may not use this mode. */ hw->fc.current_mode = hw->fc.requested_mode; @@ -3771,8 +3703,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); ew32(CTRL, ctrl); - /* - * Set the mac to wait the maximum time between each iteration + /* Set the mac to wait the maximum time between each iteration * and increase the max iterations when polling the phy; * this fixes erroneous timeouts at 10Mbps. */ @@ -3892,8 +3823,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) if (!dev_spec->kmrn_lock_loss_workaround_enabled) return 0; - /* - * Make sure link is up before proceeding. If not just return. + /* Make sure link is up before proceeding. If not just return. * Attempting this while link is negotiating fouled up link * stability */ @@ -3925,8 +3855,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) E1000_PHY_CTRL_NOND0A_GBE_DISABLE); ew32(PHY_CTRL, phy_ctrl); - /* - * Call gig speed drop workaround on Gig disable before accessing + /* Call gig speed drop workaround on Gig disable before accessing * any PHY registers */ e1000e_gig_downshift_workaround_ich8lan(hw); @@ -3983,8 +3912,7 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) E1000_PHY_CTRL_NOND0A_GBE_DISABLE); ew32(PHY_CTRL, reg); - /* - * Call gig speed drop workaround on Gig disable before + /* Call gig speed drop workaround on Gig disable before * accessing any PHY registers */ if (hw->mac.type == e1000_ich8lan) @@ -4078,8 +4006,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) goto release; e1e_rphy_locked(hw, I82579_EMI_DATA, &eee_advert); - /* - * Disable LPLU if both link partners support 100BaseT + /* Disable LPLU if both link partners support 100BaseT * EEE and 100Full is advertised on both ends of the * link. */ @@ -4091,8 +4018,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) E1000_PHY_CTRL_NOND0A_LPLU); } - /* - * For i217 Intel Rapid Start Technology support, + /* For i217 Intel Rapid Start Technology support, * when the system is going into Sx and no manageability engine * is present, the driver must configure proxy to reset only on * power good. LPI (Low Power Idle) state must also reset only @@ -4106,8 +4032,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE; e1e_wphy_locked(hw, I217_PROXY_CTRL, phy_reg); - /* - * Set bit enable LPI (EEE) to reset only on + /* Set bit enable LPI (EEE) to reset only on * power good. */ e1e_rphy_locked(hw, I217_SxCTRL, &phy_reg); @@ -4120,8 +4045,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) e1e_wphy_locked(hw, I217_MEMPWR, phy_reg); } - /* - * Enable MTA to reset for Intel Rapid Start Technology + /* Enable MTA to reset for Intel Rapid Start Technology * Support */ e1e_rphy_locked(hw, I217_CGFREG, &phy_reg); @@ -4175,8 +4099,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) return; } - /* - * For i217 Intel Rapid Start Technology support when the system + /* For i217 Intel Rapid Start Technology support when the system * is transitioning from Sx and no manageability engine is present * configure SMBus to restore on reset, disable proxy, and enable * the reset on MTA (Multicast table array). @@ -4191,8 +4114,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) } if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { - /* - * Restore clear on SMB if no manageability engine + /* Restore clear on SMB if no manageability engine * is present */ ret_val = e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg); @@ -4298,8 +4220,7 @@ static s32 e1000_led_on_pchlan(struct e1000_hw *hw) u16 data = (u16)hw->mac.ledctl_mode2; u32 i, led; - /* - * If no link, then turn LED on by setting the invert bit + /* If no link, then turn LED on by setting the invert bit * for each LED that's mode is "link_up" in ledctl_mode2. */ if (!(er32(STATUS) & E1000_STATUS_LU)) { @@ -4329,8 +4250,7 @@ static s32 e1000_led_off_pchlan(struct e1000_hw *hw) u16 data = (u16)hw->mac.ledctl_mode1; u32 i, led; - /* - * If no link, then turn LED off by clearing the invert bit + /* If no link, then turn LED off by clearing the invert bit * for each LED that's mode is "link_up" in ledctl_mode1. */ if (!(er32(STATUS) & E1000_STATUS_LU)) { @@ -4375,8 +4295,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) } else { ret_val = e1000e_get_auto_rd_done(hw); if (ret_val) { - /* - * When auto config read does not complete, do not + /* When auto config read does not complete, do not * return with an error. This can happen in situations * where there is no eeprom and prevents getting link. */ diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c index a13439928488..54d9dafaf126 100644 --- a/drivers/net/ethernet/intel/e1000e/mac.c +++ b/drivers/net/ethernet/intel/e1000e/mac.c @@ -73,8 +73,7 @@ void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) struct e1000_bus_info *bus = &hw->bus; u32 reg; - /* - * The status register reports the correct function number + /* The status register reports the correct function number * for the device regardless of function swap state. */ reg = er32(STATUS); @@ -210,8 +209,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) return 0; } - /* - * We have a valid alternate MAC address, and we want to treat it the + /* We have a valid alternate MAC address, and we want to treat it the * same as the normal permanent MAC address stored by the HW into the * RAR. Do this by mapping this address into RAR0. */ @@ -233,8 +231,7 @@ void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) { u32 rar_low, rar_high; - /* - * HW expects these in little endian so we reverse the byte order + /* 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) | @@ -246,8 +243,7 @@ void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) if (rar_low || rar_high) rar_high |= E1000_RAH_AV; - /* - * Some bridges will combine consecutive 32-bit writes into + /* Some bridges will combine consecutive 32-bit writes into * a single burst write, which will malfunction on some parts. * The flushes avoid this. */ @@ -273,15 +269,13 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) /* Register count multiplied by bits per register */ hash_mask = (hw->mac.mta_reg_count * 32) - 1; - /* - * For a mc_filter_type of 0, bit_shift is the number of left-shifts + /* For a mc_filter_type of 0, bit_shift is the number of left-shifts * where 0xFF would still fall within the hash mask. */ while (hash_mask >> bit_shift != 0xFF) bit_shift++; - /* - * The portion of the address that is used for the hash table + /* The portion of the address that is used for the hash table * is determined by the mc_filter_type setting. * The algorithm is such that there is a total of 8 bits of shifting. * The bit_shift for a mc_filter_type of 0 represents the number of @@ -423,8 +417,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) s32 ret_val; bool link; - /* - * We only want to go out to the PHY registers to see if Auto-Neg + /* We only want to go out to the PHY registers to see if Auto-Neg * has completed and/or if our link status has changed. The * get_link_status flag is set upon receiving a Link Status * Change or Rx Sequence Error interrupt. @@ -432,8 +425,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) if (!mac->get_link_status) return 0; - /* - * First we want to see if the MII Status Register reports + /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. */ @@ -446,28 +438,24 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) mac->get_link_status = false; - /* - * Check if there was DownShift, must be checked + /* Check if there was DownShift, must be checked * immediately after link-up */ e1000e_check_downshift(hw); - /* - * If we are forcing speed/duplex, then we simply return since + /* If we are forcing speed/duplex, then we simply return since * we have already determined whether we have link or not. */ if (!mac->autoneg) return -E1000_ERR_CONFIG; - /* - * Auto-Neg is enabled. Auto Speed Detection takes care + /* Auto-Neg is enabled. Auto Speed Detection takes care * of MAC speed/duplex configuration. So we only need to * configure Collision Distance in the MAC. */ mac->ops.config_collision_dist(hw); - /* - * Configure Flow Control now that Auto-Neg has completed. + /* Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. @@ -498,8 +486,7 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) status = er32(STATUS); rxcw = er32(RXCW); - /* - * If we don't have link (auto-negotiation failed or link partner + /* If we don't have link (auto-negotiation failed or link partner * cannot auto-negotiate), the cable is plugged in (we have signal), * and our link partner is not trying to auto-negotiate with us (we * are receiving idles or data), we need to force link up. We also @@ -530,8 +517,7 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) return ret_val; } } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* - * If we are forcing link and we are receiving /C/ ordered + /* If we are forcing link and we are receiving /C/ ordered * sets, re-enable auto-negotiation in the TXCW register * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. @@ -565,8 +551,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) status = er32(STATUS); rxcw = er32(RXCW); - /* - * If we don't have link (auto-negotiation failed or link partner + /* If we don't have link (auto-negotiation failed or link partner * cannot auto-negotiate), and our link partner is not trying to * auto-negotiate with us (we are receiving idles or data), * we need to force link up. We also need to give auto-negotiation @@ -595,8 +580,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) return ret_val; } } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* - * If we are forcing link and we are receiving /C/ ordered + /* If we are forcing link and we are receiving /C/ ordered * sets, re-enable auto-negotiation in the TXCW register * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. @@ -607,8 +591,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) mac->serdes_has_link = true; } else if (!(E1000_TXCW_ANE & er32(TXCW))) { - /* - * If we force link for non-auto-negotiation switch, check + /* If we force link for non-auto-negotiation switch, check * link status based on MAC synchronization for internal * serdes media type. */ @@ -665,8 +648,7 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw) s32 ret_val; u16 nvm_data; - /* - * Read and store word 0x0F of the EEPROM. This word contains bits + /* Read and store word 0x0F of the EEPROM. This word contains bits * that determine the hardware's default PAUSE (flow control) mode, * a bit that determines whether the HW defaults to enabling or * disabling auto-negotiation, and the direction of the @@ -705,15 +687,13 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw) { s32 ret_val; - /* - * In the case of the phy reset being blocked, we already have a link. + /* In the case of the phy reset being blocked, we already have a link. * We do not need to set it up again. */ if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) return 0; - /* - * If requested flow control is set to default, set flow control + /* If requested flow control is set to default, set flow control * based on the EEPROM flow control settings. */ if (hw->fc.requested_mode == e1000_fc_default) { @@ -722,8 +702,7 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw) return ret_val; } - /* - * Save off the requested flow control mode for use later. Depending + /* Save off the requested flow control mode for use later. Depending * on the link partner's capabilities, we may or may not use this mode. */ hw->fc.current_mode = hw->fc.requested_mode; @@ -735,8 +714,7 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Initialize the flow control address, type, and PAUSE timer + /* Initialize the flow control address, type, and PAUSE timer * registers to their default values. This is done even if flow * control is disabled, because it does not hurt anything to * initialize these registers. @@ -763,8 +741,7 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) struct e1000_mac_info *mac = &hw->mac; u32 txcw; - /* - * Check for a software override of the flow control settings, and + /* Check for a software override of the flow control settings, and * setup the device accordingly. If auto-negotiation is enabled, then * software will have to set the "PAUSE" bits to the correct value in * the Transmit Config Word Register (TXCW) and re-start auto- @@ -786,8 +763,7 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); break; case e1000_fc_rx_pause: - /* - * Rx Flow control is enabled and Tx Flow control is disabled + /* Rx Flow control is enabled and Tx Flow control is disabled * by a software over-ride. Since there really isn't a way to * advertise that we are capable of Rx Pause ONLY, we will * advertise that we support both symmetric and asymmetric Rx @@ -797,15 +773,13 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; case e1000_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is disabled, + /* Tx Flow control is enabled, and Rx Flow control is disabled, * by a software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); break; case e1000_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software + /* Flow control (both Rx and Tx) is enabled by a software * over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); @@ -835,8 +809,7 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) u32 i, status; s32 ret_val; - /* - * If we have a signal (the cable is plugged in, or assumed true for + /* If we have a signal (the cable is plugged in, or assumed true for * serdes media) then poll for a "Link-Up" indication in the Device * Status Register. Time-out if a link isn't seen in 500 milliseconds * seconds (Auto-negotiation should complete in less than 500 @@ -851,8 +824,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 = true; - /* - * AutoNeg failed to achieve a link, so we'll call + /* AutoNeg failed to achieve a link, so we'll call * mac->check_for_link. This routine will force the * link up if we detect a signal. This will allow us to * communicate with non-autonegotiating link partners. @@ -894,8 +866,7 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Since auto-negotiation is enabled, take the link out of reset (the + /* Since auto-negotiation is enabled, take the link out of reset (the * link will be in reset, because we previously reset the chip). This * will restart auto-negotiation. If auto-negotiation is successful * then the link-up status bit will be set and the flow control enable @@ -907,8 +878,7 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw) e1e_flush(); usleep_range(1000, 2000); - /* - * For these adapters, the SW definable pin 1 is set when the optics + /* For these adapters, the SW definable pin 1 is set when the optics * detect a signal. If we have a signal, then poll for a "Link-Up" * indication. */ @@ -954,16 +924,14 @@ s32 e1000e_set_fc_watermarks(struct e1000_hw *hw) { u32 fcrtl = 0, fcrth = 0; - /* - * Set the flow control receive threshold registers. Normally, + /* Set the flow control receive threshold registers. Normally, * these registers will be set to a default threshold that may be * adjusted later by the driver's runtime code. However, if the * ability to transmit pause frames is not enabled, then these * registers will be set to 0. */ if (hw->fc.current_mode & e1000_fc_tx_pause) { - /* - * We need to set up the Receive Threshold high and low water + /* We need to set up the Receive Threshold high and low water * marks as well as (optionally) enabling the transmission of * XON frames. */ @@ -995,8 +963,7 @@ s32 e1000e_force_mac_fc(struct e1000_hw *hw) ctrl = er32(CTRL); - /* - * Because we didn't get link via the internal auto-negotiation + /* Because we didn't get link via the internal auto-negotiation * mechanism (we either forced link or we got link via PHY * auto-neg), we have to manually enable/disable transmit an * receive flow control. @@ -1057,8 +1024,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; u16 speed, duplex; - /* - * Check for the case where we have fiber media and auto-neg failed + /* Check for the case where we have fiber media and auto-neg failed * so we had to force link. In this case, we need to force the * configuration of the MAC to match the "fc" parameter. */ @@ -1076,15 +1042,13 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) return ret_val; } - /* - * Check for the case where we have copper media and auto-neg is + /* Check for the case where we have copper media and auto-neg is * enabled. In this case, we need to check and see if Auto-Neg * has completed, and if so, how the PHY and link partner has * flow control configured. */ if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { - /* - * Read the MII Status Register and check to see if AutoNeg + /* Read the MII Status Register and check to see if AutoNeg * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ @@ -1100,8 +1064,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) return ret_val; } - /* - * The AutoNeg process has completed, so we now need to + /* The AutoNeg process has completed, so we now need to * read both the Auto Negotiation Advertisement * Register (Address 4) and the Auto_Negotiation Base * Page Ability Register (Address 5) to determine how @@ -1115,8 +1078,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Two bits in the Auto Negotiation Advertisement Register + /* Two bits in the Auto Negotiation Advertisement Register * (Address 4) and two bits in the Auto Negotiation Base * Page Ability Register (Address 5) determine flow control * for both the PHY and the link partner. The following @@ -1151,8 +1113,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) */ if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { - /* - * Now we need to check if the user selected Rx ONLY + /* Now we need to check if the user selected Rx ONLY * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise Rx * ONLY. Hence, we must now check to see if we need to @@ -1166,8 +1127,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) e_dbg("Flow Control = Rx PAUSE frames only.\n"); } } - /* - * For receiving PAUSE frames ONLY. + /* For receiving PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result @@ -1181,8 +1141,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) hw->fc.current_mode = e1000_fc_tx_pause; e_dbg("Flow Control = Tx PAUSE frames only.\n"); } - /* - * For transmitting PAUSE frames ONLY. + /* For transmitting PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result @@ -1196,16 +1155,14 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) hw->fc.current_mode = e1000_fc_rx_pause; e_dbg("Flow Control = Rx PAUSE frames only.\n"); } else { - /* - * Per the IEEE spec, at this point flow control + /* Per the IEEE spec, at this point flow control * should be disabled. */ hw->fc.current_mode = e1000_fc_none; e_dbg("Flow Control = NONE.\n"); } - /* - * Now we need to do one last check... If we auto- + /* Now we need to do one last check... If we auto- * negotiated to HALF DUPLEX, flow control should not be * enabled per IEEE 802.3 spec. */ @@ -1218,8 +1175,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) if (duplex == HALF_DUPLEX) hw->fc.current_mode = e1000_fc_none; - /* - * Now we call a subroutine to actually force the MAC + /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ ret_val = e1000e_force_mac_fc(hw); @@ -1520,8 +1476,7 @@ s32 e1000e_blink_led_generic(struct e1000_hw *hw) ledctl_blink = E1000_LEDCTL_LED0_BLINK | (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); } else { - /* - * set the blink bit for each LED that's "on" (0x0E) + /* set the blink bit for each LED that's "on" (0x0E) * in ledctl_mode2 */ ledctl_blink = hw->mac.ledctl_mode2; diff --git a/drivers/net/ethernet/intel/e1000e/manage.c b/drivers/net/ethernet/intel/e1000e/manage.c index bacc950fc684..6dc47beb3adc 100644 --- a/drivers/net/ethernet/intel/e1000e/manage.c +++ b/drivers/net/ethernet/intel/e1000e/manage.c @@ -143,8 +143,7 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw) return hw->mac.tx_pkt_filtering; } - /* - * If we can't read from the host interface for whatever + /* If we can't read from the host interface for whatever * reason, disable filtering. */ ret_val = e1000_mng_enable_host_if(hw); @@ -163,8 +162,7 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw) hdr->checksum = 0; csum = e1000_calculate_checksum((u8 *)hdr, E1000_MNG_DHCP_COOKIE_LENGTH); - /* - * If either the checksums or signature don't match, then + /* 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. */ @@ -252,8 +250,7 @@ static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, /* Calculate length in DWORDs */ length >>= 2; - /* - * The device driver writes the relevant command block into the + /* The device driver writes the relevant command block into the * ram area. */ for (i = 0; i < length; i++) { diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index f444eb0b76d8..fbf75fdca994 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -146,9 +146,11 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = { {0, NULL} }; -/* +/** * e1000_regdump - register printout routine - */ + * @hw: pointer to the HW structure + * @reginfo: pointer to the register info table + **/ static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo) { int n = 0; @@ -196,9 +198,10 @@ static void e1000e_dump_ps_pages(struct e1000_adapter *adapter, } } -/* +/** * e1000e_dump - Print registers, Tx-ring and Rx-ring - */ + * @adapter: board private structure + **/ static void e1000e_dump(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -623,8 +626,7 @@ map_skb: rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma); if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) { - /* - * Force memory writes to complete before letting h/w + /* Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only * applicable for weak-ordered memory model archs, * such as IA-64). @@ -692,8 +694,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring, goto no_buffers; } } - /* - * Refresh the desc even if buffer_addrs + /* Refresh the desc even if buffer_addrs * didn't change because each write-back * erases this info. */ @@ -726,8 +727,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring, rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) { - /* - * Force memory writes to complete before letting h/w + /* Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only * applicable for weak-ordered memory model archs, * such as IA-64). @@ -817,7 +817,8 @@ check_page: /* Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only * applicable for weak-ordered memory model archs, - * such as IA-64). */ + * such as IA-64). + */ wmb(); if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) e1000e_update_rdt_wa(rx_ring, i); @@ -891,8 +892,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done, length = le16_to_cpu(rx_desc->wb.upper.length); - /* - * !EOP means multiple descriptors were used to store a single + /* !EOP means multiple descriptors were used to store a single * packet, if that's the case we need to toss it. In fact, we * need to toss every packet with the EOP bit clear and the * next frame that _does_ have the EOP bit set, as it is by @@ -933,8 +933,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done, total_rx_bytes += length; total_rx_packets++; - /* - * code added for copybreak, this should improve + /* code added for copybreak, this should improve * performance for small packets with large amounts * of reassembly being done in the stack */ @@ -1032,15 +1031,13 @@ static void e1000_print_hw_hang(struct work_struct *work) if (!adapter->tx_hang_recheck && (adapter->flags2 & FLAG2_DMA_BURST)) { - /* - * May be block on write-back, flush and detect again + /* May be block on write-back, flush and detect again * flush pending descriptor writebacks to memory */ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); /* execute the writes immediately */ e1e_flush(); - /* - * Due to rare timing issues, write to TIDV again to ensure + /* Due to rare timing issues, write to TIDV again to ensure * the write is successful */ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); @@ -1169,8 +1166,7 @@ static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring) } if (adapter->detect_tx_hung) { - /* - * Detect a transmit hang in hardware, this serializes the + /* Detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = false; @@ -1270,14 +1266,12 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done, skb_put(skb, length); { - /* - * this looks ugly, but it seems compiler issues make + /* 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 + /* 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_* @@ -1288,8 +1282,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done, ps_page = &buffer_info->ps_pages[0]; - /* - * there is no documentation about how to call + /* there is no documentation about how to call * kmap_atomic, so we can't hold the mapping * very long */ @@ -1486,14 +1479,16 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done, skb_shinfo(rxtop)->nr_frags, buffer_info->page, 0, length); /* re-use the current skb, we only consumed the - * page */ + * page + */ buffer_info->skb = skb; skb = rxtop; rxtop = NULL; e1000_consume_page(buffer_info, skb, length); } else { /* no chain, got EOP, this buf is the packet - * copybreak to save the put_page/alloc_page */ + * copybreak to save the put_page/alloc_page + */ if (length <= copybreak && skb_tailroom(skb) >= length) { u8 *vaddr; @@ -1502,7 +1497,8 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done, length); kunmap_atomic(vaddr); /* re-use the page, so don't erase - * buffer_info->page */ + * buffer_info->page + */ skb_put(skb, length); } else { skb_fill_page_desc(skb, 0, @@ -1656,22 +1652,17 @@ static irqreturn_t e1000_intr_msi(int irq, void *data) struct e1000_hw *hw = &adapter->hw; u32 icr = er32(ICR); - /* - * read ICR disables interrupts using IAM - */ - + /* read ICR disables interrupts using IAM */ if (icr & E1000_ICR_LSC) { hw->mac.get_link_status = true; - /* - * ICH8 workaround-- Call gig speed drop workaround on cable + /* ICH8 workaround-- Call gig speed drop workaround on cable * disconnect (LSC) before accessing any PHY registers */ if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && (!(er32(STATUS) & E1000_STATUS_LU))) schedule_work(&adapter->downshift_task); - /* - * 80003ES2LAN workaround-- For packet buffer work-around on + /* 80003ES2LAN workaround-- For packet buffer work-around on * link down event; disable receives here in the ISR and reset * adapter in watchdog */ @@ -1713,31 +1704,27 @@ static irqreturn_t e1000_intr(int irq, void *data) if (!icr || test_bit(__E1000_DOWN, &adapter->state)) return IRQ_NONE; /* Not our interrupt */ - /* - * IMS will not auto-mask if INT_ASSERTED is not set, and if it is + /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is * not set, then the adapter didn't send an interrupt */ if (!(icr & E1000_ICR_INT_ASSERTED)) return IRQ_NONE; - /* - * Interrupt Auto-Mask...upon reading ICR, + /* Interrupt Auto-Mask...upon reading ICR, * interrupts are masked. No need for the * IMC write */ if (icr & E1000_ICR_LSC) { hw->mac.get_link_status = true; - /* - * ICH8 workaround-- Call gig speed drop workaround on cable + /* ICH8 workaround-- Call gig speed drop workaround on cable * disconnect (LSC) before accessing any PHY registers */ if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && (!(er32(STATUS) & E1000_STATUS_LU))) schedule_work(&adapter->downshift_task); - /* - * 80003ES2LAN workaround-- + /* 80003ES2LAN workaround-- * For packet buffer work-around on link down event; * disable receives here in the ISR and * reset adapter in watchdog @@ -2469,8 +2456,7 @@ static void e1000_set_itr(struct e1000_adapter *adapter) set_itr_now: if (new_itr != adapter->itr) { - /* - * this attempts to bias the interrupt rate towards Bulk + /* this attempts to bias the interrupt rate towards Bulk * by adding intermediate steps when interrupt rate is * increasing */ @@ -2517,7 +2503,7 @@ void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr) * e1000_alloc_queues - Allocate memory for all rings * @adapter: board private structure to initialize **/ -static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter) +static int e1000_alloc_queues(struct e1000_adapter *adapter) { int size = sizeof(struct e1000_ring); @@ -2740,8 +2726,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter) manc = er32(MANC); - /* - * enable receiving management packets to the host. this will probably + /* enable receiving management packets to the host. this will probably * generate destination unreachable messages from the host OS, but * the packets will be handled on SMBUS */ @@ -2754,8 +2739,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter) break; case e1000_82574: case e1000_82583: - /* - * Check if IPMI pass-through decision filter already exists; + /* Check if IPMI pass-through decision filter already exists; * if so, enable it. */ for (i = 0, j = 0; i < 8; i++) { @@ -2827,8 +2811,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) u32 txdctl = er32(TXDCTL(0)); txdctl &= ~(E1000_TXDCTL_PTHRESH | E1000_TXDCTL_HTHRESH | E1000_TXDCTL_WTHRESH); - /* - * set up some performance related parameters to encourage the + /* set up some performance related parameters to encourage the * hardware to use the bus more efficiently in bursts, depends * on the tx_int_delay to be enabled, * wthresh = 1 ==> burst write is disabled to avoid Tx stalls @@ -2845,8 +2828,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) { tarc = er32(TARC(0)); - /* - * set the speed mode bit, we'll clear it if we're not at + /* set the speed mode bit, we'll clear it if we're not at * gigabit link later */ #define SPEED_MODE_BIT (1 << 21) @@ -2967,8 +2949,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) rfctl |= E1000_RFCTL_EXTEN; ew32(RFCTL, rfctl); - /* - * 82571 and greater support packet-split where the protocol + /* 82571 and greater support packet-split where the protocol * header is placed in skb->data and the packet data is * placed in pages hanging off of skb_shinfo(skb)->nr_frags. * In the case of a non-split, skb->data is linearly filled, @@ -3016,7 +2997,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) /* This is useful for sniffing bad packets. */ if (adapter->netdev->features & NETIF_F_RXALL) { /* UPE and MPE will be handled by normal PROMISC logic - * in e1000e_set_rx_mode */ + * in e1000e_set_rx_mode + */ rctl |= (E1000_RCTL_SBP | /* Receive bad packets */ E1000_RCTL_BAM | /* RX All Bcast Pkts */ E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */ @@ -3071,8 +3053,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) usleep_range(10000, 20000); if (adapter->flags2 & FLAG2_DMA_BURST) { - /* - * set the writeback threshold (only takes effect if the RDTR + /* set the writeback threshold (only takes effect if the RDTR * is set). set GRAN=1 and write back up to 0x4 worth, and * enable prefetching of 0x20 Rx descriptors * granularity = 01 @@ -3083,8 +3064,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) ew32(RXDCTL(0), E1000_RXDCTL_DMA_BURST_ENABLE); ew32(RXDCTL(1), E1000_RXDCTL_DMA_BURST_ENABLE); - /* - * override the delay timers for enabling bursting, only if + /* override the delay timers for enabling bursting, only if * the value was not set by the user via module options */ if (adapter->rx_int_delay == DEFAULT_RDTR) @@ -3108,8 +3088,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) ew32(CTRL_EXT, ctrl_ext); e1e_flush(); - /* - * Setup the HW Rx Head and Tail Descriptor Pointers and + /* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ rdba = rx_ring->dma; @@ -3130,8 +3109,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) ew32(RXCSUM, rxcsum); if (adapter->hw.mac.type == e1000_pch2lan) { - /* - * With jumbo frames, excessive C-state transition + /* With jumbo frames, excessive C-state transition * latencies result in dropped transactions. */ if (adapter->netdev->mtu > ETH_DATA_LEN) { @@ -3216,8 +3194,7 @@ static int e1000e_write_uc_addr_list(struct net_device *netdev) if (!netdev_uc_empty(netdev) && rar_entries) { struct netdev_hw_addr *ha; - /* - * write the addresses in reverse order to avoid write + /* write the addresses in reverse order to avoid write * combining */ netdev_for_each_uc_addr(ha, netdev) { @@ -3269,8 +3246,7 @@ static void e1000e_set_rx_mode(struct net_device *netdev) if (netdev->flags & IFF_ALLMULTI) { rctl |= E1000_RCTL_MPE; } else { - /* - * Write addresses to the MTA, if the attempt fails + /* Write addresses to the MTA, if the attempt fails * then we should just turn on promiscuous mode so * that we can at least receive multicast traffic */ @@ -3279,8 +3255,7 @@ static void e1000e_set_rx_mode(struct net_device *netdev) rctl |= E1000_RCTL_MPE; } e1000e_vlan_filter_enable(adapter); - /* - * Write addresses to available RAR registers, if there is not + /* Write addresses to available RAR registers, if there is not * sufficient space to store all the addresses then enable * unicast promiscuous mode */ @@ -3315,8 +3290,7 @@ static void e1000e_setup_rss_hash(struct e1000_adapter *adapter) for (i = 0; i < 32; i++) ew32(RETA(i), 0); - /* - * Disable raw packet checksumming so that RSS hash is placed in + /* Disable raw packet checksumming so that RSS hash is placed in * descriptor on writeback. */ rxcsum = er32(RXCSUM); @@ -3408,8 +3382,7 @@ void e1000e_reset(struct e1000_adapter *adapter) ew32(PBA, pba); if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) { - /* - * To maintain wire speed transmits, the Tx FIFO should be + /* To maintain wire speed transmits, the Tx FIFO should be * large enough to accommodate two full transmit packets, * rounded up to the next 1KB and expressed in KB. Likewise, * the Rx FIFO should be large enough to accommodate at least @@ -3421,8 +3394,7 @@ void e1000e_reset(struct e1000_adapter *adapter) tx_space = pba >> 16; /* lower 16 bits has Rx packet buffer allocation size in KB */ pba &= 0xffff; - /* - * the Tx fifo also stores 16 bytes of information about the Tx + /* the Tx fifo also stores 16 bytes of information about the Tx * but don't include ethernet FCS because hardware appends it */ min_tx_space = (adapter->max_frame_size + @@ -3435,8 +3407,7 @@ void e1000e_reset(struct e1000_adapter *adapter) min_rx_space = ALIGN(min_rx_space, 1024); min_rx_space >>= 10; - /* - * If current Tx allocation is less than the min Tx FIFO size, + /* If current Tx allocation is less than the min Tx FIFO size, * and the min Tx FIFO size is less than the current Rx FIFO * allocation, take space away from current Rx allocation */ @@ -3444,8 +3415,7 @@ void e1000e_reset(struct e1000_adapter *adapter) ((min_tx_space - tx_space) < pba)) { pba -= min_tx_space - tx_space; - /* - * if short on Rx space, Rx wins and must trump Tx + /* if short on Rx space, Rx wins and must trump Tx * adjustment */ if (pba < min_rx_space) @@ -3455,8 +3425,7 @@ void e1000e_reset(struct e1000_adapter *adapter) ew32(PBA, pba); } - /* - * flow control settings + /* flow control settings * * The high water mark must be low enough to fit one full frame * (or the size used for early receive) above it in the Rx FIFO. @@ -3490,8 +3459,7 @@ void e1000e_reset(struct e1000_adapter *adapter) fc->low_water = fc->high_water - 8; break; case e1000_pchlan: - /* - * Workaround PCH LOM adapter hangs with certain network + /* Workaround PCH LOM adapter hangs with certain network * loads. If hangs persist, try disabling Tx flow control. */ if (adapter->netdev->mtu > ETH_DATA_LEN) { @@ -3516,8 +3484,7 @@ void e1000e_reset(struct e1000_adapter *adapter) break; } - /* - * Alignment of Tx data is on an arbitrary byte boundary with the + /* Alignment of Tx data is on an arbitrary byte boundary with the * maximum size per Tx descriptor limited only to the transmit * allocation of the packet buffer minus 96 bytes with an upper * limit of 24KB due to receive synchronization limitations. @@ -3525,8 +3492,7 @@ void e1000e_reset(struct e1000_adapter *adapter) adapter->tx_fifo_limit = min_t(u32, ((er32(PBA) >> 16) << 10) - 96, 24 << 10); - /* - * Disable Adaptive Interrupt Moderation if 2 full packets cannot + /* Disable Adaptive Interrupt Moderation if 2 full packets cannot * fit in receive buffer. */ if (adapter->itr_setting & 0x3) { @@ -3549,8 +3515,7 @@ void e1000e_reset(struct e1000_adapter *adapter) /* Allow time for pending master requests to run */ mac->ops.reset_hw(hw); - /* - * For parts with AMT enabled, let the firmware know + /* For parts with AMT enabled, let the firmware know * that the network interface is in control */ if (adapter->flags & FLAG_HAS_AMT) @@ -3579,8 +3544,7 @@ void e1000e_reset(struct e1000_adapter *adapter) if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && !(adapter->flags & FLAG_SMART_POWER_DOWN)) { u16 phy_data = 0; - /* - * speed up time to link by disabling smart power down, ignore + /* speed up time to link by disabling smart power down, ignore * the return value of this function because there is nothing * different we would do if it failed */ @@ -3628,8 +3592,7 @@ static void e1000e_flush_descriptors(struct e1000_adapter *adapter) /* execute the writes immediately */ e1e_flush(); - /* - * due to rare timing issues, write to TIDV/RDTR again to ensure the + /* due to rare timing issues, write to TIDV/RDTR again to ensure the * write is successful */ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); @@ -3647,8 +3610,7 @@ void e1000e_down(struct e1000_adapter *adapter) struct e1000_hw *hw = &adapter->hw; u32 tctl, rctl; - /* - * signal that we're down so the interrupt handler does not + /* signal that we're down so the interrupt handler does not * reschedule our watchdog timer */ set_bit(__E1000_DOWN, &adapter->state); @@ -3691,8 +3653,7 @@ void e1000e_down(struct e1000_adapter *adapter) if (!pci_channel_offline(adapter->pdev)) e1000e_reset(adapter); - /* - * TODO: for power management, we could drop the link and + /* TODO: for power management, we could drop the link and * pci_disable_device here. */ } @@ -3715,7 +3676,7 @@ void e1000e_reinit_locked(struct e1000_adapter *adapter) * Fields are initialized based on PCI device information and * OS network device settings (MTU size). **/ -static int __devinit e1000_sw_init(struct e1000_adapter *adapter) +static int e1000_sw_init(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -3755,8 +3716,7 @@ static irqreturn_t e1000_intr_msi_test(int irq, void *data) e_dbg("icr is %08X\n", icr); if (icr & E1000_ICR_RXSEQ) { adapter->flags &= ~FLAG_MSI_TEST_FAILED; - /* - * Force memory writes to complete before acknowledging the + /* Force memory writes to complete before acknowledging the * interrupt is handled. */ wmb(); @@ -3786,7 +3746,8 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) e1000e_reset_interrupt_capability(adapter); /* Assume that the test fails, if it succeeds then the test - * MSI irq handler will unset this flag */ + * MSI irq handler will unset this flag + */ adapter->flags |= FLAG_MSI_TEST_FAILED; err = pci_enable_msi(adapter->pdev); @@ -3800,8 +3761,7 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) goto msi_test_failed; } - /* - * Force memory writes to complete before enabling and firing an + /* Force memory writes to complete before enabling and firing an * interrupt. */ wmb(); @@ -3901,8 +3861,7 @@ static int e1000_open(struct net_device *netdev) if (err) goto err_setup_rx; - /* - * If AMT is enabled, let the firmware know that the network + /* If AMT is enabled, let the firmware know that the network * interface is now open and reset the part to a known state. */ if (adapter->flags & FLAG_HAS_AMT) { @@ -3923,8 +3882,7 @@ static int e1000_open(struct net_device *netdev) PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); - /* - * before we allocate an interrupt, we must be ready to handle it. + /* before we allocate an interrupt, we must be ready to handle it. * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt * as soon as we call pci_request_irq, so we have to setup our * clean_rx handler before we do so. @@ -3935,8 +3893,7 @@ static int e1000_open(struct net_device *netdev) if (err) goto err_req_irq; - /* - * Work around PCIe errata with MSI interrupts causing some chipsets to + /* Work around PCIe errata with MSI interrupts causing some chipsets to * ignore e1000e MSI messages, which means we need to test our MSI * interrupt now */ @@ -4017,16 +3974,14 @@ static int e1000_close(struct net_device *netdev) 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 + /* kill manageability vlan ID if supported, but not if a vlan with * the same ID is registered on the host OS (let 8021q kill it) */ if (adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); - /* - * If AMT is enabled, let the firmware know that the network + /* If AMT is enabled, let the firmware know that the network * interface is now closed */ if ((adapter->flags & FLAG_HAS_AMT) && @@ -4065,8 +4020,7 @@ static int e1000_set_mac(struct net_device *netdev, void *p) /* activate the work around */ e1000e_set_laa_state_82571(&adapter->hw, 1); - /* - * Hold a copy of the LAA in RAR[14] This is done so that + /* Hold a copy of the LAA in RAR[14] This is done so that * between the time RAR[0] gets clobbered and the time it * gets fixed (in e1000_watchdog), the actual LAA is in one * of the RARs and no incoming packets directed to this port @@ -4099,10 +4053,13 @@ static void e1000e_update_phy_task(struct work_struct *work) e1000_get_phy_info(&adapter->hw); } -/* +/** + * e1000_update_phy_info - timre call-back to update PHY info + * @data: pointer to adapter cast into an unsigned long + * * Need to wait a few seconds after link up to get diagnostic information from * the phy - */ + **/ static void e1000_update_phy_info(unsigned long data) { struct e1000_adapter *adapter = (struct e1000_adapter *) data; @@ -4129,8 +4086,7 @@ static void e1000e_update_phy_stats(struct e1000_adapter *adapter) if (ret_val) return; - /* - * A page set is expensive so check if already on desired page. + /* A page set is expensive so check if already on desired page. * If not, set to the page with the PHY status registers. */ hw->phy.addr = 1; @@ -4201,8 +4157,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter) struct e1000_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; - /* - * Prevent stats update while adapter is being reset, or if the pci + /* Prevent stats update while adapter is being reset, or if the pci * connection is down. */ if (adapter->link_speed == 0) @@ -4270,8 +4225,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter) /* Rx Errors */ - /* - * RLEC on some newer hardware can be incorrect so build + /* RLEC on some newer hardware can be incorrect so build * our own version based on RUC and ROC */ netdev->stats.rx_errors = adapter->stats.rxerrc + @@ -4323,8 +4277,7 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter) if (ret_val) e_warn("Error reading PHY register\n"); } else { - /* - * Do not read PHY registers if link is not up + /* Do not read PHY registers if link is not up * Set values to typical power-on defaults */ phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX); @@ -4362,8 +4315,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter) bool link_active = false; s32 ret_val = 0; - /* - * get_link_status is set on LSC (link status) interrupt or + /* get_link_status is set on LSC (link status) interrupt or * Rx sequence error interrupt. get_link_status will stay * false until the check_for_link establishes link * for copper adapters ONLY @@ -4415,8 +4367,7 @@ static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; - /* - * With 82574 controllers, PHY needs to be checked periodically + /* With 82574 controllers, PHY needs to be checked periodically * for hung state and reset, if two calls return true */ if (e1000_check_phy_82574(hw)) @@ -4484,8 +4435,7 @@ static void e1000_watchdog_task(struct work_struct *work) &adapter->link_speed, &adapter->link_duplex); e1000_print_link_info(adapter); - /* - * On supported PHYs, check for duplex mismatch only + /* On supported PHYs, check for duplex mismatch only * if link has autonegotiated at 10/100 half */ if ((hw->phy.type == e1000_phy_igp_3 || @@ -4515,8 +4465,7 @@ static void e1000_watchdog_task(struct work_struct *work) break; } - /* - * workaround: re-program speed mode bit after + /* workaround: re-program speed mode bit after * link-up event */ if ((adapter->flags & FLAG_TARC_SPEED_MODE_BIT) && @@ -4527,8 +4476,7 @@ static void e1000_watchdog_task(struct work_struct *work) ew32(TARC(0), tarc0); } - /* - * disable TSO for pcie and 10/100 speeds, to avoid + /* disable TSO for pcie and 10/100 speeds, to avoid * some hardware issues */ if (!(adapter->flags & FLAG_TSO_FORCE)) { @@ -4549,16 +4497,14 @@ static void e1000_watchdog_task(struct work_struct *work) } } - /* - * enable transmits in the hardware, need to do this + /* enable transmits in the hardware, need to do this * after setting TARC(0) */ tctl = er32(TCTL); tctl |= E1000_TCTL_EN; ew32(TCTL, tctl); - /* - * Perform any post-link-up configuration before + /* Perform any post-link-up configuration before * reporting link up. */ if (phy->ops.cfg_on_link_up) @@ -4609,8 +4555,7 @@ link_up: if (!netif_carrier_ok(netdev) && (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) { - /* - * We've lost link, so the controller stops DMA, + /* We've lost link, so the controller stops DMA, * but we've got queued Tx work that's never going * to get done, so reset controller to flush Tx. * (Do the reset outside of interrupt context). @@ -4622,8 +4567,7 @@ link_up: /* Simple mode for Interrupt Throttle Rate (ITR) */ if (adapter->itr_setting == 4) { - /* - * Symmetric Tx/Rx gets a reduced ITR=2000; + /* Symmetric Tx/Rx gets a reduced ITR=2000; * Total asymmetrical Tx or Rx gets ITR=8000; * everyone else is between 2000-8000. */ @@ -4648,8 +4592,7 @@ link_up: /* Force detection of hung controller every watchdog period */ adapter->detect_tx_hung = true; - /* - * With 82571 controllers, LAA may be overwritten due to controller + /* With 82571 controllers, LAA may be overwritten due to controller * reset from the other port. Set the appropriate LAA in RAR[0] */ if (e1000e_get_laa_state_82571(hw)) @@ -4948,8 +4891,7 @@ static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count) if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS)) tx_desc->lower.data &= ~(cpu_to_le32(E1000_TXD_CMD_IFCS)); - /* - * Force memory writes to complete before letting h/w + /* Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only * applicable for weak-ordered memory model archs, * such as IA-64). @@ -4963,8 +4905,7 @@ static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count) else writel(i, tx_ring->tail); - /* - * we need this if more than one processor can write to our tail + /* we need this if more than one processor can write to our tail * at a time, it synchronizes IO on IA64/Altix systems */ mmiowb(); @@ -5014,15 +4955,13 @@ static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) struct e1000_adapter *adapter = tx_ring->adapter; netif_stop_queue(adapter->netdev); - /* - * Herbert's original patch had: + /* Herbert's original patch had: * smp_mb__after_netif_stop_queue(); * but since that doesn't exist yet, just open code it. */ smp_mb(); - /* - * We need to check again in a case another CPU has just + /* We need to check again in a case another CPU has just * made room available. */ if (e1000_desc_unused(tx_ring) < size) @@ -5067,18 +5006,26 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, return NETDEV_TX_OK; } + /* The minimum packet size with TCTL.PSP set is 17 bytes so + * pad skb in order to meet this minimum size requirement + */ + if (unlikely(skb->len < 17)) { + if (skb_pad(skb, 17 - skb->len)) + return NETDEV_TX_OK; + skb->len = 17; + skb_set_tail_pointer(skb, 17); + } + mss = skb_shinfo(skb)->gso_size; if (mss) { u8 hdr_len; - /* - * TSO Workaround for 82571/2/3 Controllers -- if skb->data + /* TSO Workaround for 82571/2/3 Controllers -- if skb->data * points to just header, pull a few bytes of payload from * frags into skb->data */ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - /* - * we do this workaround for ES2LAN, but it is un-necessary, + /* we do this workaround for ES2LAN, but it is un-necessary, * avoiding it could save a lot of cycles */ if (skb->data_len && (hdr_len == len)) { @@ -5109,8 +5056,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, if (adapter->hw.mac.tx_pkt_filtering) e1000_transfer_dhcp_info(adapter, skb); - /* - * need: count + 2 desc gap to keep tail from touching + /* need: count + 2 desc gap to keep tail from touching * head, otherwise try next time */ if (e1000_maybe_stop_tx(tx_ring, count + 2)) @@ -5134,8 +5080,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, else if (e1000_tx_csum(tx_ring, skb)) tx_flags |= E1000_TX_FLAGS_CSUM; - /* - * Old method was to assume IPv4 packet by default if TSO was enabled. + /* Old method was to assume IPv4 packet by default if TSO was enabled. * 82571 hardware supports TSO capabilities for IPv6 as well... * no longer assume, we must. */ @@ -5222,8 +5167,7 @@ struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, /* Rx Errors */ - /* - * RLEC on some newer hardware can be incorrect so build + /* RLEC on some newer hardware can be incorrect so build * our own version based on RUC and ROC */ stats->rx_errors = adapter->stats.rxerrc + @@ -5292,8 +5236,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) if (netif_running(netdev)) e1000e_down(adapter); - /* - * NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN + /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN * means we reserve 2 more, this pushes us to allocate from the next * larger slab size. * i.e. RXBUFFER_2048 --> size-4096 slab @@ -5555,8 +5498,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, if (adapter->hw.phy.type == e1000_phy_igp_3) e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); - /* - * Release control of h/w to f/w. If f/w is AMT enabled, this + /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ e1000e_release_hw_control(adapter); @@ -5583,8 +5525,7 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep, struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev_priv(netdev); - /* - * The pci-e switch on some quad port adapters will report a + /* The pci-e switch on some quad port adapters will report a * correctable error when the MAC transitions from D0 to D3. To * prevent this we need to mask off the correctable errors on the * downstream port of the pci-e switch. @@ -5613,8 +5554,7 @@ static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) #else static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) { - /* - * Both device and parent should have the same ASPM setting. + /* Both device and parent should have the same ASPM setting. * Disable ASPM in downstream component first and then upstream. */ pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, state); @@ -5708,8 +5648,7 @@ static int __e1000_resume(struct pci_dev *pdev) netif_device_attach(netdev); - /* - * If the controller has AMT, do not set DRV_LOAD until the interface + /* If the controller has AMT, do not set DRV_LOAD until the interface * is up. For all other cases, let the f/w know that the h/w is now * under the control of the driver. */ @@ -5837,7 +5776,10 @@ static irqreturn_t e1000_intr_msix(int irq, void *data) return IRQ_HANDLED; } -/* +/** + * e1000_netpoll + * @netdev: network interface device structure + * * 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. @@ -5962,8 +5904,7 @@ static void e1000_io_resume(struct pci_dev *pdev) netif_device_attach(netdev); - /* - * If the controller has AMT, do not set DRV_LOAD until the interface + /* If the controller has AMT, do not set DRV_LOAD until the interface * is up. For all other cases, let the f/w know that the h/w is now * under the control of the driver. */ @@ -6083,8 +6024,7 @@ static const struct net_device_ops e1000e_netdev_ops = { * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. **/ -static int __devinit e1000_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct e1000_adapter *adapter; @@ -6262,14 +6202,12 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (e1000e_enable_mng_pass_thru(&adapter->hw)) adapter->flags |= FLAG_MNG_PT_ENABLED; - /* - * before reading the NVM, reset the controller to + /* before reading the NVM, reset the controller to * put the device in a known good starting state */ adapter->hw.mac.ops.reset_hw(&adapter->hw); - /* - * systems with ASPM and others may see the checksum fail on the first + /* systems with ASPM and others may see the checksum fail on the first * attempt. Let's give it a few tries */ for (i = 0;; i++) { @@ -6324,8 +6262,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, adapter->rx_ring->count = E1000_DEFAULT_RXD; adapter->tx_ring->count = E1000_DEFAULT_TXD; - /* - * Initial Wake on LAN setting - If APM wake is enabled in + /* Initial Wake on LAN setting - If APM wake is enabled in * the EEPROM, enable the ACPI Magic Packet filter */ if (adapter->flags & FLAG_APME_IN_WUC) { @@ -6349,8 +6286,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (eeprom_data & eeprom_apme_mask) adapter->eeprom_wol |= E1000_WUFC_MAG; - /* - * now that we have the eeprom settings, apply the special cases + /* now that we have the eeprom settings, apply the special cases * where the eeprom may be wrong or the board simply won't support * wake on lan on a particular port */ @@ -6367,8 +6303,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, /* reset the hardware with the new settings */ e1000e_reset(adapter); - /* - * If the controller has AMT, do not set DRV_LOAD until the interface + /* If the controller has AMT, do not set DRV_LOAD until the interface * is up. For all other cases, let the f/w know that the h/w is now * under the control of the driver. */ @@ -6425,14 +6360,13 @@ err_dma: * Hot-Plug event, or because the driver is going to be removed from * memory. **/ -static void __devexit e1000_remove(struct pci_dev *pdev) +static void e1000_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev_priv(netdev); bool down = test_bit(__E1000_DOWN, &adapter->state); - /* - * The timers may be rescheduled, so explicitly disable them + /* The timers may be rescheduled, so explicitly disable them * from being rescheduled. */ if (!down) @@ -6457,8 +6391,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev) if (pci_dev_run_wake(pdev)) pm_runtime_get_noresume(&pdev->dev); - /* - * Release control of h/w to f/w. If f/w is AMT enabled, this + /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ e1000e_release_hw_control(adapter); @@ -6578,7 +6511,7 @@ static struct pci_driver e1000_driver = { .name = e1000e_driver_name, .id_table = e1000_pci_tbl, .probe = e1000_probe, - .remove = __devexit_p(e1000_remove), + .remove = e1000_remove, #ifdef CONFIG_PM .driver = { .pm = &e1000_pm_ops, diff --git a/drivers/net/ethernet/intel/e1000e/nvm.c b/drivers/net/ethernet/intel/e1000e/nvm.c index a969f1af1b4e..b6468804cb2e 100644 --- a/drivers/net/ethernet/intel/e1000e/nvm.c +++ b/drivers/net/ethernet/intel/e1000e/nvm.c @@ -279,8 +279,7 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) e1e_flush(); udelay(1); - /* - * Read "Status Register" repeatedly until the LSB is cleared. + /* 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. @@ -321,8 +320,7 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) u32 i, eerd = 0; s32 ret_val = 0; - /* - * A check for invalid values: offset too large, too many words, + /* 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)) || @@ -364,8 +362,7 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) s32 ret_val; u16 widx = 0; - /* - * A check for invalid values: offset too large, too many words, + /* 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)) || @@ -393,8 +390,7 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) e1000_standby_nvm(hw); - /* - * Some SPI eeproms use the 8th address bit embedded in the + /* Some SPI eeproms use the 8th address bit embedded in the * opcode */ if ((nvm->address_bits == 8) && (offset >= 128)) @@ -461,8 +457,7 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, return ret_val; } - /* - * if nvm_data is not ptr guard the PBA must be in legacy format which + /* 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 */ diff --git a/drivers/net/ethernet/intel/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c index dfbfa7fd98c3..89d536dd7ff5 100644 --- a/drivers/net/ethernet/intel/e1000e/param.c +++ b/drivers/net/ethernet/intel/e1000e/param.c @@ -32,11 +32,9 @@ #include "e1000.h" -/* - * This is the only thing that needs to be changed to adjust the +/* This is the only thing that needs to be changed to adjust the * maximum number of ports that the driver can manage. */ - #define E1000_MAX_NIC 32 #define OPTION_UNSET -1 @@ -49,22 +47,19 @@ module_param(copybreak, uint, 0644); MODULE_PARM_DESC(copybreak, "Maximum size of packet that is copied to a new buffer on receive"); -/* - * All parameters are treated the same, as an integer array of values. +/* All parameters are treated the same, as an integer array of values. * This macro just reduces the need to repeat the same declaration code * over and over (plus this helps to avoid typo bugs). */ - #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } #define E1000_PARAM(X, desc) \ - static int __devinitdata X[E1000_MAX_NIC+1] \ + static int X[E1000_MAX_NIC+1] \ = E1000_PARAM_INIT; \ static unsigned int num_##X; \ module_param_array_named(X, X, int, &num_##X, 0); \ MODULE_PARM_DESC(X, desc); -/* - * Transmit Interrupt Delay in units of 1.024 microseconds +/* Transmit Interrupt Delay in units of 1.024 microseconds * Tx interrupt delay needs to typically be set to something non-zero * * Valid Range: 0-65535 @@ -74,8 +69,7 @@ E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); #define MAX_TXDELAY 0xFFFF #define MIN_TXDELAY 0 -/* - * Transmit Absolute Interrupt Delay in units of 1.024 microseconds +/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds * * Valid Range: 0-65535 */ @@ -84,8 +78,7 @@ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); #define MAX_TXABSDELAY 0xFFFF #define MIN_TXABSDELAY 0 -/* - * Receive Interrupt Delay in units of 1.024 microseconds +/* Receive Interrupt Delay in units of 1.024 microseconds * hardware will likely hang if you set this to anything but zero. * * Valid Range: 0-65535 @@ -94,8 +87,7 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); #define MAX_RXDELAY 0xFFFF #define MIN_RXDELAY 0 -/* - * Receive Absolute Interrupt Delay in units of 1.024 microseconds +/* Receive Absolute Interrupt Delay in units of 1.024 microseconds * * Valid Range: 0-65535 */ @@ -103,8 +95,7 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); #define MAX_RXABSDELAY 0xFFFF #define MIN_RXABSDELAY 0 -/* - * Interrupt Throttle Rate (interrupts/sec) +/* Interrupt Throttle Rate (interrupts/sec) * * Valid Range: 100-100000 or one of: 0=off, 1=dynamic, 3=dynamic conservative */ @@ -113,8 +104,7 @@ 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 * @@ -132,8 +122,7 @@ E1000_PARAM(IntMode, "Interrupt Mode"); #define MAX_INTMODE 2 #define MIN_INTMODE 0 -/* - * Enable Smart Power Down of the PHY +/* Enable Smart Power Down of the PHY * * Valid Range: 0, 1 * @@ -141,8 +130,7 @@ E1000_PARAM(IntMode, "Interrupt Mode"); */ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); -/* - * Enable Kumeran Lock Loss workaround +/* Enable Kumeran Lock Loss workaround * * Valid Range: 0, 1 * @@ -150,8 +138,7 @@ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); */ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); -/* - * Write Protect NVM +/* Write Protect NVM * * Valid Range: 0, 1 * @@ -159,8 +146,7 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); */ E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); -/* - * Enable CRC Stripping +/* Enable CRC Stripping * * Valid Range: 0, 1 * @@ -186,9 +172,9 @@ struct e1000_option { } arg; }; -static int __devinit e1000_validate_option(unsigned int *value, - const struct e1000_option *opt, - struct e1000_adapter *adapter) +static int e1000_validate_option(unsigned int *value, + const struct e1000_option *opt, + struct e1000_adapter *adapter) { if (*value == OPTION_UNSET) { *value = opt->def; @@ -249,7 +235,7 @@ static int __devinit e1000_validate_option(unsigned int *value, * value exists, a default value is used. The final value is stored * in a variable in the adapter structure. **/ -void __devinit e1000e_check_options(struct e1000_adapter *adapter) +void e1000e_check_options(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; int bd = adapter->bd_number; @@ -351,8 +337,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) if (num_InterruptThrottleRate > bd) { adapter->itr = InterruptThrottleRate[bd]; - /* - * Make sure a message is printed for non-special + /* Make sure a message is printed for non-special * values. And in case of an invalid option, display * warning, use default and go through itr/itr_setting * adjustment logic below @@ -361,14 +346,12 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) e1000_validate_option(&adapter->itr, &opt, adapter)) adapter->itr = opt.def; } else { - /* - * If no option specified, use default value and go + /* If no option specified, use default value and go * through the logic below to adjust itr/itr_setting */ adapter->itr = opt.def; - /* - * Make sure a message is printed for non-special + /* Make sure a message is printed for non-special * default values */ if (adapter->itr > 4) @@ -400,8 +383,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) opt.name); break; default: - /* - * Save the setting, because the dynamic bits + /* Save the setting, because the dynamic bits * change itr. * * Clear the lower two bits because diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c index fc62a3f3a5be..28b38ff37e84 100644 --- a/drivers/net/ethernet/intel/e1000e/phy.c +++ b/drivers/net/ethernet/intel/e1000e/phy.c @@ -193,8 +193,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) return -E1000_ERR_PARAM; } - /* - * Set up Op-code, Phy Address, and register offset in the MDI + /* Set up Op-code, Phy Address, and register offset in the MDI * Control register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ @@ -204,8 +203,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) ew32(MDIC, mdic); - /* - * Poll the ready bit to see if the MDI read completed + /* Poll the ready bit to see if the MDI read completed * Increasing the time out as testing showed failures with * the lower time out */ @@ -225,8 +223,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) } *data = (u16) mdic; - /* - * Allow some time after each MDIC transaction to avoid + /* Allow some time after each MDIC transaction to avoid * reading duplicate data in the next MDIC transaction. */ if (hw->mac.type == e1000_pch2lan) @@ -253,8 +250,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) return -E1000_ERR_PARAM; } - /* - * Set up Op-code, Phy Address, and register offset in the MDI + /* Set up Op-code, Phy Address, and register offset in the MDI * Control register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ @@ -265,8 +261,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) ew32(MDIC, mdic); - /* - * Poll the ready bit to see if the MDI read completed + /* Poll the ready bit to see if the MDI read completed * Increasing the time out as testing showed failures with * the lower time out */ @@ -285,8 +280,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) return -E1000_ERR_PHY; } - /* - * Allow some time after each MDIC transaction to avoid + /* Allow some time after each MDIC transaction to avoid * reading duplicate data in the next MDIC transaction. */ if (hw->mac.type == e1000_pch2lan) @@ -708,8 +702,7 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) if (ret_val) return ret_val; phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK; - /* - * Options: + /* Options: * 0 - Auto (default) * 1 - MDI mode * 2 - MDI-X mode @@ -754,8 +747,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) if (phy->type != e1000_phy_bm) phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - /* - * Options: + /* Options: * MDI/MDI-X = 0 (default) * 0 - Auto for all speeds * 1 - MDI mode @@ -780,8 +772,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) break; } - /* - * Options: + /* Options: * disable_polarity_correction = 0 (default) * Automatic Correction for Reversed Cable Polarity * 0 - Disabled @@ -818,8 +809,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) if ((phy->type == e1000_phy_m88) && (phy->revision < E1000_REVISION_4) && (phy->id != BME1000_E_PHY_ID_R2)) { - /* - * Force TX_CLK in the Extended PHY Specific Control Register + /* Force TX_CLK in the Extended PHY Specific Control Register * to 25MHz clock. */ ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); @@ -899,8 +889,7 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw) return ret_val; } - /* - * Wait 100ms for MAC to configure PHY from NVM settings, to avoid + /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid * timeout issues when LFS is enabled. */ msleep(100); @@ -936,8 +925,7 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw) /* set auto-master slave resolution settings */ if (hw->mac.autoneg) { - /* - * when autonegotiation advertisement is only 1000Mbps then we + /* when autonegotiation advertisement is only 1000Mbps then we * should disable SmartSpeed and enable Auto MasterSlave * resolution as hardware default. */ @@ -1001,16 +989,14 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) return ret_val; } - /* - * Need to parse both autoneg_advertised and fc and set up + /* Need to parse both autoneg_advertised and fc and set up * the appropriate PHY registers. First we will parse for * autoneg_advertised software override. Since we can advertise * a plethora of combinations, we need to check each bit * individually. */ - /* - * First we clear all the 10/100 mb speed bits in the Auto-Neg + /* First we clear all the 10/100 mb speed bits in the Auto-Neg * Advertisement Register (Address 4) and the 1000 mb speed bits in * the 1000Base-T Control Register (Address 9). */ @@ -1056,8 +1042,7 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; } - /* - * Check for a software override of the flow control settings, and + /* Check for a software override of the flow control settings, and * setup the PHY advertisement registers accordingly. If * auto-negotiation is enabled, then software will have to set the * "PAUSE" bits to the correct value in the Auto-Negotiation @@ -1076,15 +1061,13 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) */ switch (hw->fc.current_mode) { case e1000_fc_none: - /* - * Flow control (Rx & Tx) is completely disabled by a + /* Flow control (Rx & Tx) is completely disabled by a * software over-ride. */ mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; case e1000_fc_rx_pause: - /* - * Rx Flow control is enabled, and Tx Flow control is + /* Rx Flow control is enabled, and Tx Flow control is * disabled, by a software over-ride. * * Since there really isn't a way to advertise that we are @@ -1096,16 +1079,14 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; case e1000_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is + /* Tx Flow control is enabled, and Rx Flow control is * disabled, by a software over-ride. */ mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; break; case e1000_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software + /* Flow control (both Rx and Tx) is enabled by a software * over-ride. */ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); @@ -1142,14 +1123,12 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) s32 ret_val; u16 phy_ctrl; - /* - * Perform some bounds checking on the autoneg advertisement + /* Perform some bounds checking on the autoneg advertisement * parameter. */ phy->autoneg_advertised &= phy->autoneg_mask; - /* - * If autoneg_advertised is zero, we assume it was not defaulted + /* If autoneg_advertised is zero, we assume it was not defaulted * by the calling code so we set to advertise full capability. */ if (!phy->autoneg_advertised) @@ -1163,8 +1142,7 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) } e_dbg("Restarting Auto-Neg\n"); - /* - * Restart auto-negotiation by setting the Auto Neg Enable bit and + /* Restart auto-negotiation by setting the Auto Neg Enable bit and * the Auto Neg Restart bit in the PHY control register. */ ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl); @@ -1176,8 +1154,7 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Does the user want to wait for Auto-Neg to complete here, or + /* Does the user want to wait for Auto-Neg to complete here, or * check at a later time (for example, callback routine). */ if (phy->autoneg_wait_to_complete) { @@ -1208,16 +1185,14 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw) bool link; if (hw->mac.autoneg) { - /* - * Setup autoneg and flow control advertisement and perform + /* Setup autoneg and flow control advertisement and perform * autonegotiation. */ ret_val = e1000_copper_link_autoneg(hw); if (ret_val) return ret_val; } else { - /* - * PHY will be set to 10H, 10F, 100H or 100F + /* PHY will be set to 10H, 10F, 100H or 100F * depending on user settings. */ e_dbg("Forcing Speed and Duplex\n"); @@ -1228,8 +1203,7 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw) } } - /* - * Check link status. Wait up to 100 microseconds for link to become + /* Check link status. Wait up to 100 microseconds for link to become * valid. */ ret_val = e1000e_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10, @@ -1273,8 +1247,7 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Clear Auto-Crossover to force MDI manually. IGP requires MDI + /* Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed and duplex are forced. */ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); @@ -1328,8 +1301,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) u16 phy_data; bool link; - /* - * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI + /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI * forced whenever speed and duplex are forced. */ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); @@ -1370,8 +1342,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) if (hw->phy.type != e1000_phy_m88) { e_dbg("Link taking longer than expected.\n"); } else { - /* - * We didn't get link. + /* We didn't get link. * Reset the DSP and cross our fingers. */ ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT, @@ -1398,8 +1369,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Resetting the phy means we need to re-force TX_CLK in the + /* Resetting the phy means we need to re-force TX_CLK in the * Extended PHY Specific Control Register to 25MHz clock from * the reset value of 2.5MHz. */ @@ -1408,8 +1378,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * In addition, we must re-enable CRS on Tx for both half and full + /* In addition, we must re-enable CRS on Tx for both half and full * duplex. */ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); @@ -1573,8 +1542,7 @@ s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active) ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) return ret_val; - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. @@ -1702,8 +1670,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw) s32 ret_val; u16 data, offset, mask; - /* - * Polarity is determined based on the speed of + /* Polarity is determined based on the speed of * our connection. */ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data); @@ -1715,8 +1682,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw) offset = IGP01E1000_PHY_PCS_INIT_REG; mask = IGP01E1000_PHY_POLARITY_MASK; } else { - /* - * This really only applies to 10Mbps since + /* This really only applies to 10Mbps since * there is no polarity for 100Mbps (always 0). */ offset = IGP01E1000_PHY_PORT_STATUS; @@ -1745,8 +1711,7 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw) s32 ret_val; u16 phy_data, offset, mask; - /* - * Polarity is determined based on the reversal feature being enabled. + /* Polarity is determined based on the reversal feature being enabled. */ if (phy->polarity_correction) { offset = IFE_PHY_EXTENDED_STATUS_CONTROL; @@ -1791,8 +1756,7 @@ static s32 e1000_wait_autoneg(struct e1000_hw *hw) msleep(100); } - /* - * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation + /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation * has completed. */ return ret_val; @@ -1814,15 +1778,13 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, u16 i, phy_status; for (i = 0; i < iterations; i++) { - /* - * Some PHYs require the PHY_STATUS register to be read + /* Some PHYs require the PHY_STATUS register to be read * twice due to the link bit being sticky. No harm doing * it across the board. */ ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); if (ret_val) - /* - * If the first read fails, another entity may have + /* If the first read fails, another entity may have * ownership of the resources, wait and try again to * see if they have relinquished the resources yet. */ @@ -1913,8 +1875,7 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Getting bits 15:9, which represent the combination of + /* Getting bits 15:9, which represent the combination of * coarse and fine gain values. The result is a number * that can be put into the lookup table to obtain the * approximate cable length. @@ -2285,15 +2246,13 @@ s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw) e1e_wphy(hw, 0x1796, 0x0008); /* Change cg_icount + enable integbp for channels BCD */ e1e_wphy(hw, 0x1798, 0xD008); - /* - * Change cg_icount + enable integbp + change prop_factor_master + /* Change cg_icount + enable integbp + change prop_factor_master * to 8 for channel A */ e1e_wphy(hw, 0x1898, 0xD918); /* Disable AHT in Slave mode on channel A */ e1e_wphy(hw, 0x187A, 0x0800); - /* - * Enable LPLU and disable AN to 1000 in non-D0a states, + /* Enable LPLU and disable AN to 1000 in non-D0a states, * Enable SPD+B2B */ e1e_wphy(hw, 0x0019, 0x008D); @@ -2417,8 +2376,7 @@ s32 e1000e_determine_phy_address(struct e1000_hw *hw) e1000e_get_phy_id(hw); phy_type = e1000e_get_phy_type_from_id(hw->phy.id); - /* - * If phy_type is valid, break - we found our + /* If phy_type is valid, break - we found our * PHY address */ if (phy_type != e1000_phy_unknown) @@ -2478,8 +2436,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) if (offset > MAX_PHY_MULTI_PAGE_REG) { u32 page_shift, page_select; - /* - * Page select is register 31 for phy address 1 and 22 for + /* Page select is register 31 for phy address 1 and 22 for * phy address 2 and 3. Page select is shifted only for * phy address 1. */ @@ -2537,8 +2494,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) if (offset > MAX_PHY_MULTI_PAGE_REG) { u32 page_shift, page_select; - /* - * Page select is register 31 for phy address 1 and 22 for + /* Page select is register 31 for phy address 1 and 22 for * phy address 2 and 3. Page select is shifted only for * phy address 1. */ @@ -2683,8 +2639,7 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) return ret_val; } - /* - * Enable both PHY wakeup mode and Wakeup register page writes. + /* Enable both PHY wakeup mode and Wakeup register page writes. * Prevent a power state change by disabling ME and Host PHY wakeup. */ temp = *phy_reg; @@ -2698,8 +2653,7 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) return ret_val; } - /* - * Select Host Wakeup Registers page - caller now able to write + /* Select Host Wakeup Registers page - caller now able to write * registers on the Wakeup registers page */ return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT)); @@ -3038,8 +2992,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, if (page == HV_INTC_FC_PAGE_START) page = 0; - /* - * Workaround MDIO accesses being disabled after entering IEEE + /* Workaround MDIO accesses being disabled after entering IEEE * Power Down (when bit 11 of the PHY Control register is set) */ if ((hw->phy.type == e1000_phy_82578) && diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile index 97c197fd4a8e..624476cfa727 100644 --- a/drivers/net/ethernet/intel/igb/Makefile +++ b/drivers/net/ethernet/intel/igb/Makefile @@ -34,6 +34,4 @@ obj-$(CONFIG_IGB) += igb.o igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \ e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \ - e1000_i210.o - -igb-$(CONFIG_IGB_PTP) += igb_ptp.o + e1000_i210.o igb_ptp.o diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index ca4641e2f748..fdaaf2709d0a 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -319,6 +319,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) nvm->ops.acquire = igb_acquire_nvm_i210; nvm->ops.release = igb_release_nvm_i210; nvm->ops.read = igb_read_nvm_srrd_i210; + nvm->ops.write = igb_write_nvm_srwr_i210; nvm->ops.valid_led_default = igb_valid_led_default_i210; break; case e1000_i211: @@ -1027,6 +1028,15 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw) * continue to check for link. */ hw->mac.get_link_status = !hw->mac.serdes_has_link; + + /* Configure Flow Control now that Auto-Neg has completed. + * First, we need to restore the desired flow control + * settings because we may have had to re-autoneg with a + * different link partner. + */ + ret_val = igb_config_fc_after_link_up(hw); + if (ret_val) + hw_dbg("Error configuring flow control\n"); } else { ret_val = igb_check_for_copper_link(hw); } @@ -1277,12 +1287,20 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; + u32 phpm_reg; ctrl = rd32(E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); wr32(E1000_CTRL, ctrl); + /* Clear Go Link Disconnect bit */ + if (hw->mac.type >= e1000_82580) { + phpm_reg = rd32(E1000_82580_PHY_POWER_MGMT); + phpm_reg &= ~E1000_82580_PM_GO_LINKD; + wr32(E1000_82580_PHY_POWER_MGMT, phpm_reg); + } + ret_val = igb_setup_serdes_link_82575(hw); if (ret_val) goto out; @@ -1336,7 +1354,7 @@ out: **/ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) { - u32 ctrl_ext, ctrl_reg, reg; + u32 ctrl_ext, ctrl_reg, reg, anadv_reg; bool pcs_autoneg; s32 ret_val = E1000_SUCCESS; u16 data; @@ -1424,27 +1442,45 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); - /* - * We force flow control to prevent the CTRL register values from being - * overwritten by the autonegotiated flow control values - */ - reg |= E1000_PCS_LCTL_FORCE_FCTRL; - if (pcs_autoneg) { /* Set PCS register for autoneg */ reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ + + /* Disable force flow control for autoneg */ + reg &= ~E1000_PCS_LCTL_FORCE_FCTRL; + + /* Configure flow control advertisement for autoneg */ + anadv_reg = rd32(E1000_PCS_ANADV); + anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE); + switch (hw->fc.requested_mode) { + case e1000_fc_full: + case e1000_fc_rx_pause: + anadv_reg |= E1000_TXCW_ASM_DIR; + anadv_reg |= E1000_TXCW_PAUSE; + break; + case e1000_fc_tx_pause: + anadv_reg |= E1000_TXCW_ASM_DIR; + break; + default: + break; + } + wr32(E1000_PCS_ANADV, anadv_reg); + hw_dbg("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); } else { /* Set PCS register for forced link */ reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ + /* Force flow control for forced link */ + reg |= E1000_PCS_LCTL_FORCE_FCTRL; + hw_dbg("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); } wr32(E1000_PCS_LCTL, reg); - if (!igb_sgmii_active_82575(hw)) + if (!pcs_autoneg && !igb_sgmii_active_82575(hw)) igb_force_mac_fc(hw); return ret_val; @@ -1918,6 +1954,12 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw) hw->dev_spec._82575.global_device_reset = false; + /* due to hw errata, global device reset doesn't always + * work on 82580 + */ + if (hw->mac.type == e1000_82580) + global_device_reset = false; + /* Get current control state. */ ctrl = rd32(E1000_CTRL); @@ -2233,19 +2275,16 @@ s32 igb_set_eee_i350(struct e1000_hw *hw) /* enable or disable per user setting */ if (!(hw->dev_spec._82575.eee_disable)) { - ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | - E1000_IPCNFG_EEE_100M_AN); - eeer |= (E1000_EEER_TX_LPI_EN | - E1000_EEER_RX_LPI_EN | + u32 eee_su = rd32(E1000_EEE_SU); + + ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); + eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | E1000_EEER_LPI_FC); - /* keep the LPI clock running before EEE is enabled */ - if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) { - u32 eee_su; - eee_su = rd32(E1000_EEE_SU); - eee_su &= ~E1000_EEE_SU_LPI_CLK_STP; - wr32(E1000_EEE_SU, eee_su); - } + /* This bit should not be set in normal operation. */ + if (eee_su & E1000_EEE_SU_LPI_CLK_STP) + hw_dbg("LPI Clock Stop Bit should not be set!\n"); + } else { ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h index e85c453f5428..44b76b3b6816 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.h +++ b/drivers/net/ethernet/intel/igb/e1000_82575.h @@ -172,10 +172,13 @@ struct e1000_adv_tx_context_desc { #define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */ #define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */ #define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */ +#define E1000_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx rd Desc Relax Order */ #define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ #define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ +#define E1000_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */ #define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */ +#define E1000_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */ /* Additional DCA related definitions, note change in position of CPUID */ #define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */ diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index de4b41ec3c40..45dce06eff26 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h @@ -431,6 +431,10 @@ #define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 #define FLOW_CONTROL_TYPE 0x8808 +/* Transmit Config Word */ +#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ +#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ + /* 802.1q VLAN Packet Size */ #define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */ #define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ @@ -539,6 +543,9 @@ /* mPHY Near End Digital Loopback Override Bit */ #define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10 +#define E1000_PCS_LCTL_FORCE_FCTRL 0x80 +#define E1000_PCS_LSTS_AN_COMPLETE 0x10000 + /* PHY Control Register */ #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ @@ -636,6 +643,7 @@ /* NVM Word Offsets */ #define NVM_COMPAT 0x0003 #define NVM_ID_LED_SETTINGS 0x0004 /* SERDES output amplitude */ +#define NVM_VERSION 0x0005 #define NVM_INIT_CONTROL2_REG 0x000F #define NVM_INIT_CONTROL3_PORT_B 0x0014 #define NVM_INIT_CONTROL3_PORT_A 0x0024 @@ -653,6 +661,19 @@ #define NVM_LED_1_CFG 0x001C #define NVM_LED_0_2_CFG 0x001F +/* NVM version defines */ +#define NVM_ETRACK_WORD 0x0042 +#define NVM_COMB_VER_OFF 0x0083 +#define NVM_COMB_VER_PTR 0x003d +#define NVM_MAJOR_MASK 0xF000 +#define NVM_MINOR_MASK 0x0FF0 +#define NVM_BUILD_MASK 0x000F +#define NVM_COMB_VER_MASK 0x00FF +#define NVM_MAJOR_SHIFT 12 +#define NVM_MINOR_SHIFT 4 +#define NVM_COMB_VER_SHFT 8 +#define NVM_VER_INVALID 0xFFFF +#define NVM_ETRACK_SHIFT 16 #define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */ #define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */ @@ -860,6 +881,7 @@ #define E1000_EEER_FRC_AN 0x10000000 /* Enable EEE in loopback */ #define E1000_EEER_LPI_FC 0x00040000 /* EEE Enable on FC */ #define E1000_EEE_SU_LPI_CLK_STP 0X00800000 /* EEE LPI Clock Stop */ +#define E1000_EEER_EEE_NEG 0x20000000 /* EEE capability nego */ /* SerDes Control */ #define E1000_GEN_CTL_READY 0x80000000 diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c index 77a5f939bc74..fbcdbebb0b5f 100644 --- a/drivers/net/ethernet/intel/igb/e1000_i210.c +++ b/drivers/net/ethernet/intel/igb/e1000_i210.c @@ -35,11 +35,42 @@ #include "e1000_hw.h" #include "e1000_i210.h" -static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw); -static void igb_put_hw_semaphore_i210(struct e1000_hw *hw); -static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); -static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw); +/** + * igb_get_hw_semaphore_i210 - Acquire hardware semaphore + * @hw: pointer to the HW structure + * + * Acquire the HW semaphore to access the PHY or NVM + */ +static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw) +{ + u32 swsm; + s32 ret_val = E1000_SUCCESS; + s32 timeout = hw->nvm.word_size + 1; + s32 i = 0; + + /* Get the FW semaphore. */ + for (i = 0; i < timeout; i++) { + swsm = rd32(E1000_SWSM); + wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI); + + /* Semaphore acquired if bit latched */ + if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI) + break; + + udelay(50); + } + + if (i == timeout) { + /* Release semaphores */ + igb_put_hw_semaphore(hw); + hw_dbg("Driver can't access the NVM\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + +out: + return ret_val; +} /** * igb_acquire_nvm_i210 - Request for access to EEPROM @@ -68,6 +99,23 @@ void igb_release_nvm_i210(struct e1000_hw *hw) } /** + * igb_put_hw_semaphore_i210 - Release hardware semaphore + * @hw: pointer to the HW structure + * + * Release hardware semaphore used to access the PHY or NVM + */ +static void igb_put_hw_semaphore_i210(struct e1000_hw *hw) +{ + u32 swsm; + + swsm = rd32(E1000_SWSM); + + swsm &= ~E1000_SWSM_SWESMBI; + + wr32(E1000_SWSM, swsm); +} + +/** * igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire @@ -138,60 +186,6 @@ void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) } /** - * igb_get_hw_semaphore_i210 - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore to access the PHY or NVM - **/ -static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw) -{ - u32 swsm; - s32 ret_val = E1000_SUCCESS; - s32 timeout = hw->nvm.word_size + 1; - s32 i = 0; - - /* Get the FW semaphore. */ - for (i = 0; i < timeout; i++) { - swsm = rd32(E1000_SWSM); - wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI); - - /* Semaphore acquired if bit latched */ - if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI) - break; - - udelay(50); - } - - if (i == timeout) { - /* Release semaphores */ - igb_put_hw_semaphore(hw); - hw_dbg("Driver can't access the NVM\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - -out: - return ret_val; -} - -/** - * igb_put_hw_semaphore_i210 - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - **/ -static void igb_put_hw_semaphore_i210(struct e1000_hw *hw) -{ - u32 swsm; - - swsm = rd32(E1000_SWSM); - - swsm &= ~E1000_SWSM_SWESMBI; - - wr32(E1000_SWSM, swsm); -} - -/** * igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register * @hw: pointer to the HW structure * @offset: offset of word in the Shadow Ram to read @@ -229,49 +223,6 @@ s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, } /** - * igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR - * @hw: pointer to the HW structure - * @offset: offset within the Shadow RAM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the Shadow RAM - * - * Writes data to Shadow RAM at offset using EEWR register. - * - * If e1000_update_nvm_checksum is not called after this function , the - * data will not be committed to FLASH and also Shadow RAM will most likely - * contain an invalid checksum. - * - * If error code is returned, data and Shadow RAM may be inconsistent - buffer - * partially written. - **/ -s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - s32 status = E1000_SUCCESS; - u16 i, count; - - /* We cannot hold synchronization semaphores for too long, - * because of forceful takeover procedure. However it is more efficient - * to write in bursts than synchronizing access for each word. */ - for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { - count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? - E1000_EERD_EEWR_MAX_COUNT : (words - i); - if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { - status = igb_write_nvm_srwr(hw, offset, count, - data + i); - hw->nvm.ops.release(hw); - } else { - status = E1000_ERR_SWFW_SYNC; - } - - if (status != E1000_SUCCESS) - break; - } - - return status; -} - -/** * igb_write_nvm_srwr - Write to Shadow Ram using EEWR * @hw: pointer to the HW structure * @offset: offset within the Shadow Ram to be written to @@ -329,6 +280,50 @@ out: } /** + * igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR + * @hw: pointer to the HW structure + * @offset: offset within the Shadow RAM to be written to + * @words: number of words to write + * @data: 16 bit word(s) to be written to the Shadow RAM + * + * Writes data to Shadow RAM at offset using EEWR register. + * + * If e1000_update_nvm_checksum is not called after this function , the + * data will not be committed to FLASH and also Shadow RAM will most likely + * contain an invalid checksum. + * + * If error code is returned, data and Shadow RAM may be inconsistent - buffer + * partially written. + */ +s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data) +{ + s32 status = E1000_SUCCESS; + u16 i, count; + + /* We cannot hold synchronization semaphores for too long, + * because of forceful takeover procedure. However it is more efficient + * to write in bursts than synchronizing access for each word. + */ + for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { + count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? + E1000_EERD_EEWR_MAX_COUNT : (words - i); + if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { + status = igb_write_nvm_srwr(hw, offset, count, + data + i); + hw->nvm.ops.release(hw); + } else { + status = E1000_ERR_SWFW_SYNC; + } + + if (status != E1000_SUCCESS) + break; + } + + return status; +} + +/** * igb_read_nvm_i211 - Read NVM wrapper function for I211 * @hw: pointer to the HW structure * @address: the word address (aka eeprom offset) to read @@ -350,16 +345,40 @@ s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, if (ret_val != E1000_SUCCESS) hw_dbg("MAC Addr not found in iNVM\n"); break; - case NVM_ID_LED_SETTINGS: case NVM_INIT_CTRL_2: + ret_val = igb_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_INIT_CTRL_2_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } + break; case NVM_INIT_CTRL_4: + ret_val = igb_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_INIT_CTRL_4_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } + break; case NVM_LED_1_CFG: + ret_val = igb_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_LED_1_CFG_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } + break; case NVM_LED_0_2_CFG: igb_read_invm_i211(hw, offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_LED_0_2_CFG_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } break; - case NVM_COMPAT: - *data = ID_LED_DEFAULT_I210; - break; + case NVM_ID_LED_SETTINGS: + ret_val = igb_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = ID_LED_RESERVED_FFFF; + ret_val = E1000_SUCCESS; + } case NVM_SUB_DEV_ID: *data = hw->subsystem_device_id; break; @@ -423,6 +442,100 @@ s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data) } /** + * igb_read_invm_version - Reads iNVM version and image type + * @hw: pointer to the HW structure + * @invm_ver: version structure for the version read + * + * Reads iNVM version and image type. + **/ +s32 igb_read_invm_version(struct e1000_hw *hw, + struct e1000_fw_version *invm_ver) { + u32 *record = NULL; + u32 *next_record = NULL; + u32 i = 0; + u32 invm_dword = 0; + u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE / + E1000_INVM_RECORD_SIZE_IN_BYTES); + u32 buffer[E1000_INVM_SIZE]; + s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; + u16 version = 0; + + /* Read iNVM memory */ + for (i = 0; i < E1000_INVM_SIZE; i++) { + invm_dword = rd32(E1000_INVM_DATA_REG(i)); + buffer[i] = invm_dword; + } + + /* Read version number */ + for (i = 1; i < invm_blocks; i++) { + record = &buffer[invm_blocks - i]; + next_record = &buffer[invm_blocks - i + 1]; + + /* Check if we have first version location used */ + if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) { + version = 0; + status = E1000_SUCCESS; + break; + } + /* Check if we have second version location used */ + else if ((i == 1) && + ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) { + version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; + status = E1000_SUCCESS; + break; + } + /* Check if we have odd version location + * used and it is the last one used + */ + else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) && + ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) && + (i != 1))) { + version = (*next_record & E1000_INVM_VER_FIELD_TWO) + >> 13; + status = E1000_SUCCESS; + break; + } + /* Check if we have even version location + * used and it is the last one used + */ + else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) && + ((*record & 0x3) == 0)) { + version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; + status = E1000_SUCCESS; + break; + } + } + + if (status == E1000_SUCCESS) { + invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK) + >> E1000_INVM_MAJOR_SHIFT; + invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK; + } + /* Read Image Type */ + for (i = 1; i < invm_blocks; i++) { + record = &buffer[invm_blocks - i]; + next_record = &buffer[invm_blocks - i + 1]; + + /* Check if we have image type in first location used */ + if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) { + invm_ver->invm_img_type = 0; + status = E1000_SUCCESS; + break; + } + /* Check if we have image type in first location used */ + else if ((((*record & 0x3) == 0) && + ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) || + ((((*record & 0x3) != 0) && (i != 1)))) { + invm_ver->invm_img_type = + (*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23; + status = E1000_SUCCESS; + break; + } + } + return status; +} + +/** * igb_validate_nvm_checksum_i210 - Validate EEPROM checksum * @hw: pointer to the HW structure * @@ -519,6 +632,28 @@ out: } /** + * igb_pool_flash_update_done_i210 - Pool FLUDONE status. + * @hw: pointer to the HW structure + * + */ +static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw) +{ + s32 ret_val = -E1000_ERR_NVM; + u32 i, reg; + + for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { + reg = rd32(E1000_EECD); + if (reg & E1000_EECD_FLUDONE_I210) { + ret_val = E1000_SUCCESS; + break; + } + udelay(5); + } + + return ret_val; +} + +/** * igb_update_flash_i210 - Commit EEPROM to the flash * @hw: pointer to the HW structure * @@ -548,28 +683,6 @@ out: } /** - * igb_pool_flash_update_done_i210 - Pool FLUDONE status. - * @hw: pointer to the HW structure - * - **/ -s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw) -{ - s32 ret_val = -E1000_ERR_NVM; - u32 i, reg; - - for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { - reg = rd32(E1000_EECD); - if (reg & E1000_EECD_FLUDONE_I210) { - ret_val = E1000_SUCCESS; - break; - } - udelay(5); - } - - return ret_val; -} - -/** * igb_valid_led_default_i210 - Verify a valid default LED config * @hw: pointer to the HW structure * @data: pointer to the NVM (EEPROM) diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.h b/drivers/net/ethernet/intel/igb/e1000_i210.h index 5dc2bd3f50bc..1c89358a99ab 100644 --- a/drivers/net/ethernet/intel/igb/e1000_i210.h +++ b/drivers/net/ethernet/intel/igb/e1000_i210.h @@ -43,6 +43,8 @@ extern void igb_release_nvm_i210(struct e1000_hw *hw); extern s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data); extern s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); +extern s32 igb_read_invm_version(struct e1000_hw *hw, + struct e1000_fw_version *invm_ver); #define E1000_STM_OPCODE 0xDB00 #define E1000_EEPROM_FLASH_SIZE_WORD 0x11 @@ -65,6 +67,15 @@ enum E1000_INVM_STRUCTURE_TYPE { #define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8 #define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1 +#define E1000_INVM_ULT_BYTES_SIZE 8 +#define E1000_INVM_RECORD_SIZE_IN_BYTES 4 +#define E1000_INVM_VER_FIELD_ONE 0x1FF8 +#define E1000_INVM_VER_FIELD_TWO 0x7FE000 +#define E1000_INVM_IMGTYPE_FIELD 0x1F800000 + +#define E1000_INVM_MAJOR_MASK 0x3F0 +#define E1000_INVM_MINOR_MASK 0xF +#define E1000_INVM_MAJOR_SHIFT 4 #define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \ (ID_LED_OFF1_OFF2 << 4) | \ @@ -73,4 +84,10 @@ enum E1000_INVM_STRUCTURE_TYPE { (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_DEF1_DEF2)) +/* NVM offset defaults for i211 device */ +#define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243 +#define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1 +#define NVM_LED_1_CFG_DEFAULT_I211 0x0184 +#define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C + #endif diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c index 819c145ac762..101e6e4da97f 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.c +++ b/drivers/net/ethernet/intel/igb/e1000_mac.c @@ -839,6 +839,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val = 0; + u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg; u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; u16 speed, duplex; @@ -1040,6 +1041,129 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) goto out; } } + /* Check for the case where we have SerDes media and auto-neg is + * enabled. In this case, we need to check and see if Auto-Neg + * has completed, and if so, how the PHY and link partner has + * flow control configured. + */ + if ((hw->phy.media_type == e1000_media_type_internal_serdes) + && mac->autoneg) { + /* Read the PCS_LSTS and check to see if AutoNeg + * has completed. + */ + pcs_status_reg = rd32(E1000_PCS_LSTAT); + + if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) { + hw_dbg("PCS Auto Neg has not completed.\n"); + return ret_val; + } + + /* The AutoNeg process has completed, so we now need to + * read both the Auto Negotiation Advertisement + * Register (PCS_ANADV) and the Auto_Negotiation Base + * Page Ability Register (PCS_LPAB) to determine how + * flow control was negotiated. + */ + pcs_adv_reg = rd32(E1000_PCS_ANADV); + pcs_lp_ability_reg = rd32(E1000_PCS_LPAB); + + /* Two bits in the Auto Negotiation Advertisement Register + * (PCS_ANADV) and two bits in the Auto Negotiation Base + * Page Ability Register (PCS_LPAB) determine flow control + * for both the PHY and the link partner. The following + * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, + * 1999, describes these PAUSE resolution bits and how flow + * control is determined based upon these settings. + * NOTE: DC = Don't Care + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution + *-------|---------|-------|---------|-------------------- + * 0 | 0 | DC | DC | e1000_fc_none + * 0 | 1 | 0 | DC | e1000_fc_none + * 0 | 1 | 1 | 0 | e1000_fc_none + * 0 | 1 | 1 | 1 | e1000_fc_tx_pause + * 1 | 0 | 0 | DC | e1000_fc_none + * 1 | DC | 1 | DC | e1000_fc_full + * 1 | 1 | 0 | 0 | e1000_fc_none + * 1 | 1 | 0 | 1 | e1000_fc_rx_pause + * + * Are both PAUSE bits set to 1? If so, this implies + * Symmetric Flow Control is enabled at both ends. The + * ASM_DIR bits are irrelevant per the spec. + * + * For Symmetric Flow Control: + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | DC | 1 | DC | e1000_fc_full + * + */ + if ((pcs_adv_reg & E1000_TXCW_PAUSE) && + (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) { + /* Now we need to check if the user selected Rx ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise Rx + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->fc.requested_mode == e1000_fc_full) { + hw->fc.current_mode = e1000_fc_full; + hw_dbg("Flow Control = FULL.\n"); + } else { + hw->fc.current_mode = e1000_fc_rx_pause; + hw_dbg("Flow Control = Rx PAUSE frames only.\n"); + } + } + /* For receiving PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 0 | 1 | 1 | 1 | e1000_fc_tx_pause + */ + else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) && + (pcs_adv_reg & E1000_TXCW_ASM_DIR) && + (pcs_lp_ability_reg & E1000_TXCW_PAUSE) && + (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { + hw->fc.current_mode = e1000_fc_tx_pause; + hw_dbg("Flow Control = Tx PAUSE frames only.\n"); + } + /* For transmitting PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | 1 | 0 | 1 | e1000_fc_rx_pause + */ + else if ((pcs_adv_reg & E1000_TXCW_PAUSE) && + (pcs_adv_reg & E1000_TXCW_ASM_DIR) && + !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) && + (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { + hw->fc.current_mode = e1000_fc_rx_pause; + hw_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; + hw_dbg("Flow Control = NONE.\n"); + } + + /* Now we call a subroutine to actually force the MAC + * controller to use the correct flow control settings. + */ + pcs_ctrl_reg = rd32(E1000_PCS_LCTL); + pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL; + wr32(E1000_PCS_LCTL, pcs_ctrl_reg); + + ret_val = igb_force_mac_fc(hw); + if (ret_val) { + hw_dbg("Error forcing flow control settings\n"); + return ret_val; + } + } out: return ret_val; @@ -1391,6 +1515,10 @@ s32 igb_validate_mdi_setting(struct e1000_hw *hw) { s32 ret_val = 0; + /* All MDI settings are supported on 82580 and newer. */ + if (hw->mac.type >= e1000_82580) + goto out; + if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) { hw_dbg("Invalid MDI setting detected\n"); hw->phy.mdix = 1; diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h index cbddc4e51e30..e2b2c4b9c951 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.h +++ b/drivers/net/ethernet/intel/igb/e1000_mac.h @@ -33,6 +33,7 @@ #include "e1000_phy.h" #include "e1000_nvm.h" #include "e1000_defines.h" +#include "e1000_i210.h" /* * Functions that should not be called directly from drivers but can be used diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.c b/drivers/net/ethernet/intel/igb/e1000_nvm.c index aa5fcdf3f357..fbb7604db364 100644 --- a/drivers/net/ethernet/intel/igb/e1000_nvm.c +++ b/drivers/net/ethernet/intel/igb/e1000_nvm.c @@ -438,7 +438,7 @@ out: s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val; + s32 ret_val = -E1000_ERR_NVM; u16 widx = 0; /* @@ -448,22 +448,21 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { hw_dbg("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return ret_val; } - ret_val = hw->nvm.ops.acquire(hw); - if (ret_val) - goto out; - - msleep(10); - while (widx < words) { u8 write_opcode = NVM_WRITE_OPCODE_SPI; - ret_val = igb_ready_nvm_eeprom(hw); + ret_val = nvm->ops.acquire(hw); if (ret_val) - goto release; + return ret_val; + + ret_val = igb_ready_nvm_eeprom(hw); + if (ret_val) { + nvm->ops.release(hw); + return ret_val; + } igb_standby_nvm(hw); @@ -497,13 +496,10 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) break; } } + usleep_range(1000, 2000); + nvm->ops.release(hw); } - msleep(10); -release: - hw->nvm.ops.release(hw); - -out: return ret_val; } @@ -710,3 +706,74 @@ s32 igb_update_nvm_checksum(struct e1000_hw *hw) out: return ret_val; } + +/** + * igb_get_fw_version - Get firmware version information + * @hw: pointer to the HW structure + * @fw_vers: pointer to output structure + * + * unsupported MAC types will return all 0 version structure + **/ +void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers) +{ + u16 eeprom_verh, eeprom_verl, comb_verh, comb_verl, comb_offset; + u16 fw_version; + + memset(fw_vers, 0, sizeof(struct e1000_fw_version)); + + switch (hw->mac.type) { + case e1000_i211: + igb_read_invm_version(hw, fw_vers); + return; + case e1000_82575: + case e1000_82576: + case e1000_82580: + case e1000_i350: + case e1000_i210: + break; + default: + return; + } + /* basic eeprom version numbers */ + hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version); + fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) >> NVM_MAJOR_SHIFT; + fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK); + + /* etrack id */ + hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl); + hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh); + fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) | eeprom_verl; + + switch (hw->mac.type) { + case e1000_i210: + case e1000_i350: + /* find combo image version */ + hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset); + if ((comb_offset != 0x0) && (comb_offset != NVM_VER_INVALID)) { + + hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset + + 1), 1, &comb_verh); + hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset), + 1, &comb_verl); + + /* get Option Rom version if it exists and is valid */ + if ((comb_verh && comb_verl) && + ((comb_verh != NVM_VER_INVALID) && + (comb_verl != NVM_VER_INVALID))) { + + fw_vers->or_valid = true; + fw_vers->or_major = + comb_verl >> NVM_COMB_VER_SHFT; + fw_vers->or_build = + ((comb_verl << NVM_COMB_VER_SHFT) + | (comb_verh >> NVM_COMB_VER_SHFT)); + fw_vers->or_patch = + comb_verh & NVM_COMB_VER_MASK; + } + } + break; + default: + break; + } + return; +} diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.h b/drivers/net/ethernet/intel/igb/e1000_nvm.h index 825b0228cac0..7012d458c6f7 100644 --- a/drivers/net/ethernet/intel/igb/e1000_nvm.h +++ b/drivers/net/ethernet/intel/igb/e1000_nvm.h @@ -40,4 +40,20 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 igb_validate_nvm_checksum(struct e1000_hw *hw); s32 igb_update_nvm_checksum(struct e1000_hw *hw); +struct e1000_fw_version { + u32 etrack_id; + u16 eep_major; + u16 eep_minor; + + u8 invm_major; + u8 invm_minor; + u8 invm_img_type; + + bool or_valid; + u16 or_major; + u16 or_build; + u16 or_patch; +}; +void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers); + #endif diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c index 3404bc79f4ca..fe76004aca4e 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.c +++ b/drivers/net/ethernet/intel/igb/e1000_phy.c @@ -1207,20 +1207,25 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) u16 phy_data; bool link; - /* - * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - goto out; + /* I210 and I211 devices support Auto-Crossover in forced operation. */ + if (phy->type != e1000_phy_i210) { + /* + * Clear Auto-Crossover to force MDI manually. M88E1000 + * requires MDI forced whenever speed and duplex are forced. + */ + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data); + if (ret_val) + goto out; - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - goto out; + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data); + if (ret_val) + goto out; - hw_dbg("M88E1000 PSCR: %X\n", phy_data); + hw_dbg("M88E1000 PSCR: %X\n", phy_data); + } ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) @@ -1710,6 +1715,26 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw) switch (hw->phy.id) { case I210_I_PHY_ID: + /* Get cable length from PHY Cable Diagnostics Control Reg */ + ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) + + (I347AT4_PCDL + phy->addr), + &phy_data); + if (ret_val) + return ret_val; + + /* Check if the unit of cable length is meters or cm */ + ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) + + I347AT4_PCDC, &phy_data2); + if (ret_val) + return ret_val; + + is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT); + + /* Populate the phy structure with cable length in meters */ + phy->min_cable_length = phy_data / (is_cm ? 100 : 1); + phy->max_cable_length = phy_data / (is_cm ? 100 : 1); + phy->cable_length = phy_data / (is_cm ? 100 : 1); + break; case I347AT4_E_PHY_ID: /* Remember the original page select and set it to 7 */ ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT, diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h index 6ac3299bfcb9..ed282f877d9a 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.h +++ b/drivers/net/ethernet/intel/igb/e1000_phy.h @@ -124,6 +124,7 @@ s32 igb_check_polarity_m88(struct e1000_hw *hw); #define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */ #define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */ #define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */ +#define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */ /* Enable flexible speed on link-up */ #define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 8aad230c0592..17f1686ee411 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -34,16 +34,16 @@ #include "e1000_mac.h" #include "e1000_82575.h" -#ifdef CONFIG_IGB_PTP #include <linux/clocksource.h> #include <linux/net_tstamp.h> #include <linux/ptp_clock_kernel.h> -#endif /* CONFIG_IGB_PTP */ #include <linux/bitops.h> #include <linux/if_vlan.h> struct igb_adapter; +#define E1000_PCS_CFG_IGN_SD 1 + /* Interrupt defines */ #define IGB_START_ITR 648 /* ~6000 ints/sec */ #define IGB_4K_ITR 980 @@ -132,9 +132,10 @@ struct vf_data_storage { #define MAXIMUM_ETHERNET_VLAN_SIZE 1522 /* Supported Rx Buffer Sizes */ -#define IGB_RXBUFFER_256 256 -#define IGB_RXBUFFER_16384 16384 -#define IGB_RX_HDR_LEN IGB_RXBUFFER_256 +#define IGB_RXBUFFER_256 256 +#define IGB_RXBUFFER_2048 2048 +#define IGB_RX_HDR_LEN IGB_RXBUFFER_256 +#define IGB_RX_BUFSZ IGB_RXBUFFER_2048 /* How many Tx Descriptors do we need to call netif_wake_queue ? */ #define IGB_TX_QUEUE_WAKE 16 @@ -151,11 +152,18 @@ struct vf_data_storage { #define IGB_MNG_VLAN_NONE -1 -#define IGB_TX_FLAGS_CSUM 0x00000001 -#define IGB_TX_FLAGS_VLAN 0x00000002 -#define IGB_TX_FLAGS_TSO 0x00000004 -#define IGB_TX_FLAGS_IPV4 0x00000008 -#define IGB_TX_FLAGS_TSTAMP 0x00000010 +enum igb_tx_flags { + /* cmd_type flags */ + IGB_TX_FLAGS_VLAN = 0x01, + IGB_TX_FLAGS_TSO = 0x02, + IGB_TX_FLAGS_TSTAMP = 0x04, + + /* olinfo flags */ + IGB_TX_FLAGS_IPV4 = 0x10, + IGB_TX_FLAGS_CSUM = 0x20, +}; + +/* VLAN info */ #define IGB_TX_FLAGS_VLAN_MASK 0xffff0000 #define IGB_TX_FLAGS_VLAN_SHIFT 16 @@ -174,11 +182,9 @@ struct igb_tx_buffer { }; struct igb_rx_buffer { - struct sk_buff *skb; dma_addr_t dma; struct page *page; - dma_addr_t page_dma; - u32 page_offset; + unsigned int page_offset; }; struct igb_tx_queue_stats { @@ -205,22 +211,6 @@ struct igb_ring_container { u8 itr; /* current ITR setting for ring */ }; -struct igb_q_vector { - struct igb_adapter *adapter; /* backlink */ - int cpu; /* CPU for DCA */ - u32 eims_value; /* EIMS mask value */ - - struct igb_ring_container rx, tx; - - struct napi_struct napi; - - u16 itr_val; - u8 set_itr; - void __iomem *itr_register; - - char name[IFNAMSIZ + 9]; -}; - struct igb_ring { struct igb_q_vector *q_vector; /* backlink to q_vector */ struct net_device *netdev; /* back pointer to net_device */ @@ -232,15 +222,17 @@ struct igb_ring { void *desc; /* descriptor ring memory */ unsigned long flags; /* ring specific flags */ void __iomem *tail; /* pointer to ring tail register */ + dma_addr_t dma; /* phys address of the ring */ + unsigned int size; /* length of desc. ring in bytes */ u16 count; /* number of desc. in the ring */ u8 queue_index; /* logical index of the ring*/ u8 reg_idx; /* physical index of the ring */ - u32 size; /* length of desc. ring in bytes */ /* everything past this point are written often */ - u16 next_to_clean ____cacheline_aligned_in_smp; + u16 next_to_clean; u16 next_to_use; + u16 next_to_alloc; union { /* TX */ @@ -251,12 +243,30 @@ struct igb_ring { }; /* RX */ struct { + struct sk_buff *skb; struct igb_rx_queue_stats rx_stats; struct u64_stats_sync rx_syncp; }; }; - /* Items past this point are only used during ring alloc / free */ - dma_addr_t dma; /* phys address of the ring */ +} ____cacheline_internodealigned_in_smp; + +struct igb_q_vector { + struct igb_adapter *adapter; /* backlink */ + int cpu; /* CPU for DCA */ + u32 eims_value; /* EIMS mask value */ + + u16 itr_val; + u8 set_itr; + void __iomem *itr_register; + + struct igb_ring_container rx, tx; + + struct napi_struct napi; + struct rcu_head rcu; /* to avoid race with update stats on free */ + char name[IFNAMSIZ + 9]; + + /* for dynamic allocation of rings associated with this q_vector */ + struct igb_ring ring[0] ____cacheline_internodealigned_in_smp; }; enum e1000_ring_flags_t { @@ -362,8 +372,6 @@ struct igb_adapter { u32 eims_other; /* to not mess up cache alignment, always add to the bottom */ - u32 eeprom_wol; - u16 tx_ring_count; u16 rx_ring_count; unsigned int vfs_allocated_count; @@ -373,7 +381,6 @@ struct igb_adapter { u32 wvbr; u32 *shadow_vfta; -#ifdef CONFIG_IGB_PTP struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_caps; struct delayed_work ptp_overflow_work; @@ -382,17 +389,19 @@ struct igb_adapter { spinlock_t tmreg_lock; struct cyclecounter cc; struct timecounter tc; -#endif /* CONFIG_IGB_PTP */ char fw_version[32]; }; -#define IGB_FLAG_HAS_MSI (1 << 0) -#define IGB_FLAG_DCA_ENABLED (1 << 1) -#define IGB_FLAG_QUAD_PORT_A (1 << 2) -#define IGB_FLAG_QUEUE_PAIRS (1 << 3) -#define IGB_FLAG_DMAC (1 << 4) -#define IGB_FLAG_PTP (1 << 5) +#define IGB_FLAG_HAS_MSI (1 << 0) +#define IGB_FLAG_DCA_ENABLED (1 << 1) +#define IGB_FLAG_QUAD_PORT_A (1 << 2) +#define IGB_FLAG_QUEUE_PAIRS (1 << 3) +#define IGB_FLAG_DMAC (1 << 4) +#define IGB_FLAG_PTP (1 << 5) +#define IGB_FLAG_RSS_FIELD_IPV4_UDP (1 << 6) +#define IGB_FLAG_RSS_FIELD_IPV6_UDP (1 << 7) +#define IGB_FLAG_WOL_SUPPORTED (1 << 8) /* DMA Coalescing defines */ #define IGB_MIN_TXPBSIZE 20408 @@ -436,18 +445,27 @@ extern bool igb_has_link(struct igb_adapter *adapter); extern void igb_set_ethtool_ops(struct net_device *); extern void igb_power_up_link(struct igb_adapter *); extern void igb_set_fw_version(struct igb_adapter *); -#ifdef CONFIG_IGB_PTP extern void igb_ptp_init(struct igb_adapter *adapter); extern void igb_ptp_stop(struct igb_adapter *adapter); extern void igb_ptp_reset(struct igb_adapter *adapter); extern void igb_ptp_tx_work(struct work_struct *work); extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter); -extern void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector, - union e1000_adv_rx_desc *rx_desc, +extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, + struct sk_buff *skb); +extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, + unsigned char *va, struct sk_buff *skb); +static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector, + union e1000_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS) && + !igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) + igb_ptp_rx_rgtstamp(q_vector, skb); +} + extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -#endif /* CONFIG_IGB_PTP */ static inline s32 igb_reset_phy(struct e1000_hw *hw) { diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index 2ea012849825..bfe9208c4b18 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -37,6 +37,7 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/pm_runtime.h> +#include <linux/highmem.h> #include "igb.h" @@ -1623,6 +1624,20 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter) reg &= ~E1000_CONNSW_ENRGSRC; wr32(E1000_CONNSW, reg); + /* Unset sigdetect for SERDES loopback on + * 82580 and i350 devices. + */ + switch (hw->mac.type) { + case e1000_82580: + case e1000_i350: + reg = rd32(E1000_PCS_CFG0); + reg |= E1000_PCS_CFG_IGN_SD; + wr32(E1000_PCS_CFG0, reg); + break; + default: + break; + } + /* Set PCS register for forced speed */ reg = rd32(E1000_PCS_LCTL); reg &= ~E1000_PCS_LCTL_AN_ENABLE; /* Disable Autoneg*/ @@ -1685,16 +1700,24 @@ static void igb_create_lbtest_frame(struct sk_buff *skb, memset(&skb->data[frame_size + 12], 0xAF, 1); } -static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size) +static int igb_check_lbtest_frame(struct igb_rx_buffer *rx_buffer, + unsigned int frame_size) { - frame_size /= 2; - if (*(skb->data + 3) == 0xFF) { - if ((*(skb->data + frame_size + 10) == 0xBE) && - (*(skb->data + frame_size + 12) == 0xAF)) { - return 0; - } - } - return 13; + unsigned char *data; + bool match = true; + + frame_size >>= 1; + + data = kmap(rx_buffer->page); + + if (data[3] != 0xFF || + data[frame_size + 10] != 0xBE || + data[frame_size + 12] != 0xAF) + match = false; + + kunmap(rx_buffer->page); + + return match; } static int igb_clean_test_rings(struct igb_ring *rx_ring, @@ -1704,9 +1727,7 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring, union e1000_adv_rx_desc *rx_desc; struct igb_rx_buffer *rx_buffer_info; struct igb_tx_buffer *tx_buffer_info; - struct netdev_queue *txq; u16 rx_ntc, tx_ntc, count = 0; - unsigned int total_bytes = 0, total_packets = 0; /* initialize next to clean and descriptor values */ rx_ntc = rx_ring->next_to_clean; @@ -1717,21 +1738,24 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring, /* check rx buffer */ rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc]; - /* unmap rx buffer, will be remapped by alloc_rx_buffers */ - dma_unmap_single(rx_ring->dev, - rx_buffer_info->dma, - IGB_RX_HDR_LEN, - DMA_FROM_DEVICE); - rx_buffer_info->dma = 0; + /* sync Rx buffer for CPU read */ + dma_sync_single_for_cpu(rx_ring->dev, + rx_buffer_info->dma, + IGB_RX_BUFSZ, + DMA_FROM_DEVICE); /* verify contents of skb */ - if (!igb_check_lbtest_frame(rx_buffer_info->skb, size)) + if (igb_check_lbtest_frame(rx_buffer_info, size)) count++; + /* sync Rx buffer for device write */ + dma_sync_single_for_device(rx_ring->dev, + rx_buffer_info->dma, + IGB_RX_BUFSZ, + DMA_FROM_DEVICE); + /* unmap buffer on tx side */ tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc]; - total_bytes += tx_buffer_info->bytecount; - total_packets += tx_buffer_info->gso_segs; igb_unmap_and_free_tx_resource(tx_ring, tx_buffer_info); /* increment rx/tx next to clean counters */ @@ -1746,8 +1770,7 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring, rx_desc = IGB_RX_DESC(rx_ring, rx_ntc); } - txq = netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index); - netdev_tx_completed_queue(txq, total_packets, total_bytes); + netdev_tx_reset_queue(txring_txq(tx_ring)); /* re-map buffers to ring, store next to clean values */ igb_alloc_rx_buffers(rx_ring, count); @@ -1957,54 +1980,6 @@ static void igb_diag_test(struct net_device *netdev, msleep_interruptible(4 * 1000); } -static int igb_wol_exclusion(struct igb_adapter *adapter, - struct ethtool_wolinfo *wol) -{ - struct e1000_hw *hw = &adapter->hw; - int retval = 1; /* fail by default */ - - switch (hw->device_id) { - case E1000_DEV_ID_82575GB_QUAD_COPPER: - /* WoL not supported */ - wol->supported = 0; - break; - case E1000_DEV_ID_82575EB_FIBER_SERDES: - case E1000_DEV_ID_82576_FIBER: - case E1000_DEV_ID_82576_SERDES: - /* Wake events not supported on port B */ - if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) { - wol->supported = 0; - break; - } - /* return success for non excluded adapter ports */ - retval = 0; - break; - case E1000_DEV_ID_82576_QUAD_COPPER: - case E1000_DEV_ID_82576_QUAD_COPPER_ET2: - /* quad port adapters only support WoL on port A */ - if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) { - wol->supported = 0; - break; - } - /* return success for non excluded adapter ports */ - retval = 0; - break; - default: - /* dual port cards only support WoL on port A from now on - * unless it was enabled in the eeprom for port B - * so exclude FUNC_1 ports from having WoL enabled */ - if ((rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) && - !adapter->eeprom_wol) { - wol->supported = 0; - break; - } - - retval = 0; - } - - return retval; -} - static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct igb_adapter *adapter = netdev_priv(netdev); @@ -2014,10 +1989,7 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) WAKE_PHY; wol->wolopts = 0; - /* this function will set ->supported = 0 and return 1 if wol is not - * supported by this hardware */ - if (igb_wol_exclusion(adapter, wol) || - !device_can_wakeup(&adapter->pdev->dev)) + if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED)) return; /* apply any specific unsupported masks here */ @@ -2045,8 +2017,7 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; - if (igb_wol_exclusion(adapter, wol) || - !device_can_wakeup(&adapter->pdev->dev)) + if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED)) return wol->wolopts ? -EOPNOTSUPP : 0; /* these settings will always override what we currently have */ @@ -2301,7 +2272,6 @@ static int igb_get_ts_info(struct net_device *dev, struct igb_adapter *adapter = netdev_priv(dev); switch (adapter->hw.mac.type) { -#ifdef CONFIG_IGB_PTP case e1000_82576: case e1000_82580: case e1000_i350: @@ -2337,12 +2307,288 @@ static int igb_get_ts_info(struct net_device *dev, (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); return 0; -#endif /* CONFIG_IGB_PTP */ default: return -EOPNOTSUPP; } } +static int igb_get_rss_hash_opts(struct igb_adapter *adapter, + struct ethtool_rxnfc *cmd) +{ + cmd->data = 0; + + /* Report default options for RSS on igb */ + switch (cmd->flow_type) { + case TCP_V4_FLOW: + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + case UDP_V4_FLOW: + if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP) + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + case SCTP_V4_FLOW: + case AH_ESP_V4_FLOW: + case AH_V4_FLOW: + case ESP_V4_FLOW: + case IPV4_FLOW: + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + break; + case TCP_V6_FLOW: + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + case UDP_V6_FLOW: + if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP) + cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + case SCTP_V6_FLOW: + case AH_ESP_V6_FLOW: + case AH_V6_FLOW: + case ESP_V6_FLOW: + case IPV6_FLOW: + cmd->data |= RXH_IP_SRC | RXH_IP_DST; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int igb_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + u32 *rule_locs) +{ + struct igb_adapter *adapter = netdev_priv(dev); + int ret = -EOPNOTSUPP; + + switch (cmd->cmd) { + case ETHTOOL_GRXRINGS: + cmd->data = adapter->num_rx_queues; + ret = 0; + break; + case ETHTOOL_GRXFH: + ret = igb_get_rss_hash_opts(adapter, cmd); + break; + default: + break; + } + + return ret; +} + +#define UDP_RSS_FLAGS (IGB_FLAG_RSS_FIELD_IPV4_UDP | \ + IGB_FLAG_RSS_FIELD_IPV6_UDP) +static int igb_set_rss_hash_opt(struct igb_adapter *adapter, + struct ethtool_rxnfc *nfc) +{ + u32 flags = adapter->flags; + + /* RSS does not support anything other than hashing + * to queues on src and dst IPs and ports + */ + if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3)) + return -EINVAL; + + switch (nfc->flow_type) { + case TCP_V4_FLOW: + case TCP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST) || + !(nfc->data & RXH_L4_B_0_1) || + !(nfc->data & RXH_L4_B_2_3)) + return -EINVAL; + break; + case UDP_V4_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST)) + return -EINVAL; + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + flags &= ~IGB_FLAG_RSS_FIELD_IPV4_UDP; + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + flags |= IGB_FLAG_RSS_FIELD_IPV4_UDP; + break; + default: + return -EINVAL; + } + break; + case UDP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST)) + return -EINVAL; + switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + flags &= ~IGB_FLAG_RSS_FIELD_IPV6_UDP; + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + flags |= IGB_FLAG_RSS_FIELD_IPV6_UDP; + break; + default: + return -EINVAL; + } + break; + case AH_ESP_V4_FLOW: + case AH_V4_FLOW: + case ESP_V4_FLOW: + case SCTP_V4_FLOW: + case AH_ESP_V6_FLOW: + case AH_V6_FLOW: + case ESP_V6_FLOW: + case SCTP_V6_FLOW: + if (!(nfc->data & RXH_IP_SRC) || + !(nfc->data & RXH_IP_DST) || + (nfc->data & RXH_L4_B_0_1) || + (nfc->data & RXH_L4_B_2_3)) + return -EINVAL; + break; + default: + return -EINVAL; + } + + /* if we changed something we need to update flags */ + if (flags != adapter->flags) { + struct e1000_hw *hw = &adapter->hw; + u32 mrqc = rd32(E1000_MRQC); + + if ((flags & UDP_RSS_FLAGS) && + !(adapter->flags & UDP_RSS_FLAGS)) + dev_err(&adapter->pdev->dev, + "enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n"); + + adapter->flags = flags; + + /* Perform hash on these packet types */ + mrqc |= E1000_MRQC_RSS_FIELD_IPV4 | + E1000_MRQC_RSS_FIELD_IPV4_TCP | + E1000_MRQC_RSS_FIELD_IPV6 | + E1000_MRQC_RSS_FIELD_IPV6_TCP; + + mrqc &= ~(E1000_MRQC_RSS_FIELD_IPV4_UDP | + E1000_MRQC_RSS_FIELD_IPV6_UDP); + + if (flags & IGB_FLAG_RSS_FIELD_IPV4_UDP) + mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP; + + if (flags & IGB_FLAG_RSS_FIELD_IPV6_UDP) + mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP; + + wr32(E1000_MRQC, mrqc); + } + + return 0; +} + +static int igb_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) +{ + struct igb_adapter *adapter = netdev_priv(dev); + int ret = -EOPNOTSUPP; + + switch (cmd->cmd) { + case ETHTOOL_SRXFH: + ret = igb_set_rss_hash_opt(adapter, cmd); + break; + default: + break; + } + + return ret; +} + +static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 ipcnfg, eeer; + + if ((hw->mac.type < e1000_i350) || + (hw->phy.media_type != e1000_media_type_copper)) + return -EOPNOTSUPP; + + edata->supported = (SUPPORTED_1000baseT_Full | + SUPPORTED_100baseT_Full); + + ipcnfg = rd32(E1000_IPCNFG); + eeer = rd32(E1000_EEER); + + /* EEE status on negotiated link */ + if (ipcnfg & E1000_IPCNFG_EEE_1G_AN) + edata->advertised = ADVERTISED_1000baseT_Full; + + if (ipcnfg & E1000_IPCNFG_EEE_100M_AN) + edata->advertised |= ADVERTISED_100baseT_Full; + + if (eeer & E1000_EEER_EEE_NEG) + edata->eee_active = true; + + edata->eee_enabled = !hw->dev_spec._82575.eee_disable; + + if (eeer & E1000_EEER_TX_LPI_EN) + edata->tx_lpi_enabled = true; + + /* Report correct negotiated EEE status for devices that + * wrongly report EEE at half-duplex + */ + if (adapter->link_duplex == HALF_DUPLEX) { + edata->eee_enabled = false; + edata->eee_active = false; + edata->tx_lpi_enabled = false; + edata->advertised &= ~edata->advertised; + } + + return 0; +} + +static int igb_set_eee(struct net_device *netdev, + struct ethtool_eee *edata) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + struct ethtool_eee eee_curr; + s32 ret_val; + + if ((hw->mac.type < e1000_i350) || + (hw->phy.media_type != e1000_media_type_copper)) + return -EOPNOTSUPP; + + ret_val = igb_get_eee(netdev, &eee_curr); + if (ret_val) + return ret_val; + + if (eee_curr.eee_enabled) { + if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) { + dev_err(&adapter->pdev->dev, + "Setting EEE tx-lpi is not supported\n"); + return -EINVAL; + } + + /* Tx LPI timer is not implemented currently */ + if (edata->tx_lpi_timer) { + dev_err(&adapter->pdev->dev, + "Setting EEE Tx LPI timer is not supported\n"); + return -EINVAL; + } + + if (eee_curr.advertised != edata->advertised) { + dev_err(&adapter->pdev->dev, + "Setting EEE Advertisement is not supported\n"); + return -EINVAL; + } + + } else if (!edata->eee_enabled) { + dev_err(&adapter->pdev->dev, + "Setting EEE options are not supported with EEE disabled\n"); + return -EINVAL; + } + + if (hw->dev_spec._82575.eee_disable != !edata->eee_enabled) { + hw->dev_spec._82575.eee_disable = !edata->eee_enabled; + igb_set_eee_i350(hw); + + /* reset link */ + if (!netif_running(netdev)) + igb_reset(adapter); + } + + return 0; +} + static int igb_ethtool_begin(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); @@ -2383,6 +2629,10 @@ static const struct ethtool_ops igb_ethtool_ops = { .get_coalesce = igb_get_coalesce, .set_coalesce = igb_set_coalesce, .get_ts_info = igb_get_ts_info, + .get_rxnfc = igb_get_rxnfc, + .set_rxnfc = igb_set_rxnfc, + .get_eee = igb_get_eee, + .set_eee = igb_set_eee, .begin = igb_ethtool_begin, .complete = igb_ethtool_complete, }; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index e1ceb37ef12e..31cfe2ec75df 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -60,8 +60,8 @@ #include "igb.h" #define MAJ 4 -#define MIN 0 -#define BUILD 1 +#define MIN 1 +#define BUILD 2 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ __stringify(BUILD) "-k" char igb_driver_name[] = "igb"; @@ -118,10 +118,11 @@ static void igb_free_all_tx_resources(struct igb_adapter *); static void igb_free_all_rx_resources(struct igb_adapter *); static void igb_setup_mrqc(struct igb_adapter *); static int igb_probe(struct pci_dev *, const struct pci_device_id *); -static void __devexit igb_remove(struct pci_dev *pdev); +static void igb_remove(struct pci_dev *pdev); static int igb_sw_init(struct igb_adapter *); static int igb_open(struct net_device *); static int igb_close(struct net_device *); +static void igb_configure(struct igb_adapter *); static void igb_configure_tx(struct igb_adapter *); static void igb_configure_rx(struct igb_adapter *); static void igb_clean_all_tx_rings(struct igb_adapter *); @@ -228,7 +229,7 @@ static struct pci_driver igb_driver = { .name = igb_driver_name, .id_table = igb_pci_tbl, .probe = igb_probe, - .remove = __devexit_p(igb_remove), + .remove = igb_remove, #ifdef CONFIG_PM .driver.pm = &igb_pm_ops, #endif @@ -534,31 +535,27 @@ rx_ring_summary: if (staterr & E1000_RXD_STAT_DD) { /* Descriptor Done */ - pr_info("%s[0x%03X] %016llX %016llX -------" - "--------- %p%s\n", "RWB", i, + pr_info("%s[0x%03X] %016llX %016llX ---------------- %s\n", + "RWB", i, le64_to_cpu(u0->a), le64_to_cpu(u0->b), - buffer_info->skb, next_desc); + next_desc); } else { - pr_info("%s[0x%03X] %016llX %016llX %016llX" - " %p%s\n", "R ", i, + pr_info("%s[0x%03X] %016llX %016llX %016llX %s\n", + "R ", i, le64_to_cpu(u0->a), le64_to_cpu(u0->b), (u64)buffer_info->dma, - buffer_info->skb, next_desc); + next_desc); if (netif_msg_pktdata(adapter) && - buffer_info->dma && buffer_info->skb) { - print_hex_dump(KERN_INFO, "", - DUMP_PREFIX_ADDRESS, - 16, 1, buffer_info->skb->data, - IGB_RX_HDR_LEN, true); + buffer_info->dma && buffer_info->page) { print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 1, page_address(buffer_info->page) + buffer_info->page_offset, - PAGE_SIZE/2, true); + IGB_RX_BUFSZ, true); } } } @@ -656,80 +653,6 @@ static void igb_cache_ring_register(struct igb_adapter *adapter) } } -static void igb_free_queues(struct igb_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_tx_queues; i++) { - kfree(adapter->tx_ring[i]); - adapter->tx_ring[i] = NULL; - } - for (i = 0; i < adapter->num_rx_queues; i++) { - kfree(adapter->rx_ring[i]); - adapter->rx_ring[i] = NULL; - } - adapter->num_rx_queues = 0; - adapter->num_tx_queues = 0; -} - -/** - * igb_alloc_queues - Allocate memory for all rings - * @adapter: board private structure to initialize - * - * We allocate one ring per queue at run-time since we don't know the - * number of queues at compile-time. - **/ -static int igb_alloc_queues(struct igb_adapter *adapter) -{ - struct igb_ring *ring; - int i; - - for (i = 0; i < adapter->num_tx_queues; i++) { - ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); - if (!ring) - goto err; - ring->count = adapter->tx_ring_count; - ring->queue_index = i; - ring->dev = &adapter->pdev->dev; - ring->netdev = adapter->netdev; - /* For 82575, context index must be unique per ring. */ - if (adapter->hw.mac.type == e1000_82575) - set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags); - adapter->tx_ring[i] = ring; - } - - for (i = 0; i < adapter->num_rx_queues; i++) { - ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); - if (!ring) - goto err; - ring->count = adapter->rx_ring_count; - ring->queue_index = i; - ring->dev = &adapter->pdev->dev; - ring->netdev = adapter->netdev; - /* set flag indicating ring supports SCTP checksum offload */ - if (adapter->hw.mac.type >= e1000_82576) - set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); - - /* - * On i350, i210, and i211, loopback VLAN packets - * have the tag byte-swapped. - * */ - if (adapter->hw.mac.type >= e1000_i350) - set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags); - - adapter->rx_ring[i] = ring; - } - - igb_cache_ring_register(adapter); - - return 0; - -err: - igb_free_queues(adapter); - - return -ENOMEM; -} - /** * igb_write_ivar - configure ivar for given MSI-X vector * @hw: pointer to the HW structure @@ -909,17 +832,18 @@ static int igb_request_msix(struct igb_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct e1000_hw *hw = &adapter->hw; - int i, err = 0, vector = 0; + int i, err = 0, vector = 0, free_vector = 0; err = request_irq(adapter->msix_entries[vector].vector, igb_msix_other, 0, netdev->name, adapter); if (err) - goto out; - vector++; + goto err_out; for (i = 0; i < adapter->num_q_vectors; i++) { struct igb_q_vector *q_vector = adapter->q_vector[i]; + vector++; + q_vector->itr_register = hw->hw_addr + E1000_EITR(vector); if (q_vector->rx.ring && q_vector->tx.ring) @@ -938,13 +862,22 @@ static int igb_request_msix(struct igb_adapter *adapter) igb_msix_ring, 0, q_vector->name, q_vector); if (err) - goto out; - vector++; + goto err_free; } igb_configure_msix(adapter); return 0; -out: + +err_free: + /* free already assigned IRQs */ + free_irq(adapter->msix_entries[free_vector++].vector, adapter); + + vector--; + for (i = 0; i < vector; i++) { + free_irq(adapter->msix_entries[free_vector++].vector, + adapter->q_vector[i]); + } +err_out: return err; } @@ -960,6 +893,35 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter) } /** + * igb_free_q_vector - Free memory allocated for specific interrupt vector + * @adapter: board private structure to initialize + * @v_idx: Index of vector to be freed + * + * This function frees the memory allocated to the q_vector. In addition if + * NAPI is enabled it will delete any references to the NAPI struct prior + * to freeing the q_vector. + **/ +static void igb_free_q_vector(struct igb_adapter *adapter, int v_idx) +{ + struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; + + if (q_vector->tx.ring) + adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL; + + if (q_vector->rx.ring) + adapter->tx_ring[q_vector->rx.ring->queue_index] = NULL; + + adapter->q_vector[v_idx] = NULL; + netif_napi_del(&q_vector->napi); + + /* + * ixgbe_get_stats64() might access the rings on this vector, + * we must wait a grace period before freeing it. + */ + kfree_rcu(q_vector, rcu); +} + +/** * igb_free_q_vectors - Free memory allocated for interrupt vectors * @adapter: board private structure to initialize * @@ -969,17 +931,14 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter) **/ static void igb_free_q_vectors(struct igb_adapter *adapter) { - int v_idx; + int v_idx = adapter->num_q_vectors; - for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) { - struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; - adapter->q_vector[v_idx] = NULL; - if (!q_vector) - continue; - netif_napi_del(&q_vector->napi); - kfree(q_vector); - } + adapter->num_tx_queues = 0; + adapter->num_rx_queues = 0; adapter->num_q_vectors = 0; + + while (v_idx--) + igb_free_q_vector(adapter, v_idx); } /** @@ -990,7 +949,6 @@ static void igb_free_q_vectors(struct igb_adapter *adapter) */ static void igb_clear_interrupt_scheme(struct igb_adapter *adapter) { - igb_free_queues(adapter); igb_free_q_vectors(adapter); igb_reset_interrupt_capability(adapter); } @@ -1001,11 +959,14 @@ static void igb_clear_interrupt_scheme(struct igb_adapter *adapter) * Attempt to configure interrupts using the best available * capabilities of the hardware and kernel. **/ -static int igb_set_interrupt_capability(struct igb_adapter *adapter) +static void igb_set_interrupt_capability(struct igb_adapter *adapter, bool msix) { int err; int numvecs, i; + if (!msix) + goto msi_only; + /* Number of supported queues. */ adapter->num_rx_queues = adapter->rss_queues; if (adapter->vfs_allocated_count) @@ -1038,7 +999,7 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter) adapter->msix_entries, numvecs); if (err == 0) - goto out; + return; igb_reset_interrupt_capability(adapter); @@ -1068,105 +1029,183 @@ msi_only: adapter->num_q_vectors = 1; if (!pci_enable_msi(adapter->pdev)) adapter->flags |= IGB_FLAG_HAS_MSI; -out: - /* Notify the stack of the (possibly) reduced queue counts. */ - rtnl_lock(); - netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues); - err = netif_set_real_num_rx_queues(adapter->netdev, - adapter->num_rx_queues); - rtnl_unlock(); - return err; +} + +static void igb_add_ring(struct igb_ring *ring, + struct igb_ring_container *head) +{ + head->ring = ring; + head->count++; } /** - * igb_alloc_q_vectors - Allocate memory for interrupt vectors + * igb_alloc_q_vector - Allocate memory for a single interrupt vector * @adapter: board private structure to initialize + * @v_count: q_vectors allocated on adapter, used for ring interleaving + * @v_idx: index of vector in adapter struct + * @txr_count: total number of Tx rings to allocate + * @txr_idx: index of first Tx ring to allocate + * @rxr_count: total number of Rx rings to allocate + * @rxr_idx: index of first Rx ring to allocate * - * We allocate one q_vector per queue interrupt. If allocation fails we - * return -ENOMEM. + * We allocate one q_vector. If allocation fails we return -ENOMEM. **/ -static int igb_alloc_q_vectors(struct igb_adapter *adapter) +static int igb_alloc_q_vector(struct igb_adapter *adapter, + int v_count, int v_idx, + int txr_count, int txr_idx, + int rxr_count, int rxr_idx) { struct igb_q_vector *q_vector; - struct e1000_hw *hw = &adapter->hw; - int v_idx; + struct igb_ring *ring; + int ring_count, size; - for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) { - q_vector = kzalloc(sizeof(struct igb_q_vector), - GFP_KERNEL); - if (!q_vector) - goto err_out; - q_vector->adapter = adapter; - q_vector->itr_register = hw->hw_addr + E1000_EITR(0); - q_vector->itr_val = IGB_START_ITR; - netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64); - adapter->q_vector[v_idx] = q_vector; + /* igb only supports 1 Tx and/or 1 Rx queue per vector */ + if (txr_count > 1 || rxr_count > 1) + return -ENOMEM; + + ring_count = txr_count + rxr_count; + size = sizeof(struct igb_q_vector) + + (sizeof(struct igb_ring) * ring_count); + + /* allocate q_vector and rings */ + q_vector = kzalloc(size, GFP_KERNEL); + if (!q_vector) + return -ENOMEM; + + /* initialize NAPI */ + netif_napi_add(adapter->netdev, &q_vector->napi, + igb_poll, 64); + + /* tie q_vector and adapter together */ + adapter->q_vector[v_idx] = q_vector; + q_vector->adapter = adapter; + + /* initialize work limits */ + q_vector->tx.work_limit = adapter->tx_work_limit; + + /* initialize ITR configuration */ + q_vector->itr_register = adapter->hw.hw_addr + E1000_EITR(0); + q_vector->itr_val = IGB_START_ITR; + + /* initialize pointer to rings */ + ring = q_vector->ring; + + if (txr_count) { + /* assign generic ring traits */ + ring->dev = &adapter->pdev->dev; + ring->netdev = adapter->netdev; + + /* configure backlink on ring */ + ring->q_vector = q_vector; + + /* update q_vector Tx values */ + igb_add_ring(ring, &q_vector->tx); + + /* For 82575, context index must be unique per ring. */ + if (adapter->hw.mac.type == e1000_82575) + set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags); + + /* apply Tx specific ring traits */ + ring->count = adapter->tx_ring_count; + ring->queue_index = txr_idx; + + /* assign ring to adapter */ + adapter->tx_ring[txr_idx] = ring; + + /* push pointer to next ring */ + ring++; } - return 0; + if (rxr_count) { + /* assign generic ring traits */ + ring->dev = &adapter->pdev->dev; + ring->netdev = adapter->netdev; -err_out: - igb_free_q_vectors(adapter); - return -ENOMEM; -} + /* configure backlink on ring */ + ring->q_vector = q_vector; -static void igb_map_rx_ring_to_vector(struct igb_adapter *adapter, - int ring_idx, int v_idx) -{ - struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; + /* update q_vector Rx values */ + igb_add_ring(ring, &q_vector->rx); - q_vector->rx.ring = adapter->rx_ring[ring_idx]; - q_vector->rx.ring->q_vector = q_vector; - q_vector->rx.count++; - q_vector->itr_val = adapter->rx_itr_setting; - if (q_vector->itr_val && q_vector->itr_val <= 3) - q_vector->itr_val = IGB_START_ITR; -} + /* set flag indicating ring supports SCTP checksum offload */ + if (adapter->hw.mac.type >= e1000_82576) + set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); -static void igb_map_tx_ring_to_vector(struct igb_adapter *adapter, - int ring_idx, int v_idx) -{ - struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; + /* + * On i350, i210, and i211, loopback VLAN packets + * have the tag byte-swapped. + * */ + if (adapter->hw.mac.type >= e1000_i350) + set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags); - q_vector->tx.ring = adapter->tx_ring[ring_idx]; - q_vector->tx.ring->q_vector = q_vector; - q_vector->tx.count++; - q_vector->itr_val = adapter->tx_itr_setting; - q_vector->tx.work_limit = adapter->tx_work_limit; - if (q_vector->itr_val && q_vector->itr_val <= 3) - q_vector->itr_val = IGB_START_ITR; + /* apply Rx specific ring traits */ + ring->count = adapter->rx_ring_count; + ring->queue_index = rxr_idx; + + /* assign ring to adapter */ + adapter->rx_ring[rxr_idx] = ring; + } + + return 0; } + /** - * igb_map_ring_to_vector - maps allocated queues to vectors + * igb_alloc_q_vectors - Allocate memory for interrupt vectors + * @adapter: board private structure to initialize * - * This function maps the recently allocated queues to vectors. + * We allocate one q_vector per queue interrupt. If allocation fails we + * return -ENOMEM. **/ -static int igb_map_ring_to_vector(struct igb_adapter *adapter) +static int igb_alloc_q_vectors(struct igb_adapter *adapter) { - int i; - int v_idx = 0; + int q_vectors = adapter->num_q_vectors; + int rxr_remaining = adapter->num_rx_queues; + int txr_remaining = adapter->num_tx_queues; + int rxr_idx = 0, txr_idx = 0, v_idx = 0; + int err; - if ((adapter->num_q_vectors < adapter->num_rx_queues) || - (adapter->num_q_vectors < adapter->num_tx_queues)) - return -ENOMEM; + if (q_vectors >= (rxr_remaining + txr_remaining)) { + for (; rxr_remaining; v_idx++) { + err = igb_alloc_q_vector(adapter, q_vectors, v_idx, + 0, 0, 1, rxr_idx); - if (adapter->num_q_vectors >= - (adapter->num_rx_queues + adapter->num_tx_queues)) { - for (i = 0; i < adapter->num_rx_queues; i++) - igb_map_rx_ring_to_vector(adapter, i, v_idx++); - for (i = 0; i < adapter->num_tx_queues; i++) - igb_map_tx_ring_to_vector(adapter, i, v_idx++); - } else { - for (i = 0; i < adapter->num_rx_queues; i++) { - if (i < adapter->num_tx_queues) - igb_map_tx_ring_to_vector(adapter, i, v_idx); - igb_map_rx_ring_to_vector(adapter, i, v_idx++); + if (err) + goto err_out; + + /* update counts and index */ + rxr_remaining--; + rxr_idx++; } - for (; i < adapter->num_tx_queues; i++) - igb_map_tx_ring_to_vector(adapter, i, v_idx++); } + + for (; v_idx < q_vectors; v_idx++) { + int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx); + int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx); + err = igb_alloc_q_vector(adapter, q_vectors, v_idx, + tqpv, txr_idx, rqpv, rxr_idx); + + if (err) + goto err_out; + + /* update counts and index */ + rxr_remaining -= rqpv; + txr_remaining -= tqpv; + rxr_idx++; + txr_idx++; + } + return 0; + +err_out: + adapter->num_tx_queues = 0; + adapter->num_rx_queues = 0; + adapter->num_q_vectors = 0; + + while (v_idx--) + igb_free_q_vector(adapter, v_idx); + + return -ENOMEM; } /** @@ -1174,14 +1213,12 @@ static int igb_map_ring_to_vector(struct igb_adapter *adapter) * * This function initializes the interrupts and allocates all of the queues. **/ -static int igb_init_interrupt_scheme(struct igb_adapter *adapter) +static int igb_init_interrupt_scheme(struct igb_adapter *adapter, bool msix) { struct pci_dev *pdev = adapter->pdev; int err; - err = igb_set_interrupt_capability(adapter); - if (err) - return err; + igb_set_interrupt_capability(adapter, msix); err = igb_alloc_q_vectors(adapter); if (err) { @@ -1189,24 +1226,10 @@ static int igb_init_interrupt_scheme(struct igb_adapter *adapter) goto err_alloc_q_vectors; } - err = igb_alloc_queues(adapter); - if (err) { - dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); - goto err_alloc_queues; - } - - err = igb_map_ring_to_vector(adapter); - if (err) { - dev_err(&pdev->dev, "Invalid q_vector to ring mapping\n"); - goto err_map_queues; - } - + igb_cache_ring_register(adapter); return 0; -err_map_queues: - igb_free_queues(adapter); -err_alloc_queues: - igb_free_q_vectors(adapter); + err_alloc_q_vectors: igb_reset_interrupt_capability(adapter); return err; @@ -1229,29 +1252,17 @@ static int igb_request_irq(struct igb_adapter *adapter) if (!err) goto request_done; /* fall back to MSI */ - igb_clear_interrupt_scheme(adapter); - if (!pci_enable_msi(pdev)) - adapter->flags |= IGB_FLAG_HAS_MSI; igb_free_all_tx_resources(adapter); igb_free_all_rx_resources(adapter); - adapter->num_tx_queues = 1; - adapter->num_rx_queues = 1; - adapter->num_q_vectors = 1; - err = igb_alloc_q_vectors(adapter); - if (err) { - dev_err(&pdev->dev, - "Unable to allocate memory for vectors\n"); - goto request_done; - } - err = igb_alloc_queues(adapter); - if (err) { - dev_err(&pdev->dev, - "Unable to allocate memory for queues\n"); - igb_free_q_vectors(adapter); + + igb_clear_interrupt_scheme(adapter); + err = igb_init_interrupt_scheme(adapter, false); + if (err) goto request_done; - } + igb_setup_all_tx_resources(adapter); igb_setup_all_rx_resources(adapter); + igb_configure(adapter); } igb_assign_vector(adapter->q_vector[0], 0); @@ -1587,8 +1598,7 @@ void igb_reset(struct igb_adapter *adapter) struct e1000_hw *hw = &adapter->hw; struct e1000_mac_info *mac = &hw->mac; struct e1000_fc_info *fc = &hw->fc; - u32 pba = 0, tx_space, min_tx_space, min_rx_space; - u16 hwm; + u32 pba = 0, tx_space, min_tx_space, min_rx_space, hwm; /* Repartition Pba for greater than 9k mtu * To take effect CTRL.RST is required. @@ -1663,7 +1673,7 @@ void igb_reset(struct igb_adapter *adapter) hwm = min(((pba << 10) * 9 / 10), ((pba << 10) - 2 * adapter->max_frame_size)); - fc->high_water = hwm & 0xFFF0; /* 16-byte granularity */ + fc->high_water = hwm & 0xFFFFFFF0; /* 16-byte granularity */ fc->low_water = fc->high_water - 16; fc->pause_time = 0xFFFF; fc->send_xon = 1; @@ -1706,10 +1716,8 @@ void igb_reset(struct igb_adapter *adapter) /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE); -#ifdef CONFIG_IGB_PTP /* Re-enable PTP, where applicable. */ igb_ptp_reset(adapter); -#endif /* CONFIG_IGB_PTP */ igb_get_phy_info(hw); } @@ -1783,58 +1791,34 @@ static const struct net_device_ops igb_netdev_ops = { void igb_set_fw_version(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; - u16 eeprom_verh, eeprom_verl, comb_verh, comb_verl, comb_offset; - u16 major, build, patch, fw_version; - u32 etrack_id; - - hw->nvm.ops.read(hw, 5, 1, &fw_version); - if (adapter->hw.mac.type != e1000_i211) { - hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verh); - hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verl); - etrack_id = (eeprom_verh << IGB_ETRACK_SHIFT) | eeprom_verl; - - /* combo image version needs to be found */ - hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset); - if ((comb_offset != 0x0) && - (comb_offset != IGB_NVM_VER_INVALID)) { - hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset - + 1), 1, &comb_verh); - hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset), - 1, &comb_verl); - - /* Only display Option Rom if it exists and is valid */ - if ((comb_verh && comb_verl) && - ((comb_verh != IGB_NVM_VER_INVALID) && - (comb_verl != IGB_NVM_VER_INVALID))) { - major = comb_verl >> IGB_COMB_VER_SHFT; - build = (comb_verl << IGB_COMB_VER_SHFT) | - (comb_verh >> IGB_COMB_VER_SHFT); - patch = comb_verh & IGB_COMB_VER_MASK; - snprintf(adapter->fw_version, - sizeof(adapter->fw_version), - "%d.%d%d, 0x%08x, %d.%d.%d", - (fw_version & IGB_MAJOR_MASK) >> - IGB_MAJOR_SHIFT, - (fw_version & IGB_MINOR_MASK) >> - IGB_MINOR_SHIFT, - (fw_version & IGB_BUILD_MASK), - etrack_id, major, build, patch); - goto out; - } - } - snprintf(adapter->fw_version, sizeof(adapter->fw_version), - "%d.%d%d, 0x%08x", - (fw_version & IGB_MAJOR_MASK) >> IGB_MAJOR_SHIFT, - (fw_version & IGB_MINOR_MASK) >> IGB_MINOR_SHIFT, - (fw_version & IGB_BUILD_MASK), etrack_id); - } else { + struct e1000_fw_version fw; + + igb_get_fw_version(hw, &fw); + + switch (hw->mac.type) { + case e1000_i211: snprintf(adapter->fw_version, sizeof(adapter->fw_version), - "%d.%d%d", - (fw_version & IGB_MAJOR_MASK) >> IGB_MAJOR_SHIFT, - (fw_version & IGB_MINOR_MASK) >> IGB_MINOR_SHIFT, - (fw_version & IGB_BUILD_MASK)); + "%2d.%2d-%d", + fw.invm_major, fw.invm_minor, fw.invm_img_type); + break; + + default: + /* if option is rom valid, display its version too */ + if (fw.or_valid) { + snprintf(adapter->fw_version, + sizeof(adapter->fw_version), + "%d.%d, 0x%08x, %d.%d.%d", + fw.eep_major, fw.eep_minor, fw.etrack_id, + fw.or_major, fw.or_build, fw.or_patch); + /* no option rom */ + } else { + snprintf(adapter->fw_version, + sizeof(adapter->fw_version), + "%d.%d, 0x%08x", + fw.eep_major, fw.eep_minor, fw.etrack_id); + } + break; } -out: return; } @@ -1849,8 +1833,7 @@ out: * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. **/ -static int __devinit igb_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct igb_adapter *adapter; @@ -1861,7 +1844,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, const struct e1000_info *ei = igb_info_tbl[ent->driver_data]; unsigned long mmio_start, mmio_len; int err, pci_using_dac; - u16 eeprom_apme_mask = IGB_EEPROM_APME; u8 part_str[E1000_PBANUM_LENGTH]; /* Catch broken hardware that put the wrong VF device ID in @@ -2069,28 +2051,27 @@ static int __devinit igb_probe(struct pci_dev *pdev, igb_validate_mdi_setting(hw); - /* Initial Wake on LAN setting If APM wake is enabled in the EEPROM, - * enable the ACPI Magic Packet filter - */ - + /* By default, support wake on port A */ if (hw->bus.func == 0) - hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); - else if (hw->mac.type >= e1000_82580) + adapter->flags |= IGB_FLAG_WOL_SUPPORTED; + + /* Check the NVM for wake support on non-port A ports */ + if (hw->mac.type >= e1000_82580) hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, &eeprom_data); else if (hw->bus.func == 1) hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); - if (eeprom_data & eeprom_apme_mask) - adapter->eeprom_wol |= E1000_WUFC_MAG; + if (eeprom_data & IGB_EEPROM_APME) + adapter->flags |= IGB_FLAG_WOL_SUPPORTED; /* now that we have the eeprom settings, apply the special cases where * the eeprom may be wrong or the board simply won't support wake on * lan on a particular port */ switch (pdev->device) { case E1000_DEV_ID_82575GB_QUAD_COPPER: - adapter->eeprom_wol = 0; + adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; break; case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82576_FIBER: @@ -2098,24 +2079,38 @@ static int __devinit igb_probe(struct pci_dev *pdev, /* Wake events only supported on port A for dual fiber * regardless of eeprom setting */ if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) - adapter->eeprom_wol = 0; + adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; break; case E1000_DEV_ID_82576_QUAD_COPPER: case E1000_DEV_ID_82576_QUAD_COPPER_ET2: /* if quad port adapter, disable WoL on all but port A */ if (global_quad_port_a != 0) - adapter->eeprom_wol = 0; + adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; else adapter->flags |= IGB_FLAG_QUAD_PORT_A; /* Reset for multiple quad port adapters */ if (++global_quad_port_a == 4) global_quad_port_a = 0; break; + default: + /* If the device can't wake, don't set software support */ + if (!device_can_wakeup(&adapter->pdev->dev)) + adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; } /* initialize the wol settings based on the eeprom settings */ - adapter->wol = adapter->eeprom_wol; - device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + if (adapter->flags & IGB_FLAG_WOL_SUPPORTED) + adapter->wol |= E1000_WUFC_MAG; + + /* Some vendors want WoL disabled by default, but still supported */ + if ((hw->mac.type == e1000_i350) && + (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)) { + adapter->flags |= IGB_FLAG_WOL_SUPPORTED; + adapter->wol = 0; + } + + device_set_wakeup_enable(&adapter->pdev->dev, + adapter->flags & IGB_FLAG_WOL_SUPPORTED); /* reset the hardware with the new settings */ igb_reset(adapter); @@ -2141,10 +2136,8 @@ static int __devinit igb_probe(struct pci_dev *pdev, #endif -#ifdef CONFIG_IGB_PTP /* do hw tstamp init after resetting */ igb_ptp_init(adapter); -#endif /* CONFIG_IGB_PTP */ dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n"); /* print bus type/speed/width info */ @@ -2212,16 +2205,14 @@ err_dma: * Hot-Plug event, or because the driver is going to be removed from * memory. **/ -static void __devexit igb_remove(struct pci_dev *pdev) +static void igb_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; pm_runtime_get_noresume(&pdev->dev); -#ifdef CONFIG_IGB_PTP igb_ptp_stop(adapter); -#endif /* CONFIG_IGB_PTP */ /* * The watchdog timer may be rescheduled, so explicitly @@ -2294,7 +2285,7 @@ static void __devexit igb_remove(struct pci_dev *pdev) * mor expensive time wise to disable SR-IOV than it is to allocate and free * the memory for the VFs. **/ -static void __devinit igb_probe_vfs(struct igb_adapter * adapter) +static void igb_probe_vfs(struct igb_adapter *adapter) { #ifdef CONFIG_PCI_IOV struct pci_dev *pdev = adapter->pdev; @@ -2355,7 +2346,7 @@ out: * Fields are initialized based on PCI device information and * OS network device settings (MTU size). **/ -static int __devinit igb_sw_init(struct igb_adapter *adapter) +static int igb_sw_init(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; @@ -2461,7 +2452,7 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) GFP_ATOMIC); /* This call may decrease the number of queues */ - if (igb_init_interrupt_scheme(adapter)) { + if (igb_init_interrupt_scheme(adapter, true)) { dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); return -ENOMEM; } @@ -2531,6 +2522,17 @@ static int __igb_open(struct net_device *netdev, bool resuming) if (err) goto err_req_irq; + /* Notify the stack of the actual queue counts. */ + err = netif_set_real_num_tx_queues(adapter->netdev, + adapter->num_tx_queues); + if (err) + goto err_set_queues; + + err = netif_set_real_num_rx_queues(adapter->netdev, + adapter->num_rx_queues); + if (err) + goto err_set_queues; + /* From here on the code is the same as igb_up() */ clear_bit(__IGB_DOWN, &adapter->state); @@ -2560,6 +2562,8 @@ static int __igb_open(struct net_device *netdev, bool resuming) return 0; +err_set_queues: + igb_free_irq(adapter); err_req_irq: igb_release_hw_control(adapter); igb_power_down_link(adapter); @@ -2637,10 +2641,8 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring) tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); tx_ring->size = ALIGN(tx_ring->size, 4096); - tx_ring->desc = dma_alloc_coherent(dev, - tx_ring->size, - &tx_ring->dma, - GFP_KERNEL); + tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size, + &tx_ring->dma, GFP_KERNEL); if (!tx_ring->desc) goto err; @@ -2777,18 +2779,16 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring) if (!rx_ring->rx_buffer_info) goto err; - /* Round up to nearest 4K */ rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc); rx_ring->size = ALIGN(rx_ring->size, 4096); - rx_ring->desc = dma_alloc_coherent(dev, - rx_ring->size, - &rx_ring->dma, - GFP_KERNEL); + rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, + &rx_ring->dma, GFP_KERNEL); if (!rx_ring->desc) goto err; + rx_ring->next_to_alloc = 0; rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; @@ -2893,18 +2893,21 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) /* Don't need to set TUOFL or IPOFL, they default to 1 */ wr32(E1000_RXCSUM, rxcsum); - /* - * Generate RSS hash based on TCP port numbers and/or - * IPv4/v6 src and dst addresses since UDP cannot be - * hashed reliably due to IP fragmentation - */ + /* Generate RSS hash based on packet types, TCP/UDP + * port numbers and/or IPv4/v6 src and dst addresses + */ 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; + if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP) + mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP; + if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP) + mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP; + /* If VMDq is enabled then we set the appropriate mode for that, else * we default to RSS so that an RSS hash is calculated per packet even * if we are only using one queue */ @@ -3106,16 +3109,10 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, /* set descriptor configuration */ srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT; -#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384 - srrctl |= IGB_RXBUFFER_16384 >> E1000_SRRCTL_BSIZEPKT_SHIFT; -#else - srrctl |= (PAGE_SIZE / 2) >> E1000_SRRCTL_BSIZEPKT_SHIFT; -#endif - srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; -#ifdef CONFIG_IGB_PTP + srrctl |= IGB_RX_BUFSZ >> E1000_SRRCTL_BSIZEPKT_SHIFT; + srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; if (hw->mac.type >= e1000_82580) srrctl |= E1000_SRRCTL_TIMESTAMP; -#endif /* CONFIG_IGB_PTP */ /* Only set Drop Enable if we are supporting multiple queues */ if (adapter->vfs_allocated_count || adapter->num_rx_queues > 1) srrctl |= E1000_SRRCTL_DROP_EN; @@ -3305,36 +3302,27 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring) unsigned long size; u16 i; + if (rx_ring->skb) + dev_kfree_skb(rx_ring->skb); + rx_ring->skb = NULL; + if (!rx_ring->rx_buffer_info) return; /* Free all the Rx ring sk_buffs */ for (i = 0; i < rx_ring->count; i++) { struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i]; - if (buffer_info->dma) { - dma_unmap_single(rx_ring->dev, - buffer_info->dma, - IGB_RX_HDR_LEN, - DMA_FROM_DEVICE); - buffer_info->dma = 0; - } - if (buffer_info->skb) { - dev_kfree_skb(buffer_info->skb); - buffer_info->skb = NULL; - } - if (buffer_info->page_dma) { - dma_unmap_page(rx_ring->dev, - buffer_info->page_dma, - PAGE_SIZE / 2, - DMA_FROM_DEVICE); - buffer_info->page_dma = 0; - } - if (buffer_info->page) { - put_page(buffer_info->page); - buffer_info->page = NULL; - buffer_info->page_offset = 0; - } + if (!buffer_info->page) + continue; + + dma_unmap_page(rx_ring->dev, + buffer_info->dma, + PAGE_SIZE, + DMA_FROM_DEVICE); + __free_page(buffer_info->page); + + buffer_info->page = NULL; } size = sizeof(struct igb_rx_buffer) * rx_ring->count; @@ -3343,6 +3331,7 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring) /* Zero out the descriptor ring */ memset(rx_ring->desc, 0, rx_ring->size); + rx_ring->next_to_alloc = 0; rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; } @@ -4028,6 +4017,9 @@ static int igb_tso(struct igb_ring *tx_ring, u32 vlan_macip_lens, type_tucmd; u32 mss_l4len_idx, l4len; + if (skb->ip_summed != CHECKSUM_PARTIAL) + return 0; + if (!skb_is_gso(skb)) return 0; @@ -4148,26 +4140,32 @@ static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first) igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx); } -static __le32 igb_tx_cmd_type(u32 tx_flags) +#define IGB_SET_FLAG(_input, _flag, _result) \ + ((_flag <= _result) ? \ + ((u32)(_input & _flag) * (_result / _flag)) : \ + ((u32)(_input & _flag) / (_flag / _result))) + +static u32 igb_tx_cmd_type(struct sk_buff *skb, u32 tx_flags) { /* set type for advanced descriptor with frame checksum insertion */ - __le32 cmd_type = cpu_to_le32(E1000_ADVTXD_DTYP_DATA | - E1000_ADVTXD_DCMD_IFCS | - E1000_ADVTXD_DCMD_DEXT); + u32 cmd_type = E1000_ADVTXD_DTYP_DATA | + E1000_ADVTXD_DCMD_DEXT | + E1000_ADVTXD_DCMD_IFCS; /* set HW vlan bit if vlan is present */ - if (tx_flags & IGB_TX_FLAGS_VLAN) - cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_VLE); + cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_VLAN, + (E1000_ADVTXD_DCMD_VLE)); + + /* set segmentation bits for TSO */ + cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSO, + (E1000_ADVTXD_DCMD_TSE)); -#ifdef CONFIG_IGB_PTP /* set timestamp bit if present */ - if (unlikely(tx_flags & IGB_TX_FLAGS_TSTAMP)) - cmd_type |= cpu_to_le32(E1000_ADVTXD_MAC_TSTAMP); -#endif /* CONFIG_IGB_PTP */ + cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSTAMP, + (E1000_ADVTXD_MAC_TSTAMP)); - /* set segmentation bits for TSO */ - if (tx_flags & IGB_TX_FLAGS_TSO) - cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_TSE); + /* insert frame checksum */ + cmd_type ^= IGB_SET_FLAG(skb->no_fcs, 1, E1000_ADVTXD_DCMD_IFCS); return cmd_type; } @@ -4178,19 +4176,19 @@ static void igb_tx_olinfo_status(struct igb_ring *tx_ring, { u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT; - /* 82575 requires a unique index per ring if any offload is enabled */ - if ((tx_flags & (IGB_TX_FLAGS_CSUM | IGB_TX_FLAGS_VLAN)) && - test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) + /* 82575 requires a unique index per ring */ + if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) olinfo_status |= tx_ring->reg_idx << 4; /* insert L4 checksum */ - if (tx_flags & IGB_TX_FLAGS_CSUM) { - olinfo_status |= E1000_TXD_POPTS_TXSM << 8; + olinfo_status |= IGB_SET_FLAG(tx_flags, + IGB_TX_FLAGS_CSUM, + (E1000_TXD_POPTS_TXSM << 8)); - /* insert IPv4 checksum */ - if (tx_flags & IGB_TX_FLAGS_IPV4) - olinfo_status |= E1000_TXD_POPTS_IXSM << 8; - } + /* insert IPv4 checksum */ + olinfo_status |= IGB_SET_FLAG(tx_flags, + IGB_TX_FLAGS_IPV4, + (E1000_TXD_POPTS_IXSM << 8)); tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); } @@ -4209,33 +4207,37 @@ static void igb_tx_map(struct igb_ring *tx_ring, struct sk_buff *skb = first->skb; struct igb_tx_buffer *tx_buffer; union e1000_adv_tx_desc *tx_desc; + struct skb_frag_struct *frag; dma_addr_t dma; - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; - unsigned int data_len = skb->data_len; - unsigned int size = skb_headlen(skb); - unsigned int paylen = skb->len - hdr_len; - __le32 cmd_type; + unsigned int data_len, size; u32 tx_flags = first->tx_flags; + u32 cmd_type = igb_tx_cmd_type(skb, tx_flags); u16 i = tx_ring->next_to_use; tx_desc = IGB_TX_DESC(tx_ring, i); - igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, paylen); - cmd_type = igb_tx_cmd_type(tx_flags); + igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, skb->len - hdr_len); + + size = skb_headlen(skb); + data_len = skb->data_len; dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE); - if (dma_mapping_error(tx_ring->dev, dma)) - goto dma_error; - /* record length, and DMA address */ - dma_unmap_len_set(first, len, size); - dma_unmap_addr_set(first, dma, dma); - tx_desc->read.buffer_addr = cpu_to_le64(dma); + tx_buffer = first; + + for (frag = &skb_shinfo(skb)->frags[0];; frag++) { + if (dma_mapping_error(tx_ring->dev, dma)) + goto dma_error; + + /* record length, and DMA address */ + dma_unmap_len_set(tx_buffer, len, size); + dma_unmap_addr_set(tx_buffer, dma, dma); + + tx_desc->read.buffer_addr = cpu_to_le64(dma); - for (;;) { while (unlikely(size > IGB_MAX_DATA_PER_TXD)) { tx_desc->read.cmd_type_len = - cmd_type | cpu_to_le32(IGB_MAX_DATA_PER_TXD); + cpu_to_le32(cmd_type ^ IGB_MAX_DATA_PER_TXD); i++; tx_desc++; @@ -4243,18 +4245,18 @@ static void igb_tx_map(struct igb_ring *tx_ring, tx_desc = IGB_TX_DESC(tx_ring, 0); i = 0; } + tx_desc->read.olinfo_status = 0; dma += IGB_MAX_DATA_PER_TXD; size -= IGB_MAX_DATA_PER_TXD; - tx_desc->read.olinfo_status = 0; tx_desc->read.buffer_addr = cpu_to_le64(dma); } if (likely(!data_len)) break; - tx_desc->read.cmd_type_len = cmd_type | cpu_to_le32(size); + tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type ^ size); i++; tx_desc++; @@ -4262,32 +4264,22 @@ static void igb_tx_map(struct igb_ring *tx_ring, tx_desc = IGB_TX_DESC(tx_ring, 0); i = 0; } + tx_desc->read.olinfo_status = 0; size = skb_frag_size(frag); data_len -= size; dma = skb_frag_dma_map(tx_ring->dev, frag, 0, - size, DMA_TO_DEVICE); - if (dma_mapping_error(tx_ring->dev, dma)) - goto dma_error; + size, DMA_TO_DEVICE); tx_buffer = &tx_ring->tx_buffer_info[i]; - dma_unmap_len_set(tx_buffer, len, size); - dma_unmap_addr_set(tx_buffer, dma, dma); - - tx_desc->read.olinfo_status = 0; - tx_desc->read.buffer_addr = cpu_to_le64(dma); - - frag++; } - netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); - /* write last descriptor with RS and EOP bits */ - cmd_type |= cpu_to_le32(size) | cpu_to_le32(IGB_TXD_DCMD); - if (unlikely(skb->no_fcs)) - cmd_type &= ~(cpu_to_le32(E1000_ADVTXD_DCMD_IFCS)); - tx_desc->read.cmd_type_len = cmd_type; + cmd_type |= size | IGB_TXD_DCMD; + tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); + + netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); /* set the timestamp */ first->time_stamp = jiffies; @@ -4372,9 +4364,7 @@ static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size) netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, struct igb_ring *tx_ring) { -#ifdef CONFIG_IGB_PTP struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); -#endif /* CONFIG_IGB_PTP */ struct igb_tx_buffer *first; int tso; u32 tx_flags = 0; @@ -4397,7 +4387,6 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, first->bytecount = skb->len; first->gso_segs = 1; -#ifdef CONFIG_IGB_PTP if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && !(adapter->ptp_tx_skb))) { skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; @@ -4407,7 +4396,6 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, if (adapter->hw.mac.type == e1000_82576) schedule_work(&adapter->ptp_tx_work); } -#endif /* CONFIG_IGB_PTP */ if (vlan_tx_tag_present(skb)) { tx_flags |= IGB_TX_FLAGS_VLAN; @@ -4467,10 +4455,11 @@ static netdev_tx_t igb_xmit_frame(struct sk_buff *skb, * The minimum packet size with TCTL.PSP set is 17 so pad the skb * in order to meet this minimum size requirement. */ - if (skb->len < 17) { - if (skb_padto(skb, 17)) + if (unlikely(skb->len < 17)) { + if (skb_pad(skb, 17 - skb->len)) return NETDEV_TX_OK; skb->len = 17; + skb_set_tail_pointer(skb, 17); } return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb)); @@ -4800,7 +4789,6 @@ static irqreturn_t igb_msix_other(int irq, void *data) mod_timer(&adapter->watchdog_timer, jiffies + 1); } -#ifdef CONFIG_IGB_PTP if (icr & E1000_ICR_TS) { u32 tsicr = rd32(E1000_TSICR); @@ -4811,7 +4799,6 @@ static irqreturn_t igb_msix_other(int irq, void *data) schedule_work(&adapter->ptp_tx_work); } } -#endif /* CONFIG_IGB_PTP */ wr32(E1000_EIMS, adapter->eims_other); @@ -4851,45 +4838,63 @@ static irqreturn_t igb_msix_ring(int irq, void *data) } #ifdef CONFIG_IGB_DCA +static void igb_update_tx_dca(struct igb_adapter *adapter, + struct igb_ring *tx_ring, + int cpu) +{ + struct e1000_hw *hw = &adapter->hw; + u32 txctrl = dca3_get_tag(tx_ring->dev, cpu); + + if (hw->mac.type != e1000_82575) + txctrl <<= E1000_DCA_TXCTRL_CPUID_SHIFT; + + /* + * We can enable relaxed ordering for reads, but not writes when + * DCA is enabled. This is due to a known issue in some chipsets + * which will cause the DCA tag to be cleared. + */ + txctrl |= E1000_DCA_TXCTRL_DESC_RRO_EN | + E1000_DCA_TXCTRL_DATA_RRO_EN | + E1000_DCA_TXCTRL_DESC_DCA_EN; + + wr32(E1000_DCA_TXCTRL(tx_ring->reg_idx), txctrl); +} + +static void igb_update_rx_dca(struct igb_adapter *adapter, + struct igb_ring *rx_ring, + int cpu) +{ + struct e1000_hw *hw = &adapter->hw; + u32 rxctrl = dca3_get_tag(&adapter->pdev->dev, cpu); + + if (hw->mac.type != e1000_82575) + rxctrl <<= E1000_DCA_RXCTRL_CPUID_SHIFT; + + /* + * We can enable relaxed ordering for reads, but not writes when + * DCA is enabled. This is due to a known issue in some chipsets + * which will cause the DCA tag to be cleared. + */ + rxctrl |= E1000_DCA_RXCTRL_DESC_RRO_EN | + E1000_DCA_RXCTRL_DESC_DCA_EN; + + wr32(E1000_DCA_RXCTRL(rx_ring->reg_idx), rxctrl); +} + static void igb_update_dca(struct igb_q_vector *q_vector) { struct igb_adapter *adapter = q_vector->adapter; - struct e1000_hw *hw = &adapter->hw; int cpu = get_cpu(); if (q_vector->cpu == cpu) goto out_no_update; - if (q_vector->tx.ring) { - int q = q_vector->tx.ring->reg_idx; - u32 dca_txctrl = rd32(E1000_DCA_TXCTRL(q)); - if (hw->mac.type == e1000_82575) { - dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK; - dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); - } else { - dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576; - dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) << - E1000_DCA_TXCTRL_CPUID_SHIFT; - } - dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN; - wr32(E1000_DCA_TXCTRL(q), dca_txctrl); - } - if (q_vector->rx.ring) { - int q = q_vector->rx.ring->reg_idx; - u32 dca_rxctrl = rd32(E1000_DCA_RXCTRL(q)); - if (hw->mac.type == e1000_82575) { - dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK; - dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); - } else { - dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576; - dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) << - E1000_DCA_RXCTRL_CPUID_SHIFT; - } - dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN; - dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN; - dca_rxctrl |= E1000_DCA_RXCTRL_DATA_DCA_EN; - wr32(E1000_DCA_RXCTRL(q), dca_rxctrl); - } + if (q_vector->tx.ring) + igb_update_tx_dca(adapter, q_vector->tx.ring, cpu); + + if (q_vector->rx.ring) + igb_update_rx_dca(adapter, q_vector->rx.ring, cpu); + q_vector->cpu = cpu; out_no_update: put_cpu(); @@ -5545,7 +5550,6 @@ static irqreturn_t igb_intr_msi(int irq, void *data) mod_timer(&adapter->watchdog_timer, jiffies + 1); } -#ifdef CONFIG_IGB_PTP if (icr & E1000_ICR_TS) { u32 tsicr = rd32(E1000_TSICR); @@ -5556,7 +5560,6 @@ static irqreturn_t igb_intr_msi(int irq, void *data) schedule_work(&adapter->ptp_tx_work); } } -#endif /* CONFIG_IGB_PTP */ napi_schedule(&q_vector->napi); @@ -5599,7 +5602,6 @@ static irqreturn_t igb_intr(int irq, void *data) mod_timer(&adapter->watchdog_timer, jiffies + 1); } -#ifdef CONFIG_IGB_PTP if (icr & E1000_ICR_TS) { u32 tsicr = rd32(E1000_TSICR); @@ -5610,7 +5612,6 @@ static irqreturn_t igb_intr(int irq, void *data) schedule_work(&adapter->ptp_tx_work); } } -#endif /* CONFIG_IGB_PTP */ napi_schedule(&q_vector->napi); @@ -5840,6 +5841,181 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) return !!budget; } +/** + * igb_reuse_rx_page - page flip buffer and store it back on the ring + * @rx_ring: rx descriptor ring to store buffers on + * @old_buff: donor buffer to have page reused + * + * Synchronizes page for reuse by the adapter + **/ +static void igb_reuse_rx_page(struct igb_ring *rx_ring, + struct igb_rx_buffer *old_buff) +{ + struct igb_rx_buffer *new_buff; + u16 nta = rx_ring->next_to_alloc; + + new_buff = &rx_ring->rx_buffer_info[nta]; + + /* update, and store next to alloc */ + nta++; + rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0; + + /* transfer page from old buffer to new buffer */ + memcpy(new_buff, old_buff, sizeof(struct igb_rx_buffer)); + + /* sync the buffer for use by the device */ + dma_sync_single_range_for_device(rx_ring->dev, old_buff->dma, + old_buff->page_offset, + IGB_RX_BUFSZ, + DMA_FROM_DEVICE); +} + +/** + * igb_add_rx_frag - Add contents of Rx buffer to sk_buff + * @rx_ring: rx descriptor ring to transact packets on + * @rx_buffer: buffer containing page to add + * @rx_desc: descriptor containing length of buffer written by hardware + * @skb: sk_buff to place the data into + * + * This function will add the data contained in rx_buffer->page to the skb. + * This is done either through a direct copy if the data in the buffer is + * less than the skb header size, otherwise it will just attach the page as + * a frag to the skb. + * + * The function will then update the page offset if necessary and return + * true if the buffer can be reused by the adapter. + **/ +static bool igb_add_rx_frag(struct igb_ring *rx_ring, + struct igb_rx_buffer *rx_buffer, + union e1000_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + struct page *page = rx_buffer->page; + unsigned int size = le16_to_cpu(rx_desc->wb.upper.length); + + if ((size <= IGB_RX_HDR_LEN) && !skb_is_nonlinear(skb)) { + unsigned char *va = page_address(page) + rx_buffer->page_offset; + + if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { + igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb); + va += IGB_TS_HDR_LEN; + size -= IGB_TS_HDR_LEN; + } + + memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long))); + + /* we can reuse buffer as-is, just make sure it is local */ + if (likely(page_to_nid(page) == numa_node_id())) + return true; + + /* this page cannot be reused so discard it */ + put_page(page); + return false; + } + + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, + rx_buffer->page_offset, size, IGB_RX_BUFSZ); + + /* avoid re-using remote pages */ + if (unlikely(page_to_nid(page) != numa_node_id())) + return false; + +#if (PAGE_SIZE < 8192) + /* if we are only owner of page we can reuse it */ + if (unlikely(page_count(page) != 1)) + return false; + + /* flip page offset to other buffer */ + rx_buffer->page_offset ^= IGB_RX_BUFSZ; + + /* + * since we are the only owner of the page and we need to + * increment it, just set the value to 2 in order to avoid + * an unnecessary locked operation + */ + atomic_set(&page->_count, 2); +#else + /* move offset up to the next cache line */ + rx_buffer->page_offset += SKB_DATA_ALIGN(size); + + if (rx_buffer->page_offset > (PAGE_SIZE - IGB_RX_BUFSZ)) + return false; + + /* bump ref count on page before it is given to the stack */ + get_page(page); +#endif + + return true; +} + +static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring, + union e1000_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + struct igb_rx_buffer *rx_buffer; + struct page *page; + + rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; + + /* + * This memory barrier is needed to keep us from reading + * any other fields out of the rx_desc until we know the + * RXD_STAT_DD bit is set + */ + rmb(); + + page = rx_buffer->page; + prefetchw(page); + + if (likely(!skb)) { + void *page_addr = page_address(page) + + rx_buffer->page_offset; + + /* prefetch first cache line of first page */ + prefetch(page_addr); +#if L1_CACHE_BYTES < 128 + prefetch(page_addr + L1_CACHE_BYTES); +#endif + + /* allocate a skb to store the frags */ + skb = netdev_alloc_skb_ip_align(rx_ring->netdev, + IGB_RX_HDR_LEN); + if (unlikely(!skb)) { + rx_ring->rx_stats.alloc_failed++; + return NULL; + } + + /* + * we will be copying header into skb->data in + * pskb_may_pull so it is in our interest to prefetch + * it now to avoid a possible cache miss + */ + prefetchw(skb->data); + } + + /* we are reusing so sync this buffer for CPU use */ + dma_sync_single_range_for_cpu(rx_ring->dev, + rx_buffer->dma, + rx_buffer->page_offset, + IGB_RX_BUFSZ, + DMA_FROM_DEVICE); + + /* pull page into skb */ + if (igb_add_rx_frag(rx_ring, rx_buffer, rx_desc, skb)) { + /* hand second half of page back to the ring */ + igb_reuse_rx_page(rx_ring, rx_buffer); + } else { + /* we are not reusing the buffer so unmap it */ + dma_unmap_page(rx_ring->dev, rx_buffer->dma, + PAGE_SIZE, DMA_FROM_DEVICE); + } + + /* clear contents of rx_buffer */ + rx_buffer->page = NULL; + + return skb; +} + static inline void igb_rx_checksum(struct igb_ring *ring, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) @@ -5889,224 +6065,389 @@ static inline void igb_rx_hash(struct igb_ring *ring, skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss); } -static void igb_rx_vlan(struct igb_ring *ring, - union e1000_adv_rx_desc *rx_desc, - struct sk_buff *skb) +/** + * igb_is_non_eop - process handling of non-EOP buffers + * @rx_ring: Rx ring being processed + * @rx_desc: Rx descriptor for current buffer + * @skb: current socket buffer containing buffer in progress + * + * This function updates next to clean. If the buffer is an EOP buffer + * this function exits returning false, otherwise it will place the + * sk_buff in the next buffer to be chained and return true indicating + * that this is in fact a non-EOP buffer. + **/ +static bool igb_is_non_eop(struct igb_ring *rx_ring, + union e1000_adv_rx_desc *rx_desc) { - if (igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) { - u16 vid; - if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) && - test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags)) - vid = be16_to_cpu(rx_desc->wb.upper.vlan); - else - vid = le16_to_cpu(rx_desc->wb.upper.vlan); + u32 ntc = rx_ring->next_to_clean + 1; - __vlan_hwaccel_put_tag(skb, vid); - } + /* fetch, update, and store next to clean */ + ntc = (ntc < rx_ring->count) ? ntc : 0; + rx_ring->next_to_clean = ntc; + + prefetch(IGB_RX_DESC(rx_ring, ntc)); + + if (likely(igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP))) + return false; + + return true; } -static inline u16 igb_get_hlen(union e1000_adv_rx_desc *rx_desc) -{ - /* HW will not DMA in data larger than the given buffer, even if it - * parses the (NFS, of course) header to be larger. In that case, it - * fills the header buffer and spills the rest into the page. +/** + * igb_get_headlen - determine size of header for LRO/GRO + * @data: pointer to the start of the headers + * @max_len: total length of section to find headers in + * + * This function is meant to determine the length of headers that will + * be recognized by hardware for LRO, and GRO offloads. The main + * motivation of doing this is to only perform one pull for IPv4 TCP + * packets so that we can do basic things like calculating the gso_size + * based on the average data per packet. + **/ +static unsigned int igb_get_headlen(unsigned char *data, + unsigned int max_len) +{ + union { + unsigned char *network; + /* l2 headers */ + struct ethhdr *eth; + struct vlan_hdr *vlan; + /* l3 headers */ + struct iphdr *ipv4; + struct ipv6hdr *ipv6; + } hdr; + __be16 protocol; + u8 nexthdr = 0; /* default to not TCP */ + u8 hlen; + + /* this should never happen, but better safe than sorry */ + if (max_len < ETH_HLEN) + return max_len; + + /* initialize network frame pointer */ + hdr.network = data; + + /* set first protocol and move network header forward */ + protocol = hdr.eth->h_proto; + hdr.network += ETH_HLEN; + + /* handle any vlan tag if present */ + if (protocol == __constant_htons(ETH_P_8021Q)) { + if ((hdr.network - data) > (max_len - VLAN_HLEN)) + return max_len; + + protocol = hdr.vlan->h_vlan_encapsulated_proto; + hdr.network += VLAN_HLEN; + } + + /* handle L3 protocols */ + if (protocol == __constant_htons(ETH_P_IP)) { + if ((hdr.network - data) > (max_len - sizeof(struct iphdr))) + return max_len; + + /* access ihl as a u8 to avoid unaligned access on ia64 */ + hlen = (hdr.network[0] & 0x0F) << 2; + + /* verify hlen meets minimum size requirements */ + if (hlen < sizeof(struct iphdr)) + return hdr.network - data; + + /* record next protocol if header is present */ + if (!hdr.ipv4->frag_off) + nexthdr = hdr.ipv4->protocol; + } else if (protocol == __constant_htons(ETH_P_IPV6)) { + if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr))) + return max_len; + + /* record next protocol */ + nexthdr = hdr.ipv6->nexthdr; + hlen = sizeof(struct ipv6hdr); + } else { + return hdr.network - data; + } + + /* relocate pointer to start of L4 header */ + hdr.network += hlen; + + /* finally sort out TCP */ + if (nexthdr == IPPROTO_TCP) { + if ((hdr.network - data) > (max_len - sizeof(struct tcphdr))) + return max_len; + + /* access doff as a u8 to avoid unaligned access on ia64 */ + hlen = (hdr.network[12] & 0xF0) >> 2; + + /* verify hlen meets minimum size requirements */ + if (hlen < sizeof(struct tcphdr)) + return hdr.network - data; + + hdr.network += hlen; + } else if (nexthdr == IPPROTO_UDP) { + if ((hdr.network - data) > (max_len - sizeof(struct udphdr))) + return max_len; + + hdr.network += sizeof(struct udphdr); + } + + /* + * If everything has gone correctly hdr.network should be the + * data section of the packet and will be the end of the header. + * If not then it probably represents the end of the last recognized + * header. */ - u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) & - E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; - if (hlen > IGB_RX_HDR_LEN) - hlen = IGB_RX_HDR_LEN; - return hlen; + if ((hdr.network - data) < max_len) + return hdr.network - data; + else + return max_len; } -static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget) +/** + * igb_pull_tail - igb specific version of skb_pull_tail + * @rx_ring: rx descriptor ring packet is being transacted on + * @rx_desc: pointer to the EOP Rx descriptor + * @skb: pointer to current skb being adjusted + * + * This function is an igb specific version of __pskb_pull_tail. The + * main difference between this version and the original function is that + * this function can make several assumptions about the state of things + * that allow for significant optimizations versus the standard function. + * As a result we can do things like drop a frag and maintain an accurate + * truesize for the skb. + */ +static void igb_pull_tail(struct igb_ring *rx_ring, + union e1000_adv_rx_desc *rx_desc, + struct sk_buff *skb) { - struct igb_ring *rx_ring = q_vector->rx.ring; - union e1000_adv_rx_desc *rx_desc; - const int current_node = numa_node_id(); - unsigned int total_bytes = 0, total_packets = 0; - u16 cleaned_count = igb_desc_unused(rx_ring); - u16 i = rx_ring->next_to_clean; + struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; + unsigned char *va; + unsigned int pull_len; - rx_desc = IGB_RX_DESC(rx_ring, i); + /* + * it is valid to use page_address instead of kmap since we are + * working with pages allocated out of the lomem pool per + * alloc_page(GFP_ATOMIC) + */ + va = skb_frag_address(frag); - while (igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) { - struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i]; - struct sk_buff *skb = buffer_info->skb; - union e1000_adv_rx_desc *next_rxd; + if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { + /* retrieve timestamp from buffer */ + igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb); - buffer_info->skb = NULL; - prefetch(skb->data); + /* update pointers to remove timestamp header */ + skb_frag_size_sub(frag, IGB_TS_HDR_LEN); + frag->page_offset += IGB_TS_HDR_LEN; + skb->data_len -= IGB_TS_HDR_LEN; + skb->len -= IGB_TS_HDR_LEN; - i++; - if (i == rx_ring->count) - i = 0; + /* move va to start of packet data */ + va += IGB_TS_HDR_LEN; + } - next_rxd = IGB_RX_DESC(rx_ring, i); - prefetch(next_rxd); + /* + * we need the header to contain the greater of either ETH_HLEN or + * 60 bytes if the skb->len is less than 60 for skb_pad. + */ + pull_len = igb_get_headlen(va, IGB_RX_HDR_LEN); - /* - * This memory barrier is needed to keep us from reading - * any other fields out of the rx_desc until we know the - * RXD_STAT_DD bit is set - */ - rmb(); + /* align pull length to size of long to optimize memcpy performance */ + skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long))); - if (!skb_is_nonlinear(skb)) { - __skb_put(skb, igb_get_hlen(rx_desc)); - dma_unmap_single(rx_ring->dev, buffer_info->dma, - IGB_RX_HDR_LEN, - DMA_FROM_DEVICE); - buffer_info->dma = 0; + /* update all of the pointers */ + skb_frag_size_sub(frag, pull_len); + frag->page_offset += pull_len; + skb->data_len -= pull_len; + skb->tail += pull_len; +} + +/** + * igb_cleanup_headers - Correct corrupted or empty headers + * @rx_ring: rx descriptor ring packet is being transacted on + * @rx_desc: pointer to the EOP Rx descriptor + * @skb: pointer to current skb being fixed + * + * Address the case where we are pulling data in on pages only + * and as such no data is present in the skb header. + * + * In addition if skb is not at least 60 bytes we need to pad it so that + * it is large enough to qualify as a valid Ethernet frame. + * + * Returns true if an error was encountered and skb was freed. + **/ +static bool igb_cleanup_headers(struct igb_ring *rx_ring, + union e1000_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + + if (unlikely((igb_test_staterr(rx_desc, + E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) { + struct net_device *netdev = rx_ring->netdev; + if (!(netdev->features & NETIF_F_RXALL)) { + dev_kfree_skb_any(skb); + return true; } + } - if (rx_desc->wb.upper.length) { - u16 length = le16_to_cpu(rx_desc->wb.upper.length); + /* place header in linear portion of buffer */ + if (skb_is_nonlinear(skb)) + igb_pull_tail(rx_ring, rx_desc, skb); - skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, - buffer_info->page, - buffer_info->page_offset, - length); + /* if skb_pad returns an error the skb was freed */ + if (unlikely(skb->len < 60)) { + int pad_len = 60 - skb->len; - skb->len += length; - skb->data_len += length; - skb->truesize += PAGE_SIZE / 2; + if (skb_pad(skb, pad_len)) + return true; + __skb_put(skb, pad_len); + } - if ((page_count(buffer_info->page) != 1) || - (page_to_nid(buffer_info->page) != current_node)) - buffer_info->page = NULL; - else - get_page(buffer_info->page); + return false; +} - dma_unmap_page(rx_ring->dev, buffer_info->page_dma, - PAGE_SIZE / 2, DMA_FROM_DEVICE); - buffer_info->page_dma = 0; - } +/** + * igb_process_skb_fields - Populate skb header fields from Rx descriptor + * @rx_ring: rx descriptor ring packet is being transacted on + * @rx_desc: pointer to the EOP Rx descriptor + * @skb: pointer to current skb being populated + * + * This function checks the ring, descriptor, and packet information in + * order to populate the hash, checksum, VLAN, timestamp, protocol, and + * other fields within the skb. + **/ +static void igb_process_skb_fields(struct igb_ring *rx_ring, + union e1000_adv_rx_desc *rx_desc, + struct sk_buff *skb) +{ + struct net_device *dev = rx_ring->netdev; - if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)) { - struct igb_rx_buffer *next_buffer; - next_buffer = &rx_ring->rx_buffer_info[i]; - buffer_info->skb = next_buffer->skb; - buffer_info->dma = next_buffer->dma; - next_buffer->skb = skb; - next_buffer->dma = 0; - goto next_desc; - } + igb_rx_hash(rx_ring, rx_desc, skb); - if (unlikely((igb_test_staterr(rx_desc, - E1000_RXDEXT_ERR_FRAME_ERR_MASK)) - && !(rx_ring->netdev->features & NETIF_F_RXALL))) { - dev_kfree_skb_any(skb); - goto next_desc; - } + igb_rx_checksum(rx_ring, rx_desc, skb); -#ifdef CONFIG_IGB_PTP - igb_ptp_rx_hwtstamp(q_vector, rx_desc, skb); -#endif /* CONFIG_IGB_PTP */ - igb_rx_hash(rx_ring, rx_desc, skb); - igb_rx_checksum(rx_ring, rx_desc, skb); - igb_rx_vlan(rx_ring, rx_desc, skb); + igb_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb); - total_bytes += skb->len; - total_packets++; + if ((dev->features & NETIF_F_HW_VLAN_RX) && + igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) { + u16 vid; + if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) && + test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags)) + vid = be16_to_cpu(rx_desc->wb.upper.vlan); + else + vid = le16_to_cpu(rx_desc->wb.upper.vlan); - skb->protocol = eth_type_trans(skb, rx_ring->netdev); + __vlan_hwaccel_put_tag(skb, vid); + } - napi_gro_receive(&q_vector->napi, skb); + skb_record_rx_queue(skb, rx_ring->queue_index); - budget--; -next_desc: - if (!budget) - break; + skb->protocol = eth_type_trans(skb, rx_ring->netdev); +} + +static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) +{ + struct igb_ring *rx_ring = q_vector->rx.ring; + struct sk_buff *skb = rx_ring->skb; + unsigned int total_bytes = 0, total_packets = 0; + u16 cleaned_count = igb_desc_unused(rx_ring); + + do { + union e1000_adv_rx_desc *rx_desc; - cleaned_count++; /* return some buffers to hardware, one at a time is too slow */ if (cleaned_count >= IGB_RX_BUFFER_WRITE) { igb_alloc_rx_buffers(rx_ring, cleaned_count); cleaned_count = 0; } - /* use prefetched values */ - rx_desc = next_rxd; - } + rx_desc = IGB_RX_DESC(rx_ring, rx_ring->next_to_clean); - rx_ring->next_to_clean = i; - u64_stats_update_begin(&rx_ring->rx_syncp); - rx_ring->rx_stats.packets += total_packets; - rx_ring->rx_stats.bytes += total_bytes; - u64_stats_update_end(&rx_ring->rx_syncp); - q_vector->rx.total_packets += total_packets; - q_vector->rx.total_bytes += total_bytes; + if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) + break; - if (cleaned_count) - igb_alloc_rx_buffers(rx_ring, cleaned_count); + /* retrieve a buffer from the ring */ + skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb); - return !!budget; -} + /* exit if we failed to retrieve a buffer */ + if (!skb) + break; -static bool igb_alloc_mapped_skb(struct igb_ring *rx_ring, - struct igb_rx_buffer *bi) -{ - struct sk_buff *skb = bi->skb; - dma_addr_t dma = bi->dma; + cleaned_count++; - if (dma) - return true; + /* fetch next buffer in frame if non-eop */ + if (igb_is_non_eop(rx_ring, rx_desc)) + continue; - if (likely(!skb)) { - skb = netdev_alloc_skb_ip_align(rx_ring->netdev, - IGB_RX_HDR_LEN); - bi->skb = skb; - if (!skb) { - rx_ring->rx_stats.alloc_failed++; - return false; + /* verify the packet layout is correct */ + if (igb_cleanup_headers(rx_ring, rx_desc, skb)) { + skb = NULL; + continue; } - /* initialize skb for ring */ - skb_record_rx_queue(skb, rx_ring->queue_index); - } + /* probably a little skewed due to removing CRC */ + total_bytes += skb->len; - dma = dma_map_single(rx_ring->dev, skb->data, - IGB_RX_HDR_LEN, DMA_FROM_DEVICE); + /* populate checksum, timestamp, VLAN, and protocol */ + igb_process_skb_fields(rx_ring, rx_desc, skb); - if (dma_mapping_error(rx_ring->dev, dma)) { - rx_ring->rx_stats.alloc_failed++; - return false; - } + napi_gro_receive(&q_vector->napi, skb); - bi->dma = dma; - return true; + /* reset skb pointer */ + skb = NULL; + + /* update budget accounting */ + total_packets++; + } while (likely(total_packets < budget)); + + /* place incomplete frames back on ring for completion */ + rx_ring->skb = skb; + + u64_stats_update_begin(&rx_ring->rx_syncp); + rx_ring->rx_stats.packets += total_packets; + rx_ring->rx_stats.bytes += total_bytes; + u64_stats_update_end(&rx_ring->rx_syncp); + q_vector->rx.total_packets += total_packets; + q_vector->rx.total_bytes += total_bytes; + + if (cleaned_count) + igb_alloc_rx_buffers(rx_ring, cleaned_count); + + return (total_packets < budget); } static bool igb_alloc_mapped_page(struct igb_ring *rx_ring, struct igb_rx_buffer *bi) { struct page *page = bi->page; - dma_addr_t page_dma = bi->page_dma; - unsigned int page_offset = bi->page_offset ^ (PAGE_SIZE / 2); + dma_addr_t dma; - if (page_dma) + /* since we are recycling buffers we should seldom need to alloc */ + if (likely(page)) return true; - if (!page) { - page = __skb_alloc_page(GFP_ATOMIC, bi->skb); - bi->page = page; - if (unlikely(!page)) { - rx_ring->rx_stats.alloc_failed++; - return false; - } + /* alloc new page for storage */ + page = __skb_alloc_page(GFP_ATOMIC | __GFP_COLD, NULL); + if (unlikely(!page)) { + rx_ring->rx_stats.alloc_failed++; + return false; } - page_dma = dma_map_page(rx_ring->dev, page, - page_offset, PAGE_SIZE / 2, - DMA_FROM_DEVICE); + /* map page for use */ + dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); + + /* + * if mapping failed free memory back to system since + * there isn't much point in holding memory we can't use + */ + if (dma_mapping_error(rx_ring->dev, dma)) { + __free_page(page); - if (dma_mapping_error(rx_ring->dev, page_dma)) { rx_ring->rx_stats.alloc_failed++; return false; } - bi->page_dma = page_dma; - bi->page_offset = page_offset; + bi->dma = dma; + bi->page = page; + bi->page_offset = 0; + return true; } @@ -6120,22 +6461,23 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count) struct igb_rx_buffer *bi; u16 i = rx_ring->next_to_use; + /* nothing to do */ + if (!cleaned_count) + return; + rx_desc = IGB_RX_DESC(rx_ring, i); bi = &rx_ring->rx_buffer_info[i]; i -= rx_ring->count; - while (cleaned_count--) { - if (!igb_alloc_mapped_skb(rx_ring, bi)) - break; - - /* Refresh the desc even if buffer_addrs didn't change - * because each write-back erases this info. */ - rx_desc->read.hdr_addr = cpu_to_le64(bi->dma); - + do { if (!igb_alloc_mapped_page(rx_ring, bi)) break; - rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma); + /* + * Refresh the desc even if buffer_addrs didn't change + * because each write-back erases this info. + */ + rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); rx_desc++; bi++; @@ -6148,17 +6490,25 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count) /* clear the hdr_addr for the next_to_use descriptor */ rx_desc->read.hdr_addr = 0; - } + + cleaned_count--; + } while (cleaned_count); i += rx_ring->count; if (rx_ring->next_to_use != i) { + /* record the next descriptor to use */ rx_ring->next_to_use = i; - /* Force memory writes to complete before letting h/w + /* update next to alloc since we have filled the ring */ + rx_ring->next_to_alloc = i; + + /* + * Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only * applicable for weak-ordered memory model archs, - * such as IA-64). */ + * such as IA-64). + */ wmb(); writel(i, rx_ring->tail); } @@ -6207,10 +6557,8 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) case SIOCGMIIREG: case SIOCSMIIREG: return igb_mii_ioctl(netdev, ifr, cmd); -#ifdef CONFIG_IGB_PTP case SIOCSHWTSTAMP: return igb_ptp_hwtstamp_ioctl(netdev, ifr, cmd); -#endif /* CONFIG_IGB_PTP */ default: return -EOPNOTSUPP; } @@ -6478,7 +6826,7 @@ static int igb_resume(struct device *dev) pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3cold, 0); - if (igb_init_interrupt_scheme(adapter)) { + if (igb_init_interrupt_scheme(adapter, true)) { dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); return -ENOMEM; } @@ -6492,7 +6840,9 @@ static int igb_resume(struct device *dev) wr32(E1000_WUS, ~0); if (netdev->flags & IFF_UP) { + rtnl_lock(); err = __igb_open(netdev, true); + rtnl_unlock(); if (err) return err; } diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index ee21445157a3..ab3429729bde 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -441,18 +441,46 @@ void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter) adapter->ptp_tx_skb = NULL; } -void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector, - union e1000_adv_rx_desc *rx_desc, +/** + * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp + * @q_vector: Pointer to interrupt specific structure + * @va: Pointer to address containing Rx buffer + * @skb: Buffer containing timestamp and packet + * + * This function is meant to retrieve a timestamp from the first buffer of an + * incoming frame. The value is stored in little endian format starting on + * byte 8. + */ +void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, + unsigned char *va, + struct sk_buff *skb) +{ + __le64 *regval = (__le64 *)va; + + /* + * The timestamp is recorded in little endian format. + * DWORD: 0 1 2 3 + * Field: Reserved Reserved SYSTIML SYSTIMH + */ + igb_ptp_systim_to_hwtstamp(q_vector->adapter, skb_hwtstamps(skb), + le64_to_cpu(regval[1])); +} + +/** + * igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register + * @q_vector: Pointer to interrupt specific structure + * @skb: Buffer containing timestamp and packet + * + * This function is meant to retrieve a timestamp from the internal registers + * of the adapter and store it in the skb. + */ +void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb) { struct igb_adapter *adapter = q_vector->adapter; struct e1000_hw *hw = &adapter->hw; u64 regval; - if (!igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP | - E1000_RXDADV_STAT_TS)) - return; - /* * If this bit is set, then the RX registers contain the time stamp. No * other packet will be time stamped until we read these registers, so @@ -464,18 +492,11 @@ void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector, * If nothing went wrong, then it should have a shared tx_flags that we * can turn into a skb_shared_hwtstamps. */ - if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { - u32 *stamp = (u32 *)skb->data; - regval = le32_to_cpu(*(stamp + 2)); - regval |= (u64)le32_to_cpu(*(stamp + 3)) << 32; - skb_pull(skb, IGB_TS_HDR_LEN); - } else { - if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) - return; + if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) + return; - regval = rd32(E1000_RXSTMPL); - regval |= (u64)rd32(E1000_RXSTMPH) << 32; - } + regval = rd32(E1000_RXSTMPL); + regval |= (u64)rd32(E1000_RXSTMPH) << 32; igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); } @@ -532,18 +553,6 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, case HWTSTAMP_FILTER_NONE: tsync_rx_ctl = 0; break; - case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_ALL: - /* - * register TSYNCRXCFG must be set, therefore it is not - * possible to time stamp both Sync and Delay_Req messages - * => fall back to time stamping all packets - */ - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; - config.rx_filter = HWTSTAMP_FILTER_ALL; - break; case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE; @@ -554,31 +563,33 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE; is_l4 = true; break; + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; - tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE; - is_l2 = true; - is_l4 = true; - config.rx_filter = HWTSTAMP_FILTER_SOME; - break; + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; - tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE; - is_l2 = true; - is_l4 = true; - config.rx_filter = HWTSTAMP_FILTER_SOME; - break; - case HWTSTAMP_FILTER_PTP_V2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2; config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; is_l2 = true; is_l4 = true; break; + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_ALL: + /* 82576 cannot timestamp all packets, which it needs to do to + * support both V1 Sync and Delay_Req messages + */ + if (hw->mac.type != e1000_82576) { + tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; + config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + } + /* fall through */ default: + config.rx_filter = HWTSTAMP_FILTER_NONE; return -ERANGE; } @@ -596,6 +607,9 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) { tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; + config.rx_filter = HWTSTAMP_FILTER_ALL; + is_l2 = true; + is_l4 = true; if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { diff --git a/drivers/net/ethernet/intel/igbvf/defines.h b/drivers/net/ethernet/intel/igbvf/defines.h index 3e18045d8f89..d9fa999b1685 100644 --- a/drivers/net/ethernet/intel/igbvf/defines.h +++ b/drivers/net/ethernet/intel/igbvf/defines.h @@ -46,6 +46,7 @@ #define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ #define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ +#define E1000_RXDEXT_STATERR_LB 0x00040000 #define E1000_RXDEXT_STATERR_CE 0x01000000 #define E1000_RXDEXT_STATERR_SE 0x02000000 #define E1000_RXDEXT_STATERR_SEQ 0x04000000 diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h index a895e2f7b34d..fdca7b672776 100644 --- a/drivers/net/ethernet/intel/igbvf/igbvf.h +++ b/drivers/net/ethernet/intel/igbvf/igbvf.h @@ -295,7 +295,7 @@ struct igbvf_info { /* hardware capability, feature, and workaround flags */ #define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0) - +#define IGBVF_FLAG_RX_LB_VLAN_BSWAP (1 << 1) #define IGBVF_RX_DESC_ADV(R, i) \ (&((((R).desc))[i].rx_desc)) #define IGBVF_TX_DESC_ADV(R, i) \ diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 0ac11f527a84..277f5dfe3d90 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -47,7 +47,7 @@ #include "igbvf.h" -#define DRV_VERSION "2.0.1-k" +#define DRV_VERSION "2.0.2-k" char igbvf_driver_name[] = "igbvf"; const char igbvf_driver_version[] = DRV_VERSION; static const char igbvf_driver_string[] = @@ -107,12 +107,19 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter, struct sk_buff *skb, u32 status, u16 vlan) { + u16 vid; + if (status & E1000_RXD_STAT_VP) { - u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; + if ((adapter->flags & IGBVF_FLAG_RX_LB_VLAN_BSWAP) && + (status & E1000_RXDEXT_STATERR_LB)) + vid = be16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; + else + vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; if (test_bit(vid, adapter->active_vlans)) __vlan_hwaccel_put_tag(skb, vid); } - netif_receive_skb(skb); + + napi_gro_receive(&adapter->rx_ring->napi, skb); } static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter, @@ -184,6 +191,13 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring, buffer_info->page_offset, PAGE_SIZE / 2, DMA_FROM_DEVICE); + if (dma_mapping_error(&pdev->dev, + buffer_info->page_dma)) { + __free_page(buffer_info->page); + buffer_info->page = NULL; + dev_err(&pdev->dev, "RX DMA map failed\n"); + break; + } } if (!buffer_info->skb) { @@ -197,6 +211,12 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring, buffer_info->dma = dma_map_single(&pdev->dev, skb->data, bufsz, DMA_FROM_DEVICE); + if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { + dev_kfree_skb(buffer_info->skb); + buffer_info->skb = NULL; + dev_err(&pdev->dev, "RX DMA map failed\n"); + goto no_buffers; + } } /* Refresh the desc even if buffer_addrs didn't change because * each write-back erases this info. */ @@ -1078,7 +1098,7 @@ out: * igbvf_alloc_queues - Allocate memory for all rings * @adapter: board private structure to initialize **/ -static int __devinit igbvf_alloc_queues(struct igbvf_adapter *adapter) +static int igbvf_alloc_queues(struct igbvf_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -1530,7 +1550,7 @@ void igbvf_reinit_locked(struct igbvf_adapter *adapter) * Fields are initialized based on PCI device information and * OS network device settings (MTU size). **/ -static int __devinit igbvf_sw_init(struct igbvf_adapter *adapter) +static int igbvf_sw_init(struct igbvf_adapter *adapter) { struct net_device *netdev = adapter->netdev; s32 rc; @@ -2598,8 +2618,7 @@ static const struct net_device_ops igbvf_netdev_ops = { * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. **/ -static int __devinit igbvf_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct igbvf_adapter *adapter; @@ -2754,6 +2773,10 @@ static int __devinit igbvf_probe(struct pci_dev *pdev, /* reset the hardware with the new settings */ igbvf_reset(adapter); + /* set hardware-specific flags */ + if (adapter->hw.mac.type == e1000_vfadapt_i350) + adapter->flags |= IGBVF_FLAG_RX_LB_VLAN_BSWAP; + strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) @@ -2794,7 +2817,7 @@ err_dma: * Hot-Plug event, or because the driver is going to be removed from * memory. **/ -static void __devexit igbvf_remove(struct pci_dev *pdev) +static void igbvf_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct igbvf_adapter *adapter = netdev_priv(netdev); @@ -2851,7 +2874,7 @@ static struct pci_driver igbvf_driver = { .name = igbvf_driver_name, .id_table = igbvf_pci_tbl, .probe = igbvf_probe, - .remove = __devexit_p(igbvf_remove), + .remove = igbvf_remove, #ifdef CONFIG_PM /* Power Management Hooks */ .suspend = igbvf_suspend, diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c index d99a2d51b948..ae96c10251be 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -73,7 +73,7 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl); static int ixgb_init_module(void); static void ixgb_exit_module(void); static int ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent); -static void __devexit ixgb_remove(struct pci_dev *pdev); +static void ixgb_remove(struct pci_dev *pdev); static int ixgb_sw_init(struct ixgb_adapter *adapter); static int ixgb_open(struct net_device *netdev); static int ixgb_close(struct net_device *netdev); @@ -125,7 +125,7 @@ static struct pci_driver ixgb_driver = { .name = ixgb_driver_name, .id_table = ixgb_pci_tbl, .probe = ixgb_probe, - .remove = __devexit_p(ixgb_remove), + .remove = ixgb_remove, .err_handler = &ixgb_err_handler }; @@ -391,7 +391,7 @@ static const struct net_device_ops ixgb_netdev_ops = { * and a hardware reset occur. **/ -static int __devinit +static int ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev = NULL; @@ -558,7 +558,7 @@ err_dma_mask: * memory. **/ -static void __devexit +static void ixgb_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -584,7 +584,7 @@ ixgb_remove(struct pci_dev *pdev) * OS network device settings (MTU size). **/ -static int __devinit +static int ixgb_sw_init(struct ixgb_adapter *adapter) { struct ixgb_hw *hw = &adapter->hw; diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_param.c b/drivers/net/ethernet/intel/ixgb/ixgb_param.c index 07d83ab46e21..04a60640ddda 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_param.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_param.c @@ -47,7 +47,7 @@ #define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET } #define IXGB_PARAM(X, desc) \ - static int __devinitdata X[IXGB_MAX_NIC+1] \ + static int X[IXGB_MAX_NIC+1] \ = IXGB_PARAM_INIT; \ static unsigned int num_##X = 0; \ module_param_array_named(X, X, int, &num_##X, 0); \ @@ -199,7 +199,7 @@ struct ixgb_option { } arg; }; -static int __devinit +static int ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt) { if (*value == OPTION_UNSET) { @@ -257,7 +257,7 @@ ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt) * in a variable in the adapter structure. **/ -void __devinit +void ixgb_check_options(struct ixgb_adapter *adapter) { int bd = adapter->bd_number; diff --git a/drivers/net/ethernet/intel/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile index 89f40e51fc13..687c83d1bdab 100644 --- a/drivers/net/ethernet/intel/ixgbe/Makefile +++ b/drivers/net/ethernet/intel/ixgbe/Makefile @@ -32,13 +32,13 @@ obj-$(CONFIG_IXGBE) += ixgbe.o -ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o ixgbe_debugfs.o\ +ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \ - ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o + ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o ixgbe_ptp.o ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \ ixgbe_dcb_82599.o ixgbe_dcb_nl.o -ixgbe-$(CONFIG_IXGBE_PTP) += ixgbe_ptp.o ixgbe-$(CONFIG_IXGBE_HWMON) += ixgbe_sysfs.o +ixgbe-$(CONFIG_DEBUG_FS) += ixgbe_debugfs.o ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 30efc9f0f47a..8e786764c60e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -36,11 +36,9 @@ #include <linux/aer.h> #include <linux/if_vlan.h> -#ifdef CONFIG_IXGBE_PTP #include <linux/clocksource.h> #include <linux/net_tstamp.h> #include <linux/ptp_clock_kernel.h> -#endif /* CONFIG_IXGBE_PTP */ #include "ixgbe_type.h" #include "ixgbe_common.h" @@ -135,6 +133,7 @@ struct vf_data_storage { u16 tx_rate; u16 vlan_count; u8 spoofchk_enabled; + unsigned int vf_api; }; struct vf_macvlans { @@ -482,8 +481,9 @@ struct ixgbe_adapter { #define IXGBE_FLAG2_FDIR_REQUIRES_REINIT (u32)(1 << 7) #define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP (u32)(1 << 8) #define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP (u32)(1 << 9) -#define IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED (u32)(1 << 10) +#define IXGBE_FLAG2_PTP_ENABLED (u32)(1 << 10) #define IXGBE_FLAG2_PTP_PPS_ENABLED (u32)(1 << 11) +#define IXGBE_FLAG2_BRIDGE_MODE_VEB (u32)(1 << 12) /* Tx fast path data */ int num_tx_queues; @@ -571,7 +571,6 @@ struct ixgbe_adapter { u32 interrupt_event; u32 led_reg; -#ifdef CONFIG_IXGBE_PTP struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_caps; unsigned long last_overflow_check; @@ -580,8 +579,6 @@ struct ixgbe_adapter { struct timecounter tc; int rx_hwtstamp_filter; u32 base_incval; - u32 cycle_speed; -#endif /* CONFIG_IXGBE_PTP */ /* SR-IOV */ DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS); @@ -600,6 +597,8 @@ struct ixgbe_adapter { #ifdef CONFIG_DEBUG_FS struct dentry *ixgbe_dbg_adapter; #endif /*CONFIG_DEBUG_FS*/ + + u8 default_up; }; struct ixgbe_fdir_filter { @@ -691,6 +690,7 @@ extern s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw, u16 soft_id); extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, union ixgbe_atr_input *mask); +extern bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw); extern void ixgbe_set_rx_mode(struct net_device *netdev); #ifdef CONFIG_IXGBE_DCB extern void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter); @@ -739,7 +739,6 @@ static inline struct netdev_queue *txring_txq(const struct ixgbe_ring *ring) return netdev_get_tx_queue(ring->netdev, ring->queue_index); } -#ifdef CONFIG_IXGBE_PTP extern void ixgbe_ptp_init(struct ixgbe_adapter *adapter); extern void ixgbe_ptp_stop(struct ixgbe_adapter *adapter); extern void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter); @@ -751,7 +750,7 @@ extern void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, extern int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, struct ifreq *ifr, int cmd); extern void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter); +extern void ixgbe_ptp_reset(struct ixgbe_adapter *adapter); extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr); -#endif /* CONFIG_IXGBE_PTP */ #endif /* _IXGBE_H_ */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 1077cb2b38db..1073aea5da40 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -62,7 +62,6 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, bool autoneg, bool autoneg_wait_to_complete); static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); -static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw); static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) { @@ -99,9 +98,8 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) { s32 ret_val = 0; - u32 reg_anlp1 = 0; - u32 i = 0; u16 list_offset, data_offset, data_value; + bool got_lock = false; if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) { ixgbe_init_mac_link_ops_82599(hw); @@ -137,28 +135,36 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) usleep_range(hw->eeprom.semaphore_delay * 1000, hw->eeprom.semaphore_delay * 2000); - /* Now restart DSP by setting Restart_AN and clearing LMS */ - IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((IXGBE_READ_REG(hw, - IXGBE_AUTOC) & ~IXGBE_AUTOC_LMS_MASK) | - IXGBE_AUTOC_AN_RESTART)); - - /* Wait for AN to leave state 0 */ - for (i = 0; i < 10; i++) { - usleep_range(4000, 8000); - reg_anlp1 = IXGBE_READ_REG(hw, IXGBE_ANLP1); - if (reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK) - break; + /* Need SW/FW semaphore around AUTOC writes if LESM on, + * likewise reset_pipeline requires lock as it also writes + * AUTOC. + */ + if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { + ret_val = hw->mac.ops.acquire_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); + if (ret_val) + goto setup_sfp_out; + + got_lock = true; + } + + /* Restart DSP and set SFI mode */ + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw, + IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL)); + + ret_val = ixgbe_reset_pipeline_82599(hw); + + if (got_lock) { + hw->mac.ops.release_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); + got_lock = false; } - if (!(reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)) { - hw_dbg(hw, "sfp module setup not complete\n"); + + if (ret_val) { + hw_dbg(hw, " sfp module setup not complete\n"); ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE; goto setup_sfp_out; } - - /* Restart DSP by setting Restart_AN and return to SFI mode */ - IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw, - IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL | - IXGBE_AUTOC_AN_RESTART)); } setup_sfp_out: @@ -394,14 +400,26 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, u32 links_reg; u32 i; s32 status = 0; + bool got_lock = false; + + if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { + status = hw->mac.ops.acquire_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); + if (status) + goto out; + + got_lock = true; + } /* Restart link */ - autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); - autoc_reg |= IXGBE_AUTOC_AN_RESTART; - IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); + ixgbe_reset_pipeline_82599(hw); + + if (got_lock) + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); /* Only poll for autoneg to complete if specified to do so */ if (autoneg_wait_to_complete) { + autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_KX_KR || (autoc_reg & IXGBE_AUTOC_LMS_MASK) == @@ -425,6 +443,7 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, /* Add delay to filter out noises during initial link setup */ msleep(50); +out: return status; } @@ -779,6 +798,7 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, u32 links_reg; u32 i; ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; + bool got_lock = false; /* Check to see if speed passed in is supported. */ status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities, @@ -836,9 +856,26 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, } if (autoc != start_autoc) { + /* Need SW/FW semaphore around AUTOC writes if LESM is on, + * likewise reset_pipeline requires us to hold this lock as + * it also writes to AUTOC. + */ + if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { + status = hw->mac.ops.acquire_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); + if (status != 0) + goto out; + + got_lock = true; + } + /* Restart link */ - autoc |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); + ixgbe_reset_pipeline_82599(hw); + + if (got_lock) + hw->mac.ops.release_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); /* Only poll for autoneg to complete if specified to do so */ if (autoneg_wait_to_complete) { @@ -994,9 +1031,28 @@ mac_reset_top: hw->mac.orig_autoc2 = autoc2; hw->mac.orig_link_settings_stored = true; } else { - if (autoc != hw->mac.orig_autoc) - IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc | - IXGBE_AUTOC_AN_RESTART)); + if (autoc != hw->mac.orig_autoc) { + /* Need SW/FW semaphore around AUTOC writes if LESM is + * on, likewise reset_pipeline requires us to hold + * this lock as it also writes to AUTOC. + */ + bool got_lock = false; + if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { + status = hw->mac.ops.acquire_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); + if (status) + goto reset_hw_out; + + got_lock = true; + } + + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc); + ixgbe_reset_pipeline_82599(hw); + + if (got_lock) + hw->mac.ops.release_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); + } if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) != (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) { @@ -1022,7 +1078,7 @@ mac_reset_top: hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); /* Add the SAN MAC address to the RAR only if it's a valid address */ - if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) { + if (is_valid_ether_addr(hw->mac.san_addr)) { hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1, hw->mac.san_addr, 0, IXGBE_RAH_AV); @@ -1983,7 +2039,7 @@ fw_version_out: * Returns true if the LESM FW module is present and enabled. Otherwise * returns false. Smart Speed must be disabled if LESM FW module is enabled. **/ -static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw) +bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw) { bool lesm_enabled = false; u16 fw_offset, fw_lesm_param_offset, fw_lesm_state; @@ -2080,6 +2136,50 @@ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw, return ret_val; } +/** + * ixgbe_reset_pipeline_82599 - perform pipeline reset + * + * @hw: pointer to hardware structure + * + * Reset pipeline by asserting Restart_AN together with LMS change to ensure + * full pipeline reset. Note - We must hold the SW/FW semaphore before writing + * to AUTOC, so this function assumes the semaphore is held. + **/ +s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw) +{ + s32 i, autoc_reg, ret_val; + s32 anlp1_reg = 0; + + autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); + autoc_reg |= IXGBE_AUTOC_AN_RESTART; + + /* Write AUTOC register with toggled LMS[2] bit and Restart_AN */ + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg ^ IXGBE_AUTOC_LMS_1G_AN); + + /* Wait for AN to leave state 0 */ + for (i = 0; i < 10; i++) { + usleep_range(4000, 8000); + anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); + if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK) + break; + } + + if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) { + hw_dbg(hw, "auto negotiation not completed\n"); + ret_val = IXGBE_ERR_RESET_FAILED; + goto reset_pipeline_out; + } + + ret_val = 0; + +reset_pipeline_out: + /* Write AUTOC register with original LMS field and Restart_AN */ + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); + IXGBE_WRITE_FLUSH(hw); + + return ret_val; +} + static struct ixgbe_mac_operations mac_ops_82599 = { .init_hw = &ixgbe_init_hw_generic, .reset_hw = &ixgbe_reset_hw_82599, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index dbf37e4a45fd..5e68afdd502a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -65,13 +65,12 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw); * function check the device id to see if the associated phy supports * autoneg flow control. **/ -static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) +s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) { switch (hw->device_id) { case IXGBE_DEV_ID_X540T: case IXGBE_DEV_ID_X540T1: - return 0; case IXGBE_DEV_ID_82599_T3_LOM: return 0; default: @@ -90,6 +89,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw) s32 ret_val = 0; u32 reg = 0, reg_bp = 0; u16 reg_cu = 0; + bool got_lock = false; /* * Validate the requested mode. Strict IEEE mode does not allow @@ -210,8 +210,29 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw) * */ if (hw->phy.media_type == ixgbe_media_type_backplane) { - reg_bp |= IXGBE_AUTOC_AN_RESTART; + /* Need the SW/FW semaphore around AUTOC writes if 82599 and + * LESM is on, likewise reset_pipeline requries the lock as + * it also writes AUTOC. + */ + if ((hw->mac.type == ixgbe_mac_82599EB) && + ixgbe_verify_lesm_fw_enabled_82599(hw)) { + ret_val = hw->mac.ops.acquire_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); + if (ret_val) + goto out; + + got_lock = true; + } + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp); + + if (hw->mac.type == ixgbe_mac_82599EB) + ixgbe_reset_pipeline_82599(hw); + + if (got_lock) + hw->mac.ops.release_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); + } else if ((hw->phy.media_type == ixgbe_media_type_copper) && (ixgbe_device_supports_autoneg_fc(hw) == 0)) { hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, @@ -1762,30 +1783,6 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) } /** - * ixgbe_validate_mac_addr - Validate MAC address - * @mac_addr: pointer to MAC address. - * - * Tests a MAC address to ensure it is a valid Individual Address - **/ -s32 ixgbe_validate_mac_addr(u8 *mac_addr) -{ - s32 status = 0; - - /* Make sure it is not a multicast address */ - if (IXGBE_IS_MULTICAST(mac_addr)) - status = IXGBE_ERR_INVALID_MAC_ADDR; - /* Not a broadcast address */ - else if (IXGBE_IS_BROADCAST(mac_addr)) - status = IXGBE_ERR_INVALID_MAC_ADDR; - /* Reject the zero address */ - else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && - mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) - status = IXGBE_ERR_INVALID_MAC_ADDR; - - return status; -} - -/** * ixgbe_set_rar_generic - Set Rx address register * @hw: pointer to hardware structure * @index: Receive address register to write @@ -1889,8 +1886,7 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) * to the permanent address. * Otherwise, use the permanent address from the eeprom. */ - if (ixgbe_validate_mac_addr(hw->mac.addr) == - IXGBE_ERR_INVALID_MAC_ADDR) { + if (!is_valid_ether_addr(hw->mac.addr)) { /* Get the MAC address from the RAR0 for later reference */ hw->mac.ops.get_mac_addr(hw, hw->mac.addr); @@ -2617,6 +2613,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) bool link_up = false; u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + s32 ret_val = 0; /* * Link must be up to auto-blink the LEDs; @@ -2625,10 +2622,28 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) hw->mac.ops.check_link(hw, &speed, &link_up, false); if (!link_up) { + /* Need the SW/FW semaphore around AUTOC writes if 82599 and + * LESM is on. + */ + bool got_lock = false; + + if ((hw->mac.type == ixgbe_mac_82599EB) && + ixgbe_verify_lesm_fw_enabled_82599(hw)) { + ret_val = hw->mac.ops.acquire_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); + if (ret_val) + goto out; + + got_lock = true; + } autoc_reg |= IXGBE_AUTOC_AN_RESTART; autoc_reg |= IXGBE_AUTOC_FLU; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); IXGBE_WRITE_FLUSH(hw); + + if (got_lock) + hw->mac.ops.release_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); usleep_range(10000, 20000); } @@ -2637,7 +2652,8 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); IXGBE_WRITE_FLUSH(hw); - return 0; +out: + return ret_val; } /** @@ -2649,18 +2665,40 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) { u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + s32 ret_val = 0; + bool got_lock = false; + + /* Need the SW/FW semaphore around AUTOC writes if 82599 and + * LESM is on. + */ + if ((hw->mac.type == ixgbe_mac_82599EB) && + ixgbe_verify_lesm_fw_enabled_82599(hw)) { + ret_val = hw->mac.ops.acquire_swfw_sync(hw, + IXGBE_GSSR_MAC_CSR_SM); + if (ret_val) + goto out; + + got_lock = true; + } autoc_reg &= ~IXGBE_AUTOC_FLU; autoc_reg |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); + if (hw->mac.type == ixgbe_mac_82599EB) + ixgbe_reset_pipeline_82599(hw); + + if (got_lock) + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); + led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg &= ~IXGBE_LED_BLINK(index); led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); IXGBE_WRITE_FLUSH(hw); - return 0; +out: + return ret_val; } /** diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h index d813d1188c36..f7a0970a251c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h @@ -78,9 +78,9 @@ s32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval); s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw); +s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw); void ixgbe_fc_autoneg(struct ixgbe_hw *hw); -s32 ixgbe_validate_mac_addr(u8 *mac_addr); s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask); void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask); s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr); @@ -107,6 +107,7 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw); void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom, int strategy); +s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw); #define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8 #define IXGBE_EMC_INTERNAL_DATA 0x00 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c index 8d3a21889099..3504686d3af5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c @@ -24,9 +24,6 @@ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ - -#ifdef CONFIG_DEBUG_FS - #include <linux/debugfs.h> #include <linux/module.h> @@ -37,20 +34,6 @@ static struct dentry *ixgbe_dbg_root; static char ixgbe_dbg_reg_ops_buf[256] = ""; /** - * ixgbe_dbg_reg_ops_open - prep the debugfs pokee data item when opened - * @inode: inode that was opened - * @filp: file info - * - * Stash the adapter pointer hiding in the inode into the file pointer where - * we can find it later in the read and write calls - **/ -static int ixgbe_dbg_reg_ops_open(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - return 0; -} - -/** * ixgbe_dbg_reg_ops_read - read for reg_ops datum * @filp: the opened file * @buffer: where to write the data for the user to read @@ -61,23 +44,27 @@ static ssize_t ixgbe_dbg_reg_ops_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { struct ixgbe_adapter *adapter = filp->private_data; - char buf[256]; - int bytes_not_copied; + char *buf; int len; /* don't allow partial reads */ if (*ppos != 0) return 0; - len = snprintf(buf, sizeof(buf), "%s: %s\n", - adapter->netdev->name, ixgbe_dbg_reg_ops_buf); - if (count < len) + buf = kasprintf(GFP_KERNEL, "%s: %s\n", + adapter->netdev->name, + ixgbe_dbg_reg_ops_buf); + if (!buf) + return -ENOMEM; + + if (count < strlen(buf)) { + kfree(buf); return -ENOSPC; - bytes_not_copied = copy_to_user(buffer, buf, len); - if (bytes_not_copied < 0) - return bytes_not_copied; + } + + len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); - *ppos = len; + kfree(buf); return len; } @@ -93,7 +80,7 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp, size_t count, loff_t *ppos) { struct ixgbe_adapter *adapter = filp->private_data; - int bytes_not_copied; + int len; /* don't allow partial writes */ if (*ppos != 0) @@ -101,14 +88,15 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp, if (count >= sizeof(ixgbe_dbg_reg_ops_buf)) return -ENOSPC; - bytes_not_copied = copy_from_user(ixgbe_dbg_reg_ops_buf, buffer, count); - if (bytes_not_copied < 0) - return bytes_not_copied; - else if (bytes_not_copied < count) - count -= bytes_not_copied; - else - return -ENOSPC; - ixgbe_dbg_reg_ops_buf[count] = '\0'; + len = simple_write_to_buffer(ixgbe_dbg_reg_ops_buf, + sizeof(ixgbe_dbg_reg_ops_buf)-1, + ppos, + buffer, + count); + if (len < 0) + return len; + + ixgbe_dbg_reg_ops_buf[len] = '\0'; if (strncmp(ixgbe_dbg_reg_ops_buf, "write", 5) == 0) { u32 reg, value; @@ -142,7 +130,7 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp, static const struct file_operations ixgbe_dbg_reg_ops_fops = { .owner = THIS_MODULE, - .open = ixgbe_dbg_reg_ops_open, + .open = simple_open, .read = ixgbe_dbg_reg_ops_read, .write = ixgbe_dbg_reg_ops_write, }; @@ -150,20 +138,6 @@ static const struct file_operations ixgbe_dbg_reg_ops_fops = { static char ixgbe_dbg_netdev_ops_buf[256] = ""; /** - * ixgbe_dbg_netdev_ops_open - prep the debugfs netdev_ops data item - * @inode: inode that was opened - * @filp: file info - * - * Stash the adapter pointer hiding in the inode into the file pointer - * where we can find it later in the read and write calls - **/ -static int ixgbe_dbg_netdev_ops_open(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - return 0; -} - -/** * ixgbe_dbg_netdev_ops_read - read for netdev_ops datum * @filp: the opened file * @buffer: where to write the data for the user to read @@ -175,23 +149,27 @@ static ssize_t ixgbe_dbg_netdev_ops_read(struct file *filp, size_t count, loff_t *ppos) { struct ixgbe_adapter *adapter = filp->private_data; - char buf[256]; - int bytes_not_copied; + char *buf; int len; /* don't allow partial reads */ if (*ppos != 0) return 0; - len = snprintf(buf, sizeof(buf), "%s: %s\n", - adapter->netdev->name, ixgbe_dbg_netdev_ops_buf); - if (count < len) + buf = kasprintf(GFP_KERNEL, "%s: %s\n", + adapter->netdev->name, + ixgbe_dbg_netdev_ops_buf); + if (!buf) + return -ENOMEM; + + if (count < strlen(buf)) { + kfree(buf); return -ENOSPC; - bytes_not_copied = copy_to_user(buffer, buf, len); - if (bytes_not_copied < 0) - return bytes_not_copied; + } + + len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); - *ppos = len; + kfree(buf); return len; } @@ -207,7 +185,7 @@ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp, size_t count, loff_t *ppos) { struct ixgbe_adapter *adapter = filp->private_data; - int bytes_not_copied; + int len; /* don't allow partial writes */ if (*ppos != 0) @@ -215,15 +193,15 @@ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp, if (count >= sizeof(ixgbe_dbg_netdev_ops_buf)) return -ENOSPC; - bytes_not_copied = copy_from_user(ixgbe_dbg_netdev_ops_buf, - buffer, count); - if (bytes_not_copied < 0) - return bytes_not_copied; - else if (bytes_not_copied < count) - count -= bytes_not_copied; - else - return -ENOSPC; - ixgbe_dbg_netdev_ops_buf[count] = '\0'; + len = simple_write_to_buffer(ixgbe_dbg_netdev_ops_buf, + sizeof(ixgbe_dbg_netdev_ops_buf)-1, + ppos, + buffer, + count); + if (len < 0) + return len; + + ixgbe_dbg_netdev_ops_buf[len] = '\0'; if (strncmp(ixgbe_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) { adapter->netdev->netdev_ops->ndo_tx_timeout(adapter->netdev); @@ -238,7 +216,7 @@ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp, static const struct file_operations ixgbe_dbg_netdev_ops_fops = { .owner = THIS_MODULE, - .open = ixgbe_dbg_netdev_ops_open, + .open = simple_open, .read = ixgbe_dbg_netdev_ops_read, .write = ixgbe_dbg_netdev_ops_write, }; @@ -296,5 +274,3 @@ void ixgbe_dbg_exit(void) { debugfs_remove_recursive(ixgbe_dbg_root); } - -#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 56b20d17d0e4..326858424345 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -383,6 +383,11 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, (adapter->flags & IXGBE_FLAG_DCB_ENABLED)) return -EINVAL; + /* some devices do not support autoneg of link flow control */ + if ((pause->autoneg == AUTONEG_ENABLE) && + (ixgbe_device_supports_autoneg_fc(hw) != 0)) + return -EINVAL; + fc.disable_fc_autoneg = (pause->autoneg != AUTONEG_ENABLE); if ((pause->rx_pause && pause->tx_pause) || pause->autoneg) @@ -887,24 +892,23 @@ static int ixgbe_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - struct ixgbe_ring *temp_tx_ring, *temp_rx_ring; + struct ixgbe_ring *temp_ring; int i, err = 0; u32 new_rx_count, new_tx_count; - bool need_update = false; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) return -EINVAL; - new_rx_count = max_t(u32, ring->rx_pending, IXGBE_MIN_RXD); - new_rx_count = min_t(u32, new_rx_count, IXGBE_MAX_RXD); - new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE); - - new_tx_count = max_t(u32, ring->tx_pending, IXGBE_MIN_TXD); - new_tx_count = min_t(u32, new_tx_count, IXGBE_MAX_TXD); + new_tx_count = clamp_t(u32, ring->tx_pending, + IXGBE_MIN_TXD, IXGBE_MAX_TXD); new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE); - if ((new_tx_count == adapter->tx_ring[0]->count) && - (new_rx_count == adapter->rx_ring[0]->count)) { + new_rx_count = clamp_t(u32, ring->rx_pending, + IXGBE_MIN_RXD, IXGBE_MAX_RXD); + new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE); + + if ((new_tx_count == adapter->tx_ring_count) && + (new_rx_count == adapter->rx_ring_count)) { /* nothing to do */ return 0; } @@ -922,81 +926,80 @@ static int ixgbe_set_ringparam(struct net_device *netdev, goto clear_reset; } - temp_tx_ring = vmalloc(adapter->num_tx_queues * sizeof(struct ixgbe_ring)); - if (!temp_tx_ring) { + /* allocate temporary buffer to store rings in */ + i = max_t(int, adapter->num_tx_queues, adapter->num_rx_queues); + temp_ring = vmalloc(i * sizeof(struct ixgbe_ring)); + + if (!temp_ring) { err = -ENOMEM; goto clear_reset; } + ixgbe_down(adapter); + + /* + * Setup new Tx resources and free the old Tx resources in that order. + * We can then assign the new resources to the rings via a memcpy. + * The advantage to this approach is that we are guaranteed to still + * have resources even in the case of an allocation failure. + */ if (new_tx_count != adapter->tx_ring_count) { for (i = 0; i < adapter->num_tx_queues; i++) { - memcpy(&temp_tx_ring[i], adapter->tx_ring[i], + memcpy(&temp_ring[i], adapter->tx_ring[i], sizeof(struct ixgbe_ring)); - temp_tx_ring[i].count = new_tx_count; - err = ixgbe_setup_tx_resources(&temp_tx_ring[i]); + + temp_ring[i].count = new_tx_count; + err = ixgbe_setup_tx_resources(&temp_ring[i]); if (err) { while (i) { i--; - ixgbe_free_tx_resources(&temp_tx_ring[i]); + ixgbe_free_tx_resources(&temp_ring[i]); } - goto clear_reset; + goto err_setup; } } - need_update = true; - } - temp_rx_ring = vmalloc(adapter->num_rx_queues * sizeof(struct ixgbe_ring)); - if (!temp_rx_ring) { - err = -ENOMEM; - goto err_setup; + for (i = 0; i < adapter->num_tx_queues; i++) { + ixgbe_free_tx_resources(adapter->tx_ring[i]); + + memcpy(adapter->tx_ring[i], &temp_ring[i], + sizeof(struct ixgbe_ring)); + } + + adapter->tx_ring_count = new_tx_count; } + /* Repeat the process for the Rx rings if needed */ if (new_rx_count != adapter->rx_ring_count) { for (i = 0; i < adapter->num_rx_queues; i++) { - memcpy(&temp_rx_ring[i], adapter->rx_ring[i], + memcpy(&temp_ring[i], adapter->rx_ring[i], sizeof(struct ixgbe_ring)); - temp_rx_ring[i].count = new_rx_count; - err = ixgbe_setup_rx_resources(&temp_rx_ring[i]); + + temp_ring[i].count = new_rx_count; + err = ixgbe_setup_rx_resources(&temp_ring[i]); if (err) { while (i) { i--; - ixgbe_free_rx_resources(&temp_rx_ring[i]); + ixgbe_free_rx_resources(&temp_ring[i]); } goto err_setup; } + } - need_update = true; - } - /* if rings need to be updated, here's the place to do it in one shot */ - if (need_update) { - ixgbe_down(adapter); + for (i = 0; i < adapter->num_rx_queues; i++) { + ixgbe_free_rx_resources(adapter->rx_ring[i]); - /* tx */ - if (new_tx_count != adapter->tx_ring_count) { - for (i = 0; i < adapter->num_tx_queues; i++) { - ixgbe_free_tx_resources(adapter->tx_ring[i]); - memcpy(adapter->tx_ring[i], &temp_tx_ring[i], - sizeof(struct ixgbe_ring)); - } - adapter->tx_ring_count = new_tx_count; + memcpy(adapter->rx_ring[i], &temp_ring[i], + sizeof(struct ixgbe_ring)); } - /* rx */ - if (new_rx_count != adapter->rx_ring_count) { - for (i = 0; i < adapter->num_rx_queues; i++) { - ixgbe_free_rx_resources(adapter->rx_ring[i]); - memcpy(adapter->rx_ring[i], &temp_rx_ring[i], - sizeof(struct ixgbe_ring)); - } - adapter->rx_ring_count = new_rx_count; - } - ixgbe_up(adapter); + adapter->rx_ring_count = new_rx_count; } - vfree(temp_rx_ring); err_setup: - vfree(temp_tx_ring); + ixgbe_up(adapter); + vfree(temp_ring); clear_reset: clear_bit(__IXGBE_RESETTING, &adapter->state); return err; @@ -2669,10 +2672,12 @@ static int ixgbe_get_ts_info(struct net_device *dev, struct ixgbe_adapter *adapter = netdev_priv(dev); switch (adapter->hw.mac.type) { -#ifdef CONFIG_IXGBE_PTP case ixgbe_mac_X540: case ixgbe_mac_82599EB: info->so_timestamping = + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; @@ -2692,7 +2697,6 @@ static int ixgbe_get_ts_info(struct net_device *dev, (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); break; -#endif /* CONFIG_IXGBE_PTP */ default: return ethtool_op_get_ts_info(dev, info); break; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c index ae73ef14fdf3..252850d9a3e0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c @@ -800,6 +800,10 @@ int ixgbe_fcoe_enable(struct net_device *netdev) return -EINVAL; e_info(drv, "Enabling FCoE offload features.\n"); + + if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) + e_warn(probe, "Enabling FCoE on PF will disable legacy VFs\n"); + if (netif_running(netdev)) netdev->netdev_ops->ndo_stop(netdev); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index 17ecbcedd548..8c74f739011d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -802,10 +802,13 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, /* setup affinity mask and node */ if (cpu != -1) cpumask_set_cpu(cpu, &q_vector->affinity_mask); - else - cpumask_copy(&q_vector->affinity_mask, cpu_online_mask); q_vector->numa_node = node; +#ifdef CONFIG_IXGBE_DCA + /* initialize CPU for DCA */ + q_vector->cpu = -1; + +#endif /* initialize NAPI */ netif_napi_add(adapter->netdev, &q_vector->napi, ixgbe_poll, 64); @@ -821,6 +824,21 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, /* initialize pointer to rings */ ring = q_vector->ring; + /* intialize ITR */ + if (txr_count && !rxr_count) { + /* tx only vector */ + if (adapter->tx_itr_setting == 1) + q_vector->itr = IXGBE_10K_ITR; + else + q_vector->itr = adapter->tx_itr_setting; + } else { + /* rx or rx/tx vector */ + if (adapter->rx_itr_setting == 1) + q_vector->itr = IXGBE_20K_ITR; + else + q_vector->itr = adapter->rx_itr_setting; + } + while (txr_count) { /* assign generic ring traits */ ring->dev = &adapter->pdev->dev; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index fa3d552e1f4a..20a5af6d87d0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -44,6 +44,7 @@ #include <linux/ethtool.h> #include <linux/if.h> #include <linux/if_vlan.h> +#include <linux/if_bridge.h> #include <linux/prefetch.h> #include <scsi/fc/fc_fcoe.h> @@ -62,11 +63,7 @@ char ixgbe_default_device_descr[] = static char ixgbe_default_device_descr[] = "Intel(R) 10 Gigabit Network Connection"; #endif -#define MAJ 3 -#define MIN 9 -#define BUILD 15 -#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ - __stringify(BUILD) "-k" +#define DRV_VERSION "3.11.33-k" const char ixgbe_driver_version[] = DRV_VERSION; static const char ixgbe_copyright[] = "Copyright (c) 1999-2012 Intel Corporation."; @@ -335,11 +332,13 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter) goto exit; dev_info(&adapter->pdev->dev, "TX Rings Summary\n"); - pr_info("Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n"); + pr_info(" %s %s %s %s\n", + "Queue [NTU] [NTC] [bi(ntc)->dma ]", + "leng", "ntw", "timestamp"); for (n = 0; n < adapter->num_tx_queues; n++) { tx_ring = adapter->tx_ring[n]; tx_buffer = &tx_ring->tx_buffer_info[tx_ring->next_to_clean]; - pr_info(" %5d %5X %5X %016llX %04X %p %016llX\n", + pr_info(" %5d %5X %5X %016llX %08X %p %016llX\n", n, tx_ring->next_to_use, tx_ring->next_to_clean, (u64)dma_unmap_addr(tx_buffer, dma), dma_unmap_len(tx_buffer, len), @@ -355,13 +354,37 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter) /* Transmit Descriptor Formats * - * Advanced Transmit Descriptor + * 82598 Advanced Transmit Descriptor * +--------------------------------------------------------------+ * 0 | Buffer Address [63:0] | * +--------------------------------------------------------------+ - * 8 | PAYLEN | PORTS | IDX | STA | DCMD |DTYP | RSV | DTALEN | + * 8 | PAYLEN | POPTS | IDX | STA | DCMD |DTYP | RSV | DTALEN | * +--------------------------------------------------------------+ * 63 46 45 40 39 36 35 32 31 24 23 20 19 0 + * + * 82598 Advanced Transmit Descriptor (Write-Back Format) + * +--------------------------------------------------------------+ + * 0 | RSV [63:0] | + * +--------------------------------------------------------------+ + * 8 | RSV | STA | NXTSEQ | + * +--------------------------------------------------------------+ + * 63 36 35 32 31 0 + * + * 82599+ Advanced Transmit Descriptor + * +--------------------------------------------------------------+ + * 0 | Buffer Address [63:0] | + * +--------------------------------------------------------------+ + * 8 |PAYLEN |POPTS|CC|IDX |STA |DCMD |DTYP |MAC |RSV |DTALEN | + * +--------------------------------------------------------------+ + * 63 46 45 40 39 38 36 35 32 31 24 23 20 19 18 17 16 15 0 + * + * 82599+ Advanced Transmit Descriptor (Write-Back Format) + * +--------------------------------------------------------------+ + * 0 | RSV [63:0] | + * +--------------------------------------------------------------+ + * 8 | RSV | STA | RSV | + * +--------------------------------------------------------------+ + * 63 36 35 32 31 0 */ for (n = 0; n < adapter->num_tx_queues; n++) { @@ -369,40 +392,43 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter) pr_info("------------------------------------\n"); pr_info("TX QUEUE INDEX = %d\n", tx_ring->queue_index); pr_info("------------------------------------\n"); - pr_info("T [desc] [address 63:0 ] " - "[PlPOIdStDDt Ln] [bi->dma ] " - "leng ntw timestamp bi->skb\n"); + pr_info("%s%s %s %s %s %s\n", + "T [desc] [address 63:0 ] ", + "[PlPOIdStDDt Ln] [bi->dma ] ", + "leng", "ntw", "timestamp", "bi->skb"); for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { tx_desc = IXGBE_TX_DESC(tx_ring, i); tx_buffer = &tx_ring->tx_buffer_info[i]; u0 = (struct my_u0 *)tx_desc; - pr_info("T [0x%03X] %016llX %016llX %016llX" - " %04X %p %016llX %p", i, - le64_to_cpu(u0->a), - le64_to_cpu(u0->b), - (u64)dma_unmap_addr(tx_buffer, dma), - dma_unmap_len(tx_buffer, len), - tx_buffer->next_to_watch, - (u64)tx_buffer->time_stamp, - tx_buffer->skb); - if (i == tx_ring->next_to_use && - i == tx_ring->next_to_clean) - pr_cont(" NTC/U\n"); - else if (i == tx_ring->next_to_use) - pr_cont(" NTU\n"); - else if (i == tx_ring->next_to_clean) - pr_cont(" NTC\n"); - else - pr_cont("\n"); - - if (netif_msg_pktdata(adapter) && - tx_buffer->skb) - print_hex_dump(KERN_INFO, "", - DUMP_PREFIX_ADDRESS, 16, 1, - tx_buffer->skb->data, + if (dma_unmap_len(tx_buffer, len) > 0) { + pr_info("T [0x%03X] %016llX %016llX %016llX %08X %p %016llX %p", + i, + le64_to_cpu(u0->a), + le64_to_cpu(u0->b), + (u64)dma_unmap_addr(tx_buffer, dma), dma_unmap_len(tx_buffer, len), - true); + tx_buffer->next_to_watch, + (u64)tx_buffer->time_stamp, + tx_buffer->skb); + if (i == tx_ring->next_to_use && + i == tx_ring->next_to_clean) + pr_cont(" NTC/U\n"); + else if (i == tx_ring->next_to_use) + pr_cont(" NTU\n"); + else if (i == tx_ring->next_to_clean) + pr_cont(" NTC\n"); + else + pr_cont("\n"); + + if (netif_msg_pktdata(adapter) && + tx_buffer->skb) + print_hex_dump(KERN_INFO, "", + DUMP_PREFIX_ADDRESS, 16, 1, + tx_buffer->skb->data, + dma_unmap_len(tx_buffer, len), + true); + } } } @@ -422,7 +448,9 @@ rx_ring_summary: dev_info(&adapter->pdev->dev, "RX Rings Dump\n"); - /* Advanced Receive Descriptor (Read) Format + /* Receive Descriptor Formats + * + * 82598 Advanced Receive Descriptor (Read) Format * 63 1 0 * +-----------------------------------------------------+ * 0 | Packet Buffer Address [63:1] |A0/NSE| @@ -431,27 +459,52 @@ rx_ring_summary: * +-----------------------------------------------------+ * * - * Advanced Receive Descriptor (Write-Back) Format + * 82598 Advanced Receive Descriptor (Write-Back) Format * * 63 48 47 32 31 30 21 20 16 15 4 3 0 * +------------------------------------------------------+ - * 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS | - * | Checksum Ident | | | | Type | Type | + * 0 | RSS Hash / |SPH| HDR_LEN | RSV |Packet| RSS | + * | Packet | IP | | | | Type | Type | + * | Checksum | Ident | | | | | | * +------------------------------------------------------+ * 8 | VLAN Tag | Length | Extended Error | Extended Status | * +------------------------------------------------------+ * 63 48 47 32 31 20 19 0 + * + * 82599+ Advanced Receive Descriptor (Read) Format + * 63 1 0 + * +-----------------------------------------------------+ + * 0 | Packet Buffer Address [63:1] |A0/NSE| + * +----------------------------------------------+------+ + * 8 | Header Buffer Address [63:1] | DD | + * +-----------------------------------------------------+ + * + * + * 82599+ Advanced Receive Descriptor (Write-Back) Format + * + * 63 48 47 32 31 30 21 20 17 16 4 3 0 + * +------------------------------------------------------+ + * 0 |RSS / Frag Checksum|SPH| HDR_LEN |RSC- |Packet| RSS | + * |/ RTT / PCoE_PARAM | | | CNT | Type | Type | + * |/ Flow Dir Flt ID | | | | | | + * +------------------------------------------------------+ + * 8 | VLAN Tag | Length |Extended Error| Xtnd Status/NEXTP | + * +------------------------------------------------------+ + * 63 48 47 32 31 20 19 0 */ + for (n = 0; n < adapter->num_rx_queues; n++) { rx_ring = adapter->rx_ring[n]; pr_info("------------------------------------\n"); pr_info("RX QUEUE INDEX = %d\n", rx_ring->queue_index); pr_info("------------------------------------\n"); - pr_info("R [desc] [ PktBuf A0] " - "[ HeadBuf DD] [bi->dma ] [bi->skb] " + pr_info("%s%s%s", + "R [desc] [ PktBuf A0] ", + "[ HeadBuf DD] [bi->dma ] [bi->skb ] ", "<-- Adv Rx Read format\n"); - pr_info("RWB[desc] [PcsmIpSHl PtRs] " - "[vl er S cks ln] ---------------- [bi->skb] " + pr_info("%s%s%s", + "RWB[desc] [PcsmIpSHl PtRs] ", + "[vl er S cks ln] ---------------- [bi->skb ] ", "<-- Adv Rx Write-Back format\n"); for (i = 0; i < rx_ring->count; i++) { @@ -646,6 +699,7 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter) struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw_stats *hwstats = &adapter->stats; u32 xoff[8] = {0}; + u8 tc; int i; bool pfc_en = adapter->dcb_cfg.pfc_mode_enable; @@ -659,21 +713,26 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter) /* update stats for each tc, only valid with PFC enabled */ for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) { + u32 pxoffrxc; + switch (hw->mac.type) { case ixgbe_mac_82598EB: - xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); + pxoffrxc = IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); break; default: - xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); + pxoffrxc = IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); } - hwstats->pxoffrxc[i] += xoff[i]; + hwstats->pxoffrxc[i] += pxoffrxc; + /* Get the TC for given UP */ + tc = netdev_get_prio_tc_map(adapter->netdev, i); + xoff[tc] += pxoffrxc; } /* disarm tx queues that have received xoff frames */ for (i = 0; i < adapter->num_tx_queues; i++) { struct ixgbe_ring *tx_ring = adapter->tx_ring[i]; - u8 tc = tx_ring->dcb_tc; + tc = tx_ring->dcb_tc; if (xoff[tc]) clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state); } @@ -791,10 +850,8 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, total_bytes += tx_buffer->bytecount; total_packets += tx_buffer->gso_segs; -#ifdef CONFIG_IXGBE_PTP if (unlikely(tx_buffer->tx_flags & IXGBE_TX_FLAGS_TSTAMP)) ixgbe_ptp_tx_hwtstamp(q_vector, tx_buffer->skb); -#endif /* free the skb */ dev_kfree_skb_any(tx_buffer->skb); @@ -967,7 +1024,6 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, * which will cause the DCA tag to be cleared. */ rxctrl |= IXGBE_DCA_RXCTRL_DESC_RRO_EN | - IXGBE_DCA_RXCTRL_DATA_DCA_EN | IXGBE_DCA_RXCTRL_DESC_DCA_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(reg_idx), rxctrl); @@ -1244,6 +1300,7 @@ static unsigned int ixgbe_get_headlen(unsigned char *data, struct vlan_hdr *vlan; /* l3 headers */ struct iphdr *ipv4; + struct ipv6hdr *ipv6; } hdr; __be16 protocol; u8 nexthdr = 0; /* default to not TCP */ @@ -1281,20 +1338,30 @@ static unsigned int ixgbe_get_headlen(unsigned char *data, if (hlen < sizeof(struct iphdr)) return hdr.network - data; + /* record next protocol if header is present */ + if (!hdr.ipv4->frag_off) + nexthdr = hdr.ipv4->protocol; + } else if (protocol == __constant_htons(ETH_P_IPV6)) { + if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr))) + return max_len; + /* record next protocol */ - nexthdr = hdr.ipv4->protocol; - hdr.network += hlen; + nexthdr = hdr.ipv6->nexthdr; + hlen = sizeof(struct ipv6hdr); #ifdef IXGBE_FCOE } else if (protocol == __constant_htons(ETH_P_FCOE)) { if ((hdr.network - data) > (max_len - FCOE_HEADER_LEN)) return max_len; - hdr.network += FCOE_HEADER_LEN; + hlen = FCOE_HEADER_LEN; #endif } else { return hdr.network - data; } - /* finally sort out TCP */ + /* relocate pointer to start of L4 header */ + hdr.network += hlen; + + /* finally sort out TCP/UDP */ if (nexthdr == IPPROTO_TCP) { if ((hdr.network - data) > (max_len - sizeof(struct tcphdr))) return max_len; @@ -1307,6 +1374,11 @@ static unsigned int ixgbe_get_headlen(unsigned char *data, return hdr.network - data; hdr.network += hlen; + } else if (nexthdr == IPPROTO_UDP) { + if ((hdr.network - data) > (max_len - sizeof(struct udphdr))) + return max_len; + + hdr.network += sizeof(struct udphdr); } /* @@ -1369,9 +1441,7 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, ixgbe_rx_checksum(rx_ring, rx_desc, skb); -#ifdef CONFIG_IXGBE_PTP ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb); -#endif if ((dev->features & NETIF_F_HW_VLAN_RX) && ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { @@ -1781,7 +1851,7 @@ dma_sync: **/ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_ring *rx_ring, - int budget) + const int budget) { unsigned int total_rx_bytes = 0, total_rx_packets = 0; #ifdef IXGBE_FCOE @@ -1832,7 +1902,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; - total_rx_packets++; /* populate checksum, timestamp, VLAN, and protocol */ ixgbe_process_skb_fields(rx_ring, rx_desc, skb); @@ -1865,8 +1934,8 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, ixgbe_rx_skb(q_vector, skb); /* update budget accounting */ - budget--; - } while (likely(budget)); + total_rx_packets++; + } while (likely(total_rx_packets < budget)); u64_stats_update_begin(&rx_ring->syncp); rx_ring->stats.packets += total_rx_packets; @@ -1878,7 +1947,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, if (cleaned_count) ixgbe_alloc_rx_buffers(rx_ring, cleaned_count); - return !!budget; + return (total_rx_packets < budget); } /** @@ -1914,20 +1983,6 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) ixgbe_for_each_ring(ring, q_vector->tx) ixgbe_set_ivar(adapter, 1, ring->reg_idx, v_idx); - if (q_vector->tx.ring && !q_vector->rx.ring) { - /* tx only vector */ - if (adapter->tx_itr_setting == 1) - q_vector->itr = IXGBE_10K_ITR; - else - q_vector->itr = adapter->tx_itr_setting; - } else { - /* rx or rx/tx vector */ - if (adapter->rx_itr_setting == 1) - q_vector->itr = IXGBE_20K_ITR; - else - q_vector->itr = adapter->rx_itr_setting; - } - ixgbe_write_eitr(q_vector); } @@ -2324,10 +2379,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, break; } -#ifdef CONFIG_IXGBE_PTP if (adapter->hw.mac.type == ixgbe_mac_X540) mask |= IXGBE_EIMS_TIMESYNC; -#endif if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) && !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT)) @@ -2393,10 +2446,8 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data) ixgbe_check_fan_failure(adapter, eicr); -#ifdef CONFIG_IXGBE_PTP if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) ixgbe_ptp_check_pps_event(adapter, eicr); -#endif /* re-enable the original interrupt state, no lsc, no queues */ if (!test_bit(__IXGBE_DOWN, &adapter->state)) @@ -2588,10 +2639,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data) } ixgbe_check_fan_failure(adapter, eicr); -#ifdef CONFIG_IXGBE_PTP if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) ixgbe_ptp_check_pps_event(adapter, eicr); -#endif /* would disable interrupts here but EIAM disabled it */ napi_schedule(&q_vector->napi); @@ -2699,12 +2748,6 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) { struct ixgbe_q_vector *q_vector = adapter->q_vector[0]; - /* rx/tx vector */ - if (adapter->rx_itr_setting == 1) - q_vector->itr = IXGBE_20K_ITR; - else - q_vector->itr = adapter->rx_itr_setting; - ixgbe_write_eitr(q_vector); ixgbe_set_ivar(adapter, 0, 0, 0); @@ -3132,14 +3175,6 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter, ixgbe_configure_srrctl(adapter, ring); ixgbe_configure_rscctl(adapter, ring); - /* If operating in IOV mode set RLPML for X540 */ - if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) && - hw->mac.type == ixgbe_mac_X540) { - rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK; - rxdctl |= ((ring->netdev->mtu + ETH_HLEN + - ETH_FCS_LEN + VLAN_HLEN) | IXGBE_RXDCTL_RLPML_EN); - } - if (hw->mac.type == ixgbe_mac_82598EB) { /* * enable cache line friendly hardware writes: @@ -3211,7 +3246,8 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset ^ 1), reg_offset - 1); IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (~0) << vf_shift); IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset ^ 1), reg_offset - 1); - IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); + if (adapter->flags2 & IXGBE_FLAG2_BRIDGE_MODE_VEB) + IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); /* Map PF MAC address in RAR Entry 0 to first pool following VFs */ hw->mac.ops.set_vmdq(hw, 0, VMDQ_P(0)); @@ -3234,8 +3270,6 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); - /* enable Tx loopback for VF/PF communication */ - IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); /* Enable MAC Anti-Spoofing */ hw->mac.ops.set_mac_anti_spoofing(hw, (adapter->num_vfs != 0), @@ -3263,6 +3297,11 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter) max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE; #endif /* IXGBE_FCOE */ + + /* adjust max frame to be at least the size of a standard frame */ + if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN)) + max_frame = (ETH_FRAME_LEN + ETH_FCS_LEN); + mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) { mhadd &= ~IXGBE_MHADD_MFS_MASK; @@ -3271,9 +3310,6 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd); } - /* MHADD will allow an extra 4 bytes past for vlan tagged frames */ - max_frame += VLAN_HLEN; - hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); /* set jumbo enable since MHADD.MFS is keeping size locked at max_frame */ hlreg0 |= IXGBE_HLREG0_JUMBOEN; @@ -4072,11 +4108,8 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter) else ixgbe_configure_msi_and_legacy(adapter); - /* enable the optics for both mult-speed fiber and 82599 SFP+ fiber */ - if (hw->mac.ops.enable_tx_laser && - ((hw->phy.multispeed_fiber) || - ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) && - (hw->mac.type == ixgbe_mac_82599EB)))) + /* enable the optics for 82599 SFP+ fiber */ + if (hw->mac.ops.enable_tx_laser) hw->mac.ops.enable_tx_laser(hw); clear_bit(__IXGBE_DOWN, &adapter->state); @@ -4192,6 +4225,9 @@ void ixgbe_reset(struct ixgbe_adapter *adapter) /* update SAN MAC vmdq pool selection */ if (hw->mac.san_mac_rar_index) hw->mac.ops.set_vmdq_san_mac(hw, VMDQ_P(0)); + + if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) + ixgbe_ptp_reset(adapter); } /** @@ -4393,11 +4429,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter) if (!pci_channel_offline(adapter->pdev)) ixgbe_reset(adapter); - /* power down the optics for multispeed fiber and 82599 SFP+ fiber */ - if (hw->mac.ops.disable_tx_laser && - ((hw->phy.multispeed_fiber) || - ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) && - (hw->mac.type == ixgbe_mac_82599EB)))) + /* power down the optics for 82599 SFP+ fiber */ + if (hw->mac.ops.disable_tx_laser) hw->mac.ops.disable_tx_laser(hw); ixgbe_clean_all_tx_rings(adapter); @@ -4429,11 +4462,12 @@ static void ixgbe_tx_timeout(struct net_device *netdev) * Fields are initialized based on PCI device information and * OS network device settings (MTU size). **/ -static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) +static int ixgbe_sw_init(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; unsigned int rss; + u32 fwsm; #ifdef CONFIG_IXGBE_DCB int j; struct tc_configuration *tc; @@ -4457,7 +4491,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->max_q_vectors = MAX_Q_VECTORS_82598; break; case ixgbe_mac_X540: - adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE; + fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); + if (fwsm & IXGBE_FWSM_TS_ENABLED) + adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE; case ixgbe_mac_82599EB: adapter->max_q_vectors = MAX_Q_VECTORS_82599; adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE; @@ -4533,7 +4569,8 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) ixgbe_pbthresh_setup(adapter); hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE; hw->fc.send_xon = true; - hw->fc.disable_fc_autoneg = false; + hw->fc.disable_fc_autoneg = + (ixgbe_device_supports_autoneg_fc(hw) == 0) ? false : true; #ifdef CONFIG_PCI_IOV /* assign number of SR-IOV VFs */ @@ -4828,14 +4865,14 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; /* - * For 82599EB we cannot allow PF to change MTU greater than 1500 - * in SR-IOV mode as it may cause buffer overruns in guest VFs that - * don't allocate and chain buffers correctly. + * For 82599EB we cannot allow legacy VFs to enable their receive + * paths when MTU greater than 1500 is configured. So display a + * warning that legacy VFs will be disabled. */ if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) && (adapter->hw.mac.type == ixgbe_mac_82599EB) && (max_frame > MAXIMUM_ETHERNET_VLAN_SIZE)) - return -EINVAL; + e_warn(probe, "Setting MTU > 1500 will disable legacy VFs\n"); e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu); @@ -4901,6 +4938,8 @@ static int ixgbe_open(struct net_device *netdev) if (err) goto err_set_queues; + ixgbe_ptp_init(adapter); + ixgbe_up_complete(adapter); return 0; @@ -4932,6 +4971,8 @@ static int ixgbe_close(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + ixgbe_ptp_stop(adapter); + ixgbe_down(adapter); ixgbe_free_irq(adapter); @@ -5022,14 +5063,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) if (wufc) { ixgbe_set_rx_mode(netdev); - /* - * enable the optics for both mult-speed fiber and - * 82599 SFP+ fiber as we can WoL. - */ - if (hw->mac.ops.enable_tx_laser && - (hw->phy.multispeed_fiber || - (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber && - hw->mac.type == ixgbe_mac_82599EB))) + /* enable the optics for 82599 SFP+ fiber as we can WoL */ + if (hw->mac.ops.enable_tx_laser) hw->mac.ops.enable_tx_laser(hw); /* turn on all-multi mode if wake on multicast is enabled */ @@ -5442,6 +5477,23 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter) adapter->link_speed = link_speed; } +static void ixgbe_update_default_up(struct ixgbe_adapter *adapter) +{ +#ifdef CONFIG_IXGBE_DCB + struct net_device *netdev = adapter->netdev; + struct dcb_app app = { + .selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE, + .protocol = 0, + }; + u8 up = 0; + + if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) + up = dcb_ieee_getapp_mask(netdev, &app); + + adapter->default_up = (up > 1) ? (ffs(up) - 1) : 0; +#endif +} + /** * ixgbe_watchdog_link_is_up - update netif_carrier status and * print link up message @@ -5482,9 +5534,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) break; } -#ifdef CONFIG_IXGBE_PTP - ixgbe_ptp_start_cyclecounter(adapter); -#endif + if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) + ixgbe_ptp_start_cyclecounter(adapter); e_info(drv, "NIC Link is Up %s, Flow Control: %s\n", (link_speed == IXGBE_LINK_SPEED_10GB_FULL ? @@ -5501,6 +5552,9 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) netif_carrier_on(netdev); ixgbe_check_vf_rate_limit(adapter); + /* update the default user priority for VFs */ + ixgbe_update_default_up(adapter); + /* ping all the active vfs to let them know link has changed */ ixgbe_ping_all_vfs(adapter); } @@ -5526,9 +5580,8 @@ static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *adapter) if (ixgbe_is_sfp(hw) && hw->mac.type == ixgbe_mac_82598EB) adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP; -#ifdef CONFIG_IXGBE_PTP - ixgbe_ptp_start_cyclecounter(adapter); -#endif + if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) + ixgbe_ptp_start_cyclecounter(adapter); e_info(drv, "NIC Link is Down\n"); netif_carrier_off(netdev); @@ -5833,9 +5886,7 @@ static void ixgbe_service_task(struct work_struct *work) ixgbe_watchdog_subtask(adapter); ixgbe_fdir_reinit_subtask(adapter); ixgbe_check_hang_subtask(adapter); -#ifdef CONFIG_IXGBE_PTP ixgbe_ptp_overflow_check(adapter); -#endif ixgbe_service_event_complete(adapter); } @@ -5988,10 +6039,8 @@ static __le32 ixgbe_tx_cmd_type(u32 tx_flags) if (tx_flags & IXGBE_TX_FLAGS_HW_VLAN) cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_VLE); -#ifdef CONFIG_IXGBE_PTP if (tx_flags & IXGBE_TX_FLAGS_TSTAMP) cmd_type |= cpu_to_le32(IXGBE_ADVTXD_MAC_TSTAMP); -#endif /* set segmentation enable bits for TSO/FSO */ #ifdef IXGBE_FCOE @@ -6393,12 +6442,10 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, skb_tx_timestamp(skb); -#ifdef CONFIG_IXGBE_PTP if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; tx_flags |= IXGBE_TX_FLAGS_TSTAMP; } -#endif #ifdef CONFIG_PCI_IOV /* @@ -6485,6 +6532,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, if (skb_pad(skb, 17 - skb->len)) return NETDEV_TX_OK; skb->len = 17; + skb_set_tail_pointer(skb, 17); } tx_ring = adapter->tx_ring[skb->queue_mapping]; @@ -6547,10 +6595,8 @@ static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd) struct ixgbe_adapter *adapter = netdev_priv(netdev); switch (cmd) { -#ifdef CONFIG_IXGBE_PTP case SIOCSHWTSTAMP: return ixgbe_ptp_hwtstamp_ioctl(adapter, req, cmd); -#endif default: return mdio_mii_ioctl(&adapter->hw.phy.mdio, if_mii(req), cmd); } @@ -6910,13 +6956,16 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) return -EOPNOTSUPP; - if (ndm->ndm_state & NUD_PERMANENT) { + /* Hardware does not support aging addresses so if a + * ndm_state is given only allow permanent addresses + */ + if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) { pr_info("%s: FDB only supports static addresses\n", ixgbe_driver_name); return -EINVAL; } - if (is_unicast_ether_addr(addr)) { + if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) { u32 rar_uc_entries = IXGBE_MAX_PF_MACVLANS; if (netdev_uc_count(dev) < rar_uc_entries) @@ -6974,6 +7023,61 @@ static int ixgbe_ndo_fdb_dump(struct sk_buff *skb, return idx; } +static int ixgbe_ndo_bridge_setlink(struct net_device *dev, + struct nlmsghdr *nlh) +{ + struct ixgbe_adapter *adapter = netdev_priv(dev); + struct nlattr *attr, *br_spec; + int rem; + + if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) + return -EOPNOTSUPP; + + br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); + + nla_for_each_nested(attr, br_spec, rem) { + __u16 mode; + u32 reg = 0; + + if (nla_type(attr) != IFLA_BRIDGE_MODE) + continue; + + mode = nla_get_u16(attr); + if (mode == BRIDGE_MODE_VEPA) { + reg = 0; + adapter->flags2 &= ~IXGBE_FLAG2_BRIDGE_MODE_VEB; + } else if (mode == BRIDGE_MODE_VEB) { + reg = IXGBE_PFDTXGSWC_VT_LBEN; + adapter->flags2 |= IXGBE_FLAG2_BRIDGE_MODE_VEB; + } else + return -EINVAL; + + IXGBE_WRITE_REG(&adapter->hw, IXGBE_PFDTXGSWC, reg); + + e_info(drv, "enabling bridge mode: %s\n", + mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB"); + } + + return 0; +} + +static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, + struct net_device *dev) +{ + struct ixgbe_adapter *adapter = netdev_priv(dev); + u16 mode; + + if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) + return 0; + + if (adapter->flags2 & IXGBE_FLAG2_BRIDGE_MODE_VEB) + mode = BRIDGE_MODE_VEB; + else + mode = BRIDGE_MODE_VEPA; + + return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode); +} + static const struct net_device_ops ixgbe_netdev_ops = { .ndo_open = ixgbe_open, .ndo_stop = ixgbe_close, @@ -7013,6 +7117,8 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_fdb_add = ixgbe_ndo_fdb_add, .ndo_fdb_del = ixgbe_ndo_fdb_del, .ndo_fdb_dump = ixgbe_ndo_fdb_dump, + .ndo_bridge_setlink = ixgbe_ndo_bridge_setlink, + .ndo_bridge_getlink = ixgbe_ndo_bridge_getlink, }; /** @@ -7042,6 +7148,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id, break; case IXGBE_SUBDEV_ID_82599_SFP: case IXGBE_SUBDEV_ID_82599_RNDC: + case IXGBE_SUBDEV_ID_82599_ECNA_DP: is_wol_supported = 1; break; } @@ -7079,8 +7186,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id, * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. **/ -static int __devinit ixgbe_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct ixgbe_adapter *adapter = NULL; @@ -7340,7 +7446,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, memcpy(netdev->dev_addr, hw->mac.perm_addr, netdev->addr_len); memcpy(netdev->perm_addr, hw->mac.perm_addr, netdev->addr_len); - if (ixgbe_validate_mac_addr(netdev->perm_addr)) { + if (!is_valid_ether_addr(netdev->perm_addr)) { e_dev_err("invalid MAC address\n"); err = -EIO; goto err_sw_init; @@ -7364,10 +7470,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); -#ifdef CONFIG_IXGBE_PTP - ixgbe_ptp_init(adapter); -#endif /* CONFIG_IXGBE_PTP*/ - /* save off EEPROM version number */ hw->eeprom.ops.read(hw, 0x2e, &adapter->eeprom_verh); hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl); @@ -7420,11 +7522,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (err) goto err_register; - /* power down the optics for multispeed fiber and 82599 SFP+ fiber */ - if (hw->mac.ops.disable_tx_laser && - ((hw->phy.multispeed_fiber) || - ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) && - (hw->mac.type == ixgbe_mac_82599EB)))) + /* power down the optics for 82599 SFP+ fiber */ + if (hw->mac.ops.disable_tx_laser) hw->mac.ops.disable_tx_laser(hw); /* carrier off reporting is important to ethtool even BEFORE open */ @@ -7493,7 +7592,7 @@ err_dma: * Hot-Plug event, or because the driver is going to be removed from * memory. **/ -static void __devexit ixgbe_remove(struct pci_dev *pdev) +static void ixgbe_remove(struct pci_dev *pdev) { struct ixgbe_adapter *adapter = pci_get_drvdata(pdev); struct net_device *netdev = adapter->netdev; @@ -7505,9 +7604,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) set_bit(__IXGBE_DOWN, &adapter->state); cancel_work_sync(&adapter->service_task); -#ifdef CONFIG_IXGBE_PTP - ixgbe_ptp_stop(adapter); -#endif #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { @@ -7736,7 +7832,7 @@ static struct pci_driver ixgbe_driver = { .name = ixgbe_driver_name, .id_table = ixgbe_pci_tbl, .probe = ixgbe_probe, - .remove = __devexit_p(ixgbe_remove), + .remove = ixgbe_remove, #ifdef CONFIG_PM .suspend = ixgbe_suspend, .resume = ixgbe_resume, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h index 310bdd961075..42dd65e6ac97 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h @@ -62,12 +62,39 @@ /* bits 23:16 are used for exra info for certain messages */ #define IXGBE_VT_MSGINFO_MASK (0xFF << IXGBE_VT_MSGINFO_SHIFT) +/* definitions to support mailbox API version negotiation */ + +/* + * Each element denotes a version of the API; existing numbers may not + * change; any additions must go at the end + */ +enum ixgbe_pfvf_api_rev { + ixgbe_mbox_api_10, /* API version 1.0, linux/freebsd VF driver */ + ixgbe_mbox_api_20, /* API version 2.0, solaris Phase1 VF driver */ + ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */ + /* This value should always be last */ + ixgbe_mbox_api_unknown, /* indicates that API version is not known */ +}; + +/* mailbox API, legacy requests */ #define IXGBE_VF_RESET 0x01 /* VF requests reset */ #define IXGBE_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */ #define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */ #define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */ -#define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */ -#define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */ + +/* mailbox API, version 1.0 VF requests */ +#define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */ +#define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */ +#define IXGBE_VF_API_NEGOTIATE 0x08 /* negotiate API version */ + +/* mailbox API, version 1.1 VF requests */ +#define IXGBE_VF_GET_QUEUES 0x09 /* get queue configuration */ + +/* GET_QUEUES return data indices within the mailbox */ +#define IXGBE_VF_TX_QUEUES 1 /* number of Tx queues supported */ +#define IXGBE_VF_RX_QUEUES 2 /* number of Rx queues supported */ +#define IXGBE_VF_TRANS_VLAN 3 /* Indication of port vlan */ +#define IXGBE_VF_DEF_QUEUE 4 /* Default queue offset */ /* length of permanent address message returned from PF */ #define IXGBE_VF_PERMADDR_MSG_LEN 4 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index d9291316ee9f..bb9256a1b0a9 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -387,6 +387,15 @@ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr) struct ixgbe_hw *hw = &adapter->hw; struct ptp_clock_event event; + event.type = PTP_CLOCK_PPS; + + /* this check is necessary in case the interrupt was enabled via some + * alternative means (ex. debug_fs). Better to check here than + * everywhere that calls this function. + */ + if (!adapter->ptp_clock) + return; + switch (hw->mac.type) { case ixgbe_mac_X540: ptp_clock_event(adapter->ptp_clock, &event); @@ -411,7 +420,7 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter) unsigned long elapsed_jiffies = adapter->last_overflow_check - jiffies; struct timespec ts; - if ((adapter->flags2 & IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED) && + if ((adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) && (elapsed_jiffies >= IXGBE_OVERFLOW_PERIOD)) { ixgbe_ptp_gettime(&adapter->ptp_caps, &ts); adapter->last_overflow_check = jiffies; @@ -554,12 +563,14 @@ void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, adapter = q_vector->adapter; hw = &adapter->hw; + if (likely(!ixgbe_ptp_match(skb, adapter->rx_hwtstamp_filter))) + return; + tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); /* Check if we have a valid timestamp and make sure the skb should * have been timestamped */ - if (likely(!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID) || - !ixgbe_ptp_match(skb, adapter->rx_hwtstamp_filter))) + if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID)) return; /* @@ -622,8 +633,7 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, struct hwtstamp_config config; u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED; u32 tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED; - u32 tsync_rx_mtrl = 0; - bool is_l4 = false; + u32 tsync_rx_mtrl = PTP_EV_PORT << 16; bool is_l2 = false; u32 regval; @@ -646,16 +656,15 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, switch (config.rx_filter) { case HWTSTAMP_FILTER_NONE: tsync_rx_ctl = 0; + tsync_rx_mtrl = 0; break; case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; - tsync_rx_mtrl = IXGBE_RXMTRL_V1_SYNC_MSG; - is_l4 = true; + tsync_rx_mtrl |= IXGBE_RXMTRL_V1_SYNC_MSG; break; case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; - tsync_rx_mtrl = IXGBE_RXMTRL_V1_DELAY_REQ_MSG; - is_l4 = true; + tsync_rx_mtrl |= IXGBE_RXMTRL_V1_DELAY_REQ_MSG; break; case HWTSTAMP_FILTER_PTP_V2_EVENT: case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: @@ -668,7 +677,6 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2; is_l2 = true; - is_l4 = true; config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; break; case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: @@ -693,42 +701,15 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, /* Store filter value for later use */ adapter->rx_hwtstamp_filter = config.rx_filter; - /* define ethertype filter for timestamped packets */ + /* define ethertype filter for timestamping L2 packets */ if (is_l2) - IXGBE_WRITE_REG(hw, IXGBE_ETQF(3), + IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), (IXGBE_ETQF_FILTER_EN | /* enable filter */ IXGBE_ETQF_1588 | /* enable timestamping */ ETH_P_1588)); /* 1588 eth protocol type */ else - IXGBE_WRITE_REG(hw, IXGBE_ETQF(3), 0); - -#define PTP_PORT 319 - /* L4 Queue Filter[3]: filter by destination port and protocol */ - if (is_l4) { - u32 ftqf = (IXGBE_FTQF_PROTOCOL_UDP /* UDP */ - | IXGBE_FTQF_POOL_MASK_EN /* Pool not compared */ - | IXGBE_FTQF_QUEUE_ENABLE); - - ftqf |= ((IXGBE_FTQF_PROTOCOL_COMP_MASK /* protocol check */ - & IXGBE_FTQF_DEST_PORT_MASK /* dest check */ - & IXGBE_FTQF_SOURCE_PORT_MASK) /* source check */ - << IXGBE_FTQF_5TUPLE_MASK_SHIFT); + IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), 0); - IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(3), - (3 << IXGBE_IMIR_RX_QUEUE_SHIFT_82599 | - IXGBE_IMIR_SIZE_BP_82599)); - - /* enable port check */ - IXGBE_WRITE_REG(hw, IXGBE_SDPQF(3), - (htons(PTP_PORT) | - htons(PTP_PORT) << 16)); - - IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), ftqf); - - tsync_rx_mtrl |= PTP_PORT << 16; - } else { - IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), 0); - } /* enable/disable TX */ regval = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); @@ -759,58 +740,20 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, * ixgbe_ptp_start_cyclecounter - create the cycle counter from hw * @adapter: pointer to the adapter structure * - * this function initializes the timecounter and cyclecounter - * structures for use in generated a ns counter from the arbitrary - * fixed point cycles registers in the hardware. - * - * A change in link speed impacts the frequency of the DMA clock on - * the device, which is used to generate the cycle counter - * registers. Therefor this function is called whenever the link speed - * changes. - * - * This function also turns on the SDP pin for clock out feature (X540 - * only), because this is where the shift is first calculated. + * This function should be called to set the proper values for the TIMINCA + * register and tell the cyclecounter structure what the tick rate of SYSTIME + * is. It does not directly modify SYSTIME registers or the timecounter + * structure. It should be called whenever a new TIMINCA value is necessary, + * such as during initialization or when the link speed changes. */ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; u32 incval = 0; - u32 timinca = 0; u32 shift = 0; - u32 cycle_speed; unsigned long flags; /** - * Determine what speed we need to set the cyclecounter - * for. It should be different for 100Mb, 1Gb, and 10Gb. Treat - * unknown speeds as 10Gb. (Hence why we can't just copy the - * link_speed. - */ - switch (adapter->link_speed) { - case IXGBE_LINK_SPEED_100_FULL: - case IXGBE_LINK_SPEED_1GB_FULL: - case IXGBE_LINK_SPEED_10GB_FULL: - cycle_speed = adapter->link_speed; - break; - default: - /* cycle speed should be 10Gb when there is no link */ - cycle_speed = IXGBE_LINK_SPEED_10GB_FULL; - break; - } - - /* - * grab the current TIMINCA value from the register so that it can be - * double checked. If the register value has been cleared, it must be - * reset to the correct value for generating a cyclecounter. If - * TIMINCA is zero, the SYSTIME registers do not increment at all. - */ - timinca = IXGBE_READ_REG(hw, IXGBE_TIMINCA); - - /* Bail if the cycle speed didn't change and TIMINCA is non-zero */ - if (adapter->cycle_speed == cycle_speed && timinca) - return; - - /** * Scale the NIC cycle counter by a large factor so that * relatively small corrections to the frequency can be added * or subtracted. The drawbacks of a large factor include @@ -819,8 +762,12 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) * to nanoseconds using only a multiplier and a right-shift, * and (c) the value must fit within the timinca register space * => math based on internal DMA clock rate and available bits + * + * Note that when there is no link, internal DMA clock is same as when + * link speed is 10Gb. Set the registers correctly even when link is + * down to preserve the clock setting */ - switch (cycle_speed) { + switch (adapter->link_speed) { case IXGBE_LINK_SPEED_100_FULL: incval = IXGBE_INCVAL_100; shift = IXGBE_INCVAL_SHIFT_100; @@ -830,6 +777,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) shift = IXGBE_INCVAL_SHIFT_1GB; break; case IXGBE_LINK_SPEED_10GB_FULL: + default: incval = IXGBE_INCVAL_10GB; shift = IXGBE_INCVAL_SHIFT_10GB; break; @@ -857,18 +805,11 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) return; } - /* reset the system time registers */ - IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000); - IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000); - IXGBE_WRITE_FLUSH(hw); - - /* store the new cycle speed */ - adapter->cycle_speed = cycle_speed; - + /* update the base incval used to calculate frequency adjustment */ ACCESS_ONCE(adapter->base_incval) = incval; smp_mb(); - /* grab the ptp lock */ + /* need lock to prevent incorrect read while modifying cyclecounter */ spin_lock_irqsave(&adapter->tmreg_lock, flags); memset(&adapter->cc, 0, sizeof(adapter->cc)); @@ -877,6 +818,31 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) adapter->cc.shift = shift; adapter->cc.mult = 1; + spin_unlock_irqrestore(&adapter->tmreg_lock, flags); +} + +/** + * ixgbe_ptp_reset + * @adapter: the ixgbe private board structure + * + * When the MAC resets, all timesync features are reset. This function should be + * called to re-enable the PTP clock structure. It will re-init the timecounter + * structure based on the kernel time as well as setup the cycle counter data. + */ +void ixgbe_ptp_reset(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + unsigned long flags; + + /* set SYSTIME registers to 0 just in case */ + IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000); + IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000); + IXGBE_WRITE_FLUSH(hw); + + ixgbe_ptp_start_cyclecounter(adapter); + + spin_lock_irqsave(&adapter->tmreg_lock, flags); + /* reset the ns time counter */ timecounter_init(&adapter->tc, &adapter->cc, ktime_to_ns(ktime_get_real())); @@ -904,7 +870,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter) switch (adapter->hw.mac.type) { case ixgbe_mac_X540: - snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); + snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 250000000; adapter->ptp_caps.n_alarm = 0; @@ -918,7 +884,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter) adapter->ptp_caps.enable = ixgbe_ptp_enable; break; case ixgbe_mac_82599EB: - snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); + snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 250000000; adapter->ptp_caps.n_alarm = 0; @@ -942,11 +908,6 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter) spin_lock_init(&adapter->tmreg_lock); - ixgbe_ptp_start_cyclecounter(adapter); - - /* (Re)start the overflow check */ - adapter->flags2 |= IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED; - adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps, &adapter->pdev->dev); if (IS_ERR(adapter->ptp_clock)) { @@ -955,6 +916,11 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter) } else e_dev_info("registered PHC device on %s\n", netdev->name); + ixgbe_ptp_reset(adapter); + + /* set the flag that PTP has been enabled */ + adapter->flags2 |= IXGBE_FLAG2_PTP_ENABLED; + return; } @@ -967,7 +933,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter) void ixgbe_ptp_stop(struct ixgbe_adapter *adapter) { /* stop the overflow check task */ - adapter->flags2 &= ~(IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED | + adapter->flags2 &= ~(IXGBE_FLAG2_PTP_ENABLED | IXGBE_FLAG2_PTP_PPS_ENABLED); ixgbe_ptp_setup_sdp(adapter); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index dce48bf64d96..85cddac673ef 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -117,6 +117,10 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter, } } + /* Initialize default switching mode VEB */ + IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); + adapter->flags2 |= IXGBE_FLAG2_BRIDGE_MODE_VEB; + /* If call to enable VFs succeeded then allocate memory * for per VF control structures. */ @@ -150,16 +154,6 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter, adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE | IXGBE_FLAG2_RSC_ENABLED); -#ifdef IXGBE_FCOE - /* - * When SR-IOV is enabled 82599 cannot support jumbo frames - * so we must disable FCoE because we cannot support FCoE MTU. - */ - if (adapter->hw.mac.type == ixgbe_mac_82599EB) - adapter->flags &= ~(IXGBE_FLAG_FCOE_ENABLED | - IXGBE_FLAG_FCOE_CAPABLE); -#endif - /* enable spoof checking for all VFs */ for (i = 0; i < adapter->num_vfs; i++) adapter->vfinfo[i].spoofchk_enabled = true; @@ -265,8 +259,11 @@ void ixgbe_disable_sriov(struct ixgbe_adapter *adapter) } static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, - int entries, u16 *hash_list, u32 vf) + u32 *msgbuf, u32 vf) { + int entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) + >> IXGBE_VT_MSGINFO_SHIFT; + u16 *hash_list = (u16 *)&msgbuf[1]; struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; struct ixgbe_hw *hw = &adapter->hw; int i; @@ -353,31 +350,89 @@ static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add); } -static void ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf) +static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf) { struct ixgbe_hw *hw = &adapter->hw; - int new_mtu = msgbuf[1]; + int max_frame = msgbuf[1]; u32 max_frs; - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - /* Only X540 supports jumbo frames in IOV mode */ - if (adapter->hw.mac.type != ixgbe_mac_X540) - return; + /* + * For 82599EB we have to keep all PFs and VFs operating with + * the same max_frame value in order to avoid sending an oversize + * frame to a VF. In order to guarantee this is handled correctly + * for all cases we have several special exceptions to take into + * account before we can enable the VF for receive + */ + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + struct net_device *dev = adapter->netdev; + int pf_max_frame = dev->mtu + ETH_HLEN; + u32 reg_offset, vf_shift, vfre; + s32 err = 0; + +#ifdef CONFIG_FCOE + if (dev->features & NETIF_F_FCOE_MTU) + pf_max_frame = max_t(int, pf_max_frame, + IXGBE_FCOE_JUMBO_FRAME_SIZE); + +#endif /* CONFIG_FCOE */ + switch (adapter->vfinfo[vf].vf_api) { + case ixgbe_mbox_api_11: + /* + * Version 1.1 supports jumbo frames on VFs if PF has + * jumbo frames enabled which means legacy VFs are + * disabled + */ + if (pf_max_frame > ETH_FRAME_LEN) + break; + default: + /* + * If the PF or VF are running w/ jumbo frames enabled + * we need to shut down the VF Rx path as we cannot + * support jumbo frames on legacy VFs + */ + if ((pf_max_frame > ETH_FRAME_LEN) || + (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN))) + err = -EINVAL; + break; + } + + /* determine VF receive enable location */ + vf_shift = vf % 32; + reg_offset = vf / 32; + + /* enable or disable receive depending on error */ + vfre = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset)); + if (err) + vfre &= ~(1 << vf_shift); + else + vfre |= 1 << vf_shift; + IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), vfre); + + if (err) { + e_err(drv, "VF max_frame %d out of range\n", max_frame); + return err; + } + } /* MTU < 68 is an error and causes problems on some kernels */ - if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) { - e_err(drv, "VF mtu %d out of range\n", new_mtu); - return; + if (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE) { + e_err(drv, "VF max_frame %d out of range\n", max_frame); + return -EINVAL; } - max_frs = (IXGBE_READ_REG(hw, IXGBE_MAXFRS) & - IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT; - if (max_frs < new_mtu) { - max_frs = new_mtu << IXGBE_MHADD_MFS_SHIFT; + /* pull current max frame size from hardware */ + max_frs = IXGBE_READ_REG(hw, IXGBE_MAXFRS); + max_frs &= IXGBE_MHADD_MFS_MASK; + max_frs >>= IXGBE_MHADD_MFS_SHIFT; + + if (max_frs < max_frame) { + max_frs = max_frame << IXGBE_MHADD_MFS_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, max_frs); } - e_info(hw, "VF requests change max MTU to %d\n", new_mtu); + e_info(hw, "VF requests change max MTU to %d\n", max_frame); + + return 0; } static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe) @@ -392,35 +447,47 @@ static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe) IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr); } -static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, u32 vid, u32 vf) +static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, + u16 vid, u16 qos, u32 vf) { struct ixgbe_hw *hw = &adapter->hw; + u32 vmvir = vid | (qos << VLAN_PRIO_SHIFT) | IXGBE_VMVIR_VLANA_DEFAULT; - if (vid) - IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), - (vid | IXGBE_VMVIR_VLANA_DEFAULT)); - else - IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0); + IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), vmvir); } +static void ixgbe_clear_vmvir(struct ixgbe_adapter *adapter, u32 vf) +{ + struct ixgbe_hw *hw = &adapter->hw; + + IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0); +} static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) { struct ixgbe_hw *hw = &adapter->hw; + struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; int rar_entry = hw->mac.num_rar_entries - (vf + 1); + u8 num_tcs = netdev_get_num_tc(adapter->netdev); + + /* add PF assigned VLAN or VLAN 0 */ + ixgbe_set_vf_vlan(adapter, true, vfinfo->pf_vlan, vf); /* reset offloads to defaults */ - if (adapter->vfinfo[vf].pf_vlan) { - ixgbe_set_vf_vlan(adapter, true, - adapter->vfinfo[vf].pf_vlan, vf); - ixgbe_set_vmvir(adapter, - (adapter->vfinfo[vf].pf_vlan | - (adapter->vfinfo[vf].pf_qos << - VLAN_PRIO_SHIFT)), vf); - ixgbe_set_vmolr(hw, vf, false); + ixgbe_set_vmolr(hw, vf, !vfinfo->pf_vlan); + + /* set outgoing tags for VFs */ + if (!vfinfo->pf_vlan && !vfinfo->pf_qos && !num_tcs) { + ixgbe_clear_vmvir(adapter, vf); } else { - ixgbe_set_vf_vlan(adapter, true, 0, vf); - ixgbe_set_vmvir(adapter, 0, vf); - ixgbe_set_vmolr(hw, vf, true); + if (vfinfo->pf_qos || !num_tcs) + ixgbe_set_vmvir(adapter, vfinfo->pf_vlan, + vfinfo->pf_qos, vf); + else + ixgbe_set_vmvir(adapter, vfinfo->pf_vlan, + adapter->default_up, vf); + + if (vfinfo->spoofchk_enabled) + hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); } /* reset multicast table array for vf */ @@ -430,6 +497,9 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) ixgbe_set_rx_mode(adapter->netdev); hw->mac.ops.clear_rar(hw, rar_entry); + + /* reset VF api back to unknown */ + adapter->vfinfo[vf].vf_api = ixgbe_mbox_api_10; } static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, @@ -521,30 +591,221 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) return 0; } -static inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) +static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) { struct ixgbe_hw *hw = &adapter->hw; - u32 reg; + unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses; + u32 reg, msgbuf[4]; u32 reg_offset, vf_shift; + u8 *addr = (u8 *)(&msgbuf[1]); + + e_info(probe, "VF Reset msg received from vf %d\n", vf); + + /* reset the filters for the device */ + ixgbe_vf_reset_event(adapter, vf); + + /* set vf mac address */ + ixgbe_set_vf_mac(adapter, vf, vf_mac); vf_shift = vf % 32; reg_offset = vf / 32; - /* enable transmit and receive for vf */ + /* enable transmit for vf */ reg = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset)); - reg |= (reg | (1 << vf_shift)); + reg |= 1 << vf_shift; IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg); + /* enable receive for vf */ reg = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset)); - reg |= (reg | (1 << vf_shift)); + reg |= 1 << vf_shift; + /* + * The 82599 cannot support a mix of jumbo and non-jumbo PF/VFs. + * For more info take a look at ixgbe_set_vf_lpe + */ + if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + struct net_device *dev = adapter->netdev; + int pf_max_frame = dev->mtu + ETH_HLEN; + +#ifdef CONFIG_FCOE + if (dev->features & NETIF_F_FCOE_MTU) + pf_max_frame = max_t(int, pf_max_frame, + IXGBE_FCOE_JUMBO_FRAME_SIZE); + +#endif /* CONFIG_FCOE */ + if (pf_max_frame > ETH_FRAME_LEN) + reg &= ~(1 << vf_shift); + } IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg); + /* enable VF mailbox for further messages */ + adapter->vfinfo[vf].clear_to_send = true; + /* Enable counting of spoofed packets in the SSVPC register */ reg = IXGBE_READ_REG(hw, IXGBE_VMECM(reg_offset)); reg |= (1 << vf_shift); IXGBE_WRITE_REG(hw, IXGBE_VMECM(reg_offset), reg); - ixgbe_vf_reset_event(adapter, vf); + /* reply to reset with ack and vf mac address */ + msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK; + memcpy(addr, vf_mac, ETH_ALEN); + + /* + * Piggyback the multicast filter type so VF can compute the + * correct vectors + */ + msgbuf[3] = hw->mac.mc_filter_type; + ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf); + + return 0; +} + +static int ixgbe_set_vf_mac_addr(struct ixgbe_adapter *adapter, + u32 *msgbuf, u32 vf) +{ + u8 *new_mac = ((u8 *)(&msgbuf[1])); + + if (!is_valid_ether_addr(new_mac)) { + e_warn(drv, "VF %d attempted to set invalid mac\n", vf); + return -1; + } + + if (adapter->vfinfo[vf].pf_set_mac && + memcmp(adapter->vfinfo[vf].vf_mac_addresses, new_mac, + ETH_ALEN)) { + e_warn(drv, + "VF %d attempted to override administratively set MAC address\n" + "Reload the VF driver to resume operations\n", + vf); + return -1; + } + + return ixgbe_set_vf_mac(adapter, vf, new_mac) < 0; +} + +static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter, + u32 *msgbuf, u32 vf) +{ + struct ixgbe_hw *hw = &adapter->hw; + int add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT; + int vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK); + int err; + u8 tcs = netdev_get_num_tc(adapter->netdev); + + if (adapter->vfinfo[vf].pf_vlan || tcs) { + e_warn(drv, + "VF %d attempted to override administratively set VLAN configuration\n" + "Reload the VF driver to resume operations\n", + vf); + return -1; + } + + if (add) + adapter->vfinfo[vf].vlan_count++; + else if (adapter->vfinfo[vf].vlan_count) + adapter->vfinfo[vf].vlan_count--; + + err = ixgbe_set_vf_vlan(adapter, add, vid, vf); + if (!err && adapter->vfinfo[vf].spoofchk_enabled) + hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); + + return err; +} + +static int ixgbe_set_vf_macvlan_msg(struct ixgbe_adapter *adapter, + u32 *msgbuf, u32 vf) +{ + u8 *new_mac = ((u8 *)(&msgbuf[1])); + int index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> + IXGBE_VT_MSGINFO_SHIFT; + int err; + + if (adapter->vfinfo[vf].pf_set_mac && index > 0) { + e_warn(drv, + "VF %d requested MACVLAN filter but is administratively denied\n", + vf); + return -1; + } + + /* An non-zero index indicates the VF is setting a filter */ + if (index) { + if (!is_valid_ether_addr(new_mac)) { + e_warn(drv, "VF %d attempted to set invalid mac\n", vf); + return -1; + } + + /* + * If the VF is allowed to set MAC filters then turn off + * anti-spoofing to avoid false positives. + */ + if (adapter->vfinfo[vf].spoofchk_enabled) + ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false); + } + + err = ixgbe_set_vf_macvlan(adapter, vf, index, new_mac); + if (err == -ENOSPC) + e_warn(drv, + "VF %d has requested a MACVLAN filter but there is no space for it\n", + vf); + + return err < 0; +} + +static int ixgbe_negotiate_vf_api(struct ixgbe_adapter *adapter, + u32 *msgbuf, u32 vf) +{ + int api = msgbuf[1]; + + switch (api) { + case ixgbe_mbox_api_10: + case ixgbe_mbox_api_11: + adapter->vfinfo[vf].vf_api = api; + return 0; + default: + break; + } + + e_info(drv, "VF %d requested invalid api version %u\n", vf, api); + + return -1; +} + +static int ixgbe_get_vf_queues(struct ixgbe_adapter *adapter, + u32 *msgbuf, u32 vf) +{ + struct net_device *dev = adapter->netdev; + struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; + unsigned int default_tc = 0; + u8 num_tcs = netdev_get_num_tc(dev); + + /* verify the PF is supporting the correct APIs */ + switch (adapter->vfinfo[vf].vf_api) { + case ixgbe_mbox_api_20: + case ixgbe_mbox_api_11: + break; + default: + return -1; + } + + /* only allow 1 Tx queue for bandwidth limiting */ + msgbuf[IXGBE_VF_TX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask); + msgbuf[IXGBE_VF_RX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask); + + /* if TCs > 1 determine which TC belongs to default user priority */ + if (num_tcs > 1) + default_tc = netdev_get_prio_tc_map(dev, adapter->default_up); + + /* notify VF of need for VLAN tag stripping, and correct queue */ + if (num_tcs) + msgbuf[IXGBE_VF_TRANS_VLAN] = num_tcs; + else if (adapter->vfinfo[vf].pf_vlan || adapter->vfinfo[vf].pf_qos) + msgbuf[IXGBE_VF_TRANS_VLAN] = 1; + else + msgbuf[IXGBE_VF_TRANS_VLAN] = 0; + + /* notify VF of default queue */ + msgbuf[IXGBE_VF_DEF_QUEUE] = default_tc; + + return 0; } static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) @@ -553,10 +814,6 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) u32 msgbuf[IXGBE_VFMAILBOX_SIZE]; struct ixgbe_hw *hw = &adapter->hw; s32 retval; - int entries; - u16 *hash_list; - int add, vid, index; - u8 *new_mac; retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf); @@ -572,39 +829,13 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) /* flush the ack before we write any messages back */ IXGBE_WRITE_FLUSH(hw); + if (msgbuf[0] == IXGBE_VF_RESET) + return ixgbe_vf_reset_msg(adapter, vf); + /* * until the vf completes a virtual function reset it should not be * allowed to start any configuration. */ - - if (msgbuf[0] == IXGBE_VF_RESET) { - unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses; - new_mac = (u8 *)(&msgbuf[1]); - e_info(probe, "VF Reset msg received from vf %d\n", vf); - adapter->vfinfo[vf].clear_to_send = false; - ixgbe_vf_reset_msg(adapter, vf); - adapter->vfinfo[vf].clear_to_send = true; - - if (is_valid_ether_addr(new_mac) && - !adapter->vfinfo[vf].pf_set_mac) - ixgbe_set_vf_mac(adapter, vf, vf_mac); - else - ixgbe_set_vf_mac(adapter, - vf, adapter->vfinfo[vf].vf_mac_addresses); - - /* reply to reset with ack and vf mac address */ - msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK; - memcpy(new_mac, vf_mac, ETH_ALEN); - /* - * Piggyback the multicast filter type so VF can compute the - * correct vectors - */ - msgbuf[3] = hw->mac.mc_filter_type; - ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf); - - return retval; - } - if (!adapter->vfinfo[vf].clear_to_send) { msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK; ixgbe_write_mbx(hw, msgbuf, 1, vf); @@ -613,70 +844,25 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) switch ((msgbuf[0] & 0xFFFF)) { case IXGBE_VF_SET_MAC_ADDR: - new_mac = ((u8 *)(&msgbuf[1])); - if (is_valid_ether_addr(new_mac) && - !adapter->vfinfo[vf].pf_set_mac) { - ixgbe_set_vf_mac(adapter, vf, new_mac); - } else if (memcmp(adapter->vfinfo[vf].vf_mac_addresses, - new_mac, ETH_ALEN)) { - e_warn(drv, "VF %d attempted to override " - "administratively set MAC address\nReload " - "the VF driver to resume operations\n", vf); - retval = -1; - } + retval = ixgbe_set_vf_mac_addr(adapter, msgbuf, vf); break; case IXGBE_VF_SET_MULTICAST: - entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) - >> IXGBE_VT_MSGINFO_SHIFT; - hash_list = (u16 *)&msgbuf[1]; - retval = ixgbe_set_vf_multicasts(adapter, entries, - hash_list, vf); - break; - case IXGBE_VF_SET_LPE: - ixgbe_set_vf_lpe(adapter, msgbuf); + retval = ixgbe_set_vf_multicasts(adapter, msgbuf, vf); break; case IXGBE_VF_SET_VLAN: - add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) - >> IXGBE_VT_MSGINFO_SHIFT; - vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK); - if (adapter->vfinfo[vf].pf_vlan) { - e_warn(drv, "VF %d attempted to override " - "administratively set VLAN configuration\n" - "Reload the VF driver to resume operations\n", - vf); - retval = -1; - } else { - if (add) - adapter->vfinfo[vf].vlan_count++; - else if (adapter->vfinfo[vf].vlan_count) - adapter->vfinfo[vf].vlan_count--; - retval = ixgbe_set_vf_vlan(adapter, add, vid, vf); - if (!retval && adapter->vfinfo[vf].spoofchk_enabled) - hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); - } + retval = ixgbe_set_vf_vlan_msg(adapter, msgbuf, vf); + break; + case IXGBE_VF_SET_LPE: + retval = ixgbe_set_vf_lpe(adapter, msgbuf, vf); break; case IXGBE_VF_SET_MACVLAN: - index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> - IXGBE_VT_MSGINFO_SHIFT; - if (adapter->vfinfo[vf].pf_set_mac && index > 0) { - e_warn(drv, "VF %d requested MACVLAN filter but is " - "administratively denied\n", vf); - retval = -1; - break; - } - /* - * If the VF is allowed to set MAC filters then turn off - * anti-spoofing to avoid false positives. An index - * greater than 0 will indicate the VF is setting a - * macvlan MAC filter. - */ - if (index > 0 && adapter->vfinfo[vf].spoofchk_enabled) - ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false); - retval = ixgbe_set_vf_macvlan(adapter, vf, index, - (unsigned char *)(&msgbuf[1])); - if (retval == -ENOSPC) - e_warn(drv, "VF %d has requested a MACVLAN filter " - "but there is no space for it\n", vf); + retval = ixgbe_set_vf_macvlan_msg(adapter, msgbuf, vf); + break; + case IXGBE_VF_API_NEGOTIATE: + retval = ixgbe_negotiate_vf_api(adapter, msgbuf, vf); + break; + case IXGBE_VF_GET_QUEUES: + retval = ixgbe_get_vf_queues(adapter, msgbuf, vf); break; default: e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]); @@ -692,7 +878,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) msgbuf[0] |= IXGBE_VT_MSGTYPE_CTS; - ixgbe_write_mbx(hw, msgbuf, 1, vf); + ixgbe_write_mbx(hw, msgbuf, mbx_size, vf); return retval; } @@ -783,7 +969,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) err = ixgbe_set_vf_vlan(adapter, true, vlan, vf); if (err) goto out; - ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf); + ixgbe_set_vmvir(adapter, vlan, qos, vf); ixgbe_set_vmolr(hw, vf, false); if (adapter->vfinfo[vf].spoofchk_enabled) hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); @@ -803,7 +989,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) } else { err = ixgbe_set_vf_vlan(adapter, false, adapter->vfinfo[vf].pf_vlan, vf); - ixgbe_set_vmvir(adapter, vlan, vf); + ixgbe_clear_vmvir(adapter, vf); ixgbe_set_vmolr(hw, vf, true); hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf); if (adapter->vfinfo[vf].vlan_count) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 0722f3368092..9cd8a13711d3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -56,6 +56,7 @@ #define IXGBE_SUBDEV_ID_82599_SFP 0x11A9 #define IXGBE_SUBDEV_ID_82599_RNDC 0x1F72 #define IXGBE_SUBDEV_ID_82599_560FLR 0x17D0 +#define IXGBE_SUBDEV_ID_82599_ECNA_DP 0x0470 #define IXGBE_DEV_ID_82599_SFP_EM 0x1507 #define IXGBE_DEV_ID_82599_SFP_SF2 0x154D #define IXGBE_DEV_ID_82599EN_SFP 0x1557 @@ -1833,15 +1834,6 @@ enum { /* Number of 100 microseconds we wait for PCI Express master disable */ #define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800 -/* Check whether address is multicast. This is little-endian specific check.*/ -#define IXGBE_IS_MULTICAST(Address) \ - (bool)(((u8 *)(Address))[0] & ((u8)0x01)) - -/* Check whether an address is broadcast. */ -#define IXGBE_IS_BROADCAST(Address) \ - ((((u8 *)(Address))[0] == ((u8)0xff)) && \ - (((u8 *)(Address))[1] == ((u8)0xff))) - /* RAH */ #define IXGBE_RAH_VIND_MASK 0x003C0000 #define IXGBE_RAH_VIND_SHIFT 18 @@ -1962,6 +1954,8 @@ enum { #define IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP 0x01000000 #define IXGBE_MRQC_L3L4TXSWEN 0x00008000 +#define IXGBE_FWSM_TS_ENABLED 0x1 + /* Queue Drop Enable */ #define IXGBE_QDE_ENABLE 0x00000001 #define IXGBE_QDE_IDX_MASK 0x00007F00 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index de4da5219b71..c73b92993391 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -152,7 +152,7 @@ mac_reset_top: hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); /* Add the SAN MAC address to the RAR only if it's a valid address */ - if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) { + if (is_valid_ether_addr(hw->mac.san_addr)) { hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1, hw->mac.san_addr, 0, IXGBE_RAH_AV); diff --git a/drivers/net/ethernet/intel/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h index da17ccf5c09d..3147795bd135 100644 --- a/drivers/net/ethernet/intel/ixgbevf/defines.h +++ b/drivers/net/ethernet/intel/ixgbevf/defines.h @@ -33,8 +33,11 @@ #define IXGBE_DEV_ID_X540_VF 0x1515 #define IXGBE_VF_IRQ_CLEAR_MASK 7 -#define IXGBE_VF_MAX_TX_QUEUES 1 -#define IXGBE_VF_MAX_RX_QUEUES 1 +#define IXGBE_VF_MAX_TX_QUEUES 8 +#define IXGBE_VF_MAX_RX_QUEUES 8 + +/* DCB define */ +#define IXGBE_VF_MAX_TRAFFIC_CLASS 8 /* Link speed */ typedef u32 ixgbe_link_speed; diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 4a9c9c285685..fc0af9a3bb35 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -58,7 +58,6 @@ struct ixgbevf_ring { struct ixgbevf_ring *next; struct net_device *netdev; struct device *dev; - struct ixgbevf_adapter *adapter; /* backlink */ void *desc; /* descriptor ring memory */ dma_addr_t dma; /* phys. address of descriptor ring */ unsigned int size; /* length in bytes */ @@ -75,6 +74,8 @@ struct ixgbevf_ring { u64 total_bytes; u64 total_packets; struct u64_stats_sync syncp; + u64 hw_csum_rx_error; + u64 hw_csum_rx_good; u16 head; u16 tail; @@ -89,8 +90,8 @@ struct ixgbevf_ring { /* How many Rx Buffers do we bundle into one write to the hardware ? */ #define IXGBEVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */ -#define MAX_RX_QUEUES 1 -#define MAX_TX_QUEUES 1 +#define MAX_RX_QUEUES IXGBE_VF_MAX_RX_QUEUES +#define MAX_TX_QUEUES IXGBE_VF_MAX_TX_QUEUES #define IXGBEVF_DEFAULT_TXD 1024 #define IXGBEVF_DEFAULT_RXD 512 @@ -101,10 +102,10 @@ struct ixgbevf_ring { /* Supported Rx Buffer Sizes */ #define IXGBEVF_RXBUFFER_256 256 /* Used for packet split */ -#define IXGBEVF_RXBUFFER_3K 3072 -#define IXGBEVF_RXBUFFER_7K 7168 -#define IXGBEVF_RXBUFFER_15K 15360 -#define IXGBEVF_MAX_RXBUFFER 16384 /* largest size for single descriptor */ +#define IXGBEVF_RXBUFFER_2K 2048 +#define IXGBEVF_RXBUFFER_4K 4096 +#define IXGBEVF_RXBUFFER_8K 8192 +#define IXGBEVF_RXBUFFER_10K 10240 #define IXGBEVF_RX_HDR_SIZE IXGBEVF_RXBUFFER_256 @@ -229,6 +230,7 @@ struct ixgbevf_adapter { */ u32 flags; #define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1) +#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 1) /* OS defined structs */ struct net_device *netdev; diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index de1ad506665d..257357ae66c3 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -58,7 +58,7 @@ const char ixgbevf_driver_name[] = "ixgbevf"; static const char ixgbevf_driver_string[] = "Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver"; -#define DRV_VERSION "2.6.0-k" +#define DRV_VERSION "2.7.12-k" const char ixgbevf_driver_version[] = DRV_VERSION; static char ixgbevf_copyright[] = "Copyright (c) 2009 - 2012 Intel Corporation."; @@ -99,6 +99,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); /* forward decls */ static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector); +static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter); static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw, struct ixgbevf_ring *rx_ring, @@ -120,7 +121,6 @@ static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw, * @direction: 0 for Rx, 1 for Tx, -1 for other causes * @queue: queue to map the corresponding interrupt to * @msix_vector: the vector to map to the corresponding queue - * */ static void ixgbevf_set_ivar(struct ixgbevf_adapter *adapter, s8 direction, u8 queue, u8 msix_vector) @@ -287,17 +287,19 @@ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector, if (is_vlan && test_bit(tag & VLAN_VID_MASK, adapter->active_vlans)) __vlan_hwaccel_put_tag(skb, tag); - napi_gro_receive(&q_vector->napi, skb); + if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) + napi_gro_receive(&q_vector->napi, skb); + else + netif_rx(skb); } /** * ixgbevf_rx_checksum - indicate in skb if hw indicated a good cksum - * @adapter: address of board private structure + * @ring: pointer to Rx descriptor ring structure * @status_err: hardware indication of status of receive * @skb: skb currently being received and modified **/ -static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter, - struct ixgbevf_ring *ring, +static inline void ixgbevf_rx_checksum(struct ixgbevf_ring *ring, u32 status_err, struct sk_buff *skb) { skb_checksum_none_assert(skb); @@ -309,7 +311,7 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter, /* if IP and error */ if ((status_err & IXGBE_RXD_STAT_IPCS) && (status_err & IXGBE_RXDADV_ERR_IPE)) { - adapter->hw_csum_rx_error++; + ring->hw_csum_rx_error++; return; } @@ -317,13 +319,13 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter, return; if (status_err & IXGBE_RXDADV_ERR_TCPE) { - adapter->hw_csum_rx_error++; + ring->hw_csum_rx_error++; return; } /* It must be a TCP or UDP packet with a valid checksum */ skb->ip_summed = CHECKSUM_UNNECESSARY; - adapter->hw_csum_rx_good++; + ring->hw_csum_rx_good++; } /** @@ -337,15 +339,16 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter, struct pci_dev *pdev = adapter->pdev; union ixgbe_adv_rx_desc *rx_desc; struct ixgbevf_rx_buffer *bi; - struct sk_buff *skb; unsigned int i = rx_ring->next_to_use; bi = &rx_ring->rx_buffer_info[i]; while (cleaned_count--) { rx_desc = IXGBEVF_RX_DESC(rx_ring, i); - skb = bi->skb; - if (!skb) { + + if (!bi->skb) { + struct sk_buff *skb; + skb = netdev_alloc_skb_ip_align(rx_ring->netdev, rx_ring->rx_buf_len); if (!skb) { @@ -353,11 +356,16 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter, goto no_buffers; } bi->skb = skb; - } - if (!bi->dma) { + bi->dma = dma_map_single(&pdev->dev, skb->data, rx_ring->rx_buf_len, DMA_FROM_DEVICE); + if (dma_mapping_error(&pdev->dev, bi->dma)) { + dev_kfree_skb(skb); + bi->skb = NULL; + dev_err(&pdev->dev, "RX DMA map failed\n"); + break; + } } rx_desc->read.pkt_addr = cpu_to_le64(bi->dma); @@ -370,7 +378,6 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter, no_buffers: if (rx_ring->next_to_use != i) { rx_ring->next_to_use = i; - ixgbevf_release_rx_desc(&adapter->hw, rx_ring, i); } } @@ -454,7 +461,7 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, goto next_desc; } - ixgbevf_rx_checksum(adapter, rx_ring, staterr, skb); + ixgbevf_rx_checksum(rx_ring, staterr, skb); /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; @@ -471,6 +478,16 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, } skb->protocol = eth_type_trans(skb, rx_ring->netdev); + /* Workaround hardware that can't do proper VEPA multicast + * source pruning. + */ + if ((skb->pkt_type & (PACKET_BROADCAST | PACKET_MULTICAST)) && + !(compare_ether_addr(adapter->netdev->dev_addr, + eth_hdr(skb)->h_source))) { + dev_kfree_skb_irq(skb); + goto next_desc; + } + ixgbevf_receive_skb(q_vector, skb, staterr, rx_desc); next_desc: @@ -533,9 +550,11 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget) else per_ring_budget = budget; + adapter->flags |= IXGBE_FLAG_IN_NETPOLL; ixgbevf_for_each_ring(ring, q_vector->rx) clean_complete &= ixgbevf_clean_rx_irq(q_vector, ring, per_ring_budget); + adapter->flags &= ~IXGBE_FLAG_IN_NETPOLL; /* If all work not completed, return budget and keep polling */ if (!clean_complete) @@ -743,7 +762,6 @@ static irqreturn_t ixgbevf_msix_other(int irq, void *data) return IRQ_HANDLED; } - /** * ixgbevf_msix_clean_rings - single unshared vector rx clean (all queues) * @irq: unused @@ -1065,20 +1083,20 @@ static void ixgbevf_set_rx_buffer_len(struct ixgbevf_adapter *adapter) max_frame += VLAN_HLEN; /* - * Make best use of allocation by using all but 1K of a - * power of 2 allocation that will be used for skb->head. + * Allocate buffer sizes that fit well into 32K and + * take into account max frame size of 9.5K */ if ((hw->mac.type == ixgbe_mac_X540_vf) && (max_frame <= MAXIMUM_ETHERNET_VLAN_SIZE)) rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE; - else if (max_frame <= IXGBEVF_RXBUFFER_3K) - rx_buf_len = IXGBEVF_RXBUFFER_3K; - else if (max_frame <= IXGBEVF_RXBUFFER_7K) - rx_buf_len = IXGBEVF_RXBUFFER_7K; - else if (max_frame <= IXGBEVF_RXBUFFER_15K) - rx_buf_len = IXGBEVF_RXBUFFER_15K; + else if (max_frame <= IXGBEVF_RXBUFFER_2K) + rx_buf_len = IXGBEVF_RXBUFFER_2K; + else if (max_frame <= IXGBEVF_RXBUFFER_4K) + rx_buf_len = IXGBEVF_RXBUFFER_4K; + else if (max_frame <= IXGBEVF_RXBUFFER_8K) + rx_buf_len = IXGBEVF_RXBUFFER_8K; else - rx_buf_len = IXGBEVF_MAX_RXBUFFER; + rx_buf_len = IXGBEVF_RXBUFFER_10K; for (i = 0; i < adapter->num_rx_queues; i++) adapter->rx_ring[i].rx_buf_len = rx_buf_len; @@ -1128,15 +1146,12 @@ static int ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid) struct ixgbe_hw *hw = &adapter->hw; int err; - if (!hw->mac.ops.set_vfta) - return -EOPNOTSUPP; - - spin_lock(&adapter->mbx_lock); + spin_lock_bh(&adapter->mbx_lock); /* add VID to filter table */ err = hw->mac.ops.set_vfta(hw, vid, 0, true); - spin_unlock(&adapter->mbx_lock); + spin_unlock_bh(&adapter->mbx_lock); /* translate error return types so error makes sense */ if (err == IXGBE_ERR_MBX) @@ -1156,13 +1171,12 @@ static int ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) struct ixgbe_hw *hw = &adapter->hw; int err = -EOPNOTSUPP; - spin_lock(&adapter->mbx_lock); + spin_lock_bh(&adapter->mbx_lock); /* remove VID from filter table */ - if (hw->mac.ops.set_vfta) - err = hw->mac.ops.set_vfta(hw, vid, 0, false); + err = hw->mac.ops.set_vfta(hw, vid, 0, false); - spin_unlock(&adapter->mbx_lock); + spin_unlock_bh(&adapter->mbx_lock); clear_bit(vid, adapter->active_vlans); @@ -1206,27 +1220,27 @@ static int ixgbevf_write_uc_addr_list(struct net_device *netdev) } /** - * ixgbevf_set_rx_mode - Multicast set + * ixgbevf_set_rx_mode - Multicast and unicast set * @netdev: network interface device structure * * The set_rx_method entry point is called whenever the multicast address - * list or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper multicast mode. + * list, unicast address list or the network interface flags are updated. + * This routine is responsible for configuring the hardware for proper + * multicast mode and configuring requested unicast filters. **/ static void ixgbevf_set_rx_mode(struct net_device *netdev) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; - spin_lock(&adapter->mbx_lock); + spin_lock_bh(&adapter->mbx_lock); /* reprogram multicast list */ - if (hw->mac.ops.update_mc_addr_list) - hw->mac.ops.update_mc_addr_list(hw, netdev); + hw->mac.ops.update_mc_addr_list(hw, netdev); ixgbevf_write_uc_addr_list(netdev); - spin_unlock(&adapter->mbx_lock); + spin_unlock_bh(&adapter->mbx_lock); } static void ixgbevf_napi_enable_all(struct ixgbevf_adapter *adapter) @@ -1290,8 +1304,8 @@ static inline void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter, "not set within the polling period\n", rxr); } - ixgbevf_release_rx_desc(&adapter->hw, &adapter->rx_ring[rxr], - (adapter->rx_ring[rxr].count - 1)); + ixgbevf_release_rx_desc(hw, &adapter->rx_ring[rxr], + adapter->rx_ring[rxr].count - 1); } static void ixgbevf_save_reset_stats(struct ixgbevf_adapter *adapter) @@ -1335,11 +1349,12 @@ static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter) static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - int api[] = { ixgbe_mbox_api_10, + int api[] = { ixgbe_mbox_api_11, + ixgbe_mbox_api_10, ixgbe_mbox_api_unknown }; int err = 0, idx = 0; - spin_lock(&adapter->mbx_lock); + spin_lock_bh(&adapter->mbx_lock); while (api[idx] != ixgbe_mbox_api_unknown) { err = ixgbevf_negotiate_api_version(hw, api[idx]); @@ -1348,7 +1363,7 @@ static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter) idx++; } - spin_unlock(&adapter->mbx_lock); + spin_unlock_bh(&adapter->mbx_lock); } static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter) @@ -1389,16 +1404,14 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter) ixgbevf_configure_msix(adapter); - spin_lock(&adapter->mbx_lock); + spin_lock_bh(&adapter->mbx_lock); - if (hw->mac.ops.set_rar) { - if (is_valid_ether_addr(hw->mac.addr)) - hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0); - else - hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0); - } + if (is_valid_ether_addr(hw->mac.addr)) + hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0); + else + hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0); - spin_unlock(&adapter->mbx_lock); + spin_unlock_bh(&adapter->mbx_lock); clear_bit(__IXGBEVF_DOWN, &adapter->state); ixgbevf_napi_enable_all(adapter); @@ -1413,12 +1426,87 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter) mod_timer(&adapter->watchdog_timer, jiffies); } +static int ixgbevf_reset_queues(struct ixgbevf_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + struct ixgbevf_ring *rx_ring; + unsigned int def_q = 0; + unsigned int num_tcs = 0; + unsigned int num_rx_queues = 1; + int err, i; + + spin_lock_bh(&adapter->mbx_lock); + + /* fetch queue configuration from the PF */ + err = ixgbevf_get_queues(hw, &num_tcs, &def_q); + + spin_unlock_bh(&adapter->mbx_lock); + + if (err) + return err; + + if (num_tcs > 1) { + /* update default Tx ring register index */ + adapter->tx_ring[0].reg_idx = def_q; + + /* we need as many queues as traffic classes */ + num_rx_queues = num_tcs; + } + + /* nothing to do if we have the correct number of queues */ + if (adapter->num_rx_queues == num_rx_queues) + return 0; + + /* allocate new rings */ + rx_ring = kcalloc(num_rx_queues, + sizeof(struct ixgbevf_ring), GFP_KERNEL); + if (!rx_ring) + return -ENOMEM; + + /* setup ring fields */ + for (i = 0; i < num_rx_queues; i++) { + rx_ring[i].count = adapter->rx_ring_count; + rx_ring[i].queue_index = i; + rx_ring[i].reg_idx = i; + rx_ring[i].dev = &adapter->pdev->dev; + rx_ring[i].netdev = adapter->netdev; + + /* allocate resources on the ring */ + err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]); + if (err) { + while (i) { + i--; + ixgbevf_free_rx_resources(adapter, &rx_ring[i]); + } + kfree(rx_ring); + return err; + } + } + + /* free the existing rings and queues */ + ixgbevf_free_all_rx_resources(adapter); + adapter->num_rx_queues = 0; + kfree(adapter->rx_ring); + + /* move new rings into position on the adapter struct */ + adapter->rx_ring = rx_ring; + adapter->num_rx_queues = num_rx_queues; + + /* reset ring to vector mapping */ + ixgbevf_reset_q_vectors(adapter); + ixgbevf_map_rings_to_vectors(adapter); + + return 0; +} + void ixgbevf_up(struct ixgbevf_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; ixgbevf_negotiate_api(adapter); + ixgbevf_reset_queues(adapter); + ixgbevf_configure(adapter); ixgbevf_up_complete(adapter); @@ -1497,7 +1585,6 @@ static void ixgbevf_clean_tx_ring(struct ixgbevf_adapter *adapter, return; /* Free all the Tx ring sk_buffs */ - for (i = 0; i < tx_ring->count; i++) { tx_buffer_info = &tx_ring->tx_buffer_info[i]; ixgbevf_unmap_and_free_tx_resource(tx_ring, tx_buffer_info); @@ -1593,13 +1680,6 @@ void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter) while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) msleep(1); - /* - * Check if PF is up before re-init. If not then skip until - * later when the PF is up and ready to service requests from - * the VF via mailbox. If the VF is up and running then the - * watchdog task will continue to schedule reset tasks until - * the PF is up and running. - */ ixgbevf_down(adapter); ixgbevf_up(adapter); @@ -1611,15 +1691,11 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter) struct ixgbe_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; - spin_lock(&adapter->mbx_lock); - if (hw->mac.ops.reset_hw(hw)) hw_dbg(hw, "PF still resetting\n"); else hw->mac.ops.init_hw(hw); - spin_unlock(&adapter->mbx_lock); - if (is_valid_ether_addr(adapter->hw.mac.addr)) { memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); @@ -1628,10 +1704,11 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter) } } -static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter, - int vectors) +static int ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter, + int vectors) { - int err, vector_threshold; + int err = 0; + int vector_threshold; /* We'll want at least 2 (vector_threshold): * 1) TxQ[0] + RxQ[0] handler @@ -1647,21 +1724,18 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter, while (vectors >= vector_threshold) { err = pci_enable_msix(adapter->pdev, adapter->msix_entries, vectors); - if (!err) /* Success in acquiring all requested vectors. */ + if (!err || err < 0) /* Success or a nasty failure. */ break; - else if (err < 0) - vectors = 0; /* Nasty failure, quit now */ else /* err == number of vectors we should try again with */ vectors = err; } - if (vectors < vector_threshold) { - /* Can't allocate enough MSI-X interrupts? Oh well. - * This just means we'll go with either a single MSI - * vector or fall back to legacy interrupts. - */ - hw_dbg(&adapter->hw, - "Unable to allocate MSI-X interrupts\n"); + if (vectors < vector_threshold) + err = -ENOMEM; + + if (err) { + dev_err(&adapter->pdev->dev, + "Unable to allocate MSI-X interrupts\n"); kfree(adapter->msix_entries); adapter->msix_entries = NULL; } else { @@ -1672,6 +1746,8 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter, */ adapter->num_msix_vectors = vectors; } + + return err; } /** @@ -1717,6 +1793,7 @@ static int ixgbevf_alloc_queues(struct ixgbevf_adapter *adapter) for (i = 0; i < adapter->num_tx_queues; i++) { adapter->tx_ring[i].count = adapter->tx_ring_count; adapter->tx_ring[i].queue_index = i; + /* reg_idx may be remapped later by DCB config */ adapter->tx_ring[i].reg_idx = i; adapter->tx_ring[i].dev = &adapter->pdev->dev; adapter->tx_ring[i].netdev = adapter->netdev; @@ -1774,7 +1851,9 @@ static int ixgbevf_set_interrupt_capability(struct ixgbevf_adapter *adapter) for (vector = 0; vector < v_budget; vector++) adapter->msix_entries[vector].entry = vector; - ixgbevf_acquire_msix_vectors(adapter, v_budget); + err = ixgbevf_acquire_msix_vectors(adapter, v_budget); + if (err) + goto out; err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); if (err) @@ -1834,18 +1913,13 @@ err_out: **/ static void ixgbevf_free_q_vectors(struct ixgbevf_adapter *adapter) { - int q_idx, num_q_vectors; - int napi_vectors; - - num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; - napi_vectors = adapter->num_rx_queues; + int q_idx, num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { struct ixgbevf_q_vector *q_vector = adapter->q_vector[q_idx]; adapter->q_vector[q_idx] = NULL; - if (q_idx < napi_vectors) - netif_napi_del(&q_vector->napi); + netif_napi_del(&q_vector->napi); kfree(q_vector); } } @@ -1935,7 +2009,7 @@ static void ixgbevf_clear_interrupt_scheme(struct ixgbevf_adapter *adapter) * Fields are initialized based on PCI device information and * OS network device settings (MTU size). **/ -static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter) +static int ixgbevf_sw_init(struct ixgbevf_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; @@ -1950,8 +2024,11 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter) hw->subsystem_device_id = pdev->subsystem_device; hw->mbx.ops.init_params(hw); - hw->mac.max_tx_queues = MAX_TX_QUEUES; - hw->mac.max_rx_queues = MAX_RX_QUEUES; + + /* assume legacy case in which PF would only give VF 2 queues */ + hw->mac.max_tx_queues = 2; + hw->mac.max_rx_queues = 2; + err = hw->mac.ops.reset_hw(hw); if (err) { dev_info(&pdev->dev, @@ -1966,7 +2043,7 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter) goto out; } memcpy(adapter->netdev->dev_addr, adapter->hw.mac.addr, - adapter->netdev->addr_len); + adapter->netdev->addr_len); } /* lock to protect mailbox accesses */ @@ -2016,6 +2093,7 @@ out: void ixgbevf_update_stats(struct ixgbevf_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; + int i; UPDATE_VF_COUNTER_32bit(IXGBE_VFGPRC, adapter->stats.last_vfgprc, adapter->stats.vfgprc); @@ -2029,6 +2107,15 @@ void ixgbevf_update_stats(struct ixgbevf_adapter *adapter) adapter->stats.vfgotc); UPDATE_VF_COUNTER_32bit(IXGBE_VFMPRC, adapter->stats.last_vfmprc, adapter->stats.vfmprc); + + for (i = 0; i < adapter->num_rx_queues; i++) { + adapter->hw_csum_rx_error += + adapter->rx_ring[i].hw_csum_rx_error; + adapter->hw_csum_rx_good += + adapter->rx_ring[i].hw_csum_rx_good; + adapter->rx_ring[i].hw_csum_rx_error = 0; + adapter->rx_ring[i].hw_csum_rx_good = 0; + } } /** @@ -2103,6 +2190,7 @@ static void ixgbevf_watchdog_task(struct work_struct *work) struct ixgbe_hw *hw = &adapter->hw; u32 link_speed = adapter->link_speed; bool link_up = adapter->link_up; + s32 need_reset; adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK; @@ -2110,29 +2198,19 @@ static void ixgbevf_watchdog_task(struct work_struct *work) * Always check the link on the watchdog because we have * no LSC interrupt */ - if (hw->mac.ops.check_link) { - s32 need_reset; - - spin_lock(&adapter->mbx_lock); + spin_lock_bh(&adapter->mbx_lock); - need_reset = hw->mac.ops.check_link(hw, &link_speed, - &link_up, false); + need_reset = hw->mac.ops.check_link(hw, &link_speed, &link_up, false); - spin_unlock(&adapter->mbx_lock); + spin_unlock_bh(&adapter->mbx_lock); - if (need_reset) { - adapter->link_up = link_up; - adapter->link_speed = link_speed; - netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); - schedule_work(&adapter->reset_task); - goto pf_has_reset; - } - } else { - /* always assume link is up, if no check link - * function */ - link_speed = IXGBE_LINK_SPEED_10GB_FULL; - link_up = true; + if (need_reset) { + adapter->link_up = link_up; + adapter->link_speed = link_speed; + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); + schedule_work(&adapter->reset_task); + goto pf_has_reset; } adapter->link_up = link_up; adapter->link_speed = link_speed; @@ -2377,6 +2455,63 @@ static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter) &adapter->rx_ring[i]); } +static int ixgbevf_setup_queues(struct ixgbevf_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + struct ixgbevf_ring *rx_ring; + unsigned int def_q = 0; + unsigned int num_tcs = 0; + unsigned int num_rx_queues = 1; + int err, i; + + spin_lock_bh(&adapter->mbx_lock); + + /* fetch queue configuration from the PF */ + err = ixgbevf_get_queues(hw, &num_tcs, &def_q); + + spin_unlock_bh(&adapter->mbx_lock); + + if (err) + return err; + + if (num_tcs > 1) { + /* update default Tx ring register index */ + adapter->tx_ring[0].reg_idx = def_q; + + /* we need as many queues as traffic classes */ + num_rx_queues = num_tcs; + } + + /* nothing to do if we have the correct number of queues */ + if (adapter->num_rx_queues == num_rx_queues) + return 0; + + /* allocate new rings */ + rx_ring = kcalloc(num_rx_queues, + sizeof(struct ixgbevf_ring), GFP_KERNEL); + if (!rx_ring) + return -ENOMEM; + + /* setup ring fields */ + for (i = 0; i < num_rx_queues; i++) { + rx_ring[i].count = adapter->rx_ring_count; + rx_ring[i].queue_index = i; + rx_ring[i].reg_idx = i; + rx_ring[i].dev = &adapter->pdev->dev; + rx_ring[i].netdev = adapter->netdev; + } + + /* free the existing ring and queues */ + adapter->num_rx_queues = 0; + kfree(adapter->rx_ring); + + /* move new rings into position on the adapter struct */ + adapter->rx_ring = rx_ring; + adapter->num_rx_queues = num_rx_queues; + + return 0; +} + /** * ixgbevf_open - Called when a network interface is made active * @netdev: network interface device structure @@ -2413,6 +2548,11 @@ static int ixgbevf_open(struct net_device *netdev) ixgbevf_negotiate_api(adapter); + /* setup queue reg_idx and Rx queue count */ + err = ixgbevf_setup_queues(adapter); + if (err) + goto err_setup_queues; + /* allocate transmit descriptors */ err = ixgbevf_setup_all_tx_resources(adapter); if (err) @@ -2451,6 +2591,7 @@ err_setup_rx: ixgbevf_free_all_rx_resources(adapter); err_setup_tx: ixgbevf_free_all_tx_resources(adapter); +err_setup_queues: ixgbevf_reset(adapter); err_setup_reset: @@ -2562,9 +2703,6 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring, static bool ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring, struct sk_buff *skb, u32 tx_flags) { - - - u32 vlan_macip_lens = 0; u32 mss_l4len_idx = 0; u32 type_tucmd = 0; @@ -2678,10 +2816,10 @@ static int ixgbevf_tx_map(struct ixgbevf_ring *tx_ring, tx_buffer_info->dma = skb_frag_dma_map(tx_ring->dev, frag, offset, size, DMA_TO_DEVICE); - tx_buffer_info->mapped_as_page = true; if (dma_mapping_error(tx_ring->dev, tx_buffer_info->dma)) goto dma_error; + tx_buffer_info->mapped_as_page = true; tx_buffer_info->next_to_watch = i; len -= size; @@ -2754,7 +2892,6 @@ static void ixgbevf_tx_queue(struct ixgbevf_ring *tx_ring, int tx_flags, olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT); if (tx_flags & IXGBE_TX_FLAGS_IPV4) olinfo_status |= IXGBE_ADVTXD_POPTS_IXSM; - } /* @@ -2823,6 +2960,11 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev) #if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD unsigned short f; #endif + u8 *dst_mac = skb_header_pointer(skb, 0, 0, NULL); + if (!dst_mac || is_link_local_ether_addr(dst_mac)) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } tx_ring = &adapter->tx_ring[r_idx]; @@ -2902,12 +3044,11 @@ static int ixgbevf_set_mac(struct net_device *netdev, void *p) memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); - spin_lock(&adapter->mbx_lock); + spin_lock_bh(&adapter->mbx_lock); - if (hw->mac.ops.set_rar) - hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0); + hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0); - spin_unlock(&adapter->mbx_lock); + spin_unlock_bh(&adapter->mbx_lock); return 0; } @@ -2925,8 +3066,15 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu) int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE; - if (adapter->hw.mac.type == ixgbe_mac_X540_vf) + switch (adapter->hw.api_version) { + case ixgbe_mbox_api_11: max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE; + break; + default: + if (adapter->hw.mac.type == ixgbe_mac_X540_vf) + max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE; + break; + } /* MTU < 68 is an error and causes problems on some kernels */ if ((new_mtu < 68) || (max_frame > max_possible_frame)) @@ -3094,8 +3242,7 @@ static void ixgbevf_assign_netdev_ops(struct net_device *dev) * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. **/ -static int __devinit ixgbevf_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct ixgbevf_adapter *adapter = NULL; @@ -3223,10 +3370,6 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev, if (err) goto err_sw_init; - /* pick up the PCI bus settings for reporting later */ - if (hw->mac.ops.get_bus_info) - hw->mac.ops.get_bus_info(hw); - strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); @@ -3270,7 +3413,7 @@ err_dma: * Hot-Plug event, or because the driver is going to be removed from * memory. **/ -static void __devexit ixgbevf_remove(struct pci_dev *pdev) +static void ixgbevf_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct ixgbevf_adapter *adapter = netdev_priv(netdev); @@ -3384,7 +3527,7 @@ static struct pci_driver ixgbevf_driver = { .name = ixgbevf_driver_name, .id_table = ixgbevf_pci_tbl, .probe = ixgbevf_probe, - .remove = __devexit_p(ixgbevf_remove), + .remove = ixgbevf_remove, #ifdef CONFIG_PM /* Power Management Hooks */ .suspend = ixgbevf_suspend, diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.h b/drivers/net/ethernet/intel/ixgbevf/mbx.h index 946ce86f337f..0bc30058ff82 100644 --- a/drivers/net/ethernet/intel/ixgbevf/mbx.h +++ b/drivers/net/ethernet/intel/ixgbevf/mbx.h @@ -85,6 +85,7 @@ enum ixgbe_pfvf_api_rev { ixgbe_mbox_api_10, /* API version 1.0, linux/freebsd VF driver */ ixgbe_mbox_api_20, /* API version 2.0, solaris Phase1 VF driver */ + ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */ /* This value should always be last */ ixgbe_mbox_api_unknown, /* indicates that API version is not known */ }; @@ -100,6 +101,15 @@ enum ixgbe_pfvf_api_rev { #define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */ #define IXGBE_VF_API_NEGOTIATE 0x08 /* negotiate API version */ +/* mailbox API, version 1.1 VF requests */ +#define IXGBE_VF_GET_QUEUE 0x09 /* get queue configuration */ + +/* GET_QUEUES return data indices within the mailbox */ +#define IXGBE_VF_TX_QUEUES 1 /* number of Tx queues supported */ +#define IXGBE_VF_RX_QUEUES 2 /* number of Rx queues supported */ +#define IXGBE_VF_TRANS_VLAN 3 /* Indication of port vlan */ +#define IXGBE_VF_DEF_QUEUE 4 /* Default queue offset */ + /* length of permanent address message returned from PF */ #define IXGBE_VF_PERMADDR_MSG_LEN 4 /* word in permanent address message with the current multicast type */ diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c index 0c7447e6fcc8..0c94557b53df 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.c +++ b/drivers/net/ethernet/intel/ixgbevf/vf.c @@ -331,6 +331,9 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw, netdev_for_each_mc_addr(ha, netdev) { if (i == cnt) break; + if (is_link_local_ether_addr(ha->addr)) + continue; + vector_list[i++] = ixgbevf_mta_vector(hw, ha->addr); } @@ -513,6 +516,64 @@ int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api) return err; } +int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs, + unsigned int *default_tc) +{ + int err; + u32 msg[5]; + + /* do nothing if API doesn't support ixgbevf_get_queues */ + switch (hw->api_version) { + case ixgbe_mbox_api_11: + break; + default: + return 0; + } + + /* Fetch queue configuration from the PF */ + msg[0] = IXGBE_VF_GET_QUEUE; + msg[1] = msg[2] = msg[3] = msg[4] = 0; + err = hw->mbx.ops.write_posted(hw, msg, 5); + + if (!err) + err = hw->mbx.ops.read_posted(hw, msg, 5); + + if (!err) { + msg[0] &= ~IXGBE_VT_MSGTYPE_CTS; + + /* + * if we we didn't get an ACK there must have been + * some sort of mailbox error so we should treat it + * as such + */ + if (msg[0] != (IXGBE_VF_GET_QUEUE | IXGBE_VT_MSGTYPE_ACK)) + return IXGBE_ERR_MBX; + + /* record and validate values from message */ + hw->mac.max_tx_queues = msg[IXGBE_VF_TX_QUEUES]; + if (hw->mac.max_tx_queues == 0 || + hw->mac.max_tx_queues > IXGBE_VF_MAX_TX_QUEUES) + hw->mac.max_tx_queues = IXGBE_VF_MAX_TX_QUEUES; + + hw->mac.max_rx_queues = msg[IXGBE_VF_RX_QUEUES]; + if (hw->mac.max_rx_queues == 0 || + hw->mac.max_rx_queues > IXGBE_VF_MAX_RX_QUEUES) + hw->mac.max_rx_queues = IXGBE_VF_MAX_RX_QUEUES; + + *num_tcs = msg[IXGBE_VF_TRANS_VLAN]; + /* in case of unknown state assume we cannot tag frames */ + if (*num_tcs > hw->mac.max_rx_queues) + *num_tcs = 1; + + *default_tc = msg[IXGBE_VF_DEF_QUEUE]; + /* default to queue 0 on out-of-bounds queue number */ + if (*default_tc >= hw->mac.max_tx_queues) + *default_tc = 0; + } + + return err; +} + static const struct ixgbe_mac_operations ixgbevf_mac_ops = { .init_hw = ixgbevf_init_hw_vf, .reset_hw = ixgbevf_reset_hw_vf, diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h index 47f11a584d8c..7b1f502d1716 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.h +++ b/drivers/net/ethernet/intel/ixgbevf/vf.h @@ -174,5 +174,7 @@ struct ixgbevf_info { void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size); int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api); +int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs, + unsigned int *default_tc); #endif /* __IXGBE_VF_H__ */ diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index f8064df10cc4..0519afa413d2 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -1860,10 +1860,14 @@ jme_open(struct net_device *netdev) jme_clear_pm(jme); JME_NAPI_ENABLE(jme); - tasklet_enable(&jme->linkch_task); - tasklet_enable(&jme->txclean_task); - tasklet_hi_enable(&jme->rxclean_task); - tasklet_hi_enable(&jme->rxempty_task); + tasklet_init(&jme->linkch_task, jme_link_change_tasklet, + (unsigned long) jme); + tasklet_init(&jme->txclean_task, jme_tx_clean_tasklet, + (unsigned long) jme); + tasklet_init(&jme->rxclean_task, jme_rx_clean_tasklet, + (unsigned long) jme); + tasklet_init(&jme->rxempty_task, jme_rx_empty_tasklet, + (unsigned long) jme); rc = jme_request_irq(jme); if (rc) @@ -1948,10 +1952,10 @@ jme_close(struct net_device *netdev) JME_NAPI_DISABLE(jme); - tasklet_disable(&jme->linkch_task); - tasklet_disable(&jme->txclean_task); - tasklet_disable(&jme->rxclean_task); - tasklet_disable(&jme->rxempty_task); + tasklet_kill(&jme->linkch_task); + tasklet_kill(&jme->txclean_task); + tasklet_kill(&jme->rxclean_task); + tasklet_kill(&jme->rxempty_task); jme_disable_rx_engine(jme); jme_disable_tx_engine(jme); @@ -2961,7 +2965,7 @@ static const struct net_device_ops jme_netdev_ops = { #endif }; -static int __devinit +static int jme_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -3079,22 +3083,6 @@ jme_init_one(struct pci_dev *pdev, tasklet_init(&jme->pcc_task, jme_pcc_tasklet, (unsigned long) jme); - tasklet_init(&jme->linkch_task, - jme_link_change_tasklet, - (unsigned long) jme); - tasklet_init(&jme->txclean_task, - jme_tx_clean_tasklet, - (unsigned long) jme); - tasklet_init(&jme->rxclean_task, - jme_rx_clean_tasklet, - (unsigned long) jme); - tasklet_init(&jme->rxempty_task, - jme_rx_empty_tasklet, - (unsigned long) jme); - tasklet_disable_nosync(&jme->linkch_task); - tasklet_disable_nosync(&jme->txclean_task); - tasklet_disable_nosync(&jme->rxclean_task); - tasklet_disable_nosync(&jme->rxempty_task); jme->dpi.cur = PCC_P1; jme->reg_ghc = 0; @@ -3215,7 +3203,7 @@ err_out: return rc; } -static void __devexit +static void jme_remove_one(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -3330,7 +3318,7 @@ static struct pci_driver jme_driver = { .name = DRV_NAME, .id_table = jme_pci_tbl, .probe = jme_init_one, - .remove = __devexit_p(jme_remove_one), + .remove = jme_remove_one, .shutdown = jme_shutdown, .driver.pm = JME_PM_OPS, }; diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 003c5bc7189f..c124e67a1a1c 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -774,7 +774,7 @@ err_out: return err; } -static int __devexit +static int ltq_etop_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); @@ -789,7 +789,7 @@ ltq_etop_remove(struct platform_device *pdev) } static struct platform_driver ltq_mii_driver = { - .remove = __devexit_p(ltq_etop_remove), + .remove = ltq_etop_remove, .driver = { .name = "ltq_etop", .owner = THIS_MODULE, diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig index 0029934748bc..edfba9370922 100644 --- a/drivers/net/ethernet/marvell/Kconfig +++ b/drivers/net/ethernet/marvell/Kconfig @@ -31,6 +31,30 @@ config MV643XX_ETH Some boards that use the Discovery chipset are the Momenco Ocelot C and Jaguar ATX and Pegasos II. +config MVMDIO + tristate "Marvell MDIO interface support" + ---help--- + This driver supports the MDIO interface found in the network + interface units of the Marvell EBU SoCs (Kirkwood, Orion5x, + Dove, Armada 370 and Armada XP). + + For now, this driver is only needed for the MVNETA driver + (used on Armada 370 and XP), but it could be used in the + future by the MV643XX_ETH driver. + +config MVNETA + tristate "Marvell Armada 370/XP network interface support" + depends on MACH_ARMADA_370_XP + select PHYLIB + select MVMDIO + ---help--- + This driver supports the network interface units in the + Marvell ARMADA XP and ARMADA 370 SoC family. + + Note that this driver is distinct from the mv643xx_eth + driver, which should be used for the older Marvell SoCs + (Dove, Orion, Discovery, Kirkwood). + config PXA168_ETH tristate "Marvell pxa168 ethernet support" depends on CPU_PXA168 diff --git a/drivers/net/ethernet/marvell/Makefile b/drivers/net/ethernet/marvell/Makefile index 57e3234a37ba..7f63b4aac434 100644 --- a/drivers/net/ethernet/marvell/Makefile +++ b/drivers/net/ethernet/marvell/Makefile @@ -3,6 +3,8 @@ # obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o +obj-$(CONFIG_MVMDIO) += mvmdio.o +obj-$(CONFIG_MVNETA) += mvneta.o obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o obj-$(CONFIG_SKGE) += skge.o obj-$(CONFIG_SKY2) += sky2.o diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c new file mode 100644 index 000000000000..74f1c157a480 --- /dev/null +++ b/drivers/net/ethernet/marvell/mvmdio.c @@ -0,0 +1,228 @@ +/* + * Driver for the MDIO interface of Marvell network interfaces. + * + * Since the MDIO interface of Marvell network interfaces is shared + * between all network interfaces, having a single driver allows to + * handle concurrent accesses properly (you may have four Ethernet + * ports, but they in fact share the same SMI interface to access the + * MDIO bus). Moreover, this MDIO interface code is similar between + * the mv643xx_eth driver and the mvneta driver. For now, it is only + * used by the mvneta driver, but it could later be used by the + * mv643xx_eth driver as well. + * + * Copyright (C) 2012 Marvell + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/phy.h> +#include <linux/of_address.h> +#include <linux/of_mdio.h> +#include <linux/platform_device.h> +#include <linux/delay.h> + +#define MVMDIO_SMI_DATA_SHIFT 0 +#define MVMDIO_SMI_PHY_ADDR_SHIFT 16 +#define MVMDIO_SMI_PHY_REG_SHIFT 21 +#define MVMDIO_SMI_READ_OPERATION BIT(26) +#define MVMDIO_SMI_WRITE_OPERATION 0 +#define MVMDIO_SMI_READ_VALID BIT(27) +#define MVMDIO_SMI_BUSY BIT(28) + +struct orion_mdio_dev { + struct mutex lock; + void __iomem *smireg; +}; + +/* Wait for the SMI unit to be ready for another operation + */ +static int orion_mdio_wait_ready(struct mii_bus *bus) +{ + struct orion_mdio_dev *dev = bus->priv; + int count; + u32 val; + + count = 0; + while (1) { + val = readl(dev->smireg); + if (!(val & MVMDIO_SMI_BUSY)) + break; + + if (count > 100) { + dev_err(bus->parent, "Timeout: SMI busy for too long\n"); + return -ETIMEDOUT; + } + + udelay(10); + count++; + } + + return 0; +} + +static int orion_mdio_read(struct mii_bus *bus, int mii_id, + int regnum) +{ + struct orion_mdio_dev *dev = bus->priv; + int count; + u32 val; + int ret; + + mutex_lock(&dev->lock); + + ret = orion_mdio_wait_ready(bus); + if (ret < 0) { + mutex_unlock(&dev->lock); + return ret; + } + + writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) | + (regnum << MVMDIO_SMI_PHY_REG_SHIFT) | + MVMDIO_SMI_READ_OPERATION), + dev->smireg); + + /* Wait for the value to become available */ + count = 0; + while (1) { + val = readl(dev->smireg); + if (val & MVMDIO_SMI_READ_VALID) + break; + + if (count > 100) { + dev_err(bus->parent, "Timeout when reading PHY\n"); + mutex_unlock(&dev->lock); + return -ETIMEDOUT; + } + + udelay(10); + count++; + } + + mutex_unlock(&dev->lock); + + return val & 0xFFFF; +} + +static int orion_mdio_write(struct mii_bus *bus, int mii_id, + int regnum, u16 value) +{ + struct orion_mdio_dev *dev = bus->priv; + int ret; + + mutex_lock(&dev->lock); + + ret = orion_mdio_wait_ready(bus); + if (ret < 0) { + mutex_unlock(&dev->lock); + return ret; + } + + writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) | + (regnum << MVMDIO_SMI_PHY_REG_SHIFT) | + MVMDIO_SMI_WRITE_OPERATION | + (value << MVMDIO_SMI_DATA_SHIFT)), + dev->smireg); + + mutex_unlock(&dev->lock); + + return 0; +} + +static int orion_mdio_reset(struct mii_bus *bus) +{ + return 0; +} + +static int orion_mdio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct mii_bus *bus; + struct orion_mdio_dev *dev; + int i, ret; + + bus = mdiobus_alloc_size(sizeof(struct orion_mdio_dev)); + if (!bus) { + dev_err(&pdev->dev, "Cannot allocate MDIO bus\n"); + return -ENOMEM; + } + + bus->name = "orion_mdio_bus"; + bus->read = orion_mdio_read; + bus->write = orion_mdio_write; + bus->reset = orion_mdio_reset; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", + dev_name(&pdev->dev)); + bus->parent = &pdev->dev; + + bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); + if (!bus->irq) { + dev_err(&pdev->dev, "Cannot allocate PHY IRQ array\n"); + mdiobus_free(bus); + return -ENOMEM; + } + + for (i = 0; i < PHY_MAX_ADDR; i++) + bus->irq[i] = PHY_POLL; + + dev = bus->priv; + dev->smireg = of_iomap(pdev->dev.of_node, 0); + if (!dev->smireg) { + dev_err(&pdev->dev, "No SMI register address given in DT\n"); + kfree(bus->irq); + mdiobus_free(bus); + return -ENODEV; + } + + mutex_init(&dev->lock); + + ret = of_mdiobus_register(bus, np); + if (ret < 0) { + dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); + iounmap(dev->smireg); + kfree(bus->irq); + mdiobus_free(bus); + return ret; + } + + platform_set_drvdata(pdev, bus); + + return 0; +} + +static int orion_mdio_remove(struct platform_device *pdev) +{ + struct mii_bus *bus = platform_get_drvdata(pdev); + mdiobus_unregister(bus); + kfree(bus->irq); + mdiobus_free(bus); + return 0; +} + +static const struct of_device_id orion_mdio_match[] = { + { .compatible = "marvell,orion-mdio" }, + { } +}; +MODULE_DEVICE_TABLE(of, orion_mdio_match); + +static struct platform_driver orion_mdio_driver = { + .probe = orion_mdio_probe, + .remove = orion_mdio_remove, + .driver = { + .name = "orion-mdio", + .of_match_table = orion_mdio_match, + }, +}; + +module_platform_driver(orion_mdio_driver); + +MODULE_DESCRIPTION("Marvell MDIO interface driver"); +MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c new file mode 100644 index 000000000000..b6025c305e10 --- /dev/null +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -0,0 +1,2847 @@ +/* + * Driver for Marvell NETA network card for Armada XP and Armada 370 SoCs. + * + * Copyright (C) 2012 Marvell + * + * Rami Rosen <rosenr@marvell.com> + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/version.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/platform_device.h> +#include <linux/skbuff.h> +#include <linux/inetdevice.h> +#include <linux/mbus.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <net/ip.h> +#include <net/ipv6.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/of_mdio.h> +#include <linux/of_net.h> +#include <linux/of_address.h> +#include <linux/phy.h> +#include <linux/clk.h> + +/* Registers */ +#define MVNETA_RXQ_CONFIG_REG(q) (0x1400 + ((q) << 2)) +#define MVNETA_RXQ_HW_BUF_ALLOC BIT(1) +#define MVNETA_RXQ_PKT_OFFSET_ALL_MASK (0xf << 8) +#define MVNETA_RXQ_PKT_OFFSET_MASK(offs) ((offs) << 8) +#define MVNETA_RXQ_THRESHOLD_REG(q) (0x14c0 + ((q) << 2)) +#define MVNETA_RXQ_NON_OCCUPIED(v) ((v) << 16) +#define MVNETA_RXQ_BASE_ADDR_REG(q) (0x1480 + ((q) << 2)) +#define MVNETA_RXQ_SIZE_REG(q) (0x14a0 + ((q) << 2)) +#define MVNETA_RXQ_BUF_SIZE_SHIFT 19 +#define MVNETA_RXQ_BUF_SIZE_MASK (0x1fff << 19) +#define MVNETA_RXQ_STATUS_REG(q) (0x14e0 + ((q) << 2)) +#define MVNETA_RXQ_OCCUPIED_ALL_MASK 0x3fff +#define MVNETA_RXQ_STATUS_UPDATE_REG(q) (0x1500 + ((q) << 2)) +#define MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT 16 +#define MVNETA_RXQ_ADD_NON_OCCUPIED_MAX 255 +#define MVNETA_PORT_RX_RESET 0x1cc0 +#define MVNETA_PORT_RX_DMA_RESET BIT(0) +#define MVNETA_PHY_ADDR 0x2000 +#define MVNETA_PHY_ADDR_MASK 0x1f +#define MVNETA_MBUS_RETRY 0x2010 +#define MVNETA_UNIT_INTR_CAUSE 0x2080 +#define MVNETA_UNIT_CONTROL 0x20B0 +#define MVNETA_PHY_POLLING_ENABLE BIT(1) +#define MVNETA_WIN_BASE(w) (0x2200 + ((w) << 3)) +#define MVNETA_WIN_SIZE(w) (0x2204 + ((w) << 3)) +#define MVNETA_WIN_REMAP(w) (0x2280 + ((w) << 2)) +#define MVNETA_BASE_ADDR_ENABLE 0x2290 +#define MVNETA_PORT_CONFIG 0x2400 +#define MVNETA_UNI_PROMISC_MODE BIT(0) +#define MVNETA_DEF_RXQ(q) ((q) << 1) +#define MVNETA_DEF_RXQ_ARP(q) ((q) << 4) +#define MVNETA_TX_UNSET_ERR_SUM BIT(12) +#define MVNETA_DEF_RXQ_TCP(q) ((q) << 16) +#define MVNETA_DEF_RXQ_UDP(q) ((q) << 19) +#define MVNETA_DEF_RXQ_BPDU(q) ((q) << 22) +#define MVNETA_RX_CSUM_WITH_PSEUDO_HDR BIT(25) +#define MVNETA_PORT_CONFIG_DEFL_VALUE(q) (MVNETA_DEF_RXQ(q) | \ + MVNETA_DEF_RXQ_ARP(q) | \ + MVNETA_DEF_RXQ_TCP(q) | \ + MVNETA_DEF_RXQ_UDP(q) | \ + MVNETA_DEF_RXQ_BPDU(q) | \ + MVNETA_TX_UNSET_ERR_SUM | \ + MVNETA_RX_CSUM_WITH_PSEUDO_HDR) +#define MVNETA_PORT_CONFIG_EXTEND 0x2404 +#define MVNETA_MAC_ADDR_LOW 0x2414 +#define MVNETA_MAC_ADDR_HIGH 0x2418 +#define MVNETA_SDMA_CONFIG 0x241c +#define MVNETA_SDMA_BRST_SIZE_16 4 +#define MVNETA_NO_DESC_SWAP 0x0 +#define MVNETA_RX_BRST_SZ_MASK(burst) ((burst) << 1) +#define MVNETA_RX_NO_DATA_SWAP BIT(4) +#define MVNETA_TX_NO_DATA_SWAP BIT(5) +#define MVNETA_TX_BRST_SZ_MASK(burst) ((burst) << 22) +#define MVNETA_PORT_STATUS 0x2444 +#define MVNETA_TX_IN_PRGRS BIT(1) +#define MVNETA_TX_FIFO_EMPTY BIT(8) +#define MVNETA_RX_MIN_FRAME_SIZE 0x247c +#define MVNETA_TYPE_PRIO 0x24bc +#define MVNETA_FORCE_UNI BIT(21) +#define MVNETA_TXQ_CMD_1 0x24e4 +#define MVNETA_TXQ_CMD 0x2448 +#define MVNETA_TXQ_DISABLE_SHIFT 8 +#define MVNETA_TXQ_ENABLE_MASK 0x000000ff +#define MVNETA_ACC_MODE 0x2500 +#define MVNETA_CPU_MAP(cpu) (0x2540 + ((cpu) << 2)) +#define MVNETA_CPU_RXQ_ACCESS_ALL_MASK 0x000000ff +#define MVNETA_CPU_TXQ_ACCESS_ALL_MASK 0x0000ff00 +#define MVNETA_RXQ_TIME_COAL_REG(q) (0x2580 + ((q) << 2)) +#define MVNETA_INTR_NEW_CAUSE 0x25a0 +#define MVNETA_RX_INTR_MASK(nr_rxqs) (((1 << nr_rxqs) - 1) << 8) +#define MVNETA_INTR_NEW_MASK 0x25a4 +#define MVNETA_INTR_OLD_CAUSE 0x25a8 +#define MVNETA_INTR_OLD_MASK 0x25ac +#define MVNETA_INTR_MISC_CAUSE 0x25b0 +#define MVNETA_INTR_MISC_MASK 0x25b4 +#define MVNETA_INTR_ENABLE 0x25b8 +#define MVNETA_TXQ_INTR_ENABLE_ALL_MASK 0x0000ff00 +#define MVNETA_RXQ_INTR_ENABLE_ALL_MASK 0xff000000 +#define MVNETA_RXQ_CMD 0x2680 +#define MVNETA_RXQ_DISABLE_SHIFT 8 +#define MVNETA_RXQ_ENABLE_MASK 0x000000ff +#define MVETH_TXQ_TOKEN_COUNT_REG(q) (0x2700 + ((q) << 4)) +#define MVETH_TXQ_TOKEN_CFG_REG(q) (0x2704 + ((q) << 4)) +#define MVNETA_GMAC_CTRL_0 0x2c00 +#define MVNETA_GMAC_MAX_RX_SIZE_SHIFT 2 +#define MVNETA_GMAC_MAX_RX_SIZE_MASK 0x7ffc +#define MVNETA_GMAC0_PORT_ENABLE BIT(0) +#define MVNETA_GMAC_CTRL_2 0x2c08 +#define MVNETA_GMAC2_PSC_ENABLE BIT(3) +#define MVNETA_GMAC2_PORT_RGMII BIT(4) +#define MVNETA_GMAC2_PORT_RESET BIT(6) +#define MVNETA_GMAC_STATUS 0x2c10 +#define MVNETA_GMAC_LINK_UP BIT(0) +#define MVNETA_GMAC_SPEED_1000 BIT(1) +#define MVNETA_GMAC_SPEED_100 BIT(2) +#define MVNETA_GMAC_FULL_DUPLEX BIT(3) +#define MVNETA_GMAC_RX_FLOW_CTRL_ENABLE BIT(4) +#define MVNETA_GMAC_TX_FLOW_CTRL_ENABLE BIT(5) +#define MVNETA_GMAC_RX_FLOW_CTRL_ACTIVE BIT(6) +#define MVNETA_GMAC_TX_FLOW_CTRL_ACTIVE BIT(7) +#define MVNETA_GMAC_AUTONEG_CONFIG 0x2c0c +#define MVNETA_GMAC_FORCE_LINK_DOWN BIT(0) +#define MVNETA_GMAC_FORCE_LINK_PASS BIT(1) +#define MVNETA_GMAC_CONFIG_MII_SPEED BIT(5) +#define MVNETA_GMAC_CONFIG_GMII_SPEED BIT(6) +#define MVNETA_GMAC_CONFIG_FULL_DUPLEX BIT(12) +#define MVNETA_MIB_COUNTERS_BASE 0x3080 +#define MVNETA_MIB_LATE_COLLISION 0x7c +#define MVNETA_DA_FILT_SPEC_MCAST 0x3400 +#define MVNETA_DA_FILT_OTH_MCAST 0x3500 +#define MVNETA_DA_FILT_UCAST_BASE 0x3600 +#define MVNETA_TXQ_BASE_ADDR_REG(q) (0x3c00 + ((q) << 2)) +#define MVNETA_TXQ_SIZE_REG(q) (0x3c20 + ((q) << 2)) +#define MVNETA_TXQ_SENT_THRESH_ALL_MASK 0x3fff0000 +#define MVNETA_TXQ_SENT_THRESH_MASK(coal) ((coal) << 16) +#define MVNETA_TXQ_UPDATE_REG(q) (0x3c60 + ((q) << 2)) +#define MVNETA_TXQ_DEC_SENT_SHIFT 16 +#define MVNETA_TXQ_STATUS_REG(q) (0x3c40 + ((q) << 2)) +#define MVNETA_TXQ_SENT_DESC_SHIFT 16 +#define MVNETA_TXQ_SENT_DESC_MASK 0x3fff0000 +#define MVNETA_PORT_TX_RESET 0x3cf0 +#define MVNETA_PORT_TX_DMA_RESET BIT(0) +#define MVNETA_TX_MTU 0x3e0c +#define MVNETA_TX_TOKEN_SIZE 0x3e14 +#define MVNETA_TX_TOKEN_SIZE_MAX 0xffffffff +#define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2)) +#define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff + +#define MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK 0xff + +/* Descriptor ring Macros */ +#define MVNETA_QUEUE_NEXT_DESC(q, index) \ + (((index) < (q)->last_desc) ? ((index) + 1) : 0) + +/* Various constants */ + +/* Coalescing */ +#define MVNETA_TXDONE_COAL_PKTS 16 +#define MVNETA_RX_COAL_PKTS 32 +#define MVNETA_RX_COAL_USEC 100 + +/* Timer */ +#define MVNETA_TX_DONE_TIMER_PERIOD 10 + +/* Napi polling weight */ +#define MVNETA_RX_POLL_WEIGHT 64 + +/* The two bytes Marvell header. Either contains a special value used + * by Marvell switches when a specific hardware mode is enabled (not + * supported by this driver) or is filled automatically by zeroes on + * the RX side. Those two bytes being at the front of the Ethernet + * header, they allow to have the IP header aligned on a 4 bytes + * boundary automatically: the hardware skips those two bytes on its + * own. + */ +#define MVNETA_MH_SIZE 2 + +#define MVNETA_VLAN_TAG_LEN 4 + +#define MVNETA_CPU_D_CACHE_LINE_SIZE 32 +#define MVNETA_TX_CSUM_MAX_SIZE 9800 +#define MVNETA_ACC_MODE_EXT 1 + +/* Timeout constants */ +#define MVNETA_TX_DISABLE_TIMEOUT_MSEC 1000 +#define MVNETA_RX_DISABLE_TIMEOUT_MSEC 1000 +#define MVNETA_TX_FIFO_EMPTY_TIMEOUT 10000 + +#define MVNETA_TX_MTU_MAX 0x3ffff + +/* Max number of Rx descriptors */ +#define MVNETA_MAX_RXD 128 + +/* Max number of Tx descriptors */ +#define MVNETA_MAX_TXD 532 + +/* descriptor aligned size */ +#define MVNETA_DESC_ALIGNED_SIZE 32 + +#define MVNETA_RX_PKT_SIZE(mtu) \ + ALIGN((mtu) + MVNETA_MH_SIZE + MVNETA_VLAN_TAG_LEN + \ + ETH_HLEN + ETH_FCS_LEN, \ + MVNETA_CPU_D_CACHE_LINE_SIZE) + +#define MVNETA_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD) + +struct mvneta_stats { + struct u64_stats_sync syncp; + u64 packets; + u64 bytes; +}; + +struct mvneta_port { + int pkt_size; + void __iomem *base; + struct mvneta_rx_queue *rxqs; + struct mvneta_tx_queue *txqs; + struct timer_list tx_done_timer; + struct net_device *dev; + + u32 cause_rx_tx; + struct napi_struct napi; + + /* Flags */ + unsigned long flags; +#define MVNETA_F_TX_DONE_TIMER_BIT 0 + + /* Napi weight */ + int weight; + + /* Core clock */ + struct clk *clk; + u8 mcast_count[256]; + u16 tx_ring_size; + u16 rx_ring_size; + struct mvneta_stats tx_stats; + struct mvneta_stats rx_stats; + + struct mii_bus *mii_bus; + struct phy_device *phy_dev; + phy_interface_t phy_interface; + struct device_node *phy_node; + unsigned int link; + unsigned int duplex; + unsigned int speed; +}; + +/* The mvneta_tx_desc and mvneta_rx_desc structures describe the + * layout of the transmit and reception DMA descriptors, and their + * layout is therefore defined by the hardware design + */ +struct mvneta_tx_desc { + u32 command; /* Options used by HW for packet transmitting.*/ +#define MVNETA_TX_L3_OFF_SHIFT 0 +#define MVNETA_TX_IP_HLEN_SHIFT 8 +#define MVNETA_TX_L4_UDP BIT(16) +#define MVNETA_TX_L3_IP6 BIT(17) +#define MVNETA_TXD_IP_CSUM BIT(18) +#define MVNETA_TXD_Z_PAD BIT(19) +#define MVNETA_TXD_L_DESC BIT(20) +#define MVNETA_TXD_F_DESC BIT(21) +#define MVNETA_TXD_FLZ_DESC (MVNETA_TXD_Z_PAD | \ + MVNETA_TXD_L_DESC | \ + MVNETA_TXD_F_DESC) +#define MVNETA_TX_L4_CSUM_FULL BIT(30) +#define MVNETA_TX_L4_CSUM_NOT BIT(31) + + u16 reserverd1; /* csum_l4 (for future use) */ + u16 data_size; /* Data size of transmitted packet in bytes */ + u32 buf_phys_addr; /* Physical addr of transmitted buffer */ + u32 reserved2; /* hw_cmd - (for future use, PMT) */ + u32 reserved3[4]; /* Reserved - (for future use) */ +}; + +struct mvneta_rx_desc { + u32 status; /* Info about received packet */ +#define MVNETA_RXD_ERR_CRC 0x0 +#define MVNETA_RXD_ERR_SUMMARY BIT(16) +#define MVNETA_RXD_ERR_OVERRUN BIT(17) +#define MVNETA_RXD_ERR_LEN BIT(18) +#define MVNETA_RXD_ERR_RESOURCE (BIT(17) | BIT(18)) +#define MVNETA_RXD_ERR_CODE_MASK (BIT(17) | BIT(18)) +#define MVNETA_RXD_L3_IP4 BIT(25) +#define MVNETA_RXD_FIRST_LAST_DESC (BIT(26) | BIT(27)) +#define MVNETA_RXD_L4_CSUM_OK BIT(30) + + u16 reserved1; /* pnc_info - (for future use, PnC) */ + u16 data_size; /* Size of received packet in bytes */ + u32 buf_phys_addr; /* Physical address of the buffer */ + u32 reserved2; /* pnc_flow_id (for future use, PnC) */ + u32 buf_cookie; /* cookie for access to RX buffer in rx path */ + u16 reserved3; /* prefetch_cmd, for future use */ + u16 reserved4; /* csum_l4 - (for future use, PnC) */ + u32 reserved5; /* pnc_extra PnC (for future use, PnC) */ + u32 reserved6; /* hw_cmd (for future use, PnC and HWF) */ +}; + +struct mvneta_tx_queue { + /* Number of this TX queue, in the range 0-7 */ + u8 id; + + /* Number of TX DMA descriptors in the descriptor ring */ + int size; + + /* Number of currently used TX DMA descriptor in the + * descriptor ring + */ + int count; + + /* Array of transmitted skb */ + struct sk_buff **tx_skb; + + /* Index of last TX DMA descriptor that was inserted */ + int txq_put_index; + + /* Index of the TX DMA descriptor to be cleaned up */ + int txq_get_index; + + u32 done_pkts_coal; + + /* Virtual address of the TX DMA descriptors array */ + struct mvneta_tx_desc *descs; + + /* DMA address of the TX DMA descriptors array */ + dma_addr_t descs_phys; + + /* Index of the last TX DMA descriptor */ + int last_desc; + + /* Index of the next TX DMA descriptor to process */ + int next_desc_to_proc; +}; + +struct mvneta_rx_queue { + /* rx queue number, in the range 0-7 */ + u8 id; + + /* num of rx descriptors in the rx descriptor ring */ + int size; + + /* counter of times when mvneta_refill() failed */ + int missed; + + u32 pkts_coal; + u32 time_coal; + + /* Virtual address of the RX DMA descriptors array */ + struct mvneta_rx_desc *descs; + + /* DMA address of the RX DMA descriptors array */ + dma_addr_t descs_phys; + + /* Index of the last RX DMA descriptor */ + int last_desc; + + /* Index of the next RX DMA descriptor to process */ + int next_desc_to_proc; +}; + +static int rxq_number = 8; +static int txq_number = 8; + +static int rxq_def; +static int txq_def; + +#define MVNETA_DRIVER_NAME "mvneta" +#define MVNETA_DRIVER_VERSION "1.0" + +/* Utility/helper methods */ + +/* Write helper method */ +static void mvreg_write(struct mvneta_port *pp, u32 offset, u32 data) +{ + writel(data, pp->base + offset); +} + +/* Read helper method */ +static u32 mvreg_read(struct mvneta_port *pp, u32 offset) +{ + return readl(pp->base + offset); +} + +/* Increment txq get counter */ +static void mvneta_txq_inc_get(struct mvneta_tx_queue *txq) +{ + txq->txq_get_index++; + if (txq->txq_get_index == txq->size) + txq->txq_get_index = 0; +} + +/* Increment txq put counter */ +static void mvneta_txq_inc_put(struct mvneta_tx_queue *txq) +{ + txq->txq_put_index++; + if (txq->txq_put_index == txq->size) + txq->txq_put_index = 0; +} + + +/* Clear all MIB counters */ +static void mvneta_mib_counters_clear(struct mvneta_port *pp) +{ + int i; + u32 dummy; + + /* Perform dummy reads from MIB counters */ + for (i = 0; i < MVNETA_MIB_LATE_COLLISION; i += 4) + dummy = mvreg_read(pp, (MVNETA_MIB_COUNTERS_BASE + i)); +} + +/* Get System Network Statistics */ +struct rtnl_link_stats64 *mvneta_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct mvneta_port *pp = netdev_priv(dev); + unsigned int start; + + memset(stats, 0, sizeof(struct rtnl_link_stats64)); + + do { + start = u64_stats_fetch_begin_bh(&pp->rx_stats.syncp); + stats->rx_packets = pp->rx_stats.packets; + stats->rx_bytes = pp->rx_stats.bytes; + } while (u64_stats_fetch_retry_bh(&pp->rx_stats.syncp, start)); + + + do { + start = u64_stats_fetch_begin_bh(&pp->tx_stats.syncp); + stats->tx_packets = pp->tx_stats.packets; + stats->tx_bytes = pp->tx_stats.bytes; + } while (u64_stats_fetch_retry_bh(&pp->tx_stats.syncp, start)); + + stats->rx_errors = dev->stats.rx_errors; + stats->rx_dropped = dev->stats.rx_dropped; + + stats->tx_dropped = dev->stats.tx_dropped; + + return stats; +} + +/* Rx descriptors helper methods */ + +/* Checks whether the given RX descriptor is both the first and the + * last descriptor for the RX packet. Each RX packet is currently + * received through a single RX descriptor, so not having each RX + * descriptor with its first and last bits set is an error + */ +static int mvneta_rxq_desc_is_first_last(struct mvneta_rx_desc *desc) +{ + return (desc->status & MVNETA_RXD_FIRST_LAST_DESC) == + MVNETA_RXD_FIRST_LAST_DESC; +} + +/* Add number of descriptors ready to receive new packets */ +static void mvneta_rxq_non_occup_desc_add(struct mvneta_port *pp, + struct mvneta_rx_queue *rxq, + int ndescs) +{ + /* Only MVNETA_RXQ_ADD_NON_OCCUPIED_MAX (255) descriptors can + * be added at once + */ + while (ndescs > MVNETA_RXQ_ADD_NON_OCCUPIED_MAX) { + mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id), + (MVNETA_RXQ_ADD_NON_OCCUPIED_MAX << + MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT)); + ndescs -= MVNETA_RXQ_ADD_NON_OCCUPIED_MAX; + } + + mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id), + (ndescs << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT)); +} + +/* Get number of RX descriptors occupied by received packets */ +static int mvneta_rxq_busy_desc_num_get(struct mvneta_port *pp, + struct mvneta_rx_queue *rxq) +{ + u32 val; + + val = mvreg_read(pp, MVNETA_RXQ_STATUS_REG(rxq->id)); + return val & MVNETA_RXQ_OCCUPIED_ALL_MASK; +} + +/* Update num of rx desc called upon return from rx path or + * from mvneta_rxq_drop_pkts(). + */ +static void mvneta_rxq_desc_num_update(struct mvneta_port *pp, + struct mvneta_rx_queue *rxq, + int rx_done, int rx_filled) +{ + u32 val; + + if ((rx_done <= 0xff) && (rx_filled <= 0xff)) { + val = rx_done | + (rx_filled << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT); + mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id), val); + return; + } + + /* Only 255 descriptors can be added at once */ + while ((rx_done > 0) || (rx_filled > 0)) { + if (rx_done <= 0xff) { + val = rx_done; + rx_done = 0; + } else { + val = 0xff; + rx_done -= 0xff; + } + if (rx_filled <= 0xff) { + val |= rx_filled << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT; + rx_filled = 0; + } else { + val |= 0xff << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT; + rx_filled -= 0xff; + } + mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id), val); + } +} + +/* Get pointer to next RX descriptor to be processed by SW */ +static struct mvneta_rx_desc * +mvneta_rxq_next_desc_get(struct mvneta_rx_queue *rxq) +{ + int rx_desc = rxq->next_desc_to_proc; + + rxq->next_desc_to_proc = MVNETA_QUEUE_NEXT_DESC(rxq, rx_desc); + return rxq->descs + rx_desc; +} + +/* Change maximum receive size of the port. */ +static void mvneta_max_rx_size_set(struct mvneta_port *pp, int max_rx_size) +{ + u32 val; + + val = mvreg_read(pp, MVNETA_GMAC_CTRL_0); + val &= ~MVNETA_GMAC_MAX_RX_SIZE_MASK; + val |= ((max_rx_size - MVNETA_MH_SIZE) / 2) << + MVNETA_GMAC_MAX_RX_SIZE_SHIFT; + mvreg_write(pp, MVNETA_GMAC_CTRL_0, val); +} + + +/* Set rx queue offset */ +static void mvneta_rxq_offset_set(struct mvneta_port *pp, + struct mvneta_rx_queue *rxq, + int offset) +{ + u32 val; + + val = mvreg_read(pp, MVNETA_RXQ_CONFIG_REG(rxq->id)); + val &= ~MVNETA_RXQ_PKT_OFFSET_ALL_MASK; + + /* Offset is in */ + val |= MVNETA_RXQ_PKT_OFFSET_MASK(offset >> 3); + mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val); +} + + +/* Tx descriptors helper methods */ + +/* Update HW with number of TX descriptors to be sent */ +static void mvneta_txq_pend_desc_add(struct mvneta_port *pp, + struct mvneta_tx_queue *txq, + int pend_desc) +{ + u32 val; + + /* Only 255 descriptors can be added at once ; Assume caller + * process TX desriptors in quanta less than 256 + */ + val = pend_desc; + mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val); +} + +/* Get pointer to next TX descriptor to be processed (send) by HW */ +static struct mvneta_tx_desc * +mvneta_txq_next_desc_get(struct mvneta_tx_queue *txq) +{ + int tx_desc = txq->next_desc_to_proc; + + txq->next_desc_to_proc = MVNETA_QUEUE_NEXT_DESC(txq, tx_desc); + return txq->descs + tx_desc; +} + +/* Release the last allocated TX descriptor. Useful to handle DMA + * mapping failures in the TX path. + */ +static void mvneta_txq_desc_put(struct mvneta_tx_queue *txq) +{ + if (txq->next_desc_to_proc == 0) + txq->next_desc_to_proc = txq->last_desc - 1; + else + txq->next_desc_to_proc--; +} + +/* Set rxq buf size */ +static void mvneta_rxq_buf_size_set(struct mvneta_port *pp, + struct mvneta_rx_queue *rxq, + int buf_size) +{ + u32 val; + + val = mvreg_read(pp, MVNETA_RXQ_SIZE_REG(rxq->id)); + + val &= ~MVNETA_RXQ_BUF_SIZE_MASK; + val |= ((buf_size >> 3) << MVNETA_RXQ_BUF_SIZE_SHIFT); + + mvreg_write(pp, MVNETA_RXQ_SIZE_REG(rxq->id), val); +} + +/* Disable buffer management (BM) */ +static void mvneta_rxq_bm_disable(struct mvneta_port *pp, + struct mvneta_rx_queue *rxq) +{ + u32 val; + + val = mvreg_read(pp, MVNETA_RXQ_CONFIG_REG(rxq->id)); + val &= ~MVNETA_RXQ_HW_BUF_ALLOC; + mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val); +} + + + +/* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */ +static void mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable) +{ + u32 val; + + val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); + + if (enable) + val |= MVNETA_GMAC2_PORT_RGMII; + else + val &= ~MVNETA_GMAC2_PORT_RGMII; + + mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); +} + +/* Config SGMII port */ +static void mvneta_port_sgmii_config(struct mvneta_port *pp) +{ + u32 val; + + val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); + val |= MVNETA_GMAC2_PSC_ENABLE; + mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); +} + +/* Start the Ethernet port RX and TX activity */ +static void mvneta_port_up(struct mvneta_port *pp) +{ + int queue; + u32 q_map; + + /* Enable all initialized TXs. */ + mvneta_mib_counters_clear(pp); + q_map = 0; + for (queue = 0; queue < txq_number; queue++) { + struct mvneta_tx_queue *txq = &pp->txqs[queue]; + if (txq->descs != NULL) + q_map |= (1 << queue); + } + mvreg_write(pp, MVNETA_TXQ_CMD, q_map); + + /* Enable all initialized RXQs. */ + q_map = 0; + for (queue = 0; queue < rxq_number; queue++) { + struct mvneta_rx_queue *rxq = &pp->rxqs[queue]; + if (rxq->descs != NULL) + q_map |= (1 << queue); + } + + mvreg_write(pp, MVNETA_RXQ_CMD, q_map); +} + +/* Stop the Ethernet port activity */ +static void mvneta_port_down(struct mvneta_port *pp) +{ + u32 val; + int count; + + /* Stop Rx port activity. Check port Rx activity. */ + val = mvreg_read(pp, MVNETA_RXQ_CMD) & MVNETA_RXQ_ENABLE_MASK; + + /* Issue stop command for active channels only */ + if (val != 0) + mvreg_write(pp, MVNETA_RXQ_CMD, + val << MVNETA_RXQ_DISABLE_SHIFT); + + /* Wait for all Rx activity to terminate. */ + count = 0; + do { + if (count++ >= MVNETA_RX_DISABLE_TIMEOUT_MSEC) { + netdev_warn(pp->dev, + "TIMEOUT for RX stopped ! rx_queue_cmd: 0x08%x\n", + val); + break; + } + mdelay(1); + + val = mvreg_read(pp, MVNETA_RXQ_CMD); + } while (val & 0xff); + + /* Stop Tx port activity. Check port Tx activity. Issue stop + * command for active channels only + */ + val = (mvreg_read(pp, MVNETA_TXQ_CMD)) & MVNETA_TXQ_ENABLE_MASK; + + if (val != 0) + mvreg_write(pp, MVNETA_TXQ_CMD, + (val << MVNETA_TXQ_DISABLE_SHIFT)); + + /* Wait for all Tx activity to terminate. */ + count = 0; + do { + if (count++ >= MVNETA_TX_DISABLE_TIMEOUT_MSEC) { + netdev_warn(pp->dev, + "TIMEOUT for TX stopped status=0x%08x\n", + val); + break; + } + mdelay(1); + + /* Check TX Command reg that all Txqs are stopped */ + val = mvreg_read(pp, MVNETA_TXQ_CMD); + + } while (val & 0xff); + + /* Double check to verify that TX FIFO is empty */ + count = 0; + do { + if (count++ >= MVNETA_TX_FIFO_EMPTY_TIMEOUT) { + netdev_warn(pp->dev, + "TX FIFO empty timeout status=0x08%x\n", + val); + break; + } + mdelay(1); + + val = mvreg_read(pp, MVNETA_PORT_STATUS); + } while (!(val & MVNETA_TX_FIFO_EMPTY) && + (val & MVNETA_TX_IN_PRGRS)); + + udelay(200); +} + +/* Enable the port by setting the port enable bit of the MAC control register */ +static void mvneta_port_enable(struct mvneta_port *pp) +{ + u32 val; + + /* Enable port */ + val = mvreg_read(pp, MVNETA_GMAC_CTRL_0); + val |= MVNETA_GMAC0_PORT_ENABLE; + mvreg_write(pp, MVNETA_GMAC_CTRL_0, val); +} + +/* Disable the port and wait for about 200 usec before retuning */ +static void mvneta_port_disable(struct mvneta_port *pp) +{ + u32 val; + + /* Reset the Enable bit in the Serial Control Register */ + val = mvreg_read(pp, MVNETA_GMAC_CTRL_0); + val &= ~MVNETA_GMAC0_PORT_ENABLE; + mvreg_write(pp, MVNETA_GMAC_CTRL_0, val); + + udelay(200); +} + +/* Multicast tables methods */ + +/* Set all entries in Unicast MAC Table; queue==-1 means reject all */ +static void mvneta_set_ucast_table(struct mvneta_port *pp, int queue) +{ + int offset; + u32 val; + + if (queue == -1) { + val = 0; + } else { + val = 0x1 | (queue << 1); + val |= (val << 24) | (val << 16) | (val << 8); + } + + for (offset = 0; offset <= 0xc; offset += 4) + mvreg_write(pp, MVNETA_DA_FILT_UCAST_BASE + offset, val); +} + +/* Set all entries in Special Multicast MAC Table; queue==-1 means reject all */ +static void mvneta_set_special_mcast_table(struct mvneta_port *pp, int queue) +{ + int offset; + u32 val; + + if (queue == -1) { + val = 0; + } else { + val = 0x1 | (queue << 1); + val |= (val << 24) | (val << 16) | (val << 8); + } + + for (offset = 0; offset <= 0xfc; offset += 4) + mvreg_write(pp, MVNETA_DA_FILT_SPEC_MCAST + offset, val); + +} + +/* Set all entries in Other Multicast MAC Table. queue==-1 means reject all */ +static void mvneta_set_other_mcast_table(struct mvneta_port *pp, int queue) +{ + int offset; + u32 val; + + if (queue == -1) { + memset(pp->mcast_count, 0, sizeof(pp->mcast_count)); + val = 0; + } else { + memset(pp->mcast_count, 1, sizeof(pp->mcast_count)); + val = 0x1 | (queue << 1); + val |= (val << 24) | (val << 16) | (val << 8); + } + + for (offset = 0; offset <= 0xfc; offset += 4) + mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + offset, val); +} + +/* This method sets defaults to the NETA port: + * Clears interrupt Cause and Mask registers. + * Clears all MAC tables. + * Sets defaults to all registers. + * Resets RX and TX descriptor rings. + * Resets PHY. + * This method can be called after mvneta_port_down() to return the port + * settings to defaults. + */ +static void mvneta_defaults_set(struct mvneta_port *pp) +{ + int cpu; + int queue; + u32 val; + + /* Clear all Cause registers */ + mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0); + mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0); + mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); + + /* Mask all interrupts */ + mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); + mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); + mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); + mvreg_write(pp, MVNETA_INTR_ENABLE, 0); + + /* Enable MBUS Retry bit16 */ + mvreg_write(pp, MVNETA_MBUS_RETRY, 0x20); + + /* Set CPU queue access map - all CPUs have access to all RX + * queues and to all TX queues + */ + for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) + mvreg_write(pp, MVNETA_CPU_MAP(cpu), + (MVNETA_CPU_RXQ_ACCESS_ALL_MASK | + MVNETA_CPU_TXQ_ACCESS_ALL_MASK)); + + /* Reset RX and TX DMAs */ + mvreg_write(pp, MVNETA_PORT_RX_RESET, MVNETA_PORT_RX_DMA_RESET); + mvreg_write(pp, MVNETA_PORT_TX_RESET, MVNETA_PORT_TX_DMA_RESET); + + /* Disable Legacy WRR, Disable EJP, Release from reset */ + mvreg_write(pp, MVNETA_TXQ_CMD_1, 0); + for (queue = 0; queue < txq_number; queue++) { + mvreg_write(pp, MVETH_TXQ_TOKEN_COUNT_REG(queue), 0); + mvreg_write(pp, MVETH_TXQ_TOKEN_CFG_REG(queue), 0); + } + + mvreg_write(pp, MVNETA_PORT_TX_RESET, 0); + mvreg_write(pp, MVNETA_PORT_RX_RESET, 0); + + /* Set Port Acceleration Mode */ + val = MVNETA_ACC_MODE_EXT; + mvreg_write(pp, MVNETA_ACC_MODE, val); + + /* Update val of portCfg register accordingly with all RxQueue types */ + val = MVNETA_PORT_CONFIG_DEFL_VALUE(rxq_def); + mvreg_write(pp, MVNETA_PORT_CONFIG, val); + + val = 0; + mvreg_write(pp, MVNETA_PORT_CONFIG_EXTEND, val); + mvreg_write(pp, MVNETA_RX_MIN_FRAME_SIZE, 64); + + /* Build PORT_SDMA_CONFIG_REG */ + val = 0; + + /* Default burst size */ + val |= MVNETA_TX_BRST_SZ_MASK(MVNETA_SDMA_BRST_SIZE_16); + val |= MVNETA_RX_BRST_SZ_MASK(MVNETA_SDMA_BRST_SIZE_16); + + val |= (MVNETA_RX_NO_DATA_SWAP | MVNETA_TX_NO_DATA_SWAP | + MVNETA_NO_DESC_SWAP); + + /* Assign port SDMA configuration */ + mvreg_write(pp, MVNETA_SDMA_CONFIG, val); + + mvneta_set_ucast_table(pp, -1); + mvneta_set_special_mcast_table(pp, -1); + mvneta_set_other_mcast_table(pp, -1); + + /* Set port interrupt enable register - default enable all */ + mvreg_write(pp, MVNETA_INTR_ENABLE, + (MVNETA_RXQ_INTR_ENABLE_ALL_MASK + | MVNETA_TXQ_INTR_ENABLE_ALL_MASK)); +} + +/* Set max sizes for tx queues */ +static void mvneta_txq_max_tx_size_set(struct mvneta_port *pp, int max_tx_size) + +{ + u32 val, size, mtu; + int queue; + + mtu = max_tx_size * 8; + if (mtu > MVNETA_TX_MTU_MAX) + mtu = MVNETA_TX_MTU_MAX; + + /* Set MTU */ + val = mvreg_read(pp, MVNETA_TX_MTU); + val &= ~MVNETA_TX_MTU_MAX; + val |= mtu; + mvreg_write(pp, MVNETA_TX_MTU, val); + + /* TX token size and all TXQs token size must be larger that MTU */ + val = mvreg_read(pp, MVNETA_TX_TOKEN_SIZE); + + size = val & MVNETA_TX_TOKEN_SIZE_MAX; + if (size < mtu) { + size = mtu; + val &= ~MVNETA_TX_TOKEN_SIZE_MAX; + val |= size; + mvreg_write(pp, MVNETA_TX_TOKEN_SIZE, val); + } + for (queue = 0; queue < txq_number; queue++) { + val = mvreg_read(pp, MVNETA_TXQ_TOKEN_SIZE_REG(queue)); + + size = val & MVNETA_TXQ_TOKEN_SIZE_MAX; + if (size < mtu) { + size = mtu; + val &= ~MVNETA_TXQ_TOKEN_SIZE_MAX; + val |= size; + mvreg_write(pp, MVNETA_TXQ_TOKEN_SIZE_REG(queue), val); + } + } +} + +/* Set unicast address */ +static void mvneta_set_ucast_addr(struct mvneta_port *pp, u8 last_nibble, + int queue) +{ + unsigned int unicast_reg; + unsigned int tbl_offset; + unsigned int reg_offset; + + /* Locate the Unicast table entry */ + last_nibble = (0xf & last_nibble); + + /* offset from unicast tbl base */ + tbl_offset = (last_nibble / 4) * 4; + + /* offset within the above reg */ + reg_offset = last_nibble % 4; + + unicast_reg = mvreg_read(pp, (MVNETA_DA_FILT_UCAST_BASE + tbl_offset)); + + if (queue == -1) { + /* Clear accepts frame bit at specified unicast DA tbl entry */ + unicast_reg &= ~(0xff << (8 * reg_offset)); + } else { + unicast_reg &= ~(0xff << (8 * reg_offset)); + unicast_reg |= ((0x01 | (queue << 1)) << (8 * reg_offset)); + } + + mvreg_write(pp, (MVNETA_DA_FILT_UCAST_BASE + tbl_offset), unicast_reg); +} + +/* Set mac address */ +static void mvneta_mac_addr_set(struct mvneta_port *pp, unsigned char *addr, + int queue) +{ + unsigned int mac_h; + unsigned int mac_l; + + if (queue != -1) { + mac_l = (addr[4] << 8) | (addr[5]); + mac_h = (addr[0] << 24) | (addr[1] << 16) | + (addr[2] << 8) | (addr[3] << 0); + + mvreg_write(pp, MVNETA_MAC_ADDR_LOW, mac_l); + mvreg_write(pp, MVNETA_MAC_ADDR_HIGH, mac_h); + } + + /* Accept frames of this address */ + mvneta_set_ucast_addr(pp, addr[5], queue); +} + +/* Set the number of packets that will be received before RX interrupt + * will be generated by HW. + */ +static void mvneta_rx_pkts_coal_set(struct mvneta_port *pp, + struct mvneta_rx_queue *rxq, u32 value) +{ + mvreg_write(pp, MVNETA_RXQ_THRESHOLD_REG(rxq->id), + value | MVNETA_RXQ_NON_OCCUPIED(0)); + rxq->pkts_coal = value; +} + +/* Set the time delay in usec before RX interrupt will be generated by + * HW. + */ +static void mvneta_rx_time_coal_set(struct mvneta_port *pp, + struct mvneta_rx_queue *rxq, u32 value) +{ + u32 val; + unsigned long clk_rate; + + clk_rate = clk_get_rate(pp->clk); + val = (clk_rate / 1000000) * value; + + mvreg_write(pp, MVNETA_RXQ_TIME_COAL_REG(rxq->id), val); + rxq->time_coal = value; +} + +/* Set threshold for TX_DONE pkts coalescing */ +static void mvneta_tx_done_pkts_coal_set(struct mvneta_port *pp, + struct mvneta_tx_queue *txq, u32 value) +{ + u32 val; + + val = mvreg_read(pp, MVNETA_TXQ_SIZE_REG(txq->id)); + + val &= ~MVNETA_TXQ_SENT_THRESH_ALL_MASK; + val |= MVNETA_TXQ_SENT_THRESH_MASK(value); + + mvreg_write(pp, MVNETA_TXQ_SIZE_REG(txq->id), val); + + txq->done_pkts_coal = value; +} + +/* Trigger tx done timer in MVNETA_TX_DONE_TIMER_PERIOD msecs */ +static void mvneta_add_tx_done_timer(struct mvneta_port *pp) +{ + if (test_and_set_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags) == 0) { + pp->tx_done_timer.expires = jiffies + + msecs_to_jiffies(MVNETA_TX_DONE_TIMER_PERIOD); + add_timer(&pp->tx_done_timer); + } +} + + +/* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */ +static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc, + u32 phys_addr, u32 cookie) +{ + rx_desc->buf_cookie = cookie; + rx_desc->buf_phys_addr = phys_addr; +} + +/* Decrement sent descriptors counter */ +static void mvneta_txq_sent_desc_dec(struct mvneta_port *pp, + struct mvneta_tx_queue *txq, + int sent_desc) +{ + u32 val; + + /* Only 255 TX descriptors can be updated at once */ + while (sent_desc > 0xff) { + val = 0xff << MVNETA_TXQ_DEC_SENT_SHIFT; + mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val); + sent_desc = sent_desc - 0xff; + } + + val = sent_desc << MVNETA_TXQ_DEC_SENT_SHIFT; + mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val); +} + +/* Get number of TX descriptors already sent by HW */ +static int mvneta_txq_sent_desc_num_get(struct mvneta_port *pp, + struct mvneta_tx_queue *txq) +{ + u32 val; + int sent_desc; + + val = mvreg_read(pp, MVNETA_TXQ_STATUS_REG(txq->id)); + sent_desc = (val & MVNETA_TXQ_SENT_DESC_MASK) >> + MVNETA_TXQ_SENT_DESC_SHIFT; + + return sent_desc; +} + +/* Get number of sent descriptors and decrement counter. + * The number of sent descriptors is returned. + */ +static int mvneta_txq_sent_desc_proc(struct mvneta_port *pp, + struct mvneta_tx_queue *txq) +{ + int sent_desc; + + /* Get number of sent descriptors */ + sent_desc = mvneta_txq_sent_desc_num_get(pp, txq); + + /* Decrement sent descriptors counter */ + if (sent_desc) + mvneta_txq_sent_desc_dec(pp, txq, sent_desc); + + return sent_desc; +} + +/* Set TXQ descriptors fields relevant for CSUM calculation */ +static u32 mvneta_txq_desc_csum(int l3_offs, int l3_proto, + int ip_hdr_len, int l4_proto) +{ + u32 command; + + /* Fields: L3_offset, IP_hdrlen, L3_type, G_IPv4_chk, + * G_L4_chk, L4_type; required only for checksum + * calculation + */ + command = l3_offs << MVNETA_TX_L3_OFF_SHIFT; + command |= ip_hdr_len << MVNETA_TX_IP_HLEN_SHIFT; + + if (l3_proto == swab16(ETH_P_IP)) + command |= MVNETA_TXD_IP_CSUM; + else + command |= MVNETA_TX_L3_IP6; + + if (l4_proto == IPPROTO_TCP) + command |= MVNETA_TX_L4_CSUM_FULL; + else if (l4_proto == IPPROTO_UDP) + command |= MVNETA_TX_L4_UDP | MVNETA_TX_L4_CSUM_FULL; + else + command |= MVNETA_TX_L4_CSUM_NOT; + + return command; +} + + +/* Display more error info */ +static void mvneta_rx_error(struct mvneta_port *pp, + struct mvneta_rx_desc *rx_desc) +{ + u32 status = rx_desc->status; + + if (!mvneta_rxq_desc_is_first_last(rx_desc)) { + netdev_err(pp->dev, + "bad rx status %08x (buffer oversize), size=%d\n", + rx_desc->status, rx_desc->data_size); + return; + } + + switch (status & MVNETA_RXD_ERR_CODE_MASK) { + case MVNETA_RXD_ERR_CRC: + netdev_err(pp->dev, "bad rx status %08x (crc error), size=%d\n", + status, rx_desc->data_size); + break; + case MVNETA_RXD_ERR_OVERRUN: + netdev_err(pp->dev, "bad rx status %08x (overrun error), size=%d\n", + status, rx_desc->data_size); + break; + case MVNETA_RXD_ERR_LEN: + netdev_err(pp->dev, "bad rx status %08x (max frame length error), size=%d\n", + status, rx_desc->data_size); + break; + case MVNETA_RXD_ERR_RESOURCE: + netdev_err(pp->dev, "bad rx status %08x (resource error), size=%d\n", + status, rx_desc->data_size); + break; + } +} + +/* Handle RX checksum offload */ +static void mvneta_rx_csum(struct mvneta_port *pp, + struct mvneta_rx_desc *rx_desc, + struct sk_buff *skb) +{ + if ((rx_desc->status & MVNETA_RXD_L3_IP4) && + (rx_desc->status & MVNETA_RXD_L4_CSUM_OK)) { + skb->csum = 0; + skb->ip_summed = CHECKSUM_UNNECESSARY; + return; + } + + skb->ip_summed = CHECKSUM_NONE; +} + +/* Return tx queue pointer (find last set bit) according to causeTxDone reg */ +static struct mvneta_tx_queue *mvneta_tx_done_policy(struct mvneta_port *pp, + u32 cause) +{ + int queue = fls(cause) - 1; + + return (queue < 0 || queue >= txq_number) ? NULL : &pp->txqs[queue]; +} + +/* Free tx queue skbuffs */ +static void mvneta_txq_bufs_free(struct mvneta_port *pp, + struct mvneta_tx_queue *txq, int num) +{ + int i; + + for (i = 0; i < num; i++) { + struct mvneta_tx_desc *tx_desc = txq->descs + + txq->txq_get_index; + struct sk_buff *skb = txq->tx_skb[txq->txq_get_index]; + + mvneta_txq_inc_get(txq); + + if (!skb) + continue; + + dma_unmap_single(pp->dev->dev.parent, tx_desc->buf_phys_addr, + tx_desc->data_size, DMA_TO_DEVICE); + dev_kfree_skb_any(skb); + } +} + +/* Handle end of transmission */ +static int mvneta_txq_done(struct mvneta_port *pp, + struct mvneta_tx_queue *txq) +{ + struct netdev_queue *nq = netdev_get_tx_queue(pp->dev, txq->id); + int tx_done; + + tx_done = mvneta_txq_sent_desc_proc(pp, txq); + if (tx_done == 0) + return tx_done; + mvneta_txq_bufs_free(pp, txq, tx_done); + + txq->count -= tx_done; + + if (netif_tx_queue_stopped(nq)) { + if (txq->size - txq->count >= MAX_SKB_FRAGS + 1) + netif_tx_wake_queue(nq); + } + + return tx_done; +} + +/* Refill processing */ +static int mvneta_rx_refill(struct mvneta_port *pp, + struct mvneta_rx_desc *rx_desc) + +{ + dma_addr_t phys_addr; + struct sk_buff *skb; + + skb = netdev_alloc_skb(pp->dev, pp->pkt_size); + if (!skb) + return -ENOMEM; + + phys_addr = dma_map_single(pp->dev->dev.parent, skb->head, + MVNETA_RX_BUF_SIZE(pp->pkt_size), + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(pp->dev->dev.parent, phys_addr))) { + dev_kfree_skb(skb); + return -ENOMEM; + } + + mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)skb); + + return 0; +} + +/* Handle tx checksum */ +static u32 mvneta_skb_tx_csum(struct mvneta_port *pp, struct sk_buff *skb) +{ + if (skb->ip_summed == CHECKSUM_PARTIAL) { + int ip_hdr_len = 0; + u8 l4_proto; + + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *ip4h = ip_hdr(skb); + + /* Calculate IPv4 checksum and L4 checksum */ + ip_hdr_len = ip4h->ihl; + l4_proto = ip4h->protocol; + } else if (skb->protocol == htons(ETH_P_IPV6)) { + struct ipv6hdr *ip6h = ipv6_hdr(skb); + + /* Read l4_protocol from one of IPv6 extra headers */ + if (skb_network_header_len(skb) > 0) + ip_hdr_len = (skb_network_header_len(skb) >> 2); + l4_proto = ip6h->nexthdr; + } else + return MVNETA_TX_L4_CSUM_NOT; + + return mvneta_txq_desc_csum(skb_network_offset(skb), + skb->protocol, ip_hdr_len, l4_proto); + } + + return MVNETA_TX_L4_CSUM_NOT; +} + +/* Returns rx queue pointer (find last set bit) according to causeRxTx + * value + */ +static struct mvneta_rx_queue *mvneta_rx_policy(struct mvneta_port *pp, + u32 cause) +{ + int queue = fls(cause >> 8) - 1; + + return (queue < 0 || queue >= rxq_number) ? NULL : &pp->rxqs[queue]; +} + +/* Drop packets received by the RXQ and free buffers */ +static void mvneta_rxq_drop_pkts(struct mvneta_port *pp, + struct mvneta_rx_queue *rxq) +{ + int rx_done, i; + + rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq); + for (i = 0; i < rxq->size; i++) { + struct mvneta_rx_desc *rx_desc = rxq->descs + i; + struct sk_buff *skb = (struct sk_buff *)rx_desc->buf_cookie; + + dev_kfree_skb_any(skb); + dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr, + rx_desc->data_size, DMA_FROM_DEVICE); + } + + if (rx_done) + mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done); +} + +/* Main rx processing */ +static int mvneta_rx(struct mvneta_port *pp, int rx_todo, + struct mvneta_rx_queue *rxq) +{ + struct net_device *dev = pp->dev; + int rx_done, rx_filled; + + /* Get number of received packets */ + rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq); + + if (rx_todo > rx_done) + rx_todo = rx_done; + + rx_done = 0; + rx_filled = 0; + + /* Fairness NAPI loop */ + while (rx_done < rx_todo) { + struct mvneta_rx_desc *rx_desc = mvneta_rxq_next_desc_get(rxq); + struct sk_buff *skb; + u32 rx_status; + int rx_bytes, err; + + prefetch(rx_desc); + rx_done++; + rx_filled++; + rx_status = rx_desc->status; + skb = (struct sk_buff *)rx_desc->buf_cookie; + + if (!mvneta_rxq_desc_is_first_last(rx_desc) || + (rx_status & MVNETA_RXD_ERR_SUMMARY)) { + dev->stats.rx_errors++; + mvneta_rx_error(pp, rx_desc); + mvneta_rx_desc_fill(rx_desc, rx_desc->buf_phys_addr, + (u32)skb); + continue; + } + + dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr, + rx_desc->data_size, DMA_FROM_DEVICE); + + rx_bytes = rx_desc->data_size - + (ETH_FCS_LEN + MVNETA_MH_SIZE); + u64_stats_update_begin(&pp->rx_stats.syncp); + pp->rx_stats.packets++; + pp->rx_stats.bytes += rx_bytes; + u64_stats_update_end(&pp->rx_stats.syncp); + + /* Linux processing */ + skb_reserve(skb, MVNETA_MH_SIZE); + skb_put(skb, rx_bytes); + + skb->protocol = eth_type_trans(skb, dev); + + mvneta_rx_csum(pp, rx_desc, skb); + + napi_gro_receive(&pp->napi, skb); + + /* Refill processing */ + err = mvneta_rx_refill(pp, rx_desc); + if (err) { + netdev_err(pp->dev, "Linux processing - Can't refill\n"); + rxq->missed++; + rx_filled--; + } + } + + /* Update rxq management counters */ + mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_filled); + + return rx_done; +} + +/* Handle tx fragmentation processing */ +static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb, + struct mvneta_tx_queue *txq) +{ + struct mvneta_tx_desc *tx_desc; + int i; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + void *addr = page_address(frag->page.p) + frag->page_offset; + + tx_desc = mvneta_txq_next_desc_get(txq); + tx_desc->data_size = frag->size; + + tx_desc->buf_phys_addr = + dma_map_single(pp->dev->dev.parent, addr, + tx_desc->data_size, DMA_TO_DEVICE); + + if (dma_mapping_error(pp->dev->dev.parent, + tx_desc->buf_phys_addr)) { + mvneta_txq_desc_put(txq); + goto error; + } + + if (i == (skb_shinfo(skb)->nr_frags - 1)) { + /* Last descriptor */ + tx_desc->command = MVNETA_TXD_L_DESC | MVNETA_TXD_Z_PAD; + + txq->tx_skb[txq->txq_put_index] = skb; + + mvneta_txq_inc_put(txq); + } else { + /* Descriptor in the middle: Not First, Not Last */ + tx_desc->command = 0; + + txq->tx_skb[txq->txq_put_index] = NULL; + mvneta_txq_inc_put(txq); + } + } + + return 0; + +error: + /* Release all descriptors that were used to map fragments of + * this packet, as well as the corresponding DMA mappings + */ + for (i = i - 1; i >= 0; i--) { + tx_desc = txq->descs + i; + dma_unmap_single(pp->dev->dev.parent, + tx_desc->buf_phys_addr, + tx_desc->data_size, + DMA_TO_DEVICE); + mvneta_txq_desc_put(txq); + } + + return -ENOMEM; +} + +/* Main tx processing */ +static int mvneta_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct mvneta_port *pp = netdev_priv(dev); + struct mvneta_tx_queue *txq = &pp->txqs[txq_def]; + struct mvneta_tx_desc *tx_desc; + struct netdev_queue *nq; + int frags = 0; + u32 tx_cmd; + + if (!netif_running(dev)) + goto out; + + frags = skb_shinfo(skb)->nr_frags + 1; + nq = netdev_get_tx_queue(dev, txq_def); + + /* Get a descriptor for the first part of the packet */ + tx_desc = mvneta_txq_next_desc_get(txq); + + tx_cmd = mvneta_skb_tx_csum(pp, skb); + + tx_desc->data_size = skb_headlen(skb); + + tx_desc->buf_phys_addr = dma_map_single(dev->dev.parent, skb->data, + tx_desc->data_size, + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev->dev.parent, + tx_desc->buf_phys_addr))) { + mvneta_txq_desc_put(txq); + frags = 0; + goto out; + } + + if (frags == 1) { + /* First and Last descriptor */ + tx_cmd |= MVNETA_TXD_FLZ_DESC; + tx_desc->command = tx_cmd; + txq->tx_skb[txq->txq_put_index] = skb; + mvneta_txq_inc_put(txq); + } else { + /* First but not Last */ + tx_cmd |= MVNETA_TXD_F_DESC; + txq->tx_skb[txq->txq_put_index] = NULL; + mvneta_txq_inc_put(txq); + tx_desc->command = tx_cmd; + /* Continue with other skb fragments */ + if (mvneta_tx_frag_process(pp, skb, txq)) { + dma_unmap_single(dev->dev.parent, + tx_desc->buf_phys_addr, + tx_desc->data_size, + DMA_TO_DEVICE); + mvneta_txq_desc_put(txq); + frags = 0; + goto out; + } + } + + txq->count += frags; + mvneta_txq_pend_desc_add(pp, txq, frags); + + if (txq->size - txq->count < MAX_SKB_FRAGS + 1) + netif_tx_stop_queue(nq); + +out: + if (frags > 0) { + u64_stats_update_begin(&pp->tx_stats.syncp); + pp->tx_stats.packets++; + pp->tx_stats.bytes += skb->len; + u64_stats_update_end(&pp->tx_stats.syncp); + + } else { + dev->stats.tx_dropped++; + dev_kfree_skb_any(skb); + } + + if (txq->count >= MVNETA_TXDONE_COAL_PKTS) + mvneta_txq_done(pp, txq); + + /* If after calling mvneta_txq_done, count equals + * frags, we need to set the timer + */ + if (txq->count == frags && frags > 0) + mvneta_add_tx_done_timer(pp); + + return NETDEV_TX_OK; +} + + +/* Free tx resources, when resetting a port */ +static void mvneta_txq_done_force(struct mvneta_port *pp, + struct mvneta_tx_queue *txq) + +{ + int tx_done = txq->count; + + mvneta_txq_bufs_free(pp, txq, tx_done); + + /* reset txq */ + txq->count = 0; + txq->txq_put_index = 0; + txq->txq_get_index = 0; +} + +/* handle tx done - called from tx done timer callback */ +static u32 mvneta_tx_done_gbe(struct mvneta_port *pp, u32 cause_tx_done, + int *tx_todo) +{ + struct mvneta_tx_queue *txq; + u32 tx_done = 0; + struct netdev_queue *nq; + + *tx_todo = 0; + while (cause_tx_done != 0) { + txq = mvneta_tx_done_policy(pp, cause_tx_done); + if (!txq) + break; + + nq = netdev_get_tx_queue(pp->dev, txq->id); + __netif_tx_lock(nq, smp_processor_id()); + + if (txq->count) { + tx_done += mvneta_txq_done(pp, txq); + *tx_todo += txq->count; + } + + __netif_tx_unlock(nq); + cause_tx_done &= ~((1 << txq->id)); + } + + return tx_done; +} + +/* Compute crc8 of the specified address, using a unique algorithm , + * according to hw spec, different than generic crc8 algorithm + */ +static int mvneta_addr_crc(unsigned char *addr) +{ + int crc = 0; + int i; + + for (i = 0; i < ETH_ALEN; i++) { + int j; + + crc = (crc ^ addr[i]) << 8; + for (j = 7; j >= 0; j--) { + if (crc & (0x100 << j)) + crc ^= 0x107 << j; + } + } + + return crc; +} + +/* This method controls the net device special MAC multicast support. + * The Special Multicast Table for MAC addresses supports MAC of the form + * 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF). + * The MAC DA[7:0] bits are used as a pointer to the Special Multicast + * Table entries in the DA-Filter table. This method set the Special + * Multicast Table appropriate entry. + */ +static void mvneta_set_special_mcast_addr(struct mvneta_port *pp, + unsigned char last_byte, + int queue) +{ + unsigned int smc_table_reg; + unsigned int tbl_offset; + unsigned int reg_offset; + + /* Register offset from SMC table base */ + tbl_offset = (last_byte / 4); + /* Entry offset within the above reg */ + reg_offset = last_byte % 4; + + smc_table_reg = mvreg_read(pp, (MVNETA_DA_FILT_SPEC_MCAST + + tbl_offset * 4)); + + if (queue == -1) + smc_table_reg &= ~(0xff << (8 * reg_offset)); + else { + smc_table_reg &= ~(0xff << (8 * reg_offset)); + smc_table_reg |= ((0x01 | (queue << 1)) << (8 * reg_offset)); + } + + mvreg_write(pp, MVNETA_DA_FILT_SPEC_MCAST + tbl_offset * 4, + smc_table_reg); +} + +/* This method controls the network device Other MAC multicast support. + * The Other Multicast Table is used for multicast of another type. + * A CRC-8 is used as an index to the Other Multicast Table entries + * in the DA-Filter table. + * The method gets the CRC-8 value from the calling routine and + * sets the Other Multicast Table appropriate entry according to the + * specified CRC-8 . + */ +static void mvneta_set_other_mcast_addr(struct mvneta_port *pp, + unsigned char crc8, + int queue) +{ + unsigned int omc_table_reg; + unsigned int tbl_offset; + unsigned int reg_offset; + + tbl_offset = (crc8 / 4) * 4; /* Register offset from OMC table base */ + reg_offset = crc8 % 4; /* Entry offset within the above reg */ + + omc_table_reg = mvreg_read(pp, MVNETA_DA_FILT_OTH_MCAST + tbl_offset); + + if (queue == -1) { + /* Clear accepts frame bit at specified Other DA table entry */ + omc_table_reg &= ~(0xff << (8 * reg_offset)); + } else { + omc_table_reg &= ~(0xff << (8 * reg_offset)); + omc_table_reg |= ((0x01 | (queue << 1)) << (8 * reg_offset)); + } + + mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + tbl_offset, omc_table_reg); +} + +/* The network device supports multicast using two tables: + * 1) Special Multicast Table for MAC addresses of the form + * 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF). + * The MAC DA[7:0] bits are used as a pointer to the Special Multicast + * Table entries in the DA-Filter table. + * 2) Other Multicast Table for multicast of another type. A CRC-8 value + * is used as an index to the Other Multicast Table entries in the + * DA-Filter table. + */ +static int mvneta_mcast_addr_set(struct mvneta_port *pp, unsigned char *p_addr, + int queue) +{ + unsigned char crc_result = 0; + + if (memcmp(p_addr, "\x01\x00\x5e\x00\x00", 5) == 0) { + mvneta_set_special_mcast_addr(pp, p_addr[5], queue); + return 0; + } + + crc_result = mvneta_addr_crc(p_addr); + if (queue == -1) { + if (pp->mcast_count[crc_result] == 0) { + netdev_info(pp->dev, "No valid Mcast for crc8=0x%02x\n", + crc_result); + return -EINVAL; + } + + pp->mcast_count[crc_result]--; + if (pp->mcast_count[crc_result] != 0) { + netdev_info(pp->dev, + "After delete there are %d valid Mcast for crc8=0x%02x\n", + pp->mcast_count[crc_result], crc_result); + return -EINVAL; + } + } else + pp->mcast_count[crc_result]++; + + mvneta_set_other_mcast_addr(pp, crc_result, queue); + + return 0; +} + +/* Configure Fitering mode of Ethernet port */ +static void mvneta_rx_unicast_promisc_set(struct mvneta_port *pp, + int is_promisc) +{ + u32 port_cfg_reg, val; + + port_cfg_reg = mvreg_read(pp, MVNETA_PORT_CONFIG); + + val = mvreg_read(pp, MVNETA_TYPE_PRIO); + + /* Set / Clear UPM bit in port configuration register */ + if (is_promisc) { + /* Accept all Unicast addresses */ + port_cfg_reg |= MVNETA_UNI_PROMISC_MODE; + val |= MVNETA_FORCE_UNI; + mvreg_write(pp, MVNETA_MAC_ADDR_LOW, 0xffff); + mvreg_write(pp, MVNETA_MAC_ADDR_HIGH, 0xffffffff); + } else { + /* Reject all Unicast addresses */ + port_cfg_reg &= ~MVNETA_UNI_PROMISC_MODE; + val &= ~MVNETA_FORCE_UNI; + } + + mvreg_write(pp, MVNETA_PORT_CONFIG, port_cfg_reg); + mvreg_write(pp, MVNETA_TYPE_PRIO, val); +} + +/* register unicast and multicast addresses */ +static void mvneta_set_rx_mode(struct net_device *dev) +{ + struct mvneta_port *pp = netdev_priv(dev); + struct netdev_hw_addr *ha; + + if (dev->flags & IFF_PROMISC) { + /* Accept all: Multicast + Unicast */ + mvneta_rx_unicast_promisc_set(pp, 1); + mvneta_set_ucast_table(pp, rxq_def); + mvneta_set_special_mcast_table(pp, rxq_def); + mvneta_set_other_mcast_table(pp, rxq_def); + } else { + /* Accept single Unicast */ + mvneta_rx_unicast_promisc_set(pp, 0); + mvneta_set_ucast_table(pp, -1); + mvneta_mac_addr_set(pp, dev->dev_addr, rxq_def); + + if (dev->flags & IFF_ALLMULTI) { + /* Accept all multicast */ + mvneta_set_special_mcast_table(pp, rxq_def); + mvneta_set_other_mcast_table(pp, rxq_def); + } else { + /* Accept only initialized multicast */ + mvneta_set_special_mcast_table(pp, -1); + mvneta_set_other_mcast_table(pp, -1); + + if (!netdev_mc_empty(dev)) { + netdev_for_each_mc_addr(ha, dev) { + mvneta_mcast_addr_set(pp, ha->addr, + rxq_def); + } + } + } + } +} + +/* Interrupt handling - the callback for request_irq() */ +static irqreturn_t mvneta_isr(int irq, void *dev_id) +{ + struct mvneta_port *pp = (struct mvneta_port *)dev_id; + + /* Mask all interrupts */ + mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); + + napi_schedule(&pp->napi); + + return IRQ_HANDLED; +} + +/* NAPI handler + * Bits 0 - 7 of the causeRxTx register indicate that are transmitted + * packets on the corresponding TXQ (Bit 0 is for TX queue 1). + * Bits 8 -15 of the cause Rx Tx register indicate that are received + * packets on the corresponding RXQ (Bit 8 is for RX queue 0). + * Each CPU has its own causeRxTx register + */ +static int mvneta_poll(struct napi_struct *napi, int budget) +{ + int rx_done = 0; + u32 cause_rx_tx; + unsigned long flags; + struct mvneta_port *pp = netdev_priv(napi->dev); + + if (!netif_running(pp->dev)) { + napi_complete(napi); + return rx_done; + } + + /* Read cause register */ + cause_rx_tx = mvreg_read(pp, MVNETA_INTR_NEW_CAUSE) & + MVNETA_RX_INTR_MASK(rxq_number); + + /* For the case where the last mvneta_poll did not process all + * RX packets + */ + cause_rx_tx |= pp->cause_rx_tx; + if (rxq_number > 1) { + while ((cause_rx_tx != 0) && (budget > 0)) { + int count; + struct mvneta_rx_queue *rxq; + /* get rx queue number from cause_rx_tx */ + rxq = mvneta_rx_policy(pp, cause_rx_tx); + if (!rxq) + break; + + /* process the packet in that rx queue */ + count = mvneta_rx(pp, budget, rxq); + rx_done += count; + budget -= count; + if (budget > 0) { + /* set off the rx bit of the + * corresponding bit in the cause rx + * tx register, so that next iteration + * will find the next rx queue where + * packets are received on + */ + cause_rx_tx &= ~((1 << rxq->id) << 8); + } + } + } else { + rx_done = mvneta_rx(pp, budget, &pp->rxqs[rxq_def]); + budget -= rx_done; + } + + if (budget > 0) { + cause_rx_tx = 0; + napi_complete(napi); + local_irq_save(flags); + mvreg_write(pp, MVNETA_INTR_NEW_MASK, + MVNETA_RX_INTR_MASK(rxq_number)); + local_irq_restore(flags); + } + + pp->cause_rx_tx = cause_rx_tx; + return rx_done; +} + +/* tx done timer callback */ +static void mvneta_tx_done_timer_callback(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct mvneta_port *pp = netdev_priv(dev); + int tx_done = 0, tx_todo = 0; + + if (!netif_running(dev)) + return ; + + clear_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags); + + tx_done = mvneta_tx_done_gbe(pp, + (((1 << txq_number) - 1) & + MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK), + &tx_todo); + if (tx_todo > 0) + mvneta_add_tx_done_timer(pp); +} + +/* Handle rxq fill: allocates rxq skbs; called when initializing a port */ +static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq, + int num) +{ + struct net_device *dev = pp->dev; + int i; + + for (i = 0; i < num; i++) { + struct sk_buff *skb; + struct mvneta_rx_desc *rx_desc; + unsigned long phys_addr; + + skb = dev_alloc_skb(pp->pkt_size); + if (!skb) { + netdev_err(dev, "%s:rxq %d, %d of %d buffs filled\n", + __func__, rxq->id, i, num); + break; + } + + rx_desc = rxq->descs + i; + memset(rx_desc, 0, sizeof(struct mvneta_rx_desc)); + phys_addr = dma_map_single(dev->dev.parent, skb->head, + MVNETA_RX_BUF_SIZE(pp->pkt_size), + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(dev->dev.parent, phys_addr))) { + dev_kfree_skb(skb); + break; + } + + mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)skb); + } + + /* Add this number of RX descriptors as non occupied (ready to + * get packets) + */ + mvneta_rxq_non_occup_desc_add(pp, rxq, i); + + return i; +} + +/* Free all packets pending transmit from all TXQs and reset TX port */ +static void mvneta_tx_reset(struct mvneta_port *pp) +{ + int queue; + + /* free the skb's in the hal tx ring */ + for (queue = 0; queue < txq_number; queue++) + mvneta_txq_done_force(pp, &pp->txqs[queue]); + + mvreg_write(pp, MVNETA_PORT_TX_RESET, MVNETA_PORT_TX_DMA_RESET); + mvreg_write(pp, MVNETA_PORT_TX_RESET, 0); +} + +static void mvneta_rx_reset(struct mvneta_port *pp) +{ + mvreg_write(pp, MVNETA_PORT_RX_RESET, MVNETA_PORT_RX_DMA_RESET); + mvreg_write(pp, MVNETA_PORT_RX_RESET, 0); +} + +/* Rx/Tx queue initialization/cleanup methods */ + +/* Create a specified RX queue */ +static int mvneta_rxq_init(struct mvneta_port *pp, + struct mvneta_rx_queue *rxq) + +{ + rxq->size = pp->rx_ring_size; + + /* Allocate memory for RX descriptors */ + rxq->descs = dma_alloc_coherent(pp->dev->dev.parent, + rxq->size * MVNETA_DESC_ALIGNED_SIZE, + &rxq->descs_phys, GFP_KERNEL); + if (rxq->descs == NULL) { + netdev_err(pp->dev, + "rxq=%d: Can't allocate %d bytes for %d RX descr\n", + rxq->id, rxq->size * MVNETA_DESC_ALIGNED_SIZE, + rxq->size); + return -ENOMEM; + } + + BUG_ON(rxq->descs != + PTR_ALIGN(rxq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE)); + + rxq->last_desc = rxq->size - 1; + + /* Set Rx descriptors queue starting address */ + mvreg_write(pp, MVNETA_RXQ_BASE_ADDR_REG(rxq->id), rxq->descs_phys); + mvreg_write(pp, MVNETA_RXQ_SIZE_REG(rxq->id), rxq->size); + + /* Set Offset */ + mvneta_rxq_offset_set(pp, rxq, NET_SKB_PAD); + + /* Set coalescing pkts and time */ + mvneta_rx_pkts_coal_set(pp, rxq, rxq->pkts_coal); + mvneta_rx_time_coal_set(pp, rxq, rxq->time_coal); + + /* Fill RXQ with buffers from RX pool */ + mvneta_rxq_buf_size_set(pp, rxq, MVNETA_RX_BUF_SIZE(pp->pkt_size)); + mvneta_rxq_bm_disable(pp, rxq); + mvneta_rxq_fill(pp, rxq, rxq->size); + + return 0; +} + +/* Cleanup Rx queue */ +static void mvneta_rxq_deinit(struct mvneta_port *pp, + struct mvneta_rx_queue *rxq) +{ + mvneta_rxq_drop_pkts(pp, rxq); + + if (rxq->descs) + dma_free_coherent(pp->dev->dev.parent, + rxq->size * MVNETA_DESC_ALIGNED_SIZE, + rxq->descs, + rxq->descs_phys); + + rxq->descs = NULL; + rxq->last_desc = 0; + rxq->next_desc_to_proc = 0; + rxq->descs_phys = 0; +} + +/* Create and initialize a tx queue */ +static int mvneta_txq_init(struct mvneta_port *pp, + struct mvneta_tx_queue *txq) +{ + txq->size = pp->tx_ring_size; + + /* Allocate memory for TX descriptors */ + txq->descs = dma_alloc_coherent(pp->dev->dev.parent, + txq->size * MVNETA_DESC_ALIGNED_SIZE, + &txq->descs_phys, GFP_KERNEL); + if (txq->descs == NULL) { + netdev_err(pp->dev, + "txQ=%d: Can't allocate %d bytes for %d TX descr\n", + txq->id, txq->size * MVNETA_DESC_ALIGNED_SIZE, + txq->size); + return -ENOMEM; + } + + /* Make sure descriptor address is cache line size aligned */ + BUG_ON(txq->descs != + PTR_ALIGN(txq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE)); + + txq->last_desc = txq->size - 1; + + /* Set maximum bandwidth for enabled TXQs */ + mvreg_write(pp, MVETH_TXQ_TOKEN_CFG_REG(txq->id), 0x03ffffff); + mvreg_write(pp, MVETH_TXQ_TOKEN_COUNT_REG(txq->id), 0x3fffffff); + + /* Set Tx descriptors queue starting address */ + mvreg_write(pp, MVNETA_TXQ_BASE_ADDR_REG(txq->id), txq->descs_phys); + mvreg_write(pp, MVNETA_TXQ_SIZE_REG(txq->id), txq->size); + + txq->tx_skb = kmalloc(txq->size * sizeof(*txq->tx_skb), GFP_KERNEL); + if (txq->tx_skb == NULL) { + dma_free_coherent(pp->dev->dev.parent, + txq->size * MVNETA_DESC_ALIGNED_SIZE, + txq->descs, txq->descs_phys); + return -ENOMEM; + } + mvneta_tx_done_pkts_coal_set(pp, txq, txq->done_pkts_coal); + + return 0; +} + +/* Free allocated resources when mvneta_txq_init() fails to allocate memory*/ +static void mvneta_txq_deinit(struct mvneta_port *pp, + struct mvneta_tx_queue *txq) +{ + kfree(txq->tx_skb); + + if (txq->descs) + dma_free_coherent(pp->dev->dev.parent, + txq->size * MVNETA_DESC_ALIGNED_SIZE, + txq->descs, txq->descs_phys); + + txq->descs = NULL; + txq->last_desc = 0; + txq->next_desc_to_proc = 0; + txq->descs_phys = 0; + + /* Set minimum bandwidth for disabled TXQs */ + mvreg_write(pp, MVETH_TXQ_TOKEN_CFG_REG(txq->id), 0); + mvreg_write(pp, MVETH_TXQ_TOKEN_COUNT_REG(txq->id), 0); + + /* Set Tx descriptors queue starting address and size */ + mvreg_write(pp, MVNETA_TXQ_BASE_ADDR_REG(txq->id), 0); + mvreg_write(pp, MVNETA_TXQ_SIZE_REG(txq->id), 0); +} + +/* Cleanup all Tx queues */ +static void mvneta_cleanup_txqs(struct mvneta_port *pp) +{ + int queue; + + for (queue = 0; queue < txq_number; queue++) + mvneta_txq_deinit(pp, &pp->txqs[queue]); +} + +/* Cleanup all Rx queues */ +static void mvneta_cleanup_rxqs(struct mvneta_port *pp) +{ + int queue; + + for (queue = 0; queue < rxq_number; queue++) + mvneta_rxq_deinit(pp, &pp->rxqs[queue]); +} + + +/* Init all Rx queues */ +static int mvneta_setup_rxqs(struct mvneta_port *pp) +{ + int queue; + + for (queue = 0; queue < rxq_number; queue++) { + int err = mvneta_rxq_init(pp, &pp->rxqs[queue]); + if (err) { + netdev_err(pp->dev, "%s: can't create rxq=%d\n", + __func__, queue); + mvneta_cleanup_rxqs(pp); + return err; + } + } + + return 0; +} + +/* Init all tx queues */ +static int mvneta_setup_txqs(struct mvneta_port *pp) +{ + int queue; + + for (queue = 0; queue < txq_number; queue++) { + int err = mvneta_txq_init(pp, &pp->txqs[queue]); + if (err) { + netdev_err(pp->dev, "%s: can't create txq=%d\n", + __func__, queue); + mvneta_cleanup_txqs(pp); + return err; + } + } + + return 0; +} + +static void mvneta_start_dev(struct mvneta_port *pp) +{ + mvneta_max_rx_size_set(pp, pp->pkt_size); + mvneta_txq_max_tx_size_set(pp, pp->pkt_size); + + /* start the Rx/Tx activity */ + mvneta_port_enable(pp); + + /* Enable polling on the port */ + napi_enable(&pp->napi); + + /* Unmask interrupts */ + mvreg_write(pp, MVNETA_INTR_NEW_MASK, + MVNETA_RX_INTR_MASK(rxq_number)); + + phy_start(pp->phy_dev); + netif_tx_start_all_queues(pp->dev); +} + +static void mvneta_stop_dev(struct mvneta_port *pp) +{ + phy_stop(pp->phy_dev); + + napi_disable(&pp->napi); + + netif_carrier_off(pp->dev); + + mvneta_port_down(pp); + netif_tx_stop_all_queues(pp->dev); + + /* Stop the port activity */ + mvneta_port_disable(pp); + + /* Clear all ethernet port interrupts */ + mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); + mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0); + + /* Mask all ethernet port interrupts */ + mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); + mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); + mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); + + mvneta_tx_reset(pp); + mvneta_rx_reset(pp); +} + +/* tx timeout callback - display a message and stop/start the network device */ +static void mvneta_tx_timeout(struct net_device *dev) +{ + struct mvneta_port *pp = netdev_priv(dev); + + netdev_info(dev, "tx timeout\n"); + mvneta_stop_dev(pp); + mvneta_start_dev(pp); +} + +/* Return positive if MTU is valid */ +static int mvneta_check_mtu_valid(struct net_device *dev, int mtu) +{ + if (mtu < 68) { + netdev_err(dev, "cannot change mtu to less than 68\n"); + return -EINVAL; + } + + /* 9676 == 9700 - 20 and rounding to 8 */ + if (mtu > 9676) { + netdev_info(dev, "Illegal MTU value %d, round to 9676\n", mtu); + mtu = 9676; + } + + if (!IS_ALIGNED(MVNETA_RX_PKT_SIZE(mtu), 8)) { + netdev_info(dev, "Illegal MTU value %d, rounding to %d\n", + mtu, ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8)); + mtu = ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8); + } + + return mtu; +} + +/* Change the device mtu */ +static int mvneta_change_mtu(struct net_device *dev, int mtu) +{ + struct mvneta_port *pp = netdev_priv(dev); + int ret; + + mtu = mvneta_check_mtu_valid(dev, mtu); + if (mtu < 0) + return -EINVAL; + + dev->mtu = mtu; + + if (!netif_running(dev)) + return 0; + + /* The interface is running, so we have to force a + * reallocation of the RXQs + */ + mvneta_stop_dev(pp); + + mvneta_cleanup_txqs(pp); + mvneta_cleanup_rxqs(pp); + + pp->pkt_size = MVNETA_RX_PKT_SIZE(pp->dev->mtu); + + ret = mvneta_setup_rxqs(pp); + if (ret) { + netdev_err(pp->dev, "unable to setup rxqs after MTU change\n"); + return ret; + } + + mvneta_setup_txqs(pp); + + mvneta_start_dev(pp); + mvneta_port_up(pp); + + return 0; +} + +/* Handle setting mac address */ +static int mvneta_set_mac_addr(struct net_device *dev, void *addr) +{ + struct mvneta_port *pp = netdev_priv(dev); + u8 *mac = addr + 2; + int i; + + if (netif_running(dev)) + return -EBUSY; + + /* Remove previous address table entry */ + mvneta_mac_addr_set(pp, dev->dev_addr, -1); + + /* Set new addr in hw */ + mvneta_mac_addr_set(pp, mac, rxq_def); + + /* Set addr in the device */ + for (i = 0; i < ETH_ALEN; i++) + dev->dev_addr[i] = mac[i]; + + return 0; +} + +static void mvneta_adjust_link(struct net_device *ndev) +{ + struct mvneta_port *pp = netdev_priv(ndev); + struct phy_device *phydev = pp->phy_dev; + int status_change = 0; + + if (phydev->link) { + if ((pp->speed != phydev->speed) || + (pp->duplex != phydev->duplex)) { + u32 val; + + val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); + val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED | + MVNETA_GMAC_CONFIG_GMII_SPEED | + MVNETA_GMAC_CONFIG_FULL_DUPLEX); + + if (phydev->duplex) + val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; + + if (phydev->speed == SPEED_1000) + val |= MVNETA_GMAC_CONFIG_GMII_SPEED; + else + val |= MVNETA_GMAC_CONFIG_MII_SPEED; + + mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); + + pp->duplex = phydev->duplex; + pp->speed = phydev->speed; + } + } + + if (phydev->link != pp->link) { + if (!phydev->link) { + pp->duplex = -1; + pp->speed = 0; + } + + pp->link = phydev->link; + status_change = 1; + } + + if (status_change) { + if (phydev->link) { + u32 val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); + val |= (MVNETA_GMAC_FORCE_LINK_PASS | + MVNETA_GMAC_FORCE_LINK_DOWN); + mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); + mvneta_port_up(pp); + netdev_info(pp->dev, "link up\n"); + } else { + mvneta_port_down(pp); + netdev_info(pp->dev, "link down\n"); + } + } +} + +static int mvneta_mdio_probe(struct mvneta_port *pp) +{ + struct phy_device *phy_dev; + + phy_dev = of_phy_connect(pp->dev, pp->phy_node, mvneta_adjust_link, 0, + pp->phy_interface); + if (!phy_dev) { + netdev_err(pp->dev, "could not find the PHY\n"); + return -ENODEV; + } + + phy_dev->supported &= PHY_GBIT_FEATURES; + phy_dev->advertising = phy_dev->supported; + + pp->phy_dev = phy_dev; + pp->link = 0; + pp->duplex = 0; + pp->speed = 0; + + return 0; +} + +static void mvneta_mdio_remove(struct mvneta_port *pp) +{ + phy_disconnect(pp->phy_dev); + pp->phy_dev = NULL; +} + +static int mvneta_open(struct net_device *dev) +{ + struct mvneta_port *pp = netdev_priv(dev); + int ret; + + mvneta_mac_addr_set(pp, dev->dev_addr, rxq_def); + + pp->pkt_size = MVNETA_RX_PKT_SIZE(pp->dev->mtu); + + ret = mvneta_setup_rxqs(pp); + if (ret) + return ret; + + ret = mvneta_setup_txqs(pp); + if (ret) + goto err_cleanup_rxqs; + + /* Connect to port interrupt line */ + ret = request_irq(pp->dev->irq, mvneta_isr, 0, + MVNETA_DRIVER_NAME, pp); + if (ret) { + netdev_err(pp->dev, "cannot request irq %d\n", pp->dev->irq); + goto err_cleanup_txqs; + } + + /* In default link is down */ + netif_carrier_off(pp->dev); + + ret = mvneta_mdio_probe(pp); + if (ret < 0) { + netdev_err(dev, "cannot probe MDIO bus\n"); + goto err_free_irq; + } + + mvneta_start_dev(pp); + + return 0; + +err_free_irq: + free_irq(pp->dev->irq, pp); +err_cleanup_txqs: + mvneta_cleanup_txqs(pp); +err_cleanup_rxqs: + mvneta_cleanup_rxqs(pp); + return ret; +} + +/* Stop the port, free port interrupt line */ +static int mvneta_stop(struct net_device *dev) +{ + struct mvneta_port *pp = netdev_priv(dev); + + mvneta_stop_dev(pp); + mvneta_mdio_remove(pp); + free_irq(dev->irq, pp); + mvneta_cleanup_rxqs(pp); + mvneta_cleanup_txqs(pp); + del_timer(&pp->tx_done_timer); + clear_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags); + + return 0; +} + +/* Ethtool methods */ + +/* Get settings (phy address, speed) for ethtools */ +int mvneta_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct mvneta_port *pp = netdev_priv(dev); + + if (!pp->phy_dev) + return -ENODEV; + + return phy_ethtool_gset(pp->phy_dev, cmd); +} + +/* Set settings (phy address, speed) for ethtools */ +int mvneta_ethtool_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct mvneta_port *pp = netdev_priv(dev); + + if (!pp->phy_dev) + return -ENODEV; + + return phy_ethtool_sset(pp->phy_dev, cmd); +} + +/* Set interrupt coalescing for ethtools */ +static int mvneta_ethtool_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *c) +{ + struct mvneta_port *pp = netdev_priv(dev); + int queue; + + for (queue = 0; queue < rxq_number; queue++) { + struct mvneta_rx_queue *rxq = &pp->rxqs[queue]; + rxq->time_coal = c->rx_coalesce_usecs; + rxq->pkts_coal = c->rx_max_coalesced_frames; + mvneta_rx_pkts_coal_set(pp, rxq, rxq->pkts_coal); + mvneta_rx_time_coal_set(pp, rxq, rxq->time_coal); + } + + for (queue = 0; queue < txq_number; queue++) { + struct mvneta_tx_queue *txq = &pp->txqs[queue]; + txq->done_pkts_coal = c->tx_max_coalesced_frames; + mvneta_tx_done_pkts_coal_set(pp, txq, txq->done_pkts_coal); + } + + return 0; +} + +/* get coalescing for ethtools */ +static int mvneta_ethtool_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *c) +{ + struct mvneta_port *pp = netdev_priv(dev); + + c->rx_coalesce_usecs = pp->rxqs[0].time_coal; + c->rx_max_coalesced_frames = pp->rxqs[0].pkts_coal; + + c->tx_max_coalesced_frames = pp->txqs[0].done_pkts_coal; + return 0; +} + + +static void mvneta_ethtool_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + strlcpy(drvinfo->driver, MVNETA_DRIVER_NAME, + sizeof(drvinfo->driver)); + strlcpy(drvinfo->version, MVNETA_DRIVER_VERSION, + sizeof(drvinfo->version)); + strlcpy(drvinfo->bus_info, dev_name(&dev->dev), + sizeof(drvinfo->bus_info)); +} + + +static void mvneta_ethtool_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct mvneta_port *pp = netdev_priv(netdev); + + ring->rx_max_pending = MVNETA_MAX_RXD; + ring->tx_max_pending = MVNETA_MAX_TXD; + ring->rx_pending = pp->rx_ring_size; + ring->tx_pending = pp->tx_ring_size; +} + +static int mvneta_ethtool_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct mvneta_port *pp = netdev_priv(dev); + + if ((ring->rx_pending == 0) || (ring->tx_pending == 0)) + return -EINVAL; + pp->rx_ring_size = ring->rx_pending < MVNETA_MAX_RXD ? + ring->rx_pending : MVNETA_MAX_RXD; + pp->tx_ring_size = ring->tx_pending < MVNETA_MAX_TXD ? + ring->tx_pending : MVNETA_MAX_TXD; + + if (netif_running(dev)) { + mvneta_stop(dev); + if (mvneta_open(dev)) { + netdev_err(dev, + "error on opening device after ring param change\n"); + return -ENOMEM; + } + } + + return 0; +} + +static const struct net_device_ops mvneta_netdev_ops = { + .ndo_open = mvneta_open, + .ndo_stop = mvneta_stop, + .ndo_start_xmit = mvneta_tx, + .ndo_set_rx_mode = mvneta_set_rx_mode, + .ndo_set_mac_address = mvneta_set_mac_addr, + .ndo_change_mtu = mvneta_change_mtu, + .ndo_tx_timeout = mvneta_tx_timeout, + .ndo_get_stats64 = mvneta_get_stats64, +}; + +const struct ethtool_ops mvneta_eth_tool_ops = { + .get_link = ethtool_op_get_link, + .get_settings = mvneta_ethtool_get_settings, + .set_settings = mvneta_ethtool_set_settings, + .set_coalesce = mvneta_ethtool_set_coalesce, + .get_coalesce = mvneta_ethtool_get_coalesce, + .get_drvinfo = mvneta_ethtool_get_drvinfo, + .get_ringparam = mvneta_ethtool_get_ringparam, + .set_ringparam = mvneta_ethtool_set_ringparam, +}; + +/* Initialize hw */ +static int mvneta_init(struct mvneta_port *pp, int phy_addr) +{ + int queue; + + /* Disable port */ + mvneta_port_disable(pp); + + /* Set port default values */ + mvneta_defaults_set(pp); + + pp->txqs = kzalloc(txq_number * sizeof(struct mvneta_tx_queue), + GFP_KERNEL); + if (!pp->txqs) + return -ENOMEM; + + /* Initialize TX descriptor rings */ + for (queue = 0; queue < txq_number; queue++) { + struct mvneta_tx_queue *txq = &pp->txqs[queue]; + txq->id = queue; + txq->size = pp->tx_ring_size; + txq->done_pkts_coal = MVNETA_TXDONE_COAL_PKTS; + } + + pp->rxqs = kzalloc(rxq_number * sizeof(struct mvneta_rx_queue), + GFP_KERNEL); + if (!pp->rxqs) { + kfree(pp->txqs); + return -ENOMEM; + } + + /* Create Rx descriptor rings */ + for (queue = 0; queue < rxq_number; queue++) { + struct mvneta_rx_queue *rxq = &pp->rxqs[queue]; + rxq->id = queue; + rxq->size = pp->rx_ring_size; + rxq->pkts_coal = MVNETA_RX_COAL_PKTS; + rxq->time_coal = MVNETA_RX_COAL_USEC; + } + + return 0; +} + +static void mvneta_deinit(struct mvneta_port *pp) +{ + kfree(pp->txqs); + kfree(pp->rxqs); +} + +/* platform glue : initialize decoding windows */ +static void mvneta_conf_mbus_windows(struct mvneta_port *pp, + const struct mbus_dram_target_info *dram) +{ + u32 win_enable; + u32 win_protect; + int i; + + for (i = 0; i < 6; i++) { + mvreg_write(pp, MVNETA_WIN_BASE(i), 0); + mvreg_write(pp, MVNETA_WIN_SIZE(i), 0); + + if (i < 4) + mvreg_write(pp, MVNETA_WIN_REMAP(i), 0); + } + + win_enable = 0x3f; + win_protect = 0; + + for (i = 0; i < dram->num_cs; i++) { + const struct mbus_dram_window *cs = dram->cs + i; + mvreg_write(pp, MVNETA_WIN_BASE(i), (cs->base & 0xffff0000) | + (cs->mbus_attr << 8) | dram->mbus_dram_target_id); + + mvreg_write(pp, MVNETA_WIN_SIZE(i), + (cs->size - 1) & 0xffff0000); + + win_enable &= ~(1 << i); + win_protect |= 3 << (2 * i); + } + + mvreg_write(pp, MVNETA_BASE_ADDR_ENABLE, win_enable); +} + +/* Power up the port */ +static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) +{ + u32 val; + + /* MAC Cause register should be cleared */ + mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0); + + if (phy_mode == PHY_INTERFACE_MODE_SGMII) + mvneta_port_sgmii_config(pp); + + mvneta_gmac_rgmii_set(pp, 1); + + /* Cancel Port Reset */ + val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); + val &= ~MVNETA_GMAC2_PORT_RESET; + mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); + + while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) & + MVNETA_GMAC2_PORT_RESET) != 0) + continue; +} + +/* Device initialization routine */ +static int mvneta_probe(struct platform_device *pdev) +{ + const struct mbus_dram_target_info *dram_target_info; + struct device_node *dn = pdev->dev.of_node; + struct device_node *phy_node; + u32 phy_addr; + struct mvneta_port *pp; + struct net_device *dev; + const char *mac_addr; + int phy_mode; + int err; + + /* Our multiqueue support is not complete, so for now, only + * allow the usage of the first RX queue + */ + if (rxq_def != 0) { + dev_err(&pdev->dev, "Invalid rxq_def argument: %d\n", rxq_def); + return -EINVAL; + } + + dev = alloc_etherdev_mq(sizeof(struct mvneta_port), 8); + if (!dev) + return -ENOMEM; + + dev->irq = irq_of_parse_and_map(dn, 0); + if (dev->irq == 0) { + err = -EINVAL; + goto err_free_netdev; + } + + phy_node = of_parse_phandle(dn, "phy", 0); + if (!phy_node) { + dev_err(&pdev->dev, "no associated PHY\n"); + err = -ENODEV; + goto err_free_irq; + } + + phy_mode = of_get_phy_mode(dn); + if (phy_mode < 0) { + dev_err(&pdev->dev, "incorrect phy-mode\n"); + err = -EINVAL; + goto err_free_irq; + } + + mac_addr = of_get_mac_address(dn); + + if (!mac_addr || !is_valid_ether_addr(mac_addr)) + eth_hw_addr_random(dev); + else + memcpy(dev->dev_addr, mac_addr, ETH_ALEN); + + dev->tx_queue_len = MVNETA_MAX_TXD; + dev->watchdog_timeo = 5 * HZ; + dev->netdev_ops = &mvneta_netdev_ops; + + SET_ETHTOOL_OPS(dev, &mvneta_eth_tool_ops); + + pp = netdev_priv(dev); + + pp->tx_done_timer.function = mvneta_tx_done_timer_callback; + init_timer(&pp->tx_done_timer); + clear_bit(MVNETA_F_TX_DONE_TIMER_BIT, &pp->flags); + + pp->weight = MVNETA_RX_POLL_WEIGHT; + pp->phy_node = phy_node; + pp->phy_interface = phy_mode; + + pp->base = of_iomap(dn, 0); + if (pp->base == NULL) { + err = -ENOMEM; + goto err_free_irq; + } + + pp->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pp->clk)) { + err = PTR_ERR(pp->clk); + goto err_unmap; + } + + clk_prepare_enable(pp->clk); + + pp->tx_done_timer.data = (unsigned long)dev; + + pp->tx_ring_size = MVNETA_MAX_TXD; + pp->rx_ring_size = MVNETA_MAX_RXD; + + pp->dev = dev; + SET_NETDEV_DEV(dev, &pdev->dev); + + err = mvneta_init(pp, phy_addr); + if (err < 0) { + dev_err(&pdev->dev, "can't init eth hal\n"); + goto err_clk; + } + mvneta_port_power_up(pp, phy_mode); + + dram_target_info = mv_mbus_dram_info(); + if (dram_target_info) + mvneta_conf_mbus_windows(pp, dram_target_info); + + netif_napi_add(dev, &pp->napi, mvneta_poll, pp->weight); + + err = register_netdev(dev); + if (err < 0) { + dev_err(&pdev->dev, "failed to register\n"); + goto err_deinit; + } + + dev->features = NETIF_F_SG | NETIF_F_IP_CSUM; + dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM; + dev->priv_flags |= IFF_UNICAST_FLT; + + netdev_info(dev, "mac: %pM\n", dev->dev_addr); + + platform_set_drvdata(pdev, pp->dev); + + return 0; + +err_deinit: + mvneta_deinit(pp); +err_clk: + clk_disable_unprepare(pp->clk); +err_unmap: + iounmap(pp->base); +err_free_irq: + irq_dispose_mapping(dev->irq); +err_free_netdev: + free_netdev(dev); + return err; +} + +/* Device removal routine */ +static int mvneta_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct mvneta_port *pp = netdev_priv(dev); + + unregister_netdev(dev); + mvneta_deinit(pp); + clk_disable_unprepare(pp->clk); + iounmap(pp->base); + irq_dispose_mapping(dev->irq); + free_netdev(dev); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static const struct of_device_id mvneta_match[] = { + { .compatible = "marvell,armada-370-neta" }, + { } +}; +MODULE_DEVICE_TABLE(of, mvneta_match); + +static struct platform_driver mvneta_driver = { + .probe = mvneta_probe, + .remove = mvneta_remove, + .driver = { + .name = MVNETA_DRIVER_NAME, + .of_match_table = mvneta_match, + }, +}; + +module_platform_driver(mvneta_driver); + +MODULE_DESCRIPTION("Marvell NETA Ethernet Driver - www.marvell.com"); +MODULE_AUTHOR("Rami Rosen <rosenr@marvell.com>, Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); +MODULE_LICENSE("GPL"); + +module_param(rxq_number, int, S_IRUGO); +module_param(txq_number, int, S_IRUGO); + +module_param(rxq_def, int, S_IRUGO); +module_param(txq_def, int, S_IRUGO); diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 59489722e898..10d678d3dd01 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -1131,7 +1131,7 @@ static int pxa168_eth_open(struct net_device *dev) err = request_irq(dev->irq, pxa168_eth_int_handler, IRQF_DISABLED, dev->name, dev); if (err) { - dev_printk(KERN_ERR, &dev->dev, "can't assign irq\n"); + dev_err(&dev->dev, "can't assign irq\n"); return -EAGAIN; } pep->rx_resource_err = 0; @@ -1201,9 +1201,8 @@ static int pxa168_eth_change_mtu(struct net_device *dev, int mtu) */ pxa168_eth_stop(dev); if (pxa168_eth_open(dev)) { - dev_printk(KERN_ERR, &dev->dev, - "fatal error on re-opening device after " - "MTU change\n"); + dev_err(&dev->dev, + "fatal error on re-opening device after MTU change\n"); } return 0; diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 9b9c2ac5c4c2..5544a1fe2f94 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -3860,7 +3860,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, return dev; } -static void __devinit skge_show_addr(struct net_device *dev) +static void skge_show_addr(struct net_device *dev) { const struct skge_port *skge = netdev_priv(dev); @@ -3869,8 +3869,7 @@ static void __devinit skge_show_addr(struct net_device *dev) static int only_32bit_dma; -static int __devinit skge_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int skge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev, *dev1; struct skge_hw *hw; @@ -4012,7 +4011,7 @@ err_out: return err; } -static void __devexit skge_remove(struct pci_dev *pdev) +static void skge_remove(struct pci_dev *pdev) { struct skge_hw *hw = pci_get_drvdata(pdev); struct net_device *dev0, *dev1; @@ -4026,7 +4025,7 @@ static void __devexit skge_remove(struct pci_dev *pdev) dev0 = hw->dev[0]; unregister_netdev(dev0); - tasklet_disable(&hw->phy_task); + tasklet_kill(&hw->phy_task); spin_lock_irq(&hw->hw_lock); hw->intr_mask = 0; @@ -4142,7 +4141,7 @@ static struct pci_driver skge_driver = { .name = DRV_NAME, .id_table = skge_id_table, .probe = skge_probe, - .remove = __devexit_p(skge_remove), + .remove = skge_remove, .shutdown = skge_shutdown, .driver.pm = SKGE_PM_OPS, }; diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 78946feab4a2..3269eb38cc57 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -3140,7 +3140,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) } -static int __devinit sky2_init(struct sky2_hw *hw) +static int sky2_init(struct sky2_hw *hw) { u8 t8; @@ -4741,9 +4741,8 @@ static const struct net_device_ops sky2_netdev_ops[2] = { }; /* Initialize network device */ -static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, - unsigned port, - int highmem, int wol) +static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port, + int highmem, int wol) { struct sky2_port *sky2; struct net_device *dev = alloc_etherdev(sizeof(*sky2)); @@ -4807,7 +4806,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, return dev; } -static void __devinit sky2_show_addr(struct net_device *dev) +static void sky2_show_addr(struct net_device *dev) { const struct sky2_port *sky2 = netdev_priv(dev); @@ -4815,7 +4814,7 @@ static void __devinit sky2_show_addr(struct net_device *dev) } /* Handle software interrupt used during MSI test */ -static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id) +static irqreturn_t sky2_test_intr(int irq, void *dev_id) { struct sky2_hw *hw = dev_id; u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2); @@ -4834,7 +4833,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id) } /* Test interrupt path by forcing a a software IRQ */ -static int __devinit sky2_test_msi(struct sky2_hw *hw) +static int sky2_test_msi(struct sky2_hw *hw) { struct pci_dev *pdev = hw->pdev; int err; @@ -4896,8 +4895,7 @@ static const char *sky2_name(u8 chipid, char *buf, int sz) return buf; } -static int __devinit sky2_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev, *dev1; struct sky2_hw *hw; @@ -4919,13 +4917,13 @@ static int __devinit sky2_probe(struct pci_dev *pdev, err = pci_read_config_dword(pdev, PCI_DEV_REG2, ®); if (err) { dev_err(&pdev->dev, "PCI read config failed\n"); - goto err_out; + goto err_out_disable; } if (~reg == 0) { dev_err(&pdev->dev, "PCI configuration read error\n"); err = -EIO; - goto err_out; + goto err_out_disable; } err = pci_request_regions(pdev, DRV_NAME); @@ -5012,10 +5010,11 @@ static int __devinit sky2_probe(struct pci_dev *pdev, if (!disable_msi && pci_enable_msi(pdev) == 0) { err = sky2_test_msi(hw); - if (err == -EOPNOTSUPP) + if (err) { pci_disable_msi(pdev); - else if (err) - goto err_out_free_netdev; + if (err != -EOPNOTSUPP) + goto err_out_free_netdev; + } } err = register_netdev(dev); @@ -5063,10 +5062,10 @@ err_out_unregister_dev1: err_out_free_dev1: free_netdev(dev1); err_out_unregister: - if (hw->flags & SKY2_HW_USE_MSI) - pci_disable_msi(pdev); unregister_netdev(dev); err_out_free_netdev: + if (hw->flags & SKY2_HW_USE_MSI) + pci_disable_msi(pdev); free_netdev(dev); err_out_free_pci: pci_free_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le), @@ -5086,7 +5085,7 @@ err_out: return err; } -static void __devexit sky2_remove(struct pci_dev *pdev) +static void sky2_remove(struct pci_dev *pdev) { struct sky2_hw *hw = pci_get_drvdata(pdev); int i; @@ -5207,7 +5206,7 @@ static struct pci_driver sky2_driver = { .name = DRV_NAME, .id_table = sky2_id_table, .probe = sky2_probe, - .remove = __devexit_p(sky2_remove), + .remove = sky2_remove, .shutdown = sky2_shutdown, .driver.pm = SKY2_PM_OPS, }; diff --git a/drivers/net/ethernet/mellanox/Kconfig b/drivers/net/ethernet/mellanox/Kconfig index d8099a7903d3..bcdbc14aeff0 100644 --- a/drivers/net/ethernet/mellanox/Kconfig +++ b/drivers/net/ethernet/mellanox/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_MELLANOX bool "Mellanox devices" default y - depends on PCI && INET + depends on PCI ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig index 5f027f95cc84..eb520ab64014 100644 --- a/drivers/net/ethernet/mellanox/mlx4/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig @@ -4,9 +4,8 @@ config MLX4_EN tristate "Mellanox Technologies 10Gbit Ethernet support" - depends on PCI && INET + depends on PCI select MLX4_CORE - select INET_LRO ---help--- This driver supports Mellanox Technologies ConnectX Ethernet devices. diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 3d1899ff1076..fdc5f23d8e9f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -1498,6 +1498,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, u32 reply; u8 is_going_down = 0; int i; + unsigned long flags; slave_state[slave].comm_toggle ^= 1; reply = (u32) slave_state[slave].comm_toggle << 31; @@ -1576,12 +1577,12 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave); goto reset_slave; } - spin_lock(&priv->mfunc.master.slave_state_lock); + spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); if (!slave_state[slave].is_slave_going_down) slave_state[slave].last_cmd = cmd; else is_going_down = 1; - spin_unlock(&priv->mfunc.master.slave_state_lock); + spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); if (is_going_down) { mlx4_warn(dev, "Slave is going down aborting command(%d)" " executing from slave:%d\n", @@ -1597,10 +1598,10 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, reset_slave: /* cleanup any slave resources */ mlx4_delete_all_resources_for_slave(dev, slave); - spin_lock(&priv->mfunc.master.slave_state_lock); + spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); if (!slave_state[slave].is_slave_going_down) slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET; - spin_unlock(&priv->mfunc.master.slave_state_lock); + spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); /*with slave in the middle of flr, no need to clean resources again.*/ inform_slave_state: memset(&slave_state[slave].event_eq, 0, @@ -1755,7 +1756,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev) spin_lock_init(&s_state->lock); } - memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe)); + memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size); priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD; INIT_WORK(&priv->mfunc.master.comm_work, mlx4_master_comm_channel); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c index aa9c2f6cf3c0..b8d0854a7ad1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c @@ -51,7 +51,7 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv, int err; cq->size = entries; - cq->buf_size = cq->size * sizeof(struct mlx4_cqe); + cq->buf_size = cq->size * mdev->dev->caps.cqe_size; cq->ring = ring; cq->is_tx = mode; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c index 5d36795877cb..b799ab12a291 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c @@ -237,7 +237,7 @@ static int mlx4_en_dcbnl_ieee_setmaxrate(struct net_device *dev, if (err) return err; - memcpy(priv->maxrate, tmp, sizeof(*priv->maxrate)); + memcpy(priv->maxrate, tmp, sizeof(priv->maxrate)); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index 9d0b88eea02b..03447dad07e9 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -43,6 +43,34 @@ #define EN_ETHTOOL_SHORT_MASK cpu_to_be16(0xffff) #define EN_ETHTOOL_WORD_MASK cpu_to_be32(0xffffffff) +static int mlx4_en_moderation_update(struct mlx4_en_priv *priv) +{ + int i; + int err = 0; + + for (i = 0; i < priv->tx_ring_num; i++) { + priv->tx_cq[i].moder_cnt = priv->tx_frames; + priv->tx_cq[i].moder_time = priv->tx_usecs; + err = mlx4_en_set_cq_moder(priv, &priv->tx_cq[i]); + if (err) + return err; + } + + if (priv->adaptive_rx_coal) + return 0; + + for (i = 0; i < priv->rx_ring_num; i++) { + priv->rx_cq[i].moder_cnt = priv->rx_frames; + priv->rx_cq[i].moder_time = priv->rx_usecs; + priv->last_moder_time[i] = MLX4_EN_AUTO_CONF; + err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]); + if (err) + return err; + } + + return err; +} + static void mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) { @@ -381,7 +409,6 @@ static int mlx4_en_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) { struct mlx4_en_priv *priv = netdev_priv(dev); - int err, i; priv->rx_frames = (coal->rx_max_coalesced_frames == MLX4_EN_AUTO_CONF) ? @@ -397,14 +424,6 @@ static int mlx4_en_set_coalesce(struct net_device *dev, coal->tx_max_coalesced_frames != priv->tx_frames) { priv->tx_usecs = coal->tx_coalesce_usecs; priv->tx_frames = coal->tx_max_coalesced_frames; - for (i = 0; i < priv->tx_ring_num; i++) { - priv->tx_cq[i].moder_cnt = priv->tx_frames; - priv->tx_cq[i].moder_time = priv->tx_usecs; - if (mlx4_en_set_cq_moder(priv, &priv->tx_cq[i])) { - en_warn(priv, "Failed changing moderation " - "for TX cq %d\n", i); - } - } } /* Set adaptive coalescing params */ @@ -414,18 +433,8 @@ static int mlx4_en_set_coalesce(struct net_device *dev, priv->rx_usecs_high = coal->rx_coalesce_usecs_high; priv->sample_interval = coal->rate_sample_interval; priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce; - if (priv->adaptive_rx_coal) - return 0; - for (i = 0; i < priv->rx_ring_num; i++) { - priv->rx_cq[i].moder_cnt = priv->rx_frames; - priv->rx_cq[i].moder_time = priv->rx_usecs; - priv->last_moder_time[i] = MLX4_EN_AUTO_CONF; - err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]); - if (err) - return err; - } - return 0; + return mlx4_en_moderation_update(priv); } static int mlx4_en_set_pauseparam(struct net_device *dev, @@ -466,7 +475,6 @@ static int mlx4_en_set_ringparam(struct net_device *dev, u32 rx_size, tx_size; int port_up = 0; int err = 0; - int i; if (param->rx_jumbo_pending || param->rx_mini_pending) return -EINVAL; @@ -505,14 +513,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev, en_err(priv, "Failed starting port\n"); } - for (i = 0; i < priv->rx_ring_num; i++) { - priv->rx_cq[i].moder_cnt = priv->rx_frames; - priv->rx_cq[i].moder_time = priv->rx_usecs; - priv->last_moder_time[i] = MLX4_EN_AUTO_CONF; - err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]); - if (err) - goto out; - } + err = mlx4_en_moderation_update(priv); out: mutex_unlock(&mdev->state_lock); @@ -612,13 +613,17 @@ static int mlx4_en_validate_flow(struct net_device *dev, struct ethtool_usrip4_spec *l3_mask; struct ethtool_tcpip4_spec *l4_mask; struct ethhdr *eth_mask; - u64 full_mac = ~0ull; - u64 zero_mac = 0; if (cmd->fs.location >= MAX_NUM_OF_FS_RULES) return -EINVAL; - switch (cmd->fs.flow_type & ~FLOW_EXT) { + if (cmd->fs.flow_type & FLOW_MAC_EXT) { + /* dest mac mask must be ff:ff:ff:ff:ff:ff */ + if (!is_broadcast_ether_addr(cmd->fs.m_ext.h_dest)) + return -EINVAL; + } + + switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { case TCP_V4_FLOW: case UDP_V4_FLOW: if (cmd->fs.m_u.tcp_ip4_spec.tos) @@ -643,11 +648,11 @@ static int mlx4_en_validate_flow(struct net_device *dev, case ETHER_FLOW: eth_mask = &cmd->fs.m_u.ether_spec; /* source mac mask must not be set */ - if (memcmp(eth_mask->h_source, &zero_mac, ETH_ALEN)) + if (!is_zero_ether_addr(eth_mask->h_source)) return -EINVAL; /* dest mac mask must be ff:ff:ff:ff:ff:ff */ - if (memcmp(eth_mask->h_dest, &full_mac, ETH_ALEN)) + if (!is_broadcast_ether_addr(eth_mask->h_dest)) return -EINVAL; if (!all_zeros_or_all_ones(eth_mask->h_proto)) @@ -746,7 +751,6 @@ static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev, struct list_head *rule_list_h) { int err; - u64 mac; __be64 be_mac; struct ethhdr *eth_spec; struct mlx4_en_priv *priv = netdev_priv(dev); @@ -761,12 +765,16 @@ static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev, if (!spec_l2) return -ENOMEM; - mac = priv->mac & MLX4_MAC_MASK; - be_mac = cpu_to_be64(mac << 16); + if (cmd->fs.flow_type & FLOW_MAC_EXT) { + memcpy(&be_mac, cmd->fs.h_ext.h_dest, ETH_ALEN); + } else { + u64 mac = priv->mac & MLX4_MAC_MASK; + be_mac = cpu_to_be64(mac << 16); + } spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH; memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN); - if ((cmd->fs.flow_type & ~FLOW_EXT) != ETHER_FLOW) + if ((cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) != ETHER_FLOW) memcpy(spec_l2->eth.dst_mac, &be_mac, ETH_ALEN); if ((cmd->fs.flow_type & FLOW_EXT) && cmd->fs.m_ext.vlan_tci) { @@ -776,7 +784,7 @@ static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev, list_add_tail(&spec_l2->list, rule_list_h); - switch (cmd->fs.flow_type & ~FLOW_EXT) { + switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { case ETHER_FLOW: eth_spec = &cmd->fs.h_u.ether_spec; memcpy(&spec_l2->eth.dst_mac, eth_spec->h_dest, ETH_ALEN); @@ -998,6 +1006,73 @@ static int mlx4_en_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) return err; } +static void mlx4_en_get_channels(struct net_device *dev, + struct ethtool_channels *channel) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + + memset(channel, 0, sizeof(*channel)); + + channel->max_rx = MAX_RX_RINGS; + channel->max_tx = MLX4_EN_MAX_TX_RING_P_UP; + + channel->rx_count = priv->rx_ring_num; + channel->tx_count = priv->tx_ring_num / MLX4_EN_NUM_UP; +} + +static int mlx4_en_set_channels(struct net_device *dev, + struct ethtool_channels *channel) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + int port_up; + int err = 0; + + if (channel->other_count || channel->combined_count || + channel->tx_count > MLX4_EN_MAX_TX_RING_P_UP || + channel->rx_count > MAX_RX_RINGS || + !channel->tx_count || !channel->rx_count) + return -EINVAL; + + mutex_lock(&mdev->state_lock); + if (priv->port_up) { + port_up = 1; + mlx4_en_stop_port(dev); + } + + mlx4_en_free_resources(priv); + + priv->num_tx_rings_p_up = channel->tx_count; + priv->tx_ring_num = channel->tx_count * MLX4_EN_NUM_UP; + priv->rx_ring_num = channel->rx_count; + + err = mlx4_en_alloc_resources(priv); + if (err) { + en_err(priv, "Failed reallocating port resources\n"); + goto out; + } + + netif_set_real_num_tx_queues(dev, priv->tx_ring_num); + netif_set_real_num_rx_queues(dev, priv->rx_ring_num); + + mlx4_en_setup_tc(dev, MLX4_EN_NUM_UP); + + en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num); + en_warn(priv, "Using %d RX rings\n", priv->rx_ring_num); + + if (port_up) { + err = mlx4_en_start_port(dev); + if (err) + en_err(priv, "Failed starting port\n"); + } + + err = mlx4_en_moderation_update(priv); + +out: + mutex_unlock(&mdev->state_lock); + return err; +} + const struct ethtool_ops mlx4_en_ethtool_ops = { .get_drvinfo = mlx4_en_get_drvinfo, .get_settings = mlx4_en_get_settings, @@ -1022,6 +1097,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size, .get_rxfh_indir = mlx4_en_get_rxfh_indir, .set_rxfh_indir = mlx4_en_set_rxfh_indir, + .get_channels = mlx4_en_get_channels, + .set_channels = mlx4_en_set_channels, }; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index d09b0d9ca68b..8611c89f034d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -250,7 +250,7 @@ static void *mlx4_en_add(struct mlx4_dev *dev) rounddown_pow_of_two(max_t(int, MIN_RX_RINGS, min_t(int, dev->caps.num_comp_vectors, - MAX_RX_RINGS))); + DEF_RX_RINGS))); } else { mdev->profile.prof[i].rx_ring_num = rounddown_pow_of_two( min_t(int, dev->caps.comp_pool/ diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index edd9cb8d3e1d..75a3f467bb5b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -47,11 +47,11 @@ #include "mlx4_en.h" #include "en_port.h" -static int mlx4_en_setup_tc(struct net_device *dev, u8 up) +int mlx4_en_setup_tc(struct net_device *dev, u8 up) { struct mlx4_en_priv *priv = netdev_priv(dev); int i; - unsigned int q, offset = 0; + unsigned int offset = 0; if (up && up != MLX4_EN_NUM_UP) return -EINVAL; @@ -59,10 +59,9 @@ static int mlx4_en_setup_tc(struct net_device *dev, u8 up) netdev_set_num_tc(dev, up); /* Partition Tx queues evenly amongst UP's */ - q = priv->tx_ring_num / up; for (i = 0; i < up; i++) { - netdev_set_tc_queue(dev, i, q, offset); - offset += q; + netdev_set_tc_queue(dev, i, priv->num_tx_rings_p_up, offset); + offset += priv->num_tx_rings_p_up; } return 0; @@ -870,7 +869,7 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv) /* If we haven't received a specific coalescing setting * (module param), we set the moderation parameters as follows: * - moder_cnt is set to the number of mtu sized packets to - * satisfy our coelsing target. + * satisfy our coalescing target. * - moder_time is set to a fixed value. */ priv->rx_frames = MLX4_EN_RX_COAL_TARGET; @@ -1114,7 +1113,7 @@ int mlx4_en_start_port(struct net_device *dev) /* Configure ring */ tx_ring = &priv->tx_ring[i]; err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn, - i / priv->mdev->profile.num_tx_rings_p_up); + i / priv->num_tx_rings_p_up); if (err) { en_err(priv, "Failed allocating Tx ring\n"); mlx4_en_deactivate_cq(priv, cq); @@ -1564,10 +1563,13 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, int err; dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv), - prof->tx_ring_num, prof->rx_ring_num); + MAX_TX_RINGS, MAX_RX_RINGS); if (dev == NULL) return -ENOMEM; + netif_set_real_num_tx_queues(dev, prof->tx_ring_num); + netif_set_real_num_rx_queues(dev, prof->rx_ring_num); + SET_NETDEV_DEV(dev, &mdev->dev->pdev->dev); dev->dev_id = port - 1; @@ -1586,20 +1588,23 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->flags = prof->flags; priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE | MLX4_WQE_CTRL_SOLICITED); + priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up; priv->tx_ring_num = prof->tx_ring_num; - priv->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring) * - priv->tx_ring_num, GFP_KERNEL); + + priv->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring) * MAX_TX_RINGS, + GFP_KERNEL); if (!priv->tx_ring) { err = -ENOMEM; goto out; } - priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq) * priv->tx_ring_num, - GFP_KERNEL); + priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq) * MAX_RX_RINGS, + GFP_KERNEL); if (!priv->tx_cq) { err = -ENOMEM; goto out; } priv->rx_ring_num = prof->rx_ring_num; + priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0; priv->mac_index = -1; priv->msg_enable = MLX4_EN_MSG_LEVEL; spin_lock_init(&priv->stats_lock); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 5aba5ecdf1e2..fed26d867f4e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -566,6 +566,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud struct ethhdr *ethh; dma_addr_t dma; u64 s_mac; + int factor = priv->cqe_factor; if (!priv->port_up) return 0; @@ -574,7 +575,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud * descriptor offset can be deduced from the CQE index instead of * reading 'cqe->index' */ index = cq->mcq.cons_index & ring->size_mask; - cqe = &cq->buf[index]; + cqe = &cq->buf[(index << factor) + factor]; /* Process all completed CQEs */ while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK, @@ -630,7 +631,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) && (cqe->checksum == cpu_to_be16(0xffff))) { ring->csum_ok++; - /* This packet is eligible for LRO if it is: + /* This packet is eligible for GRO if it is: * - DIX Ethernet (type interpretation) * - TCP/IP (v4) * - without IP options @@ -667,7 +668,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud goto next; } - /* LRO not possible, complete processing here */ + /* GRO not possible, complete processing here */ ip_summed = CHECKSUM_UNNECESSARY; } else { ip_summed = CHECKSUM_NONE; @@ -709,12 +710,9 @@ next: ++cq->mcq.cons_index; index = (cq->mcq.cons_index) & ring->size_mask; - cqe = &cq->buf[index]; - if (++polled == budget) { - /* We are here because we reached the NAPI budget - - * flush only pending LRO sessions */ + cqe = &cq->buf[(index << factor) + factor]; + if (++polled == budget) goto out; - } } out: diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index b35094c590ba..6771b69f40d5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -315,12 +315,13 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq) struct mlx4_cqe *buf = cq->buf; u32 packets = 0; u32 bytes = 0; + int factor = priv->cqe_factor; if (!priv->port_up) return; index = cons_index & size_mask; - cqe = &buf[index]; + cqe = &buf[(index << factor) + factor]; ring_index = ring->cons & size_mask; /* Process all completed CQEs */ @@ -349,7 +350,7 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq) ++cons_index; index = cons_index & size_mask; - cqe = &buf[index]; + cqe = &buf[(index << factor) + factor]; } @@ -523,7 +524,7 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb) { struct mlx4_en_priv *priv = netdev_priv(dev); - u16 rings_p_up = priv->mdev->profile.num_tx_rings_p_up; + u16 rings_p_up = priv->num_tx_rings_p_up; u8 up = 0; if (dev->num_tc) @@ -629,10 +630,15 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ring->tx_csum++; } - /* Copy dst mac address to wqe */ - ethh = (struct ethhdr *)skb->data; - tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); - tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); + if (mlx4_is_mfunc(mdev->dev) || priv->validate_loopback) { + /* Copy dst mac address to wqe. This allows loopback in eSwitch, + * so that VFs and PF can communicate with each other + */ + ethh = (struct ethhdr *)skb->data; + tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); + tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); + } + /* Handle LSO (TSO) packets */ if (lso_header_size) { /* Mark opcode as LSO */ diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index c48cf6f6529c..251ae2f93116 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -101,15 +101,21 @@ static void eq_set_ci(struct mlx4_eq *eq, int req_not) mb(); } -static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry) +static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry, u8 eqe_factor) { - unsigned long off = (entry & (eq->nent - 1)) * MLX4_EQ_ENTRY_SIZE; - return eq->page_list[off / PAGE_SIZE].buf + off % PAGE_SIZE; + /* (entry & (eq->nent - 1)) gives us a cyclic array */ + unsigned long offset = (entry & (eq->nent - 1)) * (MLX4_EQ_ENTRY_SIZE << eqe_factor); + /* CX3 is capable of extending the EQE from 32 to 64 bytes. + * When this feature is enabled, the first (in the lower addresses) + * 32 bytes in the 64 byte EQE are reserved and the next 32 bytes + * contain the legacy EQE information. + */ + return eq->page_list[offset / PAGE_SIZE].buf + (offset + (eqe_factor ? MLX4_EQ_ENTRY_SIZE : 0)) % PAGE_SIZE; } -static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq) +static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq, u8 eqe_factor) { - struct mlx4_eqe *eqe = get_eqe(eq, eq->cons_index); + struct mlx4_eqe *eqe = get_eqe(eq, eq->cons_index, eqe_factor); return !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? NULL : eqe; } @@ -177,7 +183,7 @@ static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe) return; } - memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1); + memcpy(s_eqe, eqe, dev->caps.eqe_size - 1); s_eqe->slave_id = slave; /* ensure all information is written before setting the ownersip bit */ wmb(); @@ -401,6 +407,7 @@ void mlx4_master_handle_slave_flr(struct work_struct *work) struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; int i; int err; + unsigned long flags; mlx4_dbg(dev, "mlx4_handle_slave_flr\n"); @@ -412,10 +419,10 @@ void mlx4_master_handle_slave_flr(struct work_struct *work) mlx4_delete_all_resources_for_slave(dev, i); /*return the slave to running mode*/ - spin_lock(&priv->mfunc.master.slave_state_lock); + spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); slave_state[i].last_cmd = MLX4_COMM_CMD_RESET; slave_state[i].is_slave_going_down = 0; - spin_unlock(&priv->mfunc.master.slave_state_lock); + spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); /*notify the FW:*/ err = mlx4_cmd(dev, 0, i, 0, MLX4_CMD_INFORM_FLR_DONE, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); @@ -440,8 +447,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) u8 update_slave_state; int i; enum slave_port_gen_event gen_event; + unsigned long flags; - while ((eqe = next_eqe_sw(eq))) { + while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor))) { /* * Make sure we read EQ entry contents after we've * checked the ownership bit. @@ -647,13 +655,13 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) } else update_slave_state = 1; - spin_lock(&priv->mfunc.master.slave_state_lock); + spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); if (update_slave_state) { priv->mfunc.master.slave_state[flr_slave].active = false; priv->mfunc.master.slave_state[flr_slave].last_cmd = MLX4_COMM_CMD_FLR; priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1; } - spin_unlock(&priv->mfunc.master.slave_state_lock); + spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); queue_work(priv->mfunc.master.comm_wq, &priv->mfunc.master.slave_flr_event_work); break; @@ -864,7 +872,8 @@ static int mlx4_create_eq(struct mlx4_dev *dev, int nent, eq->dev = dev; eq->nent = roundup_pow_of_two(max(nent, 2)); - npages = PAGE_ALIGN(eq->nent * MLX4_EQ_ENTRY_SIZE) / PAGE_SIZE; + /* CX3 is capable of extending the CQE/EQE from 32 to 64 bytes */ + npages = PAGE_ALIGN(eq->nent * (MLX4_EQ_ENTRY_SIZE << dev->caps.eqe_factor)) / PAGE_SIZE; eq->page_list = kmalloc(npages * sizeof *eq->page_list, GFP_KERNEL); @@ -966,8 +975,9 @@ static void mlx4_free_eq(struct mlx4_dev *dev, struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_cmd_mailbox *mailbox; int err; - int npages = PAGE_ALIGN(MLX4_EQ_ENTRY_SIZE * eq->nent) / PAGE_SIZE; int i; + /* CX3 is capable of extending the CQE/EQE from 32 to 64 bytes */ + int npages = PAGE_ALIGN((MLX4_EQ_ENTRY_SIZE << dev->caps.eqe_factor) * eq->nent) / PAGE_SIZE; mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 4f30b99324cf..8b3d0512a46b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -110,6 +110,8 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags) [42] = "Multicast VEP steering support", [48] = "Counters support", [59] = "Port management change event support", + [61] = "64 byte EQE support", + [62] = "64 byte CQE support", }; int i; @@ -235,7 +237,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, field = dev->caps.num_ports; MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); - size = 0; /* no PF behaviour is set for now */ + size = dev->caps.function_caps; /* set PF behaviours */ MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_PF_BHVR_OFFSET); field = 0; /* protected FMR support not available as yet */ @@ -1237,6 +1239,24 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS) *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 4); + /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */ + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_EQE) { + *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 29); + dev->caps.eqe_size = 64; + dev->caps.eqe_factor = 1; + } else { + dev->caps.eqe_size = 32; + dev->caps.eqe_factor = 0; + } + + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_CQE) { + *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 30); + dev->caps.cqe_size = 64; + dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_64B_CQE; + } else { + dev->caps.cqe_size = 32; + } + /* QPC/EEC/CQC/EQC/RDMARC attributes */ MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET); @@ -1318,7 +1338,9 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, { struct mlx4_cmd_mailbox *mailbox; __be32 *outbox; + u32 dword_field; int err; + u8 byte_field; #define QUERY_HCA_GLOBAL_CAPS_OFFSET 0x04 @@ -1351,10 +1373,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); + MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET); + if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) { + param->steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; + } else { + MLX4_GET(byte_field, outbox, INIT_HCA_UC_STEERING_OFFSET); + if (byte_field & 0x8) + param->steering_mode = MLX4_STEERING_MODE_B0; + else + param->steering_mode = MLX4_STEERING_MODE_A0; + } /* steering attributes */ - if (dev->caps.steering_mode == - MLX4_STEERING_MODE_DEVICE_MANAGED) { - + if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET); MLX4_GET(param->log_mc_entry_sz, outbox, INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); @@ -1370,6 +1400,13 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); } + /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */ + MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_OFFSETS); + if (byte_field & 0x20) /* 64-bytes eqe enabled */ + param->dev_cap_enabled |= MLX4_DEV_CAP_64B_EQE_ENABLED; + if (byte_field & 0x40) /* 64-bytes cqe enabled */ + param->dev_cap_enabled |= MLX4_DEV_CAP_64B_CQE_ENABLED; + /* TPT attributes */ MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET); diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h index 85abe9c11a22..dbf2f69cc59f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/drivers/net/ethernet/mellanox/mlx4/fw.h @@ -172,6 +172,8 @@ struct mlx4_init_hca_param { u8 log_uar_sz; u8 uar_page_sz; /* log pg sz in 4k chunks */ u8 fs_hash_enable_bits; + u8 steering_mode; /* for QUERY_HCA */ + u64 dev_cap_enabled; }; struct mlx4_init_ib_param { diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 2aa80afd98d2..a6542d75374c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -85,20 +85,26 @@ static int probe_vf; module_param(probe_vf, int, 0644); MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)"); -int mlx4_log_num_mgm_entry_size = 10; +int mlx4_log_num_mgm_entry_size = MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE; module_param_named(log_num_mgm_entry_size, mlx4_log_num_mgm_entry_size, int, 0444); MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num" " of qp per mcg, for example:" - " 10 gives 248.range: 9<=" + " 10 gives 248.range: 7 <=" " log_num_mgm_entry_size <= 12." - " Not in use with device managed" - " flow steering"); + " To activate device managed" + " flow steering when available, set to -1"); + +static bool enable_64b_cqe_eqe; +module_param(enable_64b_cqe_eqe, bool, 0444); +MODULE_PARM_DESC(enable_64b_cqe_eqe, + "Enable 64 byte CQEs/EQEs when the the FW supports this"); #define HCA_GLOBAL_CAP_MASK 0 -#define PF_CONTEXT_BEHAVIOUR_MASK 0 -static char mlx4_version[] __devinitdata = +#define PF_CONTEXT_BEHAVIOUR_MASK MLX4_FUNC_CAP_64B_EQE_CQE + +static char mlx4_version[] = DRV_NAME ": Mellanox ConnectX core driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; @@ -275,28 +281,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.max_gso_sz = dev_cap->max_gso_sz; dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz; - if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN) { - dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; - dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; - dev->caps.fs_log_max_ucast_qp_range_size = - dev_cap->fs_log_max_ucast_qp_range_size; - } else { - if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && - dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) { - dev->caps.steering_mode = MLX4_STEERING_MODE_B0; - } else { - dev->caps.steering_mode = MLX4_STEERING_MODE_A0; - - if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER || - dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) - mlx4_warn(dev, "Must have UC_STEER and MC_STEER flags " - "set to use B0 steering. Falling back to A0 steering mode.\n"); - } - dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); - } - mlx4_dbg(dev, "Steering mode is: %s\n", - mlx4_steering_mode_str(dev->caps.steering_mode)); - /* Sense port always allowed on supported devices for ConnectX-1 and -2 */ if (mlx4_priv(dev)->pci_dev_data & MLX4_PCI_DEV_FORCE_SENSE_PORT) dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT; @@ -386,6 +370,21 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH]; dev->caps.sqp_demux = (mlx4_is_master(dev)) ? MLX4_MAX_NUM_SLAVES : 0; + + if (!enable_64b_cqe_eqe) { + if (dev_cap->flags & + (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) { + mlx4_warn(dev, "64B EQEs/CQEs supported by the device but not enabled\n"); + dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_CQE; + dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_EQE; + } + } + + if ((dev_cap->flags & + (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) && + mlx4_is_master(dev)) + dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE; + return 0; } /*The function checks if there are live vf, return the num of them*/ @@ -472,6 +471,23 @@ int mlx4_is_slave_active(struct mlx4_dev *dev, int slave) } EXPORT_SYMBOL(mlx4_is_slave_active); +static void slave_adjust_steering_mode(struct mlx4_dev *dev, + struct mlx4_dev_cap *dev_cap, + struct mlx4_init_hca_param *hca_param) +{ + dev->caps.steering_mode = hca_param->steering_mode; + if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { + dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; + dev->caps.fs_log_max_ucast_qp_range_size = + dev_cap->fs_log_max_ucast_qp_range_size; + } else + dev->caps.num_qp_per_mgm = + 4 * ((1 << hca_param->log_mc_entry_sz)/16 - 2); + + mlx4_dbg(dev, "Steering mode is: %s\n", + mlx4_steering_mode_str(dev->caps.steering_mode)); +} + static int mlx4_slave_cap(struct mlx4_dev *dev) { int err; @@ -599,6 +615,23 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) goto err_mem; } + if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_EQE_ENABLED) { + dev->caps.eqe_size = 64; + dev->caps.eqe_factor = 1; + } else { + dev->caps.eqe_size = 32; + dev->caps.eqe_factor = 0; + } + + if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_CQE_ENABLED) { + dev->caps.cqe_size = 64; + dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_64B_CQE; + } else { + dev->caps.cqe_size = 32; + } + + slave_adjust_steering_mode(dev, &dev_cap, &hca_param); + return 0; err_mem: @@ -1285,6 +1318,59 @@ static void mlx4_parav_master_pf_caps(struct mlx4_dev *dev) } } +static int choose_log_fs_mgm_entry_size(int qp_per_entry) +{ + int i = MLX4_MIN_MGM_LOG_ENTRY_SIZE; + + for (i = MLX4_MIN_MGM_LOG_ENTRY_SIZE; i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE; + i++) { + if (qp_per_entry <= 4 * ((1 << i) / 16 - 2)) + break; + } + + return (i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE) ? i : -1; +} + +static void choose_steering_mode(struct mlx4_dev *dev, + struct mlx4_dev_cap *dev_cap) +{ + if (mlx4_log_num_mgm_entry_size == -1 && + dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN && + (!mlx4_is_mfunc(dev) || + (dev_cap->fs_max_num_qp_per_entry >= (num_vfs + 1))) && + choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry) >= + MLX4_MIN_MGM_LOG_ENTRY_SIZE) { + dev->oper_log_mgm_entry_size = + choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry); + dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; + dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; + dev->caps.fs_log_max_ucast_qp_range_size = + dev_cap->fs_log_max_ucast_qp_range_size; + } else { + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && + dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) + dev->caps.steering_mode = MLX4_STEERING_MODE_B0; + else { + dev->caps.steering_mode = MLX4_STEERING_MODE_A0; + + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER || + dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) + mlx4_warn(dev, "Must have both UC_STEER and MC_STEER flags " + "set to use B0 steering. Falling back to A0 steering mode.\n"); + } + dev->oper_log_mgm_entry_size = + mlx4_log_num_mgm_entry_size > 0 ? + mlx4_log_num_mgm_entry_size : + MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE; + dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); + } + mlx4_dbg(dev, "Steering mode is: %s, oper_log_mgm_entry_size = %d, " + "modparam log_num_mgm_entry_size = %d\n", + mlx4_steering_mode_str(dev->caps.steering_mode), + dev->oper_log_mgm_entry_size, + mlx4_log_num_mgm_entry_size); +} + static int mlx4_init_hca(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); @@ -1324,6 +1410,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev) goto err_stop_fw; } + choose_steering_mode(dev, &dev_cap); + if (mlx4_is_master(dev)) mlx4_parav_master_pf_caps(dev); @@ -1702,15 +1790,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) int i; if (msi_x) { - /* In multifunction mode each function gets 2 msi-X vectors - * one for data path completions anf the other for asynch events - * or command completions */ - if (mlx4_is_mfunc(dev)) { - nreq = 2; - } else { - nreq = min_t(int, dev->caps.num_eqs - - dev->caps.reserved_eqs, nreq); - } + nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, + nreq); entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); if (!entries) @@ -2224,8 +2305,7 @@ err_disable_pdev: return err; } -static int __devinit mlx4_init_one(struct pci_dev *pdev, - const struct pci_device_id *id) +static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { printk_once(KERN_INFO "%s", mlx4_version); @@ -2391,7 +2471,7 @@ static struct pci_driver mlx4_driver = { .name = DRV_NAME, .id_table = mlx4_pci_table, .probe = mlx4_init_one, - .remove = __devexit_p(mlx4_remove_one), + .remove = mlx4_remove_one, .err_handler = &mlx4_err_handler, }; @@ -2417,6 +2497,17 @@ static int __init mlx4_verify_params(void) port_type_array[0] = true; } + if (mlx4_log_num_mgm_entry_size != -1 && + (mlx4_log_num_mgm_entry_size < MLX4_MIN_MGM_LOG_ENTRY_SIZE || + mlx4_log_num_mgm_entry_size > MLX4_MAX_MGM_LOG_ENTRY_SIZE)) { + pr_warning("mlx4_core: mlx4_log_num_mgm_entry_size (%d) not " + "in legal range (-1 or %d..%d)\n", + mlx4_log_num_mgm_entry_size, + MLX4_MIN_MGM_LOG_ENTRY_SIZE, + MLX4_MAX_MGM_LOG_ENTRY_SIZE); + return -1; + } + return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index e151c21baf2b..1ee4db3c6400 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -54,12 +54,7 @@ struct mlx4_mgm { int mlx4_get_mgm_entry_size(struct mlx4_dev *dev) { - if (dev->caps.steering_mode == - MLX4_STEERING_MODE_DEVICE_MANAGED) - return 1 << MLX4_FS_MGM_LOG_ENTRY_SIZE; - else - return min((1 << mlx4_log_num_mgm_entry_size), - MLX4_MAX_MGM_ENTRY_SIZE); + return 1 << dev->oper_log_mgm_entry_size; } int mlx4_get_qp_per_mgm(struct mlx4_dev *dev) diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 1cf42036d7bb..116c5c29d2d1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -94,8 +94,10 @@ enum { }; enum { - MLX4_MAX_MGM_ENTRY_SIZE = 0x1000, - MLX4_MAX_QP_PER_MGM = 4 * (MLX4_MAX_MGM_ENTRY_SIZE / 16 - 2), + MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE = 10, + MLX4_MIN_MGM_LOG_ENTRY_SIZE = 7, + MLX4_MAX_MGM_LOG_ENTRY_SIZE = 12, + MLX4_MAX_QP_PER_MGM = 4 * ((1 << MLX4_MAX_MGM_LOG_ENTRY_SIZE) / 16 - 2), MLX4_MTT_ENTRY_PER_SEG = 8, }; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 9d27e42264e2..8d54412ada63 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -67,7 +67,8 @@ #define MLX4_EN_PAGE_SHIFT 12 #define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT) -#define MAX_RX_RINGS 16 +#define DEF_RX_RINGS 16 +#define MAX_RX_RINGS 128 #define MIN_RX_RINGS 4 #define TXBB_SIZE 64 #define HEADROOM (2048 / TXBB_SIZE + 1) @@ -95,8 +96,6 @@ #define MLX4_EN_ALLOC_SIZE PAGE_ALIGN(16384) #define MLX4_EN_ALLOC_ORDER get_order(MLX4_EN_ALLOC_SIZE) -#define MLX4_EN_MAX_LRO_DESCRIPTORS 32 - /* Receive fragment sizes; we use at most 4 fragments (for 9600 byte MTU * and 4K allocations) */ enum { @@ -120,13 +119,15 @@ enum { #define MLX4_EN_NUM_UP 8 #define MLX4_EN_DEF_TX_RING_SIZE 512 #define MLX4_EN_DEF_RX_RING_SIZE 1024 +#define MAX_TX_RINGS (MLX4_EN_MAX_TX_RING_P_UP * \ + MLX4_EN_NUM_UP) /* Target number of packets to coalesce with interrupt moderation */ #define MLX4_EN_RX_COAL_TARGET 44 #define MLX4_EN_RX_COAL_TIME 0x10 #define MLX4_EN_TX_COAL_PKTS 16 -#define MLX4_EN_TX_COAL_TIME 0x80 +#define MLX4_EN_TX_COAL_TIME 0x10 #define MLX4_EN_RX_RATE_LOW 400000 #define MLX4_EN_RX_COAL_TIME_LOW 0 @@ -290,21 +291,6 @@ struct mlx4_en_rx_ring { unsigned long csum_none; }; - -static inline int mlx4_en_can_lro(__be16 status) -{ - return (status & cpu_to_be16(MLX4_CQE_STATUS_IPV4 | - MLX4_CQE_STATUS_IPV4F | - MLX4_CQE_STATUS_IPV6 | - MLX4_CQE_STATUS_IPV4OPT | - MLX4_CQE_STATUS_TCP | - MLX4_CQE_STATUS_UDP | - MLX4_CQE_STATUS_IPOK)) == - cpu_to_be16(MLX4_CQE_STATUS_IPV4 | - MLX4_CQE_STATUS_IPOK | - MLX4_CQE_STATUS_TCP); -} - struct mlx4_en_cq { struct mlx4_cq mcq; struct mlx4_hwq_resources wqres; @@ -487,12 +473,14 @@ struct mlx4_en_priv { int mac_index; unsigned max_mtu; int base_qpn; + int cqe_factor; struct mlx4_en_rss_map rss_map; __be32 ctrl_flags; u32 flags; #define MLX4_EN_FLAG_PROMISC 0x1 #define MLX4_EN_FLAG_MC_PROMISC 0x2 + u8 num_tx_rings_p_up; u32 tx_ring_num; u32 rx_ring_num; u32 rx_skb_size; @@ -613,6 +601,8 @@ int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port); extern const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops; #endif +int mlx4_en_setup_tc(struct net_device *dev, u8 up); + #ifdef CONFIG_RFS_ACCEL void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv, struct mlx4_en_rx_ring *rx_ring); diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index b05705f50f0f..561ed2a22a17 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -3071,6 +3071,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; int err; + int qpn; struct mlx4_net_trans_rule_hw_ctrl *ctrl; struct _rule_hw *rule_header; int header_id; @@ -3080,13 +3081,21 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, return -EOPNOTSUPP; ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; + qpn = be32_to_cpu(ctrl->qpn) & 0xffffff; + err = get_res(dev, slave, qpn, RES_QP, NULL); + if (err) { + pr_err("Steering rule with qpn 0x%x rejected.\n", qpn); + return err; + } rule_header = (struct _rule_hw *)(ctrl + 1); header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id)); switch (header_id) { case MLX4_NET_TRANS_RULE_ID_ETH: - if (validate_eth_header_mac(slave, rule_header, rlist)) - return -EINVAL; + if (validate_eth_header_mac(slave, rule_header, rlist)) { + err = -EINVAL; + goto err_put; + } break; case MLX4_NET_TRANS_RULE_ID_IB: break; @@ -3094,14 +3103,17 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, case MLX4_NET_TRANS_RULE_ID_TCP: case MLX4_NET_TRANS_RULE_ID_UDP: pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n"); - if (add_eth_header(dev, slave, inbox, rlist, header_id)) - return -EINVAL; + if (add_eth_header(dev, slave, inbox, rlist, header_id)) { + err = -EINVAL; + goto err_put; + } vhcr->in_modifier += sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2; break; default: pr_err("Corrupted mailbox.\n"); - return -EINVAL; + err = -EINVAL; + goto err_put; } err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, @@ -3109,16 +3121,18 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); if (err) - return err; + goto err_put; err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0); if (err) { mlx4_err(dev, "Fail to add flow steering resources.\n "); /* detach rule*/ mlx4_cmd(dev, vhcr->out_param, 0, 0, - MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, + MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); } +err_put: + put_res(dev, slave, qpn, RES_QP); return err; } diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c index dccae1d1743a..07a6ebc47c92 100644 --- a/drivers/net/ethernet/micrel/ks8695net.c +++ b/drivers/net/ethernet/micrel/ks8695net.c @@ -1249,9 +1249,6 @@ ks8695_open(struct net_device *ndev) struct ks8695_priv *ksp = netdev_priv(ndev); int ret; - if (!is_valid_ether_addr(ndev->dev_addr)) - return -EADDRNOTAVAIL; - ks8695_reset(ksp); ks8695_update_mac(ksp); @@ -1277,7 +1274,7 @@ ks8695_open(struct net_device *ndev) * This initialises the LAN switch in the KS8695 to a known-good * set of defaults. */ -static void __devinit +static void ks8695_init_switch(struct ks8695_priv *ksp) { u32 ctrl; @@ -1305,7 +1302,7 @@ ks8695_init_switch(struct ks8695_priv *ksp) * This initialises a KS8695's WAN phy to sensible values for * autonegotiation etc. */ -static void __devinit +static void ks8695_init_wan_phy(struct ks8695_priv *ksp) { u32 ctrl; @@ -1349,7 +1346,7 @@ static const struct net_device_ops ks8695_netdev_ops = { * wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan * port. */ -static int __devinit +static int ks8695_probe(struct platform_device *pdev) { struct ks8695_priv *ksp; @@ -1597,7 +1594,7 @@ ks8695_drv_resume(struct platform_device *pdev) * * This unregisters and releases a KS8695 ethernet device. */ -static int __devexit +static int ks8695_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); @@ -1620,7 +1617,7 @@ static struct platform_driver ks8695_driver = { .owner = THIS_MODULE, }, .probe = ks8695_probe, - .remove = __devexit_p(ks8695_drv_remove), + .remove = ks8695_drv_remove, .suspend = ks8695_drv_suspend, .resume = ks8695_drv_resume, }; diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c index 24fb049ac2f2..b71eb39ab448 100644 --- a/drivers/net/ethernet/micrel/ks8842.c +++ b/drivers/net/ethernet/micrel/ks8842.c @@ -1141,7 +1141,7 @@ static const struct ethtool_ops ks8842_ethtool_ops = { .get_link = ethtool_op_get_link, }; -static int __devinit ks8842_probe(struct platform_device *pdev) +static int ks8842_probe(struct platform_device *pdev) { int err = -ENOMEM; struct resource *iomem; @@ -1240,7 +1240,7 @@ err_mem_region: return err; } -static int __devexit ks8842_remove(struct platform_device *pdev) +static int ks8842_remove(struct platform_device *pdev) { struct net_device *netdev = platform_get_drvdata(pdev); struct ks8842_adapter *adapter = netdev_priv(netdev); @@ -1262,7 +1262,7 @@ static struct platform_driver ks8842_platform_driver = { .owner = THIS_MODULE, }, .probe = ks8842_probe, - .remove = __devexit_p(ks8842_remove), + .remove = ks8842_remove, }; module_platform_driver(ks8842_platform_driver); diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 1540ebeb8669..286816a4e783 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -1415,7 +1415,7 @@ static int ks8851_resume(struct spi_device *spi) #define ks8851_resume NULL #endif -static int __devinit ks8851_probe(struct spi_device *spi) +static int ks8851_probe(struct spi_device *spi) { struct net_device *ndev; struct ks8851_net *ks; @@ -1534,7 +1534,7 @@ err_irq: return ret; } -static int __devexit ks8851_remove(struct spi_device *spi) +static int ks8851_remove(struct spi_device *spi) { struct ks8851_net *priv = dev_get_drvdata(&spi->dev); @@ -1554,7 +1554,7 @@ static struct spi_driver ks8851_driver = { .owner = THIS_MODULE, }, .probe = ks8851_probe, - .remove = __devexit_p(ks8851_remove), + .remove = ks8851_remove, .suspend = ks8851_suspend, .resume = ks8851_resume, }; diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index 38529edfe350..ef8f9f92e547 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c @@ -1506,7 +1506,7 @@ static int ks_hw_init(struct ks_net *ks) } -static int __devinit ks8851_probe(struct platform_device *pdev) +static int ks8851_probe(struct platform_device *pdev) { int err = -ENOMEM; struct resource *io_d, *io_c; @@ -1641,7 +1641,7 @@ err_mem_region: return err; } -static int __devexit ks8851_remove(struct platform_device *pdev) +static int ks8851_remove(struct platform_device *pdev) { struct net_device *netdev = platform_get_drvdata(pdev); struct ks_net *ks = netdev_priv(netdev); @@ -1663,7 +1663,7 @@ static struct platform_driver ks8851_platform_driver = { .owner = THIS_MODULE, }, .probe = ks8851_probe, - .remove = __devexit_p(ks8851_remove), + .remove = ks8851_remove, }; module_platform_driver(ks8851_platform_driver); diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index 693a88dddb48..8ebc352bcbe6 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -1487,7 +1487,7 @@ struct dev_priv { #define DRV_VERSION "1.0.0" #define DRV_RELDATE "Feb 8, 2010" -static char version[] __devinitdata = +static char version[] = "Micrel " DEVICE_NAME " " DRV_VERSION " (" DRV_RELDATE ")"; static u8 DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x88, 0x42, 0x01 }; @@ -4761,7 +4761,7 @@ static void transmit_cleanup(struct dev_info *hw_priv, int normal) struct ksz_dma_buf *dma_buf; struct net_device *dev = NULL; - spin_lock(&hw_priv->hwlock); + spin_lock_irq(&hw_priv->hwlock); last = info->last; while (info->avail < info->alloc) { @@ -4795,7 +4795,7 @@ static void transmit_cleanup(struct dev_info *hw_priv, int normal) info->avail++; } info->last = last; - spin_unlock(&hw_priv->hwlock); + spin_unlock_irq(&hw_priv->hwlock); /* Notify the network subsystem that the packet has been sent. */ if (dev) @@ -5259,11 +5259,15 @@ static irqreturn_t netdev_intr(int irq, void *dev_id) struct dev_info *hw_priv = priv->adapter; struct ksz_hw *hw = &hw_priv->hw; + spin_lock(&hw_priv->hwlock); + hw_read_intr(hw, &int_enable); /* Not our interrupt! */ - if (!int_enable) + if (!int_enable) { + spin_unlock(&hw_priv->hwlock); return IRQ_NONE; + } do { hw_ack_intr(hw, int_enable); @@ -5310,6 +5314,8 @@ static irqreturn_t netdev_intr(int irq, void *dev_id) hw_ena_intr(hw); + spin_unlock(&hw_priv->hwlock); + return IRQ_HANDLED; } @@ -5407,8 +5413,8 @@ static int netdev_close(struct net_device *dev) /* Delay for receive task to stop scheduling itself. */ msleep(2000 / HZ); - tasklet_disable(&hw_priv->rx_tasklet); - tasklet_disable(&hw_priv->tx_tasklet); + tasklet_kill(&hw_priv->rx_tasklet); + tasklet_kill(&hw_priv->tx_tasklet); free_irq(dev->irq, hw_priv->dev); transmit_cleanup(hw_priv, 0); @@ -5459,8 +5465,10 @@ static int prepare_hardware(struct net_device *dev) rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev); if (rc) return rc; - tasklet_enable(&hw_priv->rx_tasklet); - tasklet_enable(&hw_priv->tx_tasklet); + tasklet_init(&hw_priv->rx_tasklet, rx_proc_task, + (unsigned long) hw_priv); + tasklet_init(&hw_priv->tx_tasklet, tx_proc_task, + (unsigned long) hw_priv); hw->promiscuous = 0; hw->all_multi = 0; @@ -6917,8 +6925,7 @@ static void read_other_addr(struct ksz_hw *hw) #define PCI_VENDOR_ID_MICREL_KS 0x16c6 #endif -static int __devinit pcidev_init(struct pci_dev *pdev, - const struct pci_device_id *id) +static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id) { struct net_device *dev; struct dev_priv *priv; @@ -7033,16 +7040,6 @@ static int __devinit pcidev_init(struct pci_dev *pdev, spin_lock_init(&hw_priv->hwlock); mutex_init(&hw_priv->lock); - /* tasklet is enabled. */ - tasklet_init(&hw_priv->rx_tasklet, rx_proc_task, - (unsigned long) hw_priv); - tasklet_init(&hw_priv->tx_tasklet, tx_proc_task, - (unsigned long) hw_priv); - - /* tasklet_enable will decrement the atomic counter. */ - tasklet_disable(&hw_priv->rx_tasklet); - tasklet_disable(&hw_priv->tx_tasklet); - for (i = 0; i < TOTAL_PORT_NUM; i++) init_waitqueue_head(&hw_priv->counter[i].counter); @@ -7251,18 +7248,7 @@ static struct pci_driver pci_device_driver = { .remove = pcidev_exit }; -static int __init ksz884x_init_module(void) -{ - return pci_register_driver(&pci_device_driver); -} - -static void __exit ksz884x_cleanup_module(void) -{ - pci_unregister_driver(&pci_device_driver); -} - -module_init(ksz884x_init_module); -module_exit(ksz884x_cleanup_module); +module_pci_driver(pci_device_driver); MODULE_DESCRIPTION("KSZ8841/2 PCI network driver"); MODULE_AUTHOR("Tristram Ha <Tristram.Ha@micrel.com>"); diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c index 6118bdad244f..a99456c3dd87 100644 --- a/drivers/net/ethernet/microchip/enc28j60.c +++ b/drivers/net/ethernet/microchip/enc28j60.c @@ -1541,7 +1541,7 @@ static const struct net_device_ops enc28j60_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit enc28j60_probe(struct spi_device *spi) +static int enc28j60_probe(struct spi_device *spi) { struct net_device *dev; struct enc28j60_net *priv; @@ -1617,7 +1617,7 @@ error_alloc: return ret; } -static int __devexit enc28j60_remove(struct spi_device *spi) +static int enc28j60_remove(struct spi_device *spi) { struct enc28j60_net *priv = dev_get_drvdata(&spi->dev); @@ -1637,7 +1637,7 @@ static struct spi_driver enc28j60_driver = { .owner = THIS_MODULE, }, .probe = enc28j60_probe, - .remove = __devexit_p(enc28j60_remove), + .remove = enc28j60_remove, }; static int __init enc28j60_init(void) diff --git a/drivers/net/ethernet/myricom/Kconfig b/drivers/net/ethernet/myricom/Kconfig index 540f0c6fc160..3932d081fa21 100644 --- a/drivers/net/ethernet/myricom/Kconfig +++ b/drivers/net/ethernet/myricom/Kconfig @@ -23,7 +23,6 @@ config MYRI10GE depends on PCI && INET select FW_LOADER select CRC32 - select INET_LRO ---help--- This driver supports Myricom Myri-10G Dual Protocol interface in Ethernet mode. If the eeprom on your board is not recent enough, diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 83516e3369c9..f8408d6e961c 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -50,7 +50,6 @@ #include <linux/etherdevice.h> #include <linux/if_ether.h> #include <linux/if_vlan.h> -#include <linux/inet_lro.h> #include <linux/dca.h> #include <linux/ip.h> #include <linux/inet.h> @@ -96,8 +95,6 @@ MODULE_LICENSE("Dual BSD/GPL"); #define MYRI10GE_EEPROM_STRINGS_SIZE 256 #define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2) -#define MYRI10GE_MAX_LRO_DESCRIPTORS 8 -#define MYRI10GE_LRO_MAX_PKTS 64 #define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff) #define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff @@ -165,8 +162,6 @@ struct myri10ge_rx_done { dma_addr_t bus; int cnt; int idx; - struct net_lro_mgr lro_mgr; - struct net_lro_desc lro_desc[MYRI10GE_MAX_LRO_DESCRIPTORS]; }; struct myri10ge_slice_netstats { @@ -338,11 +333,6 @@ static int myri10ge_debug = -1; /* defaults above */ module_param(myri10ge_debug, int, 0); MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); -static int myri10ge_lro_max_pkts = MYRI10GE_LRO_MAX_PKTS; -module_param(myri10ge_lro_max_pkts, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_lro_max_pkts, - "Number of LRO packets to be aggregated"); - static int myri10ge_fill_thresh = 256; module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed"); @@ -1197,36 +1187,6 @@ static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum) } } -static inline void -myri10ge_rx_skb_build(struct sk_buff *skb, u8 * va, - struct skb_frag_struct *rx_frags, int len, int hlen) -{ - struct skb_frag_struct *skb_frags; - - skb->len = skb->data_len = len; - /* attach the page(s) */ - - skb_frags = skb_shinfo(skb)->frags; - while (len > 0) { - memcpy(skb_frags, rx_frags, sizeof(*skb_frags)); - len -= skb_frag_size(rx_frags); - skb_frags++; - rx_frags++; - skb_shinfo(skb)->nr_frags++; - } - - /* pskb_may_pull is not available in irq context, but - * skb_pull() (for ether_pad and eth_type_trans()) requires - * the beginning of the packet in skb_headlen(), move it - * manually */ - skb_copy_to_linear_data(skb, va, hlen); - skb_shinfo(skb)->frags[0].page_offset += hlen; - skb_frag_size_sub(&skb_shinfo(skb)->frags[0], hlen); - skb->data_len -= hlen; - skb->tail += hlen; - skb_pull(skb, MXGEFW_PAD); -} - static void myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, int bytes, int watchdog) @@ -1304,18 +1264,50 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev, } } -#define MYRI10GE_HLEN 64 /* The number of bytes to copy from a - * page into an skb */ +/* + * GRO does not support acceleration of tagged vlan frames, and + * this NIC does not support vlan tag offload, so we must pop + * the tag ourselves to be able to achieve GRO performance that + * is comparable to LRO. + */ + +static inline void +myri10ge_vlan_rx(struct net_device *dev, void *addr, struct sk_buff *skb) +{ + u8 *va; + struct vlan_ethhdr *veh; + struct skb_frag_struct *frag; + __wsum vsum; + + va = addr; + va += MXGEFW_PAD; + veh = (struct vlan_ethhdr *)va; + if ((dev->features & NETIF_F_HW_VLAN_RX) == NETIF_F_HW_VLAN_RX && + veh->h_vlan_proto == htons(ETH_P_8021Q)) { + /* fixup csum if needed */ + if (skb->ip_summed == CHECKSUM_COMPLETE) { + vsum = csum_partial(va + ETH_HLEN, VLAN_HLEN, 0); + skb->csum = csum_sub(skb->csum, vsum); + } + /* pop tag */ + __vlan_hwaccel_put_tag(skb, ntohs(veh->h_vlan_TCI)); + memmove(va + VLAN_HLEN, va, 2 * ETH_ALEN); + skb->len -= VLAN_HLEN; + skb->data_len -= VLAN_HLEN; + frag = skb_shinfo(skb)->frags; + frag->page_offset += VLAN_HLEN; + skb_frag_size_set(frag, skb_frag_size(frag) - VLAN_HLEN); + } +} static inline int -myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum, - bool lro_enabled) +myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum) { struct myri10ge_priv *mgp = ss->mgp; struct sk_buff *skb; - struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME]; + struct skb_frag_struct *rx_frags; struct myri10ge_rx_buf *rx; - int i, idx, hlen, remainder, bytes; + int i, idx, remainder, bytes; struct pci_dev *pdev = mgp->pdev; struct net_device *dev = mgp->dev; u8 *va; @@ -1332,67 +1324,48 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum, idx = rx->cnt & rx->mask; va = page_address(rx->info[idx].page) + rx->info[idx].page_offset; prefetch(va); + + skb = napi_get_frags(&ss->napi); + if (unlikely(skb == NULL)) { + ss->stats.rx_dropped++; + for (i = 0, remainder = len; remainder > 0; i++) { + myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes); + put_page(rx->info[idx].page); + rx->cnt++; + idx = rx->cnt & rx->mask; + remainder -= MYRI10GE_ALLOC_SIZE; + } + return 0; + } + rx_frags = skb_shinfo(skb)->frags; /* Fill skb_frag_struct(s) with data from our receive */ for (i = 0, remainder = len; remainder > 0; i++) { myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes); - __skb_frag_set_page(&rx_frags[i], rx->info[idx].page); - rx_frags[i].page_offset = rx->info[idx].page_offset; - if (remainder < MYRI10GE_ALLOC_SIZE) - skb_frag_size_set(&rx_frags[i], remainder); - else - skb_frag_size_set(&rx_frags[i], MYRI10GE_ALLOC_SIZE); + skb_fill_page_desc(skb, i, rx->info[idx].page, + rx->info[idx].page_offset, + remainder < MYRI10GE_ALLOC_SIZE ? + remainder : MYRI10GE_ALLOC_SIZE); rx->cnt++; idx = rx->cnt & rx->mask; remainder -= MYRI10GE_ALLOC_SIZE; } - if (lro_enabled) { - rx_frags[0].page_offset += MXGEFW_PAD; - skb_frag_size_sub(&rx_frags[0], MXGEFW_PAD); - len -= MXGEFW_PAD; - lro_receive_frags(&ss->rx_done.lro_mgr, rx_frags, - /* opaque, will come back in get_frag_header */ - len, len, - (void *)(__force unsigned long)csum, csum); - - return 1; - } - - hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN; - - /* allocate an skb to attach the page(s) to. This is done - * after trying LRO, so as to avoid skb allocation overheads */ - - skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16); - if (unlikely(skb == NULL)) { - ss->stats.rx_dropped++; - do { - i--; - __skb_frag_unref(&rx_frags[i]); - } while (i != 0); - return 0; - } + /* remove padding */ + rx_frags[0].page_offset += MXGEFW_PAD; + rx_frags[0].size -= MXGEFW_PAD; + len -= MXGEFW_PAD; - /* Attach the pages to the skb, and trim off any padding */ - myri10ge_rx_skb_build(skb, va, rx_frags, len, hlen); - if (skb_frag_size(&skb_shinfo(skb)->frags[0]) <= 0) { - skb_frag_unref(skb, 0); - skb_shinfo(skb)->nr_frags = 0; - } else { - skb->truesize += bytes * skb_shinfo(skb)->nr_frags; + skb->len = len; + skb->data_len = len; + skb->truesize += len; + if (dev->features & NETIF_F_RXCSUM) { + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum = csum; } - skb->protocol = eth_type_trans(skb, dev); + myri10ge_vlan_rx(mgp->dev, va, skb); skb_record_rx_queue(skb, ss - &mgp->ss[0]); - if (dev->features & NETIF_F_RXCSUM) { - if ((skb->protocol == htons(ETH_P_IP)) || - (skb->protocol == htons(ETH_P_IPV6))) { - skb->csum = csum; - skb->ip_summed = CHECKSUM_COMPLETE; - } else - myri10ge_vlan_ip_csum(skb, csum); - } - netif_receive_skb(skb); + napi_gro_frags(&ss->napi); return 1; } @@ -1480,18 +1453,11 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) u16 length; __wsum checksum; - /* - * Prevent compiler from generating more than one ->features memory - * access to avoid theoretical race condition with functions that - * change NETIF_F_LRO flag at runtime. - */ - bool lro_enabled = !!(ACCESS_ONCE(mgp->dev->features) & NETIF_F_LRO); - while (rx_done->entry[idx].length != 0 && work_done < budget) { length = ntohs(rx_done->entry[idx].length); rx_done->entry[idx].length = 0; checksum = csum_unfold(rx_done->entry[idx].checksum); - rx_ok = myri10ge_rx_done(ss, length, checksum, lro_enabled); + rx_ok = myri10ge_rx_done(ss, length, checksum); rx_packets += rx_ok; rx_bytes += rx_ok * (unsigned long)length; cnt++; @@ -1503,9 +1469,6 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) ss->stats.rx_packets += rx_packets; ss->stats.rx_bytes += rx_bytes; - if (lro_enabled) - lro_flush_all(&rx_done->lro_mgr); - /* restock receive rings if needed */ if (ss->rx_small.fill_cnt - ss->rx_small.cnt < myri10ge_fill_thresh) myri10ge_alloc_rx_pages(mgp, &ss->rx_small, @@ -1779,7 +1742,6 @@ static const char myri10ge_gstrings_slice_stats[][ETH_GSTRING_LEN] = { "tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt", "wake_queue", "stop_queue", "tx_linearized", - "LRO aggregated", "LRO flushed", "LRO avg aggr", "LRO no_desc", }; #define MYRI10GE_NET_STATS_LEN 21 @@ -1880,14 +1842,6 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, data[i++] = (unsigned int)ss->tx.wake_queue; data[i++] = (unsigned int)ss->tx.stop_queue; data[i++] = (unsigned int)ss->tx.linearized; - data[i++] = ss->rx_done.lro_mgr.stats.aggregated; - data[i++] = ss->rx_done.lro_mgr.stats.flushed; - if (ss->rx_done.lro_mgr.stats.flushed) - data[i++] = ss->rx_done.lro_mgr.stats.aggregated / - ss->rx_done.lro_mgr.stats.flushed; - else - data[i++] = 0; - data[i++] = ss->rx_done.lro_mgr.stats.no_desc; } } @@ -1931,7 +1885,7 @@ static int myri10ge_led(struct myri10ge_priv *mgp, int on) } if (!on) pattern = swab32(readl(mgp->sram + pattern_off + 4)); - writel(htonl(pattern), mgp->sram + pattern_off); + writel(swab32(pattern), mgp->sram + pattern_off); return 0; } @@ -2271,67 +2225,6 @@ static void myri10ge_free_irq(struct myri10ge_priv *mgp) pci_disable_msix(pdev); } -static int -myri10ge_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, - void **ip_hdr, void **tcpudp_hdr, - u64 * hdr_flags, void *priv) -{ - struct ethhdr *eh; - struct vlan_ethhdr *veh; - struct iphdr *iph; - u8 *va = skb_frag_address(frag); - unsigned long ll_hlen; - /* passed opaque through lro_receive_frags() */ - __wsum csum = (__force __wsum) (unsigned long)priv; - - /* find the mac header, aborting if not IPv4 */ - - eh = (struct ethhdr *)va; - *mac_hdr = eh; - ll_hlen = ETH_HLEN; - if (eh->h_proto != htons(ETH_P_IP)) { - if (eh->h_proto == htons(ETH_P_8021Q)) { - veh = (struct vlan_ethhdr *)va; - if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) - return -1; - - ll_hlen += VLAN_HLEN; - - /* - * HW checksum starts ETH_HLEN bytes into - * frame, so we must subtract off the VLAN - * header's checksum before csum can be used - */ - csum = csum_sub(csum, csum_partial(va + ETH_HLEN, - VLAN_HLEN, 0)); - } else { - return -1; - } - } - *hdr_flags = LRO_IPV4; - - iph = (struct iphdr *)(va + ll_hlen); - *ip_hdr = iph; - if (iph->protocol != IPPROTO_TCP) - return -1; - if (ip_is_fragment(iph)) - return -1; - *hdr_flags |= LRO_TCP; - *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); - - /* verify the IP checksum */ - if (unlikely(ip_fast_csum((u8 *) iph, iph->ihl))) - return -1; - - /* verify the checksum */ - if (unlikely(csum_tcpudp_magic(iph->saddr, iph->daddr, - ntohs(iph->tot_len) - (iph->ihl << 2), - IPPROTO_TCP, csum))) - return -1; - - return 0; -} - static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice) { struct myri10ge_cmd cmd; @@ -2401,8 +2294,7 @@ static int myri10ge_open(struct net_device *dev) struct myri10ge_priv *mgp = netdev_priv(dev); struct myri10ge_cmd cmd; int i, status, big_pow2, slice; - u8 *itable; - struct net_lro_mgr *lro_mgr; + u8 __iomem *itable; if (mgp->running != MYRI10GE_ETH_STOPPED) return -EBUSY; @@ -2513,19 +2405,6 @@ static int myri10ge_open(struct net_device *dev) goto abort_with_rings; } - lro_mgr = &ss->rx_done.lro_mgr; - lro_mgr->dev = dev; - lro_mgr->features = LRO_F_NAPI; - lro_mgr->ip_summed = CHECKSUM_COMPLETE; - lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; - lro_mgr->max_desc = MYRI10GE_MAX_LRO_DESCRIPTORS; - lro_mgr->lro_arr = ss->rx_done.lro_desc; - lro_mgr->get_frag_header = myri10ge_get_frag_header; - lro_mgr->max_aggr = myri10ge_lro_max_pkts; - lro_mgr->frag_align_pad = 2; - if (lro_mgr->max_aggr > MAX_SKB_FRAGS) - lro_mgr->max_aggr = MAX_SKB_FRAGS; - /* must happen prior to any irq */ napi_enable(&(ss)->napi); } @@ -2878,7 +2757,7 @@ again: flags_next |= next_is_first * MXGEFW_FLAGS_FIRST; rdma_count |= -(chop | next_is_first); - rdma_count += chop & !next_is_first; + rdma_count += chop & ~next_is_first; } else if (likely(cum_len_next >= 0)) { /* header ends */ int small; @@ -3143,15 +3022,6 @@ static int myri10ge_set_mac_address(struct net_device *dev, void *addr) return 0; } -static netdev_features_t myri10ge_fix_features(struct net_device *dev, - netdev_features_t features) -{ - if (!(features & NETIF_F_RXCSUM)) - features &= ~NETIF_F_LRO; - - return features; -} - static int myri10ge_change_mtu(struct net_device *dev, int new_mtu) { struct myri10ge_priv *mgp = netdev_priv(dev); @@ -3878,7 +3748,6 @@ static const struct net_device_ops myri10ge_netdev_ops = { .ndo_get_stats64 = myri10ge_get_stats, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = myri10ge_change_mtu, - .ndo_fix_features = myri10ge_fix_features, .ndo_set_rx_mode = myri10ge_set_multicast_list, .ndo_set_mac_address = myri10ge_set_mac_address, }; @@ -3967,9 +3836,9 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto abort_with_mtrr; } hdr_offset = - ntohl(__raw_readl(mgp->sram + MCP_HEADER_PTR_OFFSET)) & 0xffffc; + swab32(readl(mgp->sram + MCP_HEADER_PTR_OFFSET)) & 0xffffc; ss_offset = hdr_offset + offsetof(struct mcp_gen_header, string_specs); - mgp->sram_size = ntohl(__raw_readl(mgp->sram + ss_offset)); + mgp->sram_size = swab32(readl(mgp->sram + ss_offset)); if (mgp->sram_size > mgp->board_span || mgp->sram_size <= MYRI10GE_FW_OFFSET) { dev_err(&pdev->dev, @@ -4018,7 +3887,11 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->netdev_ops = &myri10ge_netdev_ops; netdev->mtu = myri10ge_initial_mtu; - netdev->hw_features = mgp->features | NETIF_F_LRO | NETIF_F_RXCSUM; + netdev->hw_features = mgp->features | NETIF_F_RXCSUM; + + /* fake NETIF_F_HW_VLAN_RX for good GRO performance */ + netdev->hw_features |= NETIF_F_HW_VLAN_RX; + netdev->features = netdev->hw_features; if (dac_enabled) diff --git a/drivers/net/ethernet/natsemi/ibmlana.c b/drivers/net/ethernet/natsemi/ibmlana.c index 3f94ddbf4dc0..923e640d604c 100644 --- a/drivers/net/ethernet/natsemi/ibmlana.c +++ b/drivers/net/ethernet/natsemi/ibmlana.c @@ -900,7 +900,7 @@ static short ibmlana_adapter_ids[] __initdata = { 0x0000 }; -static char *ibmlana_adapter_names[] __devinitdata = { +static char *ibmlana_adapter_names[] = { "IBM LAN Adapter/A", NULL }; @@ -916,7 +916,7 @@ static const struct net_device_ops ibmlana_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit ibmlana_init_one(struct device *kdev) +static int ibmlana_init_one(struct device *kdev) { struct mca_device *mdev = to_mca_device(kdev); struct net_device *dev; diff --git a/drivers/net/ethernet/natsemi/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c index 95dd39ffb230..b0b361546365 100644 --- a/drivers/net/ethernet/natsemi/jazzsonic.c +++ b/drivers/net/ethernet/natsemi/jazzsonic.c @@ -117,7 +117,7 @@ static const struct net_device_ops sonic_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, }; -static int __devinit sonic_probe1(struct net_device *dev) +static int sonic_probe1(struct net_device *dev) { static unsigned version_printed; unsigned int silicon_revision; @@ -220,7 +220,7 @@ out: * Probe for a SONIC ethernet controller on a Mips Jazz board. * Actually probing is superfluous but we're paranoid. */ -static int __devinit jazz_sonic_probe(struct platform_device *pdev) +static int jazz_sonic_probe(struct platform_device *pdev) { struct net_device *dev; struct sonic_local *lp; @@ -270,7 +270,7 @@ MODULE_ALIAS("platform:jazzsonic"); #include "sonic.c" -static int __devexit jazz_sonic_device_remove (struct platform_device *pdev) +static int jazz_sonic_device_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct sonic_local* lp = netdev_priv(dev); @@ -286,7 +286,7 @@ static int __devexit jazz_sonic_device_remove (struct platform_device *pdev) static struct platform_driver jazz_sonic_driver = { .probe = jazz_sonic_probe, - .remove = __devexit_p(jazz_sonic_device_remove), + .remove = jazz_sonic_device_remove, .driver = { .name = jazz_sonic_string, .owner = THIS_MODULE, diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c index b9680ba5a325..0ffde69c8d01 100644 --- a/drivers/net/ethernet/natsemi/macsonic.c +++ b/drivers/net/ethernet/natsemi/macsonic.c @@ -196,7 +196,7 @@ static const struct net_device_ops macsonic_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, }; -static int __devinit macsonic_init(struct net_device *dev) +static int macsonic_init(struct net_device *dev) { struct sonic_local* lp = netdev_priv(dev); @@ -245,7 +245,7 @@ static int __devinit macsonic_init(struct net_device *dev) memcmp(mac, "\x00\x80\x19", 3) && \ memcmp(mac, "\x00\x05\x02", 3)) -static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev) +static void mac_onboard_sonic_ethernet_addr(struct net_device *dev) { struct sonic_local *lp = netdev_priv(dev); const int prom_addr = ONBOARD_SONIC_PROM_BASE; @@ -309,7 +309,7 @@ static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev) eth_hw_addr_random(dev); } -static int __devinit mac_onboard_sonic_probe(struct net_device *dev) +static int mac_onboard_sonic_probe(struct net_device *dev) { struct sonic_local* lp = netdev_priv(dev); int sr; @@ -420,9 +420,8 @@ static int __devinit mac_onboard_sonic_probe(struct net_device *dev) return macsonic_init(dev); } -static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev, - unsigned long prom_addr, - int id) +static int mac_nubus_sonic_ethernet_addr(struct net_device *dev, + unsigned long prom_addr, int id) { int i; for(i = 0; i < 6; i++) @@ -435,7 +434,7 @@ static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev, return 0; } -static int __devinit macsonic_ident(struct nubus_dev *ndev) +static int macsonic_ident(struct nubus_dev *ndev) { if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC && ndev->dr_sw == NUBUS_DRSW_SONIC_LC) @@ -460,7 +459,7 @@ static int __devinit macsonic_ident(struct nubus_dev *ndev) return -1; } -static int __devinit mac_nubus_sonic_probe(struct net_device *dev) +static int mac_nubus_sonic_probe(struct net_device *dev) { static int slots; struct nubus_dev* ndev = NULL; @@ -573,7 +572,7 @@ static int __devinit mac_nubus_sonic_probe(struct net_device *dev) return macsonic_init(dev); } -static int __devinit mac_sonic_probe(struct platform_device *pdev) +static int mac_sonic_probe(struct platform_device *pdev) { struct net_device *dev; struct sonic_local *lp; @@ -619,7 +618,7 @@ MODULE_ALIAS("platform:macsonic"); #include "sonic.c" -static int __devexit mac_sonic_device_remove (struct platform_device *pdev) +static int mac_sonic_device_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct sonic_local* lp = netdev_priv(dev); @@ -634,7 +633,7 @@ static int __devexit mac_sonic_device_remove (struct platform_device *pdev) static struct platform_driver mac_sonic_driver = { .probe = mac_sonic_probe, - .remove = __devexit_p(mac_sonic_device_remove), + .remove = mac_sonic_device_remove, .driver = { .name = mac_sonic_string, .owner = THIS_MODULE, diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c index dbaaa99a0d43..f4ad60c97eae 100644 --- a/drivers/net/ethernet/natsemi/natsemi.c +++ b/drivers/net/ethernet/natsemi/natsemi.c @@ -127,7 +127,7 @@ static int full_duplex[MAX_UNITS]; #define NATSEMI_RX_LIMIT 2046 /* maximum supported by hardware */ /* These identify the driver base version and may not be removed. */ -static const char version[] __devinitconst = +static const char version[] = KERN_INFO DRV_NAME " dp8381x driver, version " DRV_VERSION ", " DRV_RELDATE "\n" " originally by Donald Becker <becker@scyld.com>\n" @@ -242,7 +242,7 @@ static struct { const char *name; unsigned long flags; unsigned int eeprom_size; -} natsemi_pci_info[] __devinitdata = { +} natsemi_pci_info[] = { { "Aculab E1/T1 PMXc cPCI carrier card", NATSEMI_FLAG_IGNORE_PHY, 128 }, { "NatSemi DP8381[56]", 0, 24 }, }; @@ -742,7 +742,7 @@ static void move_int_phy(struct net_device *dev, int addr) udelay(1); } -static void __devinit natsemi_init_media (struct net_device *dev) +static void natsemi_init_media(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); u32 tmp; @@ -797,8 +797,7 @@ static const struct net_device_ops natsemi_netdev_ops = { #endif }; -static int __devinit natsemi_probe1 (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int natsemi_probe1(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; struct netdev_private *np; @@ -3214,7 +3213,7 @@ static int netdev_close(struct net_device *dev) } -static void __devexit natsemi_remove1 (struct pci_dev *pdev) +static void natsemi_remove1(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); void __iomem * ioaddr = ns_ioaddr(dev); @@ -3353,7 +3352,7 @@ static struct pci_driver natsemi_driver = { .name = DRV_NAME, .id_table = natsemi_pci_tbl, .probe = natsemi_probe1, - .remove = __devexit_p(natsemi_remove1), + .remove = natsemi_remove1, #ifdef CONFIG_PM .suspend = natsemi_suspend, .resume = natsemi_resume, diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index d52728b3c436..77c070de621e 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -1941,8 +1941,8 @@ static const struct net_device_ops netdev_ops = { .ndo_tx_timeout = ns83820_tx_timeout, }; -static int __devinit ns83820_init_one(struct pci_dev *pci_dev, - const struct pci_device_id *id) +static int ns83820_init_one(struct pci_dev *pci_dev, + const struct pci_device_id *id) { struct net_device *ndev; struct ns83820 *dev; @@ -2241,7 +2241,7 @@ out: return err; } -static void __devexit ns83820_remove_one(struct pci_dev *pci_dev) +static void ns83820_remove_one(struct pci_dev *pci_dev) { struct net_device *ndev = pci_get_drvdata(pci_dev); struct ns83820 *dev = PRIV(ndev); /* ok even if NULL */ @@ -2272,7 +2272,7 @@ static struct pci_driver driver = { .name = "ns83820", .id_table = ns83820_pci_tbl, .probe = ns83820_init_one, - .remove = __devexit_p(ns83820_remove_one), + .remove = ns83820_remove_one, #if 0 /* FIXME: implement */ .suspend = , .resume = , diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c index 7dfe88398d7d..5e4748e855f6 100644 --- a/drivers/net/ethernet/natsemi/xtsonic.c +++ b/drivers/net/ethernet/natsemi/xtsonic.c @@ -249,7 +249,7 @@ out: * Actually probing is superfluous but we're paranoid. */ -int __devinit xtsonic_probe(struct platform_device *pdev) +int xtsonic_probe(struct platform_device *pdev) { struct net_device *dev; struct sonic_local *lp; @@ -297,7 +297,7 @@ MODULE_PARM_DESC(sonic_debug, "xtsonic debug level (1-4)"); #include "sonic.c" -static int __devexit xtsonic_device_remove (struct platform_device *pdev) +static int xtsonic_device_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct sonic_local *lp = netdev_priv(dev); @@ -314,7 +314,7 @@ static int __devexit xtsonic_device_remove (struct platform_device *pdev) static struct platform_driver xtsonic_driver = { .probe = xtsonic_probe, - .remove = __devexit_p(xtsonic_device_remove), + .remove = xtsonic_device_remove, .driver = { .name = xtsonic_string, }, diff --git a/drivers/net/ethernet/neterion/Kconfig b/drivers/net/ethernet/neterion/Kconfig index ff26b54bd3fb..87abb4f10c43 100644 --- a/drivers/net/ethernet/neterion/Kconfig +++ b/drivers/net/ethernet/neterion/Kconfig @@ -32,7 +32,7 @@ config S2IO config VXGE tristate "Exar X3100 Series 10GbE PCIe Server Adapter" - depends on PCI && INET + depends on PCI ---help--- This driver supports Exar Corp's X3100 Series 10 GbE PCIe I/O Virtualized Server Adapter. diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index de50547c187d..7c94c089212f 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -494,7 +494,7 @@ static struct pci_driver s2io_driver = { .name = "S2IO", .id_table = s2io_tbl, .probe = s2io_init_nic, - .remove = __devexit_p(s2io_rem_nic), + .remove = s2io_rem_nic, .err_handler = &s2io_err_handler, }; @@ -1040,7 +1040,7 @@ static int s2io_verify_pci_mode(struct s2io_nic *nic) static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev) { struct pci_dev *tdev = NULL; - while ((tdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) { + for_each_pci_dev(tdev) { if (tdev->vendor == NEC_VENID && tdev->device == NEC_DEVID) { if (tdev->bus == s2io_pdev->bus->parent) { pci_dev_put(tdev); @@ -7702,7 +7702,7 @@ static const struct net_device_ops s2io_netdev_ops = { * returns 0 on success and negative on failure. */ -static int __devinit +static int s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) { struct s2io_nic *sp; @@ -8200,7 +8200,7 @@ mem_alloc_failed: * from memory. */ -static void __devexit s2io_rem_nic(struct pci_dev *pdev) +static void s2io_rem_nic(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct s2io_nic *sp; @@ -8239,7 +8239,8 @@ static int __init s2io_starter(void) /** * s2io_closer - Cleanup routine for the driver - * Description: This function is the cleanup routine for the driver. It unregist * ers the driver. + * Description: This function is the cleanup routine for the driver. It + * unregisters the driver. */ static __exit void s2io_closer(void) diff --git a/drivers/net/ethernet/neterion/s2io.h b/drivers/net/ethernet/neterion/s2io.h index d5596926a1ef..d89b6ed82c51 100644 --- a/drivers/net/ethernet/neterion/s2io.h +++ b/drivers/net/ethernet/neterion/s2io.h @@ -1075,9 +1075,8 @@ static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order) /* * Prototype declaration. */ -static int __devinit s2io_init_nic(struct pci_dev *pdev, - const struct pci_device_id *pre); -static void __devexit s2io_rem_nic(struct pci_dev *pdev); +static int s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre); +static void s2io_rem_nic(struct pci_dev *pdev); static int init_shared_mem(struct s2io_nic *sp); static void free_shared_mem(struct s2io_nic *sp); static int init_nic(struct s2io_nic *nic); diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.c b/drivers/net/ethernet/neterion/vxge/vxge-config.c index c2e420a84d22..fbe5363cb89c 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-config.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c @@ -993,7 +993,7 @@ exit: * for the driver, FW version information, and the first mac address for * each vpath */ -enum vxge_hw_status __devinit +enum vxge_hw_status vxge_hw_device_hw_info_get(void __iomem *bar0, struct vxge_hw_device_hw_info *hw_info) { @@ -1310,7 +1310,7 @@ __vxge_hw_device_config_check(struct vxge_hw_device_config *new_config) * When done, the driver allocates sizeof(struct __vxge_hw_device) bytes for HW * to enable the latter to perform Titan hardware initialization. */ -enum vxge_hw_status __devinit +enum vxge_hw_status vxge_hw_device_initialize( struct __vxge_hw_device **devh, struct vxge_hw_device_attr *attr, @@ -2917,7 +2917,7 @@ exit: * vxge_hw_device_config_default_get - Initialize device config with defaults. * Initialize Titan device config with default values. */ -enum vxge_hw_status __devinit +enum vxge_hw_status vxge_hw_device_config_default_get(struct vxge_hw_device_config *device_config) { u32 i; diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.h b/drivers/net/ethernet/neterion/vxge/vxge-config.h index 9e0c1eed5dc5..6ce4412fcc1a 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-config.h +++ b/drivers/net/ethernet/neterion/vxge/vxge-config.h @@ -1846,11 +1846,11 @@ struct vxge_hw_vpath_attr { struct vxge_hw_fifo_attr fifo_attr; }; -enum vxge_hw_status __devinit vxge_hw_device_hw_info_get( +enum vxge_hw_status vxge_hw_device_hw_info_get( void __iomem *bar0, struct vxge_hw_device_hw_info *hw_info); -enum vxge_hw_status __devinit vxge_hw_device_config_default_get( +enum vxge_hw_status vxge_hw_device_config_default_get( struct vxge_hw_device_config *device_config); /** @@ -1877,7 +1877,7 @@ u16 vxge_hw_device_link_width_get(struct __vxge_hw_device *devh); const u8 * vxge_hw_device_product_name_get(struct __vxge_hw_device *devh); -enum vxge_hw_status __devinit vxge_hw_device_initialize( +enum vxge_hw_status vxge_hw_device_initialize( struct __vxge_hw_device **devh, struct vxge_hw_device_attr *attr, struct vxge_hw_device_config *device_config); diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index 3e5b7509502c..7c87105ca049 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -3371,10 +3371,9 @@ static const struct net_device_ops vxge_netdev_ops = { #endif }; -static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, - struct vxge_config *config, - int high_dma, int no_of_vpath, - struct vxgedev **vdev_out) +static int vxge_device_register(struct __vxge_hw_device *hldev, + struct vxge_config *config, int high_dma, + int no_of_vpath, struct vxgedev **vdev_out) { struct net_device *ndev; enum vxge_hw_status status = VXGE_HW_OK; @@ -3672,9 +3671,8 @@ static void verify_bandwidth(void) /* * Vpath configuration */ -static int __devinit vxge_config_vpaths( - struct vxge_hw_device_config *device_config, - u64 vpath_mask, struct vxge_config *config_param) +static int vxge_config_vpaths(struct vxge_hw_device_config *device_config, + u64 vpath_mask, struct vxge_config *config_param) { int i, no_of_vpaths = 0, default_no_vpath = 0, temp; u32 txdl_size, txdl_per_memblock; @@ -3859,9 +3857,8 @@ static int __devinit vxge_config_vpaths( } /* initialize device configuratrions */ -static void __devinit vxge_device_config_init( - struct vxge_hw_device_config *device_config, - int *intr_type) +static void vxge_device_config_init(struct vxge_hw_device_config *device_config, + int *intr_type) { /* Used for CQRQ/SRQ. */ device_config->dma_blockpool_initial = @@ -3912,7 +3909,7 @@ static void __devinit vxge_device_config_init( device_config->rth_it_type); } -static void __devinit vxge_print_parm(struct vxgedev *vdev, u64 vpath_mask) +static void vxge_print_parm(struct vxgedev *vdev, u64 vpath_mask) { int i; @@ -4269,7 +4266,7 @@ static int vxge_probe_fw_update(struct vxgedev *vdev) return ret; } -static int __devinit is_sriov_initialized(struct pci_dev *pdev) +static int is_sriov_initialized(struct pci_dev *pdev) { int pos; u16 ctrl; @@ -4300,7 +4297,7 @@ static const struct vxge_hw_uld_cbs vxge_callbacks = { * returns 0 on success and negative on failure. * */ -static int __devinit +static int vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) { struct __vxge_hw_device *hldev; @@ -4764,7 +4761,7 @@ _exit0: * Description: This function is called by the Pci subsystem to release a * PCI device and free up all resource held up by the device. */ -static void __devexit vxge_remove(struct pci_dev *pdev) +static void vxge_remove(struct pci_dev *pdev) { struct __vxge_hw_device *hldev; struct vxgedev *vdev; @@ -4809,7 +4806,7 @@ static struct pci_driver vxge_driver = { .name = VXGE_DRIVER_NAME, .id_table = vxge_id_table, .probe = vxge_probe, - .remove = __devexit_p(vxge_remove), + .remove = vxge_remove, #ifdef CONFIG_PM .suspend = vxge_pm_suspend, .resume = vxge_pm_resume, diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c index 6893a65ae55f..cbd6a529d0c0 100644 --- a/drivers/net/ethernet/nuvoton/w90p910_ether.c +++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c @@ -978,7 +978,7 @@ static int w90p910_ether_setup(struct net_device *dev) return 0; } -static int __devinit w90p910_ether_probe(struct platform_device *pdev) +static int w90p910_ether_probe(struct platform_device *pdev) { struct w90p910_ether *ether; struct net_device *dev; @@ -1071,7 +1071,7 @@ failed_free: return error; } -static int __devexit w90p910_ether_remove(struct platform_device *pdev) +static int w90p910_ether_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct w90p910_ether *ether = netdev_priv(dev); @@ -1096,7 +1096,7 @@ static int __devexit w90p910_ether_remove(struct platform_device *pdev) static struct platform_driver w90p910_ether_driver = { .probe = w90p910_ether_probe, - .remove = __devexit_p(w90p910_ether_remove), + .remove = w90p910_ether_remove, .driver = { .name = "nuc900-emc", .owner = THIS_MODULE, diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 876beceaf2d7..87fa5919c455 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -1821,6 +1821,11 @@ static int nv_alloc_rx(struct net_device *dev) skb->data, skb_tailroom(skb), PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(np->pci_dev, + np->put_rx_ctx->dma)) { + kfree_skb(skb); + goto packet_dropped; + } np->put_rx_ctx->dma_len = skb_tailroom(skb); np->put_rx.orig->buf = cpu_to_le32(np->put_rx_ctx->dma); wmb(); @@ -1830,6 +1835,7 @@ static int nv_alloc_rx(struct net_device *dev) if (unlikely(np->put_rx_ctx++ == np->last_rx_ctx)) np->put_rx_ctx = np->first_rx_ctx; } else { +packet_dropped: u64_stats_update_begin(&np->swstats_rx_syncp); np->stat_rx_dropped++; u64_stats_update_end(&np->swstats_rx_syncp); @@ -1856,6 +1862,11 @@ static int nv_alloc_rx_optimized(struct net_device *dev) skb->data, skb_tailroom(skb), PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(np->pci_dev, + np->put_rx_ctx->dma)) { + kfree_skb(skb); + goto packet_dropped; + } np->put_rx_ctx->dma_len = skb_tailroom(skb); np->put_rx.ex->bufhigh = cpu_to_le32(dma_high(np->put_rx_ctx->dma)); np->put_rx.ex->buflow = cpu_to_le32(dma_low(np->put_rx_ctx->dma)); @@ -1866,6 +1877,7 @@ static int nv_alloc_rx_optimized(struct net_device *dev) if (unlikely(np->put_rx_ctx++ == np->last_rx_ctx)) np->put_rx_ctx = np->first_rx_ctx; } else { +packet_dropped: u64_stats_update_begin(&np->swstats_rx_syncp); np->stat_rx_dropped++; u64_stats_update_end(&np->swstats_rx_syncp); @@ -2217,6 +2229,15 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; np->put_tx_ctx->dma = pci_map_single(np->pci_dev, skb->data + offset, bcnt, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(np->pci_dev, + np->put_tx_ctx->dma)) { + /* on DMA mapping error - drop the packet */ + kfree_skb(skb); + u64_stats_update_begin(&np->swstats_tx_syncp); + np->stat_tx_dropped++; + u64_stats_update_end(&np->swstats_tx_syncp); + return NETDEV_TX_OK; + } np->put_tx_ctx->dma_len = bcnt; np->put_tx_ctx->dma_single = 1; put_tx->buf = cpu_to_le32(np->put_tx_ctx->dma); @@ -2337,6 +2358,15 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; np->put_tx_ctx->dma = pci_map_single(np->pci_dev, skb->data + offset, bcnt, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(np->pci_dev, + np->put_tx_ctx->dma)) { + /* on DMA mapping error - drop the packet */ + kfree_skb(skb); + u64_stats_update_begin(&np->swstats_tx_syncp); + np->stat_tx_dropped++; + u64_stats_update_end(&np->swstats_tx_syncp); + return NETDEV_TX_OK; + } np->put_tx_ctx->dma_len = bcnt; np->put_tx_ctx->dma_single = 1; put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma)); @@ -5003,6 +5033,11 @@ static int nv_loopback_test(struct net_device *dev) test_dma_addr = pci_map_single(np->pci_dev, tx_skb->data, skb_tailroom(tx_skb), PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(np->pci_dev, + test_dma_addr)) { + dev_kfree_skb_any(tx_skb); + goto out; + } pkt_data = skb_put(tx_skb, pkt_len); for (i = 0; i < pkt_len; i++) pkt_data[i] = (u8)(i & 0xff); @@ -5520,7 +5555,7 @@ static const struct net_device_ops nv_netdev_ops_optimized = { #endif }; -static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) +static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { struct net_device *dev; struct fe_priv *np; @@ -5995,7 +6030,7 @@ static void nv_restore_mac_addr(struct pci_dev *pci_dev) base + NvRegTransmitPoll); } -static void __devexit nv_remove(struct pci_dev *pci_dev) +static void nv_remove(struct pci_dev *pci_dev) { struct net_device *dev = pci_get_drvdata(pci_dev); @@ -6271,7 +6306,7 @@ static struct pci_driver driver = { .name = DRV_NAME, .id_table = pci_tbl, .probe = nv_probe, - .remove = __devexit_p(nv_remove), + .remove = nv_remove, .shutdown = nv_shutdown, .driver.pm = NV_PM_OPS, }; diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 53743f7a2ca9..3466ca1e8f6c 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1219,9 +1219,6 @@ static int lpc_eth_open(struct net_device *ndev) if (netif_msg_ifup(pldat)) dev_dbg(&pldat->pdev->dev, "enabling %s\n", ndev->name); - if (!is_valid_ether_addr(ndev->dev_addr)) - return -EADDRNOTAVAIL; - __lpc_eth_clock_enable(pldat, true); /* Reset and initialize */ @@ -1301,6 +1298,7 @@ static const struct net_device_ops lpc_netdev_ops = { .ndo_set_rx_mode = lpc_eth_set_multicast_list, .ndo_do_ioctl = lpc_eth_ioctl, .ndo_set_mac_address = lpc_set_mac_address, + .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = eth_change_mtu, }; @@ -1524,6 +1522,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev) pldat->dma_buff_base_p); free_irq(ndev->irq, ndev); iounmap(pldat->net_base); + mdiobus_unregister(pldat->mii_bus); mdiobus_free(pldat->mii_bus); clk_disable(pldat->clk); clk_put(pldat->clk); @@ -1596,7 +1595,7 @@ MODULE_DEVICE_TABLE(of, lpc_eth_match); static struct platform_driver lpc_eth_driver = { .probe = lpc_eth_drv_probe, - .remove = __devexit_p(lpc_eth_drv_remove), + .remove = lpc_eth_drv_remove, #ifdef CONFIG_PM .suspend = lpc_eth_drv_suspend, .resume = lpc_eth_drv_resume, diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c index f97719c48516..b5499198e029 100644 --- a/drivers/net/ethernet/octeon/octeon_mgmt.c +++ b/drivers/net/ethernet/octeon/octeon_mgmt.c @@ -1419,7 +1419,7 @@ static const struct net_device_ops octeon_mgmt_ops = { #endif }; -static int __devinit octeon_mgmt_probe(struct platform_device *pdev) +static int octeon_mgmt_probe(struct platform_device *pdev) { struct net_device *netdev; struct octeon_mgmt *p; @@ -1559,7 +1559,7 @@ err: return result; } -static int __devexit octeon_mgmt_remove(struct platform_device *pdev) +static int octeon_mgmt_remove(struct platform_device *pdev) { struct net_device *netdev = dev_get_drvdata(&pdev->dev); @@ -1583,7 +1583,7 @@ static struct platform_driver octeon_mgmt_driver = { .of_match_table = octeon_mgmt_match, }, .probe = octeon_mgmt_probe, - .remove = __devexit_p(octeon_mgmt_remove), + .remove = octeon_mgmt_remove, }; extern void octeon_mdiobus_force_mod_depencency(void); diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig index 5296cc8d3cba..34d05bf72b2e 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig +++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig @@ -7,6 +7,7 @@ config PCH_GBE depends on PCI select NET_CORE select MII + select PTP_1588_CLOCK_PCH ---help--- This is a gigabit ethernet driver for EG20T PCH. EG20T PCH is the platform controller hub that is used in Intel's @@ -20,19 +21,3 @@ config PCH_GBE purpose use. ML7223/ML7831 is companion chip for Intel Atom E6xx series. ML7223/ML7831 is completely compatible for Intel EG20T PCH. - -if PCH_GBE - -config PCH_PTP - bool "PCH PTP clock support" - default n - depends on EXPERIMENTAL - select PPS - select PTP_1588_CLOCK - select PTP_1588_CLOCK_PCH - ---help--- - Say Y here if you want to use Precision Time Protocol (PTP) in the - driver. PTP is a method to precisely synchronize distributed clocks - over Ethernet networks. - -endif # PCH_GBE diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h index b07311eaa693..7fb7e178c74e 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h @@ -649,7 +649,6 @@ extern void pch_gbe_free_tx_resources(struct pch_gbe_adapter *adapter, extern void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter, struct pch_gbe_rx_ring *rx_ring); extern void pch_gbe_update_stats(struct pch_gbe_adapter *adapter); -#ifdef CONFIG_PCH_PTP extern u32 pch_ch_control_read(struct pci_dev *pdev); extern void pch_ch_control_write(struct pci_dev *pdev, u32 val); extern u32 pch_ch_event_read(struct pci_dev *pdev); @@ -659,7 +658,6 @@ extern u32 pch_src_uuid_hi_read(struct pci_dev *pdev); extern u64 pch_rx_snap_read(struct pci_dev *pdev); extern u64 pch_tx_snap_read(struct pci_dev *pdev); extern int pch_set_station_address(u8 *addr, struct pci_dev *pdev); -#endif /* pch_gbe_param.c */ extern void pch_gbe_check_options(struct pch_gbe_adapter *adapter); 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 4c4fe5b1a29a..39ab4d09faaa 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 @@ -21,10 +21,8 @@ #include "pch_gbe.h" #include "pch_gbe_api.h" #include <linux/module.h> -#ifdef CONFIG_PCH_PTP #include <linux/net_tstamp.h> #include <linux/ptp_classify.h> -#endif #define DRV_VERSION "1.01" const char pch_driver_version[] = DRV_VERSION; @@ -98,7 +96,6 @@ const char pch_driver_version[] = DRV_VERSION; #define PCH_GBE_INT_DISABLE_ALL 0 -#ifdef CONFIG_PCH_PTP /* Macros for ieee1588 */ /* 0x40 Time Synchronization Channel Control Register Bits */ #define MASTER_MODE (1<<0) @@ -113,7 +110,6 @@ const char pch_driver_version[] = DRV_VERSION; #define PTP_L4_MULTICAST_SA "01:00:5e:00:01:81" #define PTP_L2_MULTICAST_SA "01:1b:19:00:00:00" -#endif static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT; @@ -122,7 +118,6 @@ static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg, int data); static void pch_gbe_set_multi(struct net_device *netdev); -#ifdef CONFIG_PCH_PTP static struct sock_filter ptp_filter[] = { PTP_FILTER }; @@ -291,7 +286,6 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; } -#endif inline void pch_gbe_mac_load_mac_addr(struct pch_gbe_hw *hw) { @@ -1244,9 +1238,7 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter, (int)sizeof(struct pch_gbe_tx_desc) * ring_num, &hw->reg->TX_DSC_SW_P); -#ifdef CONFIG_PCH_PTP pch_tx_timestamp(adapter, skb); -#endif dev_kfree_skb_any(skb); } @@ -1730,9 +1722,7 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, /* Write meta date of skb */ skb_put(skb, length); -#ifdef CONFIG_PCH_PTP pch_rx_timestamp(adapter, skb); -#endif skb->protocol = eth_type_trans(skb, netdev); if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK) @@ -2334,10 +2324,8 @@ static int pch_gbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) pr_debug("cmd : 0x%04x\n", cmd); -#ifdef CONFIG_PCH_PTP if (cmd == SIOCSHWTSTAMP) return hwtstamp_ioctl(netdev, ifr, cmd); -#endif return generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL); } @@ -2623,14 +2611,12 @@ static int pch_gbe_probe(struct pci_dev *pdev, goto err_free_netdev; } -#ifdef CONFIG_PCH_PTP adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number, PCI_DEVFN(12, 4)); if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) { pr_err("Bad ptp filter\n"); return -EINVAL; } -#endif netdev->netdev_ops = &pch_gbe_netdev_ops; netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD; diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c index c2367158350e..bf829ee30077 100644 --- a/drivers/net/ethernet/packetengines/hamachi.c +++ b/drivers/net/ethernet/packetengines/hamachi.c @@ -166,7 +166,7 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include <asm/unaligned.h> #include <asm/cache.h> -static const char version[] __devinitconst = +static const char version[] = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" " Some modifications by Eric kasten <kasten@nscl.msu.edu>\n" " Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n"; @@ -576,8 +576,8 @@ static const struct net_device_ops hamachi_netdev_ops = { }; -static int __devinit hamachi_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int hamachi_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct hamachi_private *hmp; int option, i, rx_int_var, tx_int_var, boguscnt; @@ -791,7 +791,7 @@ err_out: return ret; } -static int __devinit read_eeprom(void __iomem *ioaddr, int location) +static int read_eeprom(void __iomem *ioaddr, int location) { int bogus_cnt = 1000; @@ -1894,7 +1894,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } -static void __devexit hamachi_remove_one (struct pci_dev *pdev) +static void hamachi_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -1923,7 +1923,7 @@ static struct pci_driver hamachi_driver = { .name = DRV_NAME, .id_table = hamachi_pci_tbl, .probe = hamachi_init_one, - .remove = __devexit_p(hamachi_remove_one), + .remove = hamachi_remove_one, }; static int __init hamachi_init (void) diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c index 04e622fd468d..fbaed4fa72fa 100644 --- a/drivers/net/ethernet/packetengines/yellowfin.c +++ b/drivers/net/ethernet/packetengines/yellowfin.c @@ -106,7 +106,7 @@ static int gx_fix; #include <asm/io.h> /* These identify the driver base version and may not be removed. */ -static const char version[] __devinitconst = +static const char version[] = KERN_INFO DRV_NAME ".c:v1.05 1/09/2001 Written by Donald Becker <becker@scyld.com>\n" " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n"; @@ -367,8 +367,8 @@ static const struct net_device_ops netdev_ops = { .ndo_tx_timeout = yellowfin_tx_timeout, }; -static int __devinit yellowfin_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int yellowfin_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct net_device *dev; struct yellowfin_private *np; @@ -522,7 +522,7 @@ err_out_free_netdev: return -ENODEV; } -static int __devinit read_eeprom(void __iomem *ioaddr, int location) +static int read_eeprom(void __iomem *ioaddr, int location) { int bogus_cnt = 10000; /* Typical 33Mhz: 1050 ticks */ @@ -1372,7 +1372,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } -static void __devexit yellowfin_remove_one (struct pci_dev *pdev) +static void yellowfin_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct yellowfin_private *np; @@ -1399,7 +1399,7 @@ static struct pci_driver yellowfin_driver = { .name = DRV_NAME, .id_table = yellowfin_pci_tbl, .probe = yellowfin_init_one, - .remove = __devexit_p(yellowfin_remove_one), + .remove = yellowfin_remove_one, }; diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index 6fa74d530e44..0be5844d6372 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -1727,7 +1727,7 @@ static const struct net_device_ops pasemi_netdev_ops = { #endif }; -static int __devinit +static int pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; @@ -1849,7 +1849,7 @@ out_disable_device: } -static void __devexit pasemi_mac_remove(struct pci_dev *pdev) +static void pasemi_mac_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct pasemi_mac *mac; @@ -1884,7 +1884,7 @@ static struct pci_driver pasemi_mac_driver = { .name = "pasemi_mac", .id_table = pasemi_mac_pci_tbl, .probe = pasemi_mac_probe, - .remove = __devexit_p(pasemi_mac_remove), + .remove = pasemi_mac_remove, }; static void __exit pasemi_mac_cleanup_module(void) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c index 10468e7932dd..4ca2c196c98a 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c @@ -218,7 +218,7 @@ skip: check_sfp_module = netif_running(dev) && adapter->has_link_events; } else { - ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg); + ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg); ecmd->advertising |= (ADVERTISED_TP | ADVERTISED_Autoneg); ecmd->port = PORT_TP; @@ -381,7 +381,7 @@ static u32 netxen_nic_test_link(struct net_device *dev) static int netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, - u8 * bytes) + u8 *bytes) { struct netxen_adapter *adapter = netdev_priv(dev); int offset; @@ -488,6 +488,8 @@ netxen_nic_get_pauseparam(struct net_device *dev, __u32 val; int port = adapter->physical_port; + pause->autoneg = 0; + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS)) return; @@ -496,19 +498,19 @@ netxen_nic_get_pauseparam(struct net_device *dev, pause->rx_pause = netxen_gb_get_rx_flowctl(val); val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL); switch (port) { - case 0: - pause->tx_pause = !(netxen_gb_get_gb0_mask(val)); - break; - case 1: - pause->tx_pause = !(netxen_gb_get_gb1_mask(val)); - break; - case 2: - pause->tx_pause = !(netxen_gb_get_gb2_mask(val)); - break; - case 3: - default: - pause->tx_pause = !(netxen_gb_get_gb3_mask(val)); - break; + case 0: + pause->tx_pause = !(netxen_gb_get_gb0_mask(val)); + break; + case 1: + pause->tx_pause = !(netxen_gb_get_gb1_mask(val)); + break; + case 2: + pause->tx_pause = !(netxen_gb_get_gb2_mask(val)); + break; + case 3: + default: + pause->tx_pause = !(netxen_gb_get_gb3_mask(val)); + break; } } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS)) @@ -532,6 +534,11 @@ netxen_nic_set_pauseparam(struct net_device *dev, struct netxen_adapter *adapter = netdev_priv(dev); __u32 val; int port = adapter->physical_port; + + /* not supported */ + if (pause->autoneg) + return -EINVAL; + /* read mode */ if (adapter->ahw.port_type == NETXEN_NIC_GBE) { if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS)) @@ -549,31 +556,31 @@ netxen_nic_set_pauseparam(struct net_device *dev, /* set autoneg */ val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL); switch (port) { - case 0: - if (pause->tx_pause) - netxen_gb_unset_gb0_mask(val); - else - netxen_gb_set_gb0_mask(val); - break; - case 1: - if (pause->tx_pause) - netxen_gb_unset_gb1_mask(val); - else - netxen_gb_set_gb1_mask(val); - break; - case 2: - if (pause->tx_pause) - netxen_gb_unset_gb2_mask(val); - else - netxen_gb_set_gb2_mask(val); - break; - case 3: - default: - if (pause->tx_pause) - netxen_gb_unset_gb3_mask(val); - else - netxen_gb_set_gb3_mask(val); - break; + case 0: + if (pause->tx_pause) + netxen_gb_unset_gb0_mask(val); + else + netxen_gb_set_gb0_mask(val); + break; + case 1: + if (pause->tx_pause) + netxen_gb_unset_gb1_mask(val); + else + netxen_gb_set_gb1_mask(val); + break; + case 2: + if (pause->tx_pause) + netxen_gb_unset_gb2_mask(val); + else + netxen_gb_set_gb2_mask(val); + break; + case 3: + default: + if (pause->tx_pause) + netxen_gb_unset_gb3_mask(val); + else + netxen_gb_set_gb3_mask(val); + break; } NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val); } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { @@ -636,7 +643,7 @@ static int netxen_get_sset_count(struct net_device *dev, int sset) static void netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, - u64 * data) + u64 *data) { memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN); if ((data[0] = netxen_nic_reg_test(dev))) @@ -647,7 +654,7 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, } static void -netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data) +netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 *data) { int index; @@ -668,7 +675,7 @@ netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data) static void netxen_nic_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 * data) + struct ethtool_stats *stats, u64 *data) { struct netxen_adapter *adapter = netdev_priv(dev); int index; diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index bc165f4d0f65..695667d471a1 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -144,7 +144,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) buffrag->length, PCI_DMA_TODEVICE); buffrag->dma = 0ULL; } - for (j = 0; j < cmd_buf->frag_count; j++) { + for (j = 1; j < cmd_buf->frag_count; j++) { buffrag++; if (buffrag->dma) { pci_unmap_page(adapter->pdev, buffrag->dma, diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index df450616ab37..69e321a65077 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -60,9 +60,9 @@ static int auto_fw_reset = AUTO_FW_RESET_ENABLED; module_param(auto_fw_reset, int, 0644); MODULE_PARM_DESC(auto_fw_reset,"Auto firmware reset (0=disabled, 1=enabled"); -static int __devinit netxen_nic_probe(struct pci_dev *pdev, +static int netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); -static void __devexit netxen_nic_remove(struct pci_dev *pdev); +static void netxen_nic_remove(struct pci_dev *pdev); static int netxen_nic_open(struct net_device *netdev); static int netxen_nic_close(struct net_device *netdev); static netdev_tx_t netxen_nic_xmit_frame(struct sk_buff *, @@ -1397,7 +1397,7 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter) } #endif -static int __devinit +static int netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev = NULL; @@ -1569,7 +1569,7 @@ void netxen_cleanup_minidump(struct netxen_adapter *adapter) } } -static void __devexit netxen_nic_remove(struct pci_dev *pdev) +static void netxen_nic_remove(struct pci_dev *pdev) { struct netxen_adapter *adapter; struct net_device *netdev; @@ -1963,10 +1963,12 @@ unwind: while (--i >= 0) { nf = &pbuf->frag_array[i+1]; pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); + nf->dma = 0ULL; } nf = &pbuf->frag_array[0]; pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); + nf->dma = 0ULL; out_err: return -ENOMEM; @@ -3350,7 +3352,7 @@ static struct pci_driver netxen_driver = { .name = netxen_nic_driver_name, .id_table = netxen_pci_tbl, .probe = netxen_nic_probe, - .remove = __devexit_p(netxen_nic_remove), + .remove = netxen_nic_remove, #ifdef CONFIG_PM .suspend = netxen_nic_suspend, .resume = netxen_nic_resume, diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index 6407d0d77e81..67a679aaf29a 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -1920,7 +1920,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev, { struct ql_tx_buf_cb *tx_cb; int i; - int retval = 0; if (mac_rsp->flags & OB_MAC_IOCB_RSP_S) { netdev_warn(qdev->ndev, @@ -1935,7 +1934,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev, "Frame too short to be legal, frame not sent\n"); qdev->ndev->stats.tx_errors++; - retval = -EIO; goto frame_not_sent; } @@ -1944,7 +1942,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev, mac_rsp->transaction_id); qdev->ndev->stats.tx_errors++; - retval = -EIO; goto invalid_seg_count; } @@ -3772,8 +3769,8 @@ static const struct net_device_ops ql3xxx_netdev_ops = { .ndo_tx_timeout = ql3xxx_tx_timeout, }; -static int __devinit ql3xxx_probe(struct pci_dev *pdev, - const struct pci_device_id *pci_entry) +static int ql3xxx_probe(struct pci_dev *pdev, + const struct pci_device_id *pci_entry) { struct net_device *ndev = NULL; struct ql3_adapter *qdev = NULL; @@ -3928,7 +3925,7 @@ err_out: return err; } -static void __devexit ql3xxx_remove(struct pci_dev *pdev) +static void ql3xxx_remove(struct pci_dev *pdev) { struct net_device *ndev = pci_get_drvdata(pdev); struct ql3_adapter *qdev = netdev_priv(ndev); @@ -3955,18 +3952,7 @@ static struct pci_driver ql3xxx_driver = { .name = DRV_NAME, .id_table = ql3xxx_pci_tbl, .probe = ql3xxx_probe, - .remove = __devexit_p(ql3xxx_remove), + .remove = ql3xxx_remove, }; -static int __init ql3xxx_init_module(void) -{ - return pci_register_driver(&ql3xxx_driver); -} - -static void __exit ql3xxx_exit(void) -{ - pci_unregister_driver(&ql3xxx_driver); -} - -module_init(ql3xxx_init_module); -module_exit(ql3xxx_exit); +module_pci_driver(ql3xxx_driver); diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile index ddba83ef3f44..c4b8ced83829 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/Makefile +++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_QLCNIC) := qlcnic.o qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \ - qlcnic_ethtool.o qlcnic_ctx.o + qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \ + qlcnic_sysfs.o qlcnic_minidump.o diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index eaa1db9fec32..bc7ec64e9c7a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -36,8 +36,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 0 -#define _QLCNIC_LINUX_SUBVERSION 29 -#define QLCNIC_LINUX_VERSIONID "5.0.29" +#define _QLCNIC_LINUX_SUBVERSION 30 +#define QLCNIC_LINUX_VERSIONID "5.0.30" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) @@ -89,16 +89,6 @@ #define QLCNIC_CT_DEFAULT_RX_BUF_LEN 2048 #define QLCNIC_LRO_BUFFER_EXTRA 2048 -/* Opcodes to be used with the commands */ -#define TX_ETHER_PKT 0x01 -#define TX_TCP_PKT 0x02 -#define TX_UDP_PKT 0x03 -#define TX_IP_PKT 0x04 -#define TX_TCP_LSO 0x05 -#define TX_TCP_LSO6 0x06 -#define TX_TCPV6_PKT 0x0b -#define TX_UDPV6_PKT 0x0c - /* Tx defines */ #define QLCNIC_MAX_FRAGS_PER_TX 14 #define MAX_TSO_HEADER_DESC 2 @@ -147,28 +137,6 @@ * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when * we are doing LSO (above the 1500 size packet) only. */ - -#define FLAGS_VLAN_TAGGED 0x10 -#define FLAGS_VLAN_OOB 0x40 - -#define qlcnic_set_tx_vlan_tci(cmd_desc, v) \ - (cmd_desc)->vlan_TCI = cpu_to_le16(v); -#define qlcnic_set_cmd_desc_port(cmd_desc, var) \ - ((cmd_desc)->port_ctxid |= ((var) & 0x0F)) -#define qlcnic_set_cmd_desc_ctxid(cmd_desc, var) \ - ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0)) - -#define qlcnic_set_tx_port(_desc, _port) \ - ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)) - -#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \ - ((_desc)->flags_opcode |= \ - cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))) - -#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \ - ((_desc)->nfrags__length = \ - cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8))) - struct cmd_desc_type0 { u8 tcp_hdr_offset; /* For LSO only */ u8 ip_hdr_offset; /* For LSO only */ @@ -203,65 +171,6 @@ struct rcv_desc { __le64 addr_buffer; } __packed; -/* opcode field in status_desc */ -#define QLCNIC_SYN_OFFLOAD 0x03 -#define QLCNIC_RXPKT_DESC 0x04 -#define QLCNIC_OLD_RXPKT_DESC 0x3f -#define QLCNIC_RESPONSE_DESC 0x05 -#define QLCNIC_LRO_DESC 0x12 - -/* for status field in status_desc */ -#define STATUS_CKSUM_LOOP 0 -#define STATUS_CKSUM_OK 2 - -/* owner bits of status_desc */ -#define STATUS_OWNER_HOST (0x1ULL << 56) -#define STATUS_OWNER_PHANTOM (0x2ULL << 56) - -/* Status descriptor: - 0-3 port, 4-7 status, 8-11 type, 12-27 total_length - 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset - 53-55 desc_cnt, 56-57 owner, 58-63 opcode - */ -#define qlcnic_get_sts_port(sts_data) \ - ((sts_data) & 0x0F) -#define qlcnic_get_sts_status(sts_data) \ - (((sts_data) >> 4) & 0x0F) -#define qlcnic_get_sts_type(sts_data) \ - (((sts_data) >> 8) & 0x0F) -#define qlcnic_get_sts_totallength(sts_data) \ - (((sts_data) >> 12) & 0xFFFF) -#define qlcnic_get_sts_refhandle(sts_data) \ - (((sts_data) >> 28) & 0xFFFF) -#define qlcnic_get_sts_prot(sts_data) \ - (((sts_data) >> 44) & 0x0F) -#define qlcnic_get_sts_pkt_offset(sts_data) \ - (((sts_data) >> 48) & 0x1F) -#define qlcnic_get_sts_desc_cnt(sts_data) \ - (((sts_data) >> 53) & 0x7) -#define qlcnic_get_sts_opcode(sts_data) \ - (((sts_data) >> 58) & 0x03F) - -#define qlcnic_get_lro_sts_refhandle(sts_data) \ - ((sts_data) & 0x0FFFF) -#define qlcnic_get_lro_sts_length(sts_data) \ - (((sts_data) >> 16) & 0x0FFFF) -#define qlcnic_get_lro_sts_l2_hdr_offset(sts_data) \ - (((sts_data) >> 32) & 0x0FF) -#define qlcnic_get_lro_sts_l4_hdr_offset(sts_data) \ - (((sts_data) >> 40) & 0x0FF) -#define qlcnic_get_lro_sts_timestamp(sts_data) \ - (((sts_data) >> 48) & 0x1) -#define qlcnic_get_lro_sts_type(sts_data) \ - (((sts_data) >> 49) & 0x7) -#define qlcnic_get_lro_sts_push_flag(sts_data) \ - (((sts_data) >> 52) & 0x1) -#define qlcnic_get_lro_sts_seq_number(sts_data) \ - ((sts_data) & 0x0FFFFFFFF) -#define qlcnic_get_lro_sts_mss(sts_data1) \ - ((sts_data1 >> 32) & 0x0FFFF) - - struct status_desc { __le64 status_desc_data[2]; } __attribute__ ((aligned(16))); @@ -280,16 +189,16 @@ struct status_desc { #define QLCNIC_UNI_FIRMWARE_IDX_OFF 29 struct uni_table_desc{ - u32 findex; - u32 num_entries; - u32 entry_size; - u32 reserved[5]; + __le32 findex; + __le32 num_entries; + __le32 entry_size; + __le32 reserved[5]; }; struct uni_data_desc{ - u32 findex; - u32 size; - u32 reserved[5]; + __le32 findex; + __le32 size; + __le32 reserved[5]; }; /* Flash Defines and Structures */ @@ -416,19 +325,19 @@ struct qlcnic_nic_intr_coalesce { }; struct qlcnic_dump_template_hdr { - __le32 type; - __le32 offset; - __le32 size; - __le32 cap_mask; - __le32 num_entries; - __le32 version; - __le32 timestamp; - __le32 checksum; - __le32 drv_cap_mask; - __le32 sys_info[3]; - __le32 saved_state[16]; - __le32 cap_sizes[8]; - __le32 rsvd[0]; + u32 type; + u32 offset; + u32 size; + u32 cap_mask; + u32 num_entries; + u32 version; + u32 timestamp; + u32 checksum; + u32 drv_cap_mask; + u32 sys_info[3]; + u32 saved_state[16]; + u32 cap_sizes[8]; + u32 rsvd[0]; }; struct qlcnic_fw_dump { @@ -456,11 +365,41 @@ struct qlcnic_hardware_context { u8 pci_func; u8 linkup; u8 loopback_state; + u8 beacon_state; + u8 has_link_events; + u8 fw_type; + u8 physical_port; + u8 reset_context; + u8 msix_supported; + u8 max_mac_filters; + u8 mc_enabled; + u8 max_mc_count; + u8 diag_test; + u8 num_msix; + u8 nic_mode; + char diag_cnt; + u16 port_type; u16 board_type; - u8 beacon_state; + u16 link_speed; + u16 link_duplex; + u16 link_autoneg; + u16 module_type; + u16 op_mode; + u16 switch_mode; + u16 max_tx_ques; + u16 max_rx_ques; + u16 max_mtu; + u32 msg_enable; + u16 act_pci_func; + + u32 capabilities; + u32 temp; + u32 int_vec_bit; + u32 fw_hal_version; + struct qlcnic_hardware_ops *hw_ops; struct qlcnic_nic_intr_coalesce coal; struct qlcnic_fw_dump fw_dump; }; @@ -521,6 +460,7 @@ struct qlcnic_host_sds_ring { } ____cacheline_internodealigned_in_smp; struct qlcnic_host_tx_ring { + u16 ctx_id; u32 producer; u32 sw_consumer; u32 num_desc; @@ -985,6 +925,7 @@ struct qlcnic_adapter { unsigned long state; u32 flags; + int max_drv_tx_rings; u16 num_txd; u16 num_rxd; u16 num_jumbo_rxd; @@ -993,57 +934,28 @@ struct qlcnic_adapter { u8 max_rds_rings; u8 max_sds_rings; - u8 msix_supported; u8 portnum; - u8 physical_port; - u8 reset_context; - u8 mc_enabled; - u8 max_mc_count; u8 fw_wait_cnt; u8 fw_fail_cnt; u8 tx_timeo_cnt; u8 need_fw_reset; - u8 has_link_events; - u8 fw_type; - u16 tx_context_id; u16 is_up; - - u16 link_speed; - u16 link_duplex; - u16 link_autoneg; - u16 module_type; - - u16 op_mode; - u16 switch_mode; - u16 max_tx_ques; - u16 max_rx_ques; - u16 max_mtu; u16 pvid; - u32 fw_hal_version; - u32 capabilities; u32 irq; - u32 temp; - - u32 int_vec_bit; u32 heartbeat; - u8 max_mac_filters; u8 dev_state; - u8 diag_test; - char diag_cnt; u8 reset_ack_timeo; u8 dev_init_timeo; - u16 msg_enable; u8 mac_addr[ETH_ALEN]; u64 dev_rst_time; u8 mac_learn; unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)]; - struct qlcnic_npar_info *npars; struct qlcnic_eswitch *eswitch; struct qlcnic_nic_template *nic_ops; @@ -1057,24 +969,22 @@ struct qlcnic_adapter { void __iomem *isr_int_vec; struct msix_entry *msix_entries; - struct delayed_work fw_work; - struct qlcnic_filter_hash fhash; spinlock_t tx_clean_lock; spinlock_t mac_learn_lock; - __le32 file_prd_off; /*File fw product offset*/ + u32 file_prd_off; /*File fw product offset*/ u32 fw_version; const struct firmware *fw; }; -struct qlcnic_info { +struct qlcnic_info_le { __le16 pci_func; - __le16 op_mode; /* 1 = Priv, 2 = NP, 3 = NP passthru */ + __le16 op_mode; /* 1 = Priv, 2 = NP, 3 = NP passthru */ __le16 phys_port; - __le16 switch_mode; /* 0 = disabled, 1 = int, 2 = ext */ + __le16 switch_mode; /* 0 = disabled, 1 = int, 2 = ext */ __le32 capabilities; u8 max_mac_filters; @@ -1088,13 +998,28 @@ struct qlcnic_info { u8 reserved2[104]; } __packed; -struct qlcnic_pci_info { - __le16 id; /* pci function id */ - __le16 active; /* 1 = Enabled */ - __le16 type; /* 1 = NIC, 2 = FCoE, 3 = iSCSI */ - __le16 default_port; /* default port number */ +struct qlcnic_info { + u16 pci_func; + u16 op_mode; + u16 phys_port; + u16 switch_mode; + u32 capabilities; + u8 max_mac_filters; + u8 reserved1; + u16 max_mtu; + u16 max_tx_ques; + u16 max_rx_ques; + u16 min_tx_bw; + u16 max_tx_bw; +}; + +struct qlcnic_pci_info_le { + __le16 id; /* pci function id */ + __le16 active; /* 1 = Enabled */ + __le16 type; /* 1 = NIC, 2 = FCoE, 3 = iSCSI */ + __le16 default_port; /* default port number */ - __le16 tx_min_bw; /* Multiple of 100mbpc */ + __le16 tx_min_bw; /* Multiple of 100mbpc */ __le16 tx_max_bw; __le16 reserved1[2]; @@ -1102,6 +1027,16 @@ struct qlcnic_pci_info { u8 reserved2[106]; } __packed; +struct qlcnic_pci_info { + u16 id; + u16 active; + u16 type; + u16 default_port; + u16 tx_min_bw; + u16 tx_max_bw; + u8 mac[ETH_ALEN]; +}; + struct qlcnic_npar_info { u16 pvid; u16 min_bw; @@ -1116,6 +1051,7 @@ struct qlcnic_npar_info { u8 mac_anti_spoof; u8 promisc_mode; u8 offload_flags; + u8 pci_func; }; struct qlcnic_eswitch { @@ -1208,7 +1144,7 @@ do { \ (VAL1) += (VAL2); \ } while (0) -struct qlcnic_mac_statistics{ +struct qlcnic_mac_statistics_le { __le64 mac_tx_frames; __le64 mac_tx_bytes; __le64 mac_tx_mcast_pkts; @@ -1248,7 +1184,45 @@ struct qlcnic_mac_statistics{ __le64 mac_align_error; } __packed; -struct __qlcnic_esw_statistics { +struct qlcnic_mac_statistics { + u64 mac_tx_frames; + u64 mac_tx_bytes; + u64 mac_tx_mcast_pkts; + u64 mac_tx_bcast_pkts; + u64 mac_tx_pause_cnt; + u64 mac_tx_ctrl_pkt; + u64 mac_tx_lt_64b_pkts; + u64 mac_tx_lt_127b_pkts; + u64 mac_tx_lt_255b_pkts; + u64 mac_tx_lt_511b_pkts; + u64 mac_tx_lt_1023b_pkts; + u64 mac_tx_lt_1518b_pkts; + u64 mac_tx_gt_1518b_pkts; + u64 rsvd1[3]; + u64 mac_rx_frames; + u64 mac_rx_bytes; + u64 mac_rx_mcast_pkts; + u64 mac_rx_bcast_pkts; + u64 mac_rx_pause_cnt; + u64 mac_rx_ctrl_pkt; + u64 mac_rx_lt_64b_pkts; + u64 mac_rx_lt_127b_pkts; + u64 mac_rx_lt_255b_pkts; + u64 mac_rx_lt_511b_pkts; + u64 mac_rx_lt_1023b_pkts; + u64 mac_rx_lt_1518b_pkts; + u64 mac_rx_gt_1518b_pkts; + u64 rsvd2[3]; + u64 mac_rx_length_error; + u64 mac_rx_length_small; + u64 mac_rx_length_large; + u64 mac_rx_jabber; + u64 mac_rx_dropped; + u64 mac_rx_crc_error; + u64 mac_align_error; +}; + +struct qlcnic_esw_stats_le { __le16 context_id; __le16 version; __le16 size; @@ -1263,147 +1237,27 @@ struct __qlcnic_esw_statistics { __le64 rsvd[3]; } __packed; +struct __qlcnic_esw_statistics { + u16 context_id; + u16 version; + u16 size; + u16 unused; + u64 unicast_frames; + u64 multicast_frames; + u64 broadcast_frames; + u64 dropped_frames; + u64 errors; + u64 local_frames; + u64 numbytes; + u64 rsvd[3]; +}; + struct qlcnic_esw_statistics { struct __qlcnic_esw_statistics rx; struct __qlcnic_esw_statistics tx; }; -struct qlcnic_common_entry_hdr { - __le32 type; - __le32 offset; - __le32 cap_size; - u8 mask; - u8 rsvd[2]; - u8 flags; -} __packed; - -struct __crb { - __le32 addr; - u8 stride; - u8 rsvd1[3]; - __le32 data_size; - __le32 no_ops; - __le32 rsvd2[4]; -} __packed; - -struct __ctrl { - __le32 addr; - u8 stride; - u8 index_a; - __le16 timeout; - __le32 data_size; - __le32 no_ops; - u8 opcode; - u8 index_v; - u8 shl_val; - u8 shr_val; - __le32 val1; - __le32 val2; - __le32 val3; -} __packed; - -struct __cache { - __le32 addr; - __le16 stride; - __le16 init_tag_val; - __le32 size; - __le32 no_ops; - __le32 ctrl_addr; - __le32 ctrl_val; - __le32 read_addr; - u8 read_addr_stride; - u8 read_addr_num; - u8 rsvd1[2]; -} __packed; - -struct __ocm { - u8 rsvd[8]; - __le32 size; - __le32 no_ops; - u8 rsvd1[8]; - __le32 read_addr; - __le32 read_addr_stride; -} __packed; - -struct __mem { - u8 rsvd[24]; - __le32 addr; - __le32 size; -} __packed; - -struct __mux { - __le32 addr; - u8 rsvd[4]; - __le32 size; - __le32 no_ops; - __le32 val; - __le32 val_stride; - __le32 read_addr; - u8 rsvd2[4]; -} __packed; - -struct __queue { - __le32 sel_addr; - __le16 stride; - u8 rsvd[2]; - __le32 size; - __le32 no_ops; - u8 rsvd2[8]; - __le32 read_addr; - u8 read_addr_stride; - u8 read_addr_cnt; - u8 rsvd3[2]; -} __packed; - -struct qlcnic_dump_entry { - struct qlcnic_common_entry_hdr hdr; - union { - struct __crb crb; - struct __cache cache; - struct __ocm ocm; - struct __mem mem; - struct __mux mux; - struct __queue que; - struct __ctrl ctrl; - } region; -} __packed; - -enum op_codes { - QLCNIC_DUMP_NOP = 0, - QLCNIC_DUMP_READ_CRB = 1, - QLCNIC_DUMP_READ_MUX = 2, - QLCNIC_DUMP_QUEUE = 3, - QLCNIC_DUMP_BRD_CONFIG = 4, - QLCNIC_DUMP_READ_OCM = 6, - QLCNIC_DUMP_PEG_REG = 7, - QLCNIC_DUMP_L1_DTAG = 8, - QLCNIC_DUMP_L1_ITAG = 9, - QLCNIC_DUMP_L1_DATA = 11, - QLCNIC_DUMP_L1_INST = 12, - QLCNIC_DUMP_L2_DTAG = 21, - QLCNIC_DUMP_L2_ITAG = 22, - QLCNIC_DUMP_L2_DATA = 23, - QLCNIC_DUMP_L2_INST = 24, - QLCNIC_DUMP_READ_ROM = 71, - QLCNIC_DUMP_READ_MEM = 72, - QLCNIC_DUMP_READ_CTRL = 98, - QLCNIC_DUMP_TLHDR = 99, - QLCNIC_DUMP_RDEND = 255 -}; - -#define QLCNIC_DUMP_WCRB BIT_0 -#define QLCNIC_DUMP_RWCRB BIT_1 -#define QLCNIC_DUMP_ANDCRB BIT_2 -#define QLCNIC_DUMP_ORCRB BIT_3 -#define QLCNIC_DUMP_POLLCRB BIT_4 -#define QLCNIC_DUMP_RD_SAVE BIT_5 -#define QLCNIC_DUMP_WRT_SAVED BIT_6 -#define QLCNIC_DUMP_MOD_SAVE_ST BIT_7 -#define QLCNIC_DUMP_SKIP BIT_7 - -#define QLCNIC_DUMP_MASK_MIN 3 #define QLCNIC_DUMP_MASK_DEF 0x1f -#define QLCNIC_DUMP_MASK_MAX 0xff #define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed #define QLCNIC_ENABLE_FW_DUMP 0xaddfeed #define QLCNIC_DISABLE_FW_DUMP 0xbadfeed @@ -1411,12 +1265,6 @@ enum op_codes { #define QLCNIC_SET_QUIESCENT 0xadd00010 #define QLCNIC_RESET_QUIESCENT 0xadd00020 -struct qlcnic_dump_operations { - enum op_codes opcode; - u32 (*handler)(struct qlcnic_adapter *, - struct qlcnic_dump_entry *, u32 *); -}; - struct _cdrp_cmd { u32 cmd; u32 arg1; @@ -1432,7 +1280,7 @@ struct qlcnic_cmd_args { int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter); int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config); -u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off); +int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off); int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *, ulong off, u32 data); int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *, u64 off, u64 data); int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *, u64 off, u64 *data); @@ -1474,6 +1322,8 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int); #define __QLCNIC_MAX_LED_RATE 0xf #define __QLCNIC_MAX_LED_STATE 0x2 +#define MAX_CTL_CHECK 1000 + int qlcnic_get_board_info(struct qlcnic_adapter *adapter); int qlcnic_wol_supported(struct qlcnic_adapter *adapter); int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate); @@ -1496,7 +1346,7 @@ int qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr, int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter); void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter); -void __iomem *qlcnic_get_ioaddr(struct qlcnic_adapter *, u32); +void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *, u32); int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter); void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter); @@ -1530,9 +1380,8 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features); int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable); int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable); int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); -void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, - struct qlcnic_host_tx_ring *tx_ring); -void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *); +void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *); +void qlcnic_fetch_mac(u32, u32, u8, u8 *); void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring); void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter); int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode); @@ -1571,12 +1420,32 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8); int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *); extern int qlcnic_config_tso; +int qlcnic_napi_add(struct qlcnic_adapter *, struct net_device *); +void qlcnic_napi_del(struct qlcnic_adapter *adapter); +void qlcnic_napi_enable(struct qlcnic_adapter *adapter); +void qlcnic_napi_disable(struct qlcnic_adapter *adapter); +int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int); +void qlcnic_free_sds_rings(struct qlcnic_recv_context *); +void qlcnic_free_tx_rings(struct qlcnic_adapter *); +int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *); + +void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter); +void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter); +void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter); +void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); +int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); +int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); +void qlcnic_set_vlan_config(struct qlcnic_adapter *, + struct qlcnic_esw_func_cfg *); +void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *, + struct qlcnic_esw_func_cfg *); + /* * QLOGIC Board information */ #define QLCNIC_MAX_BOARD_NAME_LEN 100 -struct qlcnic_brdinfo { +struct qlcnic_board_info { unsigned short vendor; unsigned short device; unsigned short sub_vendor; @@ -1584,30 +1453,6 @@ struct qlcnic_brdinfo { char short_name[QLCNIC_MAX_BOARD_NAME_LEN]; }; -static const struct qlcnic_brdinfo qlcnic_boards[] = { - {0x1077, 0x8020, 0x1077, 0x203, - "8200 Series Single Port 10GbE Converged Network Adapter " - "(TCP/IP Networking)"}, - {0x1077, 0x8020, 0x1077, 0x207, - "8200 Series Dual Port 10GbE Converged Network Adapter " - "(TCP/IP Networking)"}, - {0x1077, 0x8020, 0x1077, 0x20b, - "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"}, - {0x1077, 0x8020, 0x1077, 0x20c, - "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"}, - {0x1077, 0x8020, 0x1077, 0x20f, - "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"}, - {0x1077, 0x8020, 0x103c, 0x3733, - "NC523SFP 10Gb 2-port Server Adapter"}, - {0x1077, 0x8020, 0x103c, 0x3346, - "CN1000Q Dual Port Converged Network Adapter"}, - {0x1077, 0x8020, 0x1077, 0x210, - "QME8242-k 10GbE Dual Port Mezzanine Card"}, - {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"}, -}; - -#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards) - static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring) { if (likely(tx_ring->producer < tx_ring->sw_consumer)) @@ -1617,6 +1462,21 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring) tx_ring->producer; } +static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring) +{ + writel(0, sds_ring->crb_intr_mask); +} + +static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring) +{ + struct qlcnic_adapter *adapter = sds_ring->adapter; + + writel(0x1, sds_ring->crb_intr_mask); + + if (!QLCNIC_IS_MSI_FAMILY(adapter)) + writel(0xfbff, adapter->tgt_mask_reg); +} + extern const struct ethtool_ops qlcnic_ethtool_ops; extern const struct ethtool_ops qlcnic_ethtool_failed_ops; @@ -1627,10 +1487,17 @@ struct qlcnic_nic_template { }; #define QLCDB(adapter, lvl, _fmt, _args...) do { \ - if (NETIF_MSG_##lvl & adapter->msg_enable) \ + if (NETIF_MSG_##lvl & adapter->ahw->msg_enable) \ printk(KERN_INFO "%s: %s: " _fmt, \ dev_name(&adapter->pdev->dev), \ __func__, ##_args); \ } while (0) +#define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020 +static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) +{ + unsigned short device = adapter->pdev->device; + return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false; +} + #endif /* __QLCNIC_H_ */ diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 2a179d087207..b14b8f0787ea 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -7,6 +7,18 @@ #include "qlcnic.h" +static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func) +{ + int i; + + for (i = 0; i < adapter->ahw->act_pci_func; i++) { + if (adapter->npars[i].pci_func == pci_func) + return i; + } + + return -1; +} + static u32 qlcnic_poll_rsp(struct qlcnic_adapter *adapter) { @@ -35,7 +47,7 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd) struct qlcnic_hardware_context *ahw = adapter->ahw; signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw->pci_func, - adapter->fw_hal_version); + adapter->ahw->fw_hal_version); /* Acquire semaphore before accessing CRB */ if (qlcnic_api_lock(adapter)) { @@ -103,7 +115,7 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd) } -static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size) +static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u32 temp_size) { uint64_t sum = 0; int count = temp_size / sizeof(uint32_t); @@ -117,12 +129,12 @@ static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size) int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) { int err, i; - u16 temp_size; void *tmp_addr; - u32 version, csum, *template, *tmp_buf; + u32 temp_size, version, csum, *template; + __le32 *tmp_buf; struct qlcnic_cmd_args cmd; struct qlcnic_hardware_context *ahw; - struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl; + struct qlcnic_dump_template_hdr *tmpl_hdr; dma_addr_t tmp_addr_t = 0; ahw = adapter->ahw; @@ -138,6 +150,8 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) } temp_size = cmd.rsp.arg2; version = cmd.rsp.arg3; + dev_info(&adapter->pdev->dev, + "minidump template version = 0x%x", version); if (!temp_size) return -EIO; @@ -162,14 +176,6 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) err = -EIO; goto error; } - tmp_tmpl = tmp_addr; - csum = qlcnic_temp_checksum((uint32_t *) tmp_addr, temp_size); - if (csum) { - dev_err(&adapter->pdev->dev, - "Template header checksum validation failed\n"); - err = -EIO; - goto error; - } ahw->fw_dump.tmpl_hdr = vzalloc(temp_size); if (!ahw->fw_dump.tmpl_hdr) { err = -EIO; @@ -180,6 +186,14 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) for (i = 0; i < temp_size/sizeof(u32); i++) *template++ = __le32_to_cpu(*tmp_buf++); + csum = qlcnic_temp_checksum((u32 *)ahw->fw_dump.tmpl_hdr, temp_size); + if (csum) { + dev_err(&adapter->pdev->dev, + "Template header checksum validation failed\n"); + err = -EIO; + goto error; + } + tmpl_hdr = ahw->fw_dump.tmpl_hdr; tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF; ahw->fw_dump.enable = 1; @@ -231,6 +245,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) size_t rq_size, rsp_size; u32 cap, reg, val, reg2; int err; + u16 temp; struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; @@ -267,8 +282,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) cap |= QLCNIC_CAP0_LRO_MSS; - prq->valid_field_offset = offsetof(struct qlcnic_hostrq_rx_ctx, - msix_handler); + temp = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler); + prq->valid_field_offset = cpu_to_le16(temp); prq->txrx_sds_binding = nsds_rings - 1; prq->capabilities[0] = cpu_to_le32(cap); @@ -453,8 +468,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp; - adapter->tx_context_id = - le16_to_cpu(prsp->context_id); + adapter->tx_ring->ctx_id = le16_to_cpu(prsp->context_id); } else { dev_err(&adapter->pdev->dev, "Failed to create tx ctx in firmware%d\n", err); @@ -476,7 +490,7 @@ qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter) struct qlcnic_cmd_args cmd; memset(&cmd, 0, sizeof(cmd)); - cmd.req.arg1 = adapter->tx_context_id; + cmd.req.arg1 = adapter->tx_ring->ctx_id; cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET; cmd.req.arg3 = 0; cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_TX_CTX; @@ -671,7 +685,7 @@ int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) err = cmd.rsp.cmd; if (err == QLCNIC_RCODE_SUCCESS) - qlcnic_fetch_mac(adapter, cmd.rsp.arg1, cmd.rsp.arg2, 0, mac); + qlcnic_fetch_mac(cmd.rsp.arg1, cmd.rsp.arg2, 0, mac); else { dev_err(&adapter->pdev->dev, "Failed to get mac address%d\n", err); @@ -687,10 +701,10 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, { int err; dma_addr_t nic_dma_t; - struct qlcnic_info *nic_info; + struct qlcnic_info_le *nic_info; void *nic_info_addr; struct qlcnic_cmd_args cmd; - size_t nic_size = sizeof(struct qlcnic_info); + size_t nic_size = sizeof(struct qlcnic_info_le); nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, &nic_dma_t, GFP_KERNEL); @@ -745,10 +759,10 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) dma_addr_t nic_dma_t; void *nic_info_addr; struct qlcnic_cmd_args cmd; - struct qlcnic_info *nic_info; - size_t nic_size = sizeof(struct qlcnic_info); + struct qlcnic_info_le *nic_info; + size_t nic_size = sizeof(struct qlcnic_info_le); - if (adapter->op_mode != QLCNIC_MGMT_FUNC) + if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) return err; nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, @@ -796,9 +810,9 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, int err = 0, i; struct qlcnic_cmd_args cmd; dma_addr_t pci_info_dma_t; - struct qlcnic_pci_info *npar; + struct qlcnic_pci_info_le *npar; void *pci_info_addr; - size_t npar_size = sizeof(struct qlcnic_pci_info); + size_t npar_size = sizeof(struct qlcnic_pci_info_le); size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC; pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size, @@ -816,11 +830,14 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, qlcnic_issue_cmd(adapter, &cmd); err = cmd.rsp.cmd; + adapter->ahw->act_pci_func = 0; if (err == QLCNIC_RCODE_SUCCESS) { for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) { pci_info->id = le16_to_cpu(npar->id); pci_info->active = le16_to_cpu(npar->active); pci_info->type = le16_to_cpu(npar->type); + if (pci_info->type == QLCNIC_TYPE_NIC) + adapter->ahw->act_pci_func++; pci_info->default_port = le16_to_cpu(npar->default_port); pci_info->tx_min_bw = @@ -848,8 +865,8 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, u32 arg1; struct qlcnic_cmd_args cmd; - if (adapter->op_mode != QLCNIC_MGMT_FUNC || - !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) + if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC || + !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) return err; arg1 = id | (enable_mirroring ? BIT_4 : 0); @@ -877,8 +894,8 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) { - size_t stats_size = sizeof(struct __qlcnic_esw_statistics); - struct __qlcnic_esw_statistics *stats; + size_t stats_size = sizeof(struct qlcnic_esw_stats_le); + struct qlcnic_esw_stats_le *stats; dma_addr_t stats_dma_t; void *stats_addr; u32 arg1; @@ -888,8 +905,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, if (esw_stats == NULL) return -ENOMEM; - if (adapter->op_mode != QLCNIC_MGMT_FUNC && - func != adapter->ahw->pci_func) { + if ((adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) && + (func != adapter->ahw->pci_func)) { dev_err(&adapter->pdev->dev, "Not privilege to query stats for func=%d", func); return -EIO; @@ -939,9 +956,9 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, struct qlcnic_mac_statistics *mac_stats) { - struct qlcnic_mac_statistics *stats; + struct qlcnic_mac_statistics_le *stats; struct qlcnic_cmd_args cmd; - size_t stats_size = sizeof(struct qlcnic_mac_statistics); + size_t stats_size = sizeof(struct qlcnic_mac_statistics_le); dma_addr_t stats_dma_t; void *stats_addr; int err; @@ -1000,7 +1017,7 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch, if (esw_stats == NULL) return -ENOMEM; - if (adapter->op_mode != QLCNIC_MGMT_FUNC) + if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) return -EIO; if (adapter->npars == NULL) return -EIO; @@ -1015,12 +1032,13 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch, esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL; esw_stats->context_id = eswitch; - for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { + for (i = 0; i < adapter->ahw->act_pci_func; i++) { if (adapter->npars[i].phy_port != eswitch) continue; memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics)); - if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats)) + if (qlcnic_get_port_stats(adapter, adapter->npars[i].pci_func, + rx_tx, &port_stats)) continue; esw_stats->size = port_stats.size; @@ -1051,7 +1069,7 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, u32 arg1; struct qlcnic_cmd_args cmd; - if (adapter->op_mode != QLCNIC_MGMT_FUNC) + if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) return -EIO; if (func_esw == QLCNIC_STATS_PORT) { @@ -1119,15 +1137,18 @@ op_type = 1 for port vlan_id int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, struct qlcnic_esw_func_cfg *esw_cfg) { - int err = -EIO; + int err = -EIO, index; u32 arg1, arg2 = 0; struct qlcnic_cmd_args cmd; u8 pci_func; - if (adapter->op_mode != QLCNIC_MGMT_FUNC) + if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) return err; pci_func = esw_cfg->pci_func; - arg1 = (adapter->npars[pci_func].phy_port & BIT_0); + index = qlcnic_is_valid_nic_func(adapter, pci_func); + if (index < 0) + return err; + arg1 = (adapter->npars[index].phy_port & BIT_0); arg1 |= (pci_func << 8); if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) @@ -1139,7 +1160,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, case QLCNIC_PORT_DEFAULTS: arg1 |= (BIT_4 | BIT_6 | BIT_7); arg2 |= (BIT_0 | BIT_1); - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) + if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) arg2 |= (BIT_2 | BIT_3); if (!(esw_cfg->discard_tagged)) arg1 &= ~BIT_4; @@ -1191,11 +1212,17 @@ qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, struct qlcnic_esw_func_cfg *esw_cfg) { u32 arg1, arg2; + int index; u8 phy_port; - if (adapter->op_mode == QLCNIC_MGMT_FUNC) - phy_port = adapter->npars[esw_cfg->pci_func].phy_port; - else - phy_port = adapter->physical_port; + + if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) { + index = qlcnic_is_valid_nic_func(adapter, esw_cfg->pci_func); + if (index < 0) + return -EIO; + phy_port = adapter->npars[index].phy_port; + } else { + phy_port = adapter->ahw->physical_port; + } arg1 = phy_port; arg1 |= (esw_cfg->pci_func << 8); if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 9e9e78a5c4d7..74b98110c5b4 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -208,9 +208,9 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full); - ethtool_cmd_speed_set(ecmd, adapter->link_speed); - ecmd->duplex = adapter->link_duplex; - ecmd->autoneg = adapter->link_autoneg; + ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed); + ecmd->duplex = adapter->ahw->link_duplex; + ecmd->autoneg = adapter->ahw->link_autoneg; } else if (adapter->ahw->port_type == QLCNIC_XGBE) { u32 val; @@ -224,10 +224,10 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->advertising = ADVERTISED_10000baseT_Full; } - if (netif_running(dev) && adapter->has_link_events) { - ethtool_cmd_speed_set(ecmd, adapter->link_speed); - ecmd->autoneg = adapter->link_autoneg; - ecmd->duplex = adapter->link_duplex; + if (netif_running(dev) && adapter->ahw->has_link_events) { + ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed); + ecmd->autoneg = adapter->ahw->link_autoneg; + ecmd->duplex = adapter->ahw->link_duplex; goto skip; } @@ -238,7 +238,7 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) return -EIO; skip: - ecmd->phy_address = adapter->physical_port; + ecmd->phy_address = adapter->ahw->physical_port; ecmd->transceiver = XCVR_EXTERNAL; switch (adapter->ahw->board_type) { @@ -254,7 +254,7 @@ skip: ecmd->supported |= SUPPORTED_TP; ecmd->advertising |= ADVERTISED_TP; ecmd->port = PORT_TP; - ecmd->autoneg = adapter->link_autoneg; + ecmd->autoneg = adapter->ahw->link_autoneg; break; case QLCNIC_BRDTYPE_P3P_IMEZ: case QLCNIC_BRDTYPE_P3P_XG_LOM: @@ -270,7 +270,7 @@ skip: ecmd->advertising |= ADVERTISED_TP; ecmd->supported |= SUPPORTED_TP; check_sfp_module = netif_running(dev) && - adapter->has_link_events; + adapter->ahw->has_link_events; case QLCNIC_BRDTYPE_P3P_10G_XFP: ecmd->supported |= SUPPORTED_FIBRE; ecmd->advertising |= ADVERTISED_FIBRE; @@ -285,7 +285,7 @@ skip: (ADVERTISED_FIBRE | ADVERTISED_TP); ecmd->port = PORT_FIBRE; check_sfp_module = netif_running(dev) && - adapter->has_link_events; + adapter->ahw->has_link_events; } else { ecmd->autoneg = AUTONEG_ENABLE; ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg); @@ -301,7 +301,7 @@ skip: } if (check_sfp_module) { - switch (adapter->module_type) { + switch (adapter->ahw->module_type) { case LINKEVENT_MODULE_OPTICAL_UNKNOWN: case LINKEVENT_MODULE_OPTICAL_SRLR: case LINKEVENT_MODULE_OPTICAL_LRM: @@ -359,9 +359,9 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) else if (ret) return -EIO; - adapter->link_speed = ethtool_cmd_speed(ecmd); - adapter->link_duplex = ecmd->duplex; - adapter->link_autoneg = ecmd->autoneg; + adapter->ahw->link_speed = ethtool_cmd_speed(ecmd); + adapter->ahw->link_duplex = ecmd->duplex; + adapter->ahw->link_autoneg = ecmd->autoneg; if (!netif_running(dev)) return 0; @@ -508,14 +508,15 @@ qlcnic_set_ringparam(struct net_device *dev, static void qlcnic_get_channels(struct net_device *dev, struct ethtool_channels *channel) { + int min; struct qlcnic_adapter *adapter = netdev_priv(dev); - channel->max_rx = rounddown_pow_of_two(min_t(int, - adapter->max_rx_ques, num_online_cpus())); - channel->max_tx = adapter->max_tx_ques; + min = min_t(int, adapter->ahw->max_rx_ques, num_online_cpus()); + channel->max_rx = rounddown_pow_of_two(min); + channel->max_tx = adapter->ahw->max_tx_ques; channel->rx_count = adapter->max_sds_rings; - channel->tx_count = adapter->max_tx_ques; + channel->tx_count = adapter->ahw->max_tx_ques; } static int qlcnic_set_channels(struct net_device *dev, @@ -543,7 +544,7 @@ qlcnic_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { struct qlcnic_adapter *adapter = netdev_priv(netdev); - int port = adapter->physical_port; + int port = adapter->ahw->physical_port; __u32 val; if (adapter->ahw->port_type == QLCNIC_GBE) { @@ -588,7 +589,7 @@ qlcnic_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { struct qlcnic_adapter *adapter = netdev_priv(netdev); - int port = adapter->physical_port; + int port = adapter->ahw->physical_port; __u32 val; /* read mode */ @@ -703,7 +704,7 @@ static int qlcnic_irq_test(struct net_device *netdev) if (ret) goto clear_it; - adapter->diag_cnt = 0; + adapter->ahw->diag_cnt = 0; memset(&cmd, 0, sizeof(cmd)); cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST; cmd.req.arg1 = adapter->ahw->pci_func; @@ -715,7 +716,7 @@ static int qlcnic_irq_test(struct net_device *netdev) msleep(10); - ret = !adapter->diag_cnt; + ret = !adapter->ahw->diag_cnt; done: qlcnic_diag_free_res(netdev, max_sds_rings); @@ -761,7 +762,7 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) qlcnic_create_loopback_buff(skb->data, adapter->mac_addr); skb_put(skb, QLCNIC_ILB_PKT_SIZE); - adapter->diag_cnt = 0; + adapter->ahw->diag_cnt = 0; qlcnic_xmit_frame(skb, adapter->netdev); loop = 0; @@ -770,11 +771,11 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) qlcnic_process_rcv_ring_diag(sds_ring); if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) break; - } while (!adapter->diag_cnt); + } while (!adapter->ahw->diag_cnt); dev_kfree_skb_any(skb); - if (!adapter->diag_cnt) + if (!adapter->ahw->diag_cnt) QLCDB(adapter, DRV, "LB Test: packet #%d was not received\n", i + 1); else @@ -800,14 +801,15 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode) int loop = 0; int ret; - if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) { + if (!(adapter->ahw->capabilities & + QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) { netdev_info(netdev, "Firmware is not loopback test capable\n"); return -EOPNOTSUPP; } QLCDB(adapter, DRV, "%s loopback test in progress\n", mode == QLCNIC_ILB_MODE ? "internal" : "external"); - if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { + if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { netdev_warn(netdev, "Loopback test not supported for non " "privilege function\n"); return 0; @@ -826,7 +828,7 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode) if (ret) goto free_res; - adapter->diag_cnt = 0; + adapter->ahw->diag_cnt = 0; do { msleep(500); qlcnic_process_rcv_ring_diag(sds_ring); @@ -835,8 +837,8 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode) " configure request\n"); ret = -QLCNIC_FW_NOT_RESPOND; goto free_res; - } else if (adapter->diag_cnt) { - ret = adapter->diag_cnt; + } else if (adapter->ahw->diag_cnt) { + ret = adapter->ahw->diag_cnt; goto free_res; } } while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state)); @@ -1028,7 +1030,7 @@ static int qlcnic_set_led(struct net_device *dev, int max_sds_rings = adapter->max_sds_rings; int err = -EIO, active = 1; - if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { + if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { netdev_warn(dev, "LED test not supported for non " "privilege function\n"); return -EOPNOTSUPP; @@ -1207,14 +1209,14 @@ static u32 qlcnic_get_msglevel(struct net_device *netdev) { struct qlcnic_adapter *adapter = netdev_priv(netdev); - return adapter->msg_enable; + return adapter->ahw->msg_enable; } static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl) { struct qlcnic_adapter *adapter = netdev_priv(netdev); - adapter->msg_enable = msglvl; + adapter->ahw->msg_enable = msglvl; } static int @@ -1247,7 +1249,8 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, void *buffer) { int i, copy_sz; - u32 *hdr_ptr, *data; + u32 *hdr_ptr; + __le32 *data; struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h index 28a6b28192e3..49cc1ac4f057 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h @@ -792,22 +792,6 @@ static const u32 MIU_TEST_READ_DATA[] = { #define QLCNIC_FLASH_SEM2_ULK 0x0013C014 #define QLCNIC_FLASH_LOCK_ID 0x001B2100 -#define QLCNIC_RD_DUMP_REG(addr, bar0, data) do { \ - writel((addr & 0xFFFF0000), (void *) (bar0 + \ - QLCNIC_FW_DUMP_REG1)); \ - readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1)); \ - *data = readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 + \ - LSW(addr))); \ -} while (0) - -#define QLCNIC_WR_DUMP_REG(addr, bar0, data) do { \ - writel((addr & 0xFFFF0000), (void *) (bar0 + \ - QLCNIC_FW_DUMP_REG1)); \ - readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1)); \ - writel(data, (void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr)));\ - readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr))); \ -} while (0) - /* PCI function operational mode */ enum { QLCNIC_MGMT_FUNC = 0, @@ -832,55 +816,63 @@ enum { #define LSD(x) ((uint32_t)((uint64_t)(x))) #define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16)) +#define QLCNIC_MS_CTRL 0x41000090 +#define QLCNIC_MS_ADDR_LO 0x41000094 +#define QLCNIC_MS_ADDR_HI 0x41000098 +#define QLCNIC_MS_WRTDATA_LO 0x410000A0 +#define QLCNIC_MS_WRTDATA_HI 0x410000A4 +#define QLCNIC_MS_WRTDATA_ULO 0x410000B0 +#define QLCNIC_MS_WRTDATA_UHI 0x410000B4 +#define QLCNIC_MS_RDDATA_LO 0x410000A8 +#define QLCNIC_MS_RDDATA_HI 0x410000AC +#define QLCNIC_MS_RDDATA_ULO 0x410000B8 +#define QLCNIC_MS_RDDATA_UHI 0x410000BC + +#define QLCNIC_TA_WRITE_ENABLE (TA_CTL_ENABLE | TA_CTL_WRITE) +#define QLCNIC_TA_WRITE_START (TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE) +#define QLCNIC_TA_START_ENABLE (TA_CTL_START | TA_CTL_ENABLE) + #define QLCNIC_LEGACY_INTR_CONFIG \ { \ { \ .int_vec_bit = PCIX_INT_VECTOR_BIT_F0, \ .tgt_status_reg = ISR_INT_TARGET_STATUS, \ - .tgt_mask_reg = ISR_INT_TARGET_MASK, \ - .pci_int_reg = ISR_MSI_INT_TRIGGER(0) }, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK, }, \ \ { \ .int_vec_bit = PCIX_INT_VECTOR_BIT_F1, \ .tgt_status_reg = ISR_INT_TARGET_STATUS_F1, \ - .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, \ - .pci_int_reg = ISR_MSI_INT_TRIGGER(1) }, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, }, \ \ { \ .int_vec_bit = PCIX_INT_VECTOR_BIT_F2, \ .tgt_status_reg = ISR_INT_TARGET_STATUS_F2, \ - .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, \ - .pci_int_reg = ISR_MSI_INT_TRIGGER(2) }, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, }, \ \ { \ .int_vec_bit = PCIX_INT_VECTOR_BIT_F3, \ .tgt_status_reg = ISR_INT_TARGET_STATUS_F3, \ - .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, \ - .pci_int_reg = ISR_MSI_INT_TRIGGER(3) }, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, }, \ \ { \ .int_vec_bit = PCIX_INT_VECTOR_BIT_F4, \ .tgt_status_reg = ISR_INT_TARGET_STATUS_F4, \ - .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, \ - .pci_int_reg = ISR_MSI_INT_TRIGGER(4) }, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, }, \ \ { \ .int_vec_bit = PCIX_INT_VECTOR_BIT_F5, \ .tgt_status_reg = ISR_INT_TARGET_STATUS_F5, \ - .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, \ - .pci_int_reg = ISR_MSI_INT_TRIGGER(5) }, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, }, \ \ { \ .int_vec_bit = PCIX_INT_VECTOR_BIT_F6, \ .tgt_status_reg = ISR_INT_TARGET_STATUS_F6, \ - .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, \ - .pci_int_reg = ISR_MSI_INT_TRIGGER(6) }, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, }, \ \ { \ .int_vec_bit = PCIX_INT_VECTOR_BIT_F7, \ .tgt_status_reg = ISR_INT_TARGET_STATUS_F7, \ - .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, \ - .pci_int_reg = ISR_MSI_INT_TRIGGER(7) }, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, }, \ } /* NIU REGS */ diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 2a0c9dc48eb3..7a6d5ebe4e0f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c @@ -6,6 +6,7 @@ */ #include "qlcnic.h" +#include "qlcnic_hdr.h" #include <linux/slab.h> #include <net/ip.h> @@ -22,6 +23,15 @@ #define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000)) #define CRB_INDIRECT_2M (0x1e0000UL) +struct qlcnic_ms_reg_ctrl { + u32 ocm_window; + u32 control; + u32 hi; + u32 low; + u32 rd[4]; + u32 wd[4]; + u64 off; +}; #ifndef readq static inline u64 readq(void __iomem *addr) @@ -266,10 +276,44 @@ static const unsigned crb_hub_agt[64] = { 0, }; +static const u32 msi_tgt_status[8] = { + ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1, + ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3, + ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5, + ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7 +}; + /* PCI Windowing for DDR regions. */ #define QLCNIC_PCIE_SEM_TIMEOUT 10000 +static void qlcnic_read_window_reg(u32 addr, void __iomem *bar0, u32 *data) +{ + u32 dest; + void __iomem *val; + + dest = addr & 0xFFFF0000; + val = bar0 + QLCNIC_FW_DUMP_REG1; + writel(dest, val); + readl(val); + val = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr); + *data = readl(val); +} + +static void qlcnic_write_window_reg(u32 addr, void __iomem *bar0, u32 data) +{ + u32 dest; + void __iomem *val; + + dest = addr & 0xFFFF0000; + val = bar0 + QLCNIC_FW_DUMP_REG1; + writel(dest, val); + readl(val); + val = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr); + writel(data, val); + readl(val); +} + int qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg) { @@ -300,11 +344,28 @@ qlcnic_pcie_sem_unlock(struct qlcnic_adapter *adapter, int sem) QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_UNLOCK(sem))); } +static int qlcnic_ind_rd(struct qlcnic_adapter *adapter, u32 addr) +{ + u32 data; + + if (qlcnic_82xx_check(adapter)) + qlcnic_read_window_reg(addr, adapter->ahw->pci_base0, &data); + else + return -EIO; + return data; +} + +static void qlcnic_ind_wr(struct qlcnic_adapter *adapter, u32 addr, u32 data) +{ + if (qlcnic_82xx_check(adapter)) + qlcnic_write_window_reg(addr, adapter->ahw->pci_base0, data); +} + static int qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, struct cmd_desc_type0 *cmd_desc_arr, int nr_desc) { - u32 i, producer, consumer; + u32 i, producer; struct qlcnic_cmd_buffer *pbuf; struct cmd_desc_type0 *cmd_desc; struct qlcnic_host_tx_ring *tx_ring; @@ -318,7 +379,6 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, __netif_tx_lock_bh(tx_ring->txq); producer = tx_ring->producer; - consumer = tx_ring->sw_consumer; if (nr_desc >= qlcnic_tx_avail(tx_ring)) { netif_tx_stop_queue(tx_ring->txq); @@ -341,7 +401,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, pbuf->frag_count = 0; memcpy(&tx_ring->desc_head[producer], - &cmd_desc_arr[i], sizeof(struct cmd_desc_type0)); + cmd_desc, sizeof(struct cmd_desc_type0)); producer = get_next_index(producer, tx_ring->num_desc); i++; @@ -350,7 +410,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, tx_ring->producer = producer; - qlcnic_update_cmd_producer(adapter, tx_ring); + qlcnic_update_cmd_producer(tx_ring); __netif_tx_unlock_bh(tx_ring->txq); @@ -434,7 +494,7 @@ void qlcnic_set_multi(struct net_device *netdev) } if ((netdev->flags & IFF_ALLMULTI) || - (netdev_mc_count(netdev) > adapter->max_mc_count)) { + (netdev_mc_count(netdev) > adapter->ahw->max_mc_count)) { mode = VPORT_MISS_MODE_ACCEPT_MULTI; goto send_fw_cmd; } @@ -540,7 +600,7 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter) } } -int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag) +static int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag) { struct qlcnic_nic_req req; int rv; @@ -863,9 +923,8 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features) * 0 if no window access is needed. 'off' is set to 2M addr * In: 'off' is offset from base in 128M pci map */ -static int -qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter, - ulong off, void __iomem **addr) +static int qlcnic_pci_get_crb_addr_2M(struct qlcnic_hardware_context *ahw, + ulong off, void __iomem **addr) { const struct crb_128M_2M_sub_block_map *m; @@ -880,7 +939,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter, m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)]; if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) { - *addr = adapter->ahw->pci_base0 + m->start_2M + + *addr = ahw->pci_base0 + m->start_2M + (off - m->start_128M); return 0; } @@ -888,7 +947,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter, /* * Not in direct map, use crb window */ - *addr = adapter->ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16)); + *addr = ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16)); return 1; } @@ -929,7 +988,7 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data) int rv; void __iomem *addr = NULL; - rv = qlcnic_pci_get_crb_addr_2M(adapter, off, &addr); + rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr); if (rv == 0) { writel(data, addr); @@ -954,15 +1013,14 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data) return -EIO; } -u32 -qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) +int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) { unsigned long flags; int rv; u32 data = -1; void __iomem *addr = NULL; - rv = qlcnic_pci_get_crb_addr_2M(adapter, off, &addr); + rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr); if (rv == 0) return readl(addr); @@ -985,46 +1043,28 @@ qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) } -void __iomem * -qlcnic_get_ioaddr(struct qlcnic_adapter *adapter, u32 offset) +void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *ahw, + u32 offset) { void __iomem *addr = NULL; - WARN_ON(qlcnic_pci_get_crb_addr_2M(adapter, offset, &addr)); + WARN_ON(qlcnic_pci_get_crb_addr_2M(ahw, offset, &addr)); return addr; } - -static int -qlcnic_pci_set_window_2M(struct qlcnic_adapter *adapter, - u64 addr, u32 *start) -{ - u32 window; - - window = OCM_WIN_P3P(addr); - - writel(window, adapter->ahw->ocm_win_crb); - /* read back to flush */ - readl(adapter->ahw->ocm_win_crb); - - *start = QLCNIC_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr); - return 0; -} - -static int -qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off, - u64 *data, int op) +static int qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, + u32 window, u64 off, u64 *data, int op) { void __iomem *addr; - int ret; u32 start; mutex_lock(&adapter->ahw->mem_lock); - ret = qlcnic_pci_set_window_2M(adapter, off, &start); - if (ret != 0) - goto unlock; + writel(window, adapter->ahw->ocm_win_crb); + /* read back to flush */ + readl(adapter->ahw->ocm_win_crb); + start = QLCNIC_PCI_OCM0_2M + off; addr = adapter->ahw->pci_base0 + start; @@ -1033,10 +1073,12 @@ qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off, else /* write */ writeq(*data, addr); -unlock: - mutex_unlock(&adapter->ahw->mem_lock); + /* Set window to 0 */ + writel(0, adapter->ahw->ocm_win_crb); + readl(adapter->ahw->ocm_win_crb); - return ret; + mutex_unlock(&adapter->ahw->mem_lock); + return 0; } void @@ -1061,54 +1103,74 @@ qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data) mutex_unlock(&adapter->ahw->mem_lock); } -#define MAX_CTL_CHECK 1000 -int -qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter, - u64 off, u64 data) + +/* Set MS memory control data for different adapters */ +static void qlcnic_set_ms_controls(struct qlcnic_adapter *adapter, u64 off, + struct qlcnic_ms_reg_ctrl *ms) +{ + ms->control = QLCNIC_MS_CTRL; + ms->low = QLCNIC_MS_ADDR_LO; + ms->hi = QLCNIC_MS_ADDR_HI; + if (off & 0xf) { + ms->wd[0] = QLCNIC_MS_WRTDATA_LO; + ms->rd[0] = QLCNIC_MS_RDDATA_LO; + ms->wd[1] = QLCNIC_MS_WRTDATA_HI; + ms->rd[1] = QLCNIC_MS_RDDATA_HI; + ms->wd[2] = QLCNIC_MS_WRTDATA_ULO; + ms->wd[3] = QLCNIC_MS_WRTDATA_UHI; + ms->rd[2] = QLCNIC_MS_RDDATA_ULO; + ms->rd[3] = QLCNIC_MS_RDDATA_UHI; + } else { + ms->wd[0] = QLCNIC_MS_WRTDATA_ULO; + ms->rd[0] = QLCNIC_MS_RDDATA_ULO; + ms->wd[1] = QLCNIC_MS_WRTDATA_UHI; + ms->rd[1] = QLCNIC_MS_RDDATA_UHI; + ms->wd[2] = QLCNIC_MS_WRTDATA_LO; + ms->wd[3] = QLCNIC_MS_WRTDATA_HI; + ms->rd[2] = QLCNIC_MS_RDDATA_LO; + ms->rd[3] = QLCNIC_MS_RDDATA_HI; + } + + ms->ocm_window = OCM_WIN_P3P(off); + ms->off = GET_MEM_OFFS_2M(off); +} + +int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data) { - int i, j, ret; + int j, ret = 0; u32 temp, off8; - void __iomem *mem_crb; + struct qlcnic_ms_reg_ctrl ms; /* Only 64-bit aligned access */ if (off & 7) return -EIO; - /* P3 onward, test agent base for MIU and SIU is same */ - if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET, - QLCNIC_ADDR_QDR_NET_MAX)) { - mem_crb = qlcnic_get_ioaddr(adapter, - QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE); - goto correct; - } + memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl)); + if (!(ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET, + QLCNIC_ADDR_QDR_NET_MAX) || + ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, + QLCNIC_ADDR_DDR_NET_MAX))) + return -EIO; - if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) { - mem_crb = qlcnic_get_ioaddr(adapter, - QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE); - goto correct; - } + qlcnic_set_ms_controls(adapter, off, &ms); if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX)) - return qlcnic_pci_mem_access_direct(adapter, off, &data, 1); - - return -EIO; + return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window, + ms.off, &data, 1); -correct: off8 = off & ~0xf; mutex_lock(&adapter->ahw->mem_lock); - writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); - writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); + qlcnic_ind_wr(adapter, ms.low, off8); + qlcnic_ind_wr(adapter, ms.hi, 0); - i = 0; - writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL)); - writel((TA_CTL_START | TA_CTL_ENABLE), - (mem_crb + TEST_AGT_CTRL)); + qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE); + qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_START_ENABLE); for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = readl(mem_crb + TEST_AGT_CTRL); + temp = qlcnic_ind_rd(adapter, ms.control); if ((temp & TA_CTL_BUSY) == 0) break; } @@ -1118,24 +1180,18 @@ correct: goto done; } - i = (off & 0xf) ? 0 : 2; - writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i)), - mem_crb + MIU_TEST_AGT_WRDATA(i)); - writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i+1)), - mem_crb + MIU_TEST_AGT_WRDATA(i+1)); - i = (off & 0xf) ? 2 : 0; - - writel(data & 0xffffffff, - mem_crb + MIU_TEST_AGT_WRDATA(i)); - writel((data >> 32) & 0xffffffff, - mem_crb + MIU_TEST_AGT_WRDATA(i+1)); + /* This is the modify part of read-modify-write */ + qlcnic_ind_wr(adapter, ms.wd[0], qlcnic_ind_rd(adapter, ms.rd[0])); + qlcnic_ind_wr(adapter, ms.wd[1], qlcnic_ind_rd(adapter, ms.rd[1])); + /* This is the write part of read-modify-write */ + qlcnic_ind_wr(adapter, ms.wd[2], data & 0xffffffff); + qlcnic_ind_wr(adapter, ms.wd[3], (data >> 32) & 0xffffffff); - writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL)); - writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE), - (mem_crb + TEST_AGT_CTRL)); + qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_WRITE_ENABLE); + qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_WRITE_START); for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = readl(mem_crb + TEST_AGT_CTRL); + temp = qlcnic_ind_rd(adapter, ms.control); if ((temp & TA_CTL_BUSY) == 0) break; } @@ -1154,52 +1210,41 @@ done: return ret; } -int -qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter, - u64 off, u64 *data) +int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter, u64 off, u64 *data) { int j, ret; u32 temp, off8; u64 val; - void __iomem *mem_crb; + struct qlcnic_ms_reg_ctrl ms; /* Only 64-bit aligned access */ if (off & 7) return -EIO; + if (!(ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET, + QLCNIC_ADDR_QDR_NET_MAX) || + ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, + QLCNIC_ADDR_DDR_NET_MAX))) + return -EIO; - /* P3 onward, test agent base for MIU and SIU is same */ - if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET, - QLCNIC_ADDR_QDR_NET_MAX)) { - mem_crb = qlcnic_get_ioaddr(adapter, - QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE); - goto correct; - } - - if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) { - mem_crb = qlcnic_get_ioaddr(adapter, - QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE); - goto correct; - } + memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl)); + qlcnic_set_ms_controls(adapter, off, &ms); - if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX)) { - return qlcnic_pci_mem_access_direct(adapter, - off, data, 0); - } + if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX)) + return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window, + ms.off, data, 0); - return -EIO; + mutex_lock(&adapter->ahw->mem_lock); -correct: off8 = off & ~0xf; - mutex_lock(&adapter->ahw->mem_lock); + qlcnic_ind_wr(adapter, ms.low, off8); + qlcnic_ind_wr(adapter, ms.hi, 0); - writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); - writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); - writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL)); - writel((TA_CTL_START | TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL)); + qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE); + qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_START_ENABLE); for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = readl(mem_crb + TEST_AGT_CTRL); + temp = qlcnic_ind_rd(adapter, ms.control); if ((temp & TA_CTL_BUSY) == 0) break; } @@ -1210,13 +1255,10 @@ correct: "failed to read through agent\n"); ret = -EIO; } else { - off8 = MIU_TEST_AGT_RDDATA_LO; - if (off & 0xf) - off8 = MIU_TEST_AGT_RDDATA_UPPER_LO; - temp = readl(mem_crb + off8 + 4); + temp = qlcnic_ind_rd(adapter, ms.rd[3]); val = (u64)temp << 32; - val |= readl(mem_crb + off8); + val |= qlcnic_ind_rd(adapter, ms.rd[2]); *data = val; ret = 0; } @@ -1320,469 +1362,3 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) return rv; } - -/* FW dump related functions */ -static u32 -qlcnic_dump_crb(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, - u32 *buffer) -{ - int i; - u32 addr, data; - struct __crb *crb = &entry->region.crb; - void __iomem *base = adapter->ahw->pci_base0; - - addr = crb->addr; - - for (i = 0; i < crb->no_ops; i++) { - QLCNIC_RD_DUMP_REG(addr, base, &data); - *buffer++ = cpu_to_le32(addr); - *buffer++ = cpu_to_le32(data); - addr += crb->stride; - } - return crb->no_ops * 2 * sizeof(u32); -} - -static u32 -qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, - struct qlcnic_dump_entry *entry, u32 *buffer) -{ - int i, k, timeout = 0; - void __iomem *base = adapter->ahw->pci_base0; - u32 addr, data; - u8 opcode, no_ops; - struct __ctrl *ctr = &entry->region.ctrl; - struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr; - - addr = ctr->addr; - no_ops = ctr->no_ops; - - for (i = 0; i < no_ops; i++) { - k = 0; - opcode = 0; - for (k = 0; k < 8; k++) { - if (!(ctr->opcode & (1 << k))) - continue; - switch (1 << k) { - case QLCNIC_DUMP_WCRB: - QLCNIC_WR_DUMP_REG(addr, base, ctr->val1); - break; - case QLCNIC_DUMP_RWCRB: - QLCNIC_RD_DUMP_REG(addr, base, &data); - QLCNIC_WR_DUMP_REG(addr, base, data); - break; - case QLCNIC_DUMP_ANDCRB: - QLCNIC_RD_DUMP_REG(addr, base, &data); - QLCNIC_WR_DUMP_REG(addr, base, - (data & ctr->val2)); - break; - case QLCNIC_DUMP_ORCRB: - QLCNIC_RD_DUMP_REG(addr, base, &data); - QLCNIC_WR_DUMP_REG(addr, base, - (data | ctr->val3)); - break; - case QLCNIC_DUMP_POLLCRB: - while (timeout <= ctr->timeout) { - QLCNIC_RD_DUMP_REG(addr, base, &data); - if ((data & ctr->val2) == ctr->val1) - break; - msleep(1); - timeout++; - } - if (timeout > ctr->timeout) { - dev_info(&adapter->pdev->dev, - "Timed out, aborting poll CRB\n"); - return -EINVAL; - } - break; - case QLCNIC_DUMP_RD_SAVE: - if (ctr->index_a) - addr = t_hdr->saved_state[ctr->index_a]; - QLCNIC_RD_DUMP_REG(addr, base, &data); - t_hdr->saved_state[ctr->index_v] = data; - break; - case QLCNIC_DUMP_WRT_SAVED: - if (ctr->index_v) - data = t_hdr->saved_state[ctr->index_v]; - else - data = ctr->val1; - if (ctr->index_a) - addr = t_hdr->saved_state[ctr->index_a]; - QLCNIC_WR_DUMP_REG(addr, base, data); - break; - case QLCNIC_DUMP_MOD_SAVE_ST: - data = t_hdr->saved_state[ctr->index_v]; - data <<= ctr->shl_val; - data >>= ctr->shr_val; - if (ctr->val2) - data &= ctr->val2; - data |= ctr->val3; - data += ctr->val1; - t_hdr->saved_state[ctr->index_v] = data; - break; - default: - dev_info(&adapter->pdev->dev, - "Unknown opcode\n"); - break; - } - } - addr += ctr->stride; - } - return 0; -} - -static u32 -qlcnic_dump_mux(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, - u32 *buffer) -{ - int loop; - u32 val, data = 0; - struct __mux *mux = &entry->region.mux; - void __iomem *base = adapter->ahw->pci_base0; - - val = mux->val; - for (loop = 0; loop < mux->no_ops; loop++) { - QLCNIC_WR_DUMP_REG(mux->addr, base, val); - QLCNIC_RD_DUMP_REG(mux->read_addr, base, &data); - *buffer++ = cpu_to_le32(val); - *buffer++ = cpu_to_le32(data); - val += mux->val_stride; - } - return 2 * mux->no_ops * sizeof(u32); -} - -static u32 -qlcnic_dump_que(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, - u32 *buffer) -{ - int i, loop; - u32 cnt, addr, data, que_id = 0; - void __iomem *base = adapter->ahw->pci_base0; - struct __queue *que = &entry->region.que; - - addr = que->read_addr; - cnt = que->read_addr_cnt; - - for (loop = 0; loop < que->no_ops; loop++) { - QLCNIC_WR_DUMP_REG(que->sel_addr, base, que_id); - addr = que->read_addr; - for (i = 0; i < cnt; i++) { - QLCNIC_RD_DUMP_REG(addr, base, &data); - *buffer++ = cpu_to_le32(data); - addr += que->read_addr_stride; - } - que_id += que->stride; - } - return que->no_ops * cnt * sizeof(u32); -} - -static u32 -qlcnic_dump_ocm(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, - u32 *buffer) -{ - int i; - u32 data; - void __iomem *addr; - struct __ocm *ocm = &entry->region.ocm; - - addr = adapter->ahw->pci_base0 + ocm->read_addr; - for (i = 0; i < ocm->no_ops; i++) { - data = readl(addr); - *buffer++ = cpu_to_le32(data); - addr += ocm->read_addr_stride; - } - return ocm->no_ops * sizeof(u32); -} - -static u32 -qlcnic_read_rom(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, - u32 *buffer) -{ - int i, count = 0; - u32 fl_addr, size, val, lck_val, addr; - struct __mem *rom = &entry->region.mem; - void __iomem *base = adapter->ahw->pci_base0; - - fl_addr = rom->addr; - size = rom->size/4; -lock_try: - lck_val = readl(base + QLCNIC_FLASH_SEM2_LK); - if (!lck_val && count < MAX_CTL_CHECK) { - msleep(10); - count++; - goto lock_try; - } - writel(adapter->ahw->pci_func, (base + QLCNIC_FLASH_LOCK_ID)); - for (i = 0; i < size; i++) { - addr = fl_addr & 0xFFFF0000; - QLCNIC_WR_DUMP_REG(FLASH_ROM_WINDOW, base, addr); - addr = LSW(fl_addr) + FLASH_ROM_DATA; - QLCNIC_RD_DUMP_REG(addr, base, &val); - fl_addr += 4; - *buffer++ = cpu_to_le32(val); - } - readl(base + QLCNIC_FLASH_SEM2_ULK); - return rom->size; -} - -static u32 -qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter, - struct qlcnic_dump_entry *entry, u32 *buffer) -{ - int i; - u32 cnt, val, data, addr; - void __iomem *base = adapter->ahw->pci_base0; - struct __cache *l1 = &entry->region.cache; - - val = l1->init_tag_val; - - for (i = 0; i < l1->no_ops; i++) { - QLCNIC_WR_DUMP_REG(l1->addr, base, val); - QLCNIC_WR_DUMP_REG(l1->ctrl_addr, base, LSW(l1->ctrl_val)); - addr = l1->read_addr; - cnt = l1->read_addr_num; - while (cnt) { - QLCNIC_RD_DUMP_REG(addr, base, &data); - *buffer++ = cpu_to_le32(data); - addr += l1->read_addr_stride; - cnt--; - } - val += l1->stride; - } - return l1->no_ops * l1->read_addr_num * sizeof(u32); -} - -static u32 -qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter, - struct qlcnic_dump_entry *entry, u32 *buffer) -{ - int i; - u32 cnt, val, data, addr; - u8 poll_mask, poll_to, time_out = 0; - void __iomem *base = adapter->ahw->pci_base0; - struct __cache *l2 = &entry->region.cache; - - val = l2->init_tag_val; - poll_mask = LSB(MSW(l2->ctrl_val)); - poll_to = MSB(MSW(l2->ctrl_val)); - - for (i = 0; i < l2->no_ops; i++) { - QLCNIC_WR_DUMP_REG(l2->addr, base, val); - if (LSW(l2->ctrl_val)) - QLCNIC_WR_DUMP_REG(l2->ctrl_addr, base, - LSW(l2->ctrl_val)); - if (!poll_mask) - goto skip_poll; - do { - QLCNIC_RD_DUMP_REG(l2->ctrl_addr, base, &data); - if (!(data & poll_mask)) - break; - msleep(1); - time_out++; - } while (time_out <= poll_to); - - if (time_out > poll_to) { - dev_err(&adapter->pdev->dev, - "Timeout exceeded in %s, aborting dump\n", - __func__); - return -EINVAL; - } -skip_poll: - addr = l2->read_addr; - cnt = l2->read_addr_num; - while (cnt) { - QLCNIC_RD_DUMP_REG(addr, base, &data); - *buffer++ = cpu_to_le32(data); - addr += l2->read_addr_stride; - cnt--; - } - val += l2->stride; - } - return l2->no_ops * l2->read_addr_num * sizeof(u32); -} - -static u32 -qlcnic_read_memory(struct qlcnic_adapter *adapter, - struct qlcnic_dump_entry *entry, u32 *buffer) -{ - u32 addr, data, test, ret = 0; - int i, reg_read; - struct __mem *mem = &entry->region.mem; - void __iomem *base = adapter->ahw->pci_base0; - - reg_read = mem->size; - addr = mem->addr; - /* check for data size of multiple of 16 and 16 byte alignment */ - if ((addr & 0xf) || (reg_read%16)) { - dev_info(&adapter->pdev->dev, - "Unaligned memory addr:0x%x size:0x%x\n", - addr, reg_read); - return -EINVAL; - } - - mutex_lock(&adapter->ahw->mem_lock); - - while (reg_read != 0) { - QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_LO, base, addr); - QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_HI, base, 0); - QLCNIC_WR_DUMP_REG(MIU_TEST_CTR, base, - TA_CTL_ENABLE | TA_CTL_START); - - for (i = 0; i < MAX_CTL_CHECK; i++) { - QLCNIC_RD_DUMP_REG(MIU_TEST_CTR, base, &test); - if (!(test & TA_CTL_BUSY)) - break; - } - if (i == MAX_CTL_CHECK) { - if (printk_ratelimit()) { - dev_err(&adapter->pdev->dev, - "failed to read through agent\n"); - ret = -EINVAL; - goto out; - } - } - for (i = 0; i < 4; i++) { - QLCNIC_RD_DUMP_REG(MIU_TEST_READ_DATA[i], base, &data); - *buffer++ = cpu_to_le32(data); - } - addr += 16; - reg_read -= 16; - ret += 16; - } -out: - mutex_unlock(&adapter->ahw->mem_lock); - return mem->size; -} - -static u32 -qlcnic_dump_nop(struct qlcnic_adapter *adapter, - struct qlcnic_dump_entry *entry, u32 *buffer) -{ - entry->hdr.flags |= QLCNIC_DUMP_SKIP; - return 0; -} - -struct qlcnic_dump_operations fw_dump_ops[] = { - { QLCNIC_DUMP_NOP, qlcnic_dump_nop }, - { QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb }, - { QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux }, - { QLCNIC_DUMP_QUEUE, qlcnic_dump_que }, - { QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom }, - { QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm }, - { QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl }, - { QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache }, - { QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache }, - { QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache }, - { QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache }, - { QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache }, - { QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache }, - { QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache }, - { QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache }, - { QLCNIC_DUMP_READ_ROM, qlcnic_read_rom }, - { QLCNIC_DUMP_READ_MEM, qlcnic_read_memory }, - { QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl }, - { QLCNIC_DUMP_TLHDR, qlcnic_dump_nop }, - { QLCNIC_DUMP_RDEND, qlcnic_dump_nop }, -}; - -/* Walk the template and collect dump for each entry in the dump template */ -static int -qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry, - u32 size) -{ - int ret = 1; - if (size != entry->hdr.cap_size) { - dev_info(dev, - "Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n", - entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size); - dev_info(dev, "Aborting further dump capture\n"); - ret = 0; - } - return ret; -} - -int qlcnic_dump_fw(struct qlcnic_adapter *adapter) -{ - u32 *buffer; - char mesg[64]; - char *msg[] = {mesg, NULL}; - int i, k, ops_cnt, ops_index, dump_size = 0; - u32 entry_offset, dump, no_entries, buf_offset = 0; - struct qlcnic_dump_entry *entry; - struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; - struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr; - - if (fw_dump->clr) { - dev_info(&adapter->pdev->dev, - "Previous dump not cleared, not capturing dump\n"); - return -EIO; - } - /* Calculate the size for dump data area only */ - for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++) - if (i & tmpl_hdr->drv_cap_mask) - dump_size += tmpl_hdr->cap_sizes[k]; - if (!dump_size) - return -EIO; - - fw_dump->data = vzalloc(dump_size); - if (!fw_dump->data) { - dev_info(&adapter->pdev->dev, - "Unable to allocate (%d KB) for fw dump\n", - dump_size/1024); - return -ENOMEM; - } - buffer = fw_dump->data; - fw_dump->size = dump_size; - no_entries = tmpl_hdr->num_entries; - ops_cnt = ARRAY_SIZE(fw_dump_ops); - entry_offset = tmpl_hdr->offset; - tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION; - tmpl_hdr->sys_info[1] = adapter->fw_version; - - for (i = 0; i < no_entries; i++) { - entry = (void *)tmpl_hdr + entry_offset; - if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) { - entry->hdr.flags |= QLCNIC_DUMP_SKIP; - entry_offset += entry->hdr.offset; - continue; - } - /* Find the handler for this entry */ - ops_index = 0; - while (ops_index < ops_cnt) { - if (entry->hdr.type == fw_dump_ops[ops_index].opcode) - break; - ops_index++; - } - if (ops_index == ops_cnt) { - dev_info(&adapter->pdev->dev, - "Invalid entry type %d, exiting dump\n", - entry->hdr.type); - goto error; - } - /* Collect dump for this entry */ - dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer); - if (dump && !qlcnic_valid_dump_entry(&adapter->pdev->dev, entry, - dump)) - entry->hdr.flags |= QLCNIC_DUMP_SKIP; - buf_offset += entry->hdr.cap_size; - entry_offset += entry->hdr.offset; - buffer = fw_dump->data + buf_offset; - } - if (dump_size != buf_offset) { - dev_info(&adapter->pdev->dev, - "Captured(%d) and expected size(%d) do not match\n", - buf_offset, dump_size); - goto error; - } else { - fw_dump->clr = 1; - snprintf(mesg, sizeof(mesg), "FW_DUMP=%s", - adapter->netdev->name); - dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n", - fw_dump->size); - /* Send a udev event to notify availability of FW dump */ - kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg); - return 0; - } -error: - vfree(fw_dump->data); - return -EINVAL; -} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c index 0bcda9c51e9b..de79cde233de 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c @@ -25,10 +25,6 @@ static unsigned int crb_addr_xform[QLCNIC_MAX_CRB_XFORM]; #define QLCNIC_ADDR_ERROR (0xffffffff) -static void -qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, - struct qlcnic_host_rds_ring *rds_ring); - static int qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter); @@ -250,7 +246,8 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) rds_ring->dma_size = QLCNIC_P3P_RX_JUMBO_BUF_MAX_LEN; - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) + if (adapter->ahw->capabilities & + QLCNIC_FW_CAPABILITY_HW_LRO) rds_ring->dma_size += QLCNIC_LRO_BUFFER_EXTRA; rds_ring->skb_size = @@ -659,7 +656,7 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) { "Not an Ethernet NIC func=%u\n", val); return -EIO; } - adapter->physical_port = (val >> 2); + adapter->ahw->physical_port = (val >> 2); if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo)) timeo = QLCNIC_INIT_TIMEOUT_SECS; @@ -778,15 +775,15 @@ qlcnic_has_mn(struct qlcnic_adapter *adapter) static struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section) { - u32 i; + u32 i, entries; struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0]; - __le32 entries = cpu_to_le32(directory->num_entries); + entries = le32_to_cpu(directory->num_entries); for (i = 0; i < entries; i++) { - __le32 offs = cpu_to_le32(directory->findex) + - (i * cpu_to_le32(directory->entry_size)); - __le32 tab_type = cpu_to_le32(*((u32 *)&unirom[offs] + 8)); + u32 offs = le32_to_cpu(directory->findex) + + i * le32_to_cpu(directory->entry_size); + u32 tab_type = le32_to_cpu(*((__le32 *)&unirom[offs] + 8)); if (tab_type == section) return (struct uni_table_desc *) &unirom[offs]; @@ -802,17 +799,16 @@ qlcnic_validate_header(struct qlcnic_adapter *adapter) { const u8 *unirom = adapter->fw->data; struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0]; - __le32 fw_file_size = adapter->fw->size; - __le32 entries; - __le32 entry_size; - __le32 tab_size; + u32 entries, entry_size, tab_size, fw_file_size; + + fw_file_size = adapter->fw->size; if (fw_file_size < FILEHEADER_SIZE) return -EINVAL; - entries = cpu_to_le32(directory->num_entries); - entry_size = cpu_to_le32(directory->entry_size); - tab_size = cpu_to_le32(directory->findex) + (entries * entry_size); + entries = le32_to_cpu(directory->num_entries); + entry_size = le32_to_cpu(directory->entry_size); + tab_size = le32_to_cpu(directory->findex) + (entries * entry_size); if (fw_file_size < tab_size) return -EINVAL; @@ -825,29 +821,29 @@ qlcnic_validate_bootld(struct qlcnic_adapter *adapter) { struct uni_table_desc *tab_desc; struct uni_data_desc *descr; + u32 offs, tab_size, data_size, idx; const u8 *unirom = adapter->fw->data; - int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + - QLCNIC_UNI_BOOTLD_IDX_OFF)); - __le32 offs; - __le32 tab_size; - __le32 data_size; + __le32 temp; + temp = *((__le32 *)&unirom[adapter->file_prd_off] + + QLCNIC_UNI_BOOTLD_IDX_OFF); + idx = le32_to_cpu(temp); tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD); if (!tab_desc) return -EINVAL; - tab_size = cpu_to_le32(tab_desc->findex) + - (cpu_to_le32(tab_desc->entry_size) * (idx + 1)); + tab_size = le32_to_cpu(tab_desc->findex) + + le32_to_cpu(tab_desc->entry_size) * (idx + 1); if (adapter->fw->size < tab_size) return -EINVAL; - offs = cpu_to_le32(tab_desc->findex) + - (cpu_to_le32(tab_desc->entry_size) * (idx)); + offs = le32_to_cpu(tab_desc->findex) + + le32_to_cpu(tab_desc->entry_size) * idx; descr = (struct uni_data_desc *)&unirom[offs]; - data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size); + data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size); if (adapter->fw->size < data_size) return -EINVAL; @@ -861,27 +857,27 @@ qlcnic_validate_fw(struct qlcnic_adapter *adapter) struct uni_table_desc *tab_desc; struct uni_data_desc *descr; const u8 *unirom = adapter->fw->data; - int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + - QLCNIC_UNI_FIRMWARE_IDX_OFF)); - __le32 offs; - __le32 tab_size; - __le32 data_size; + u32 offs, tab_size, data_size, idx; + __le32 temp; + temp = *((__le32 *)&unirom[adapter->file_prd_off] + + QLCNIC_UNI_FIRMWARE_IDX_OFF); + idx = le32_to_cpu(temp); tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW); if (!tab_desc) return -EINVAL; - tab_size = cpu_to_le32(tab_desc->findex) + - (cpu_to_le32(tab_desc->entry_size) * (idx + 1)); + tab_size = le32_to_cpu(tab_desc->findex) + + le32_to_cpu(tab_desc->entry_size) * (idx + 1); if (adapter->fw->size < tab_size) return -EINVAL; - offs = cpu_to_le32(tab_desc->findex) + - (cpu_to_le32(tab_desc->entry_size) * (idx)); + offs = le32_to_cpu(tab_desc->findex) + + le32_to_cpu(tab_desc->entry_size) * idx; descr = (struct uni_data_desc *)&unirom[offs]; - data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size); + data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size); if (adapter->fw->size < data_size) return -EINVAL; @@ -895,19 +891,17 @@ qlcnic_validate_product_offs(struct qlcnic_adapter *adapter) struct uni_table_desc *ptab_descr; const u8 *unirom = adapter->fw->data; int mn_present = qlcnic_has_mn(adapter); - __le32 entries; - __le32 entry_size; - __le32 tab_size; - u32 i; + u32 entries, entry_size, tab_size, i; + __le32 temp; ptab_descr = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_PRODUCT_TBL); if (!ptab_descr) return -EINVAL; - entries = cpu_to_le32(ptab_descr->num_entries); - entry_size = cpu_to_le32(ptab_descr->entry_size); - tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size); + entries = le32_to_cpu(ptab_descr->num_entries); + entry_size = le32_to_cpu(ptab_descr->entry_size); + tab_size = le32_to_cpu(ptab_descr->findex) + (entries * entry_size); if (adapter->fw->size < tab_size) return -EINVAL; @@ -915,16 +909,16 @@ qlcnic_validate_product_offs(struct qlcnic_adapter *adapter) nomn: for (i = 0; i < entries; i++) { - __le32 flags, file_chiprev, offs; + u32 flags, file_chiprev, offs; u8 chiprev = adapter->ahw->revision_id; u32 flagbit; - offs = cpu_to_le32(ptab_descr->findex) + - (i * cpu_to_le32(ptab_descr->entry_size)); - flags = cpu_to_le32(*((int *)&unirom[offs] + - QLCNIC_UNI_FLAGS_OFF)); - file_chiprev = cpu_to_le32(*((int *)&unirom[offs] + - QLCNIC_UNI_CHIP_REV_OFF)); + offs = le32_to_cpu(ptab_descr->findex) + + i * le32_to_cpu(ptab_descr->entry_size); + temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_FLAGS_OFF); + flags = le32_to_cpu(temp); + temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_CHIP_REV_OFF); + file_chiprev = le32_to_cpu(temp); flagbit = mn_present ? 1 : 2; @@ -976,18 +970,20 @@ struct uni_data_desc *qlcnic_get_data_desc(struct qlcnic_adapter *adapter, u32 section, u32 idx_offset) { const u8 *unirom = adapter->fw->data; - int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + - idx_offset)); struct uni_table_desc *tab_desc; - __le32 offs; + u32 offs, idx; + __le32 temp; + + temp = *((__le32 *)&unirom[adapter->file_prd_off] + idx_offset); + idx = le32_to_cpu(temp); tab_desc = qlcnic_get_table_desc(unirom, section); if (tab_desc == NULL) return NULL; - offs = cpu_to_le32(tab_desc->findex) + - (cpu_to_le32(tab_desc->entry_size) * idx); + offs = le32_to_cpu(tab_desc->findex) + + le32_to_cpu(tab_desc->entry_size) * idx; return (struct uni_data_desc *)&unirom[offs]; } @@ -996,11 +992,13 @@ static u8 * qlcnic_get_bootld_offs(struct qlcnic_adapter *adapter) { u32 offs = QLCNIC_BOOTLD_START; + struct uni_data_desc *data_desc; - if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE) - offs = cpu_to_le32((qlcnic_get_data_desc(adapter, - QLCNIC_UNI_DIR_SECT_BOOTLD, - QLCNIC_UNI_BOOTLD_IDX_OFF))->findex); + data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_BOOTLD, + QLCNIC_UNI_BOOTLD_IDX_OFF); + + if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE) + offs = le32_to_cpu(data_desc->findex); return (u8 *)&adapter->fw->data[offs]; } @@ -1009,43 +1007,48 @@ static u8 * qlcnic_get_fw_offs(struct qlcnic_adapter *adapter) { u32 offs = QLCNIC_IMAGE_START; + struct uni_data_desc *data_desc; - if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE) - offs = cpu_to_le32((qlcnic_get_data_desc(adapter, - QLCNIC_UNI_DIR_SECT_FW, - QLCNIC_UNI_FIRMWARE_IDX_OFF))->findex); + data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW, + QLCNIC_UNI_FIRMWARE_IDX_OFF); + if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE) + offs = le32_to_cpu(data_desc->findex); return (u8 *)&adapter->fw->data[offs]; } -static __le32 -qlcnic_get_fw_size(struct qlcnic_adapter *adapter) +static u32 qlcnic_get_fw_size(struct qlcnic_adapter *adapter) { - if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE) - return cpu_to_le32((qlcnic_get_data_desc(adapter, - QLCNIC_UNI_DIR_SECT_FW, - QLCNIC_UNI_FIRMWARE_IDX_OFF))->size); + struct uni_data_desc *data_desc; + const u8 *unirom = adapter->fw->data; + + data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW, + QLCNIC_UNI_FIRMWARE_IDX_OFF); + + if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE) + return le32_to_cpu(data_desc->size); else - return cpu_to_le32( - *(u32 *)&adapter->fw->data[QLCNIC_FW_SIZE_OFFSET]); + return le32_to_cpu(*(__le32 *)&unirom[QLCNIC_FW_SIZE_OFFSET]); } -static __le32 -qlcnic_get_fw_version(struct qlcnic_adapter *adapter) +static u32 qlcnic_get_fw_version(struct qlcnic_adapter *adapter) { struct uni_data_desc *fw_data_desc; const struct firmware *fw = adapter->fw; - __le32 major, minor, sub; + u32 major, minor, sub; + __le32 version_offset; const u8 *ver_str; int i, ret; - if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE) - return cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET]); + if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) { + version_offset = *(__le32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET]; + return le32_to_cpu(version_offset); + } fw_data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW, QLCNIC_UNI_FIRMWARE_IDX_OFF); - ver_str = fw->data + cpu_to_le32(fw_data_desc->findex) + - cpu_to_le32(fw_data_desc->size) - 17; + ver_str = fw->data + le32_to_cpu(fw_data_desc->findex) + + le32_to_cpu(fw_data_desc->size) - 17; for (i = 0; i < 12; i++) { if (!strncmp(&ver_str[i], "REV=", 4)) { @@ -1061,18 +1064,20 @@ qlcnic_get_fw_version(struct qlcnic_adapter *adapter) return 0; } -static __le32 -qlcnic_get_bios_version(struct qlcnic_adapter *adapter) +static u32 qlcnic_get_bios_version(struct qlcnic_adapter *adapter) { const struct firmware *fw = adapter->fw; - __le32 bios_ver, prd_off = adapter->file_prd_off; + u32 bios_ver, prd_off = adapter->file_prd_off; + u8 *version_offset; + __le32 temp; - if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE) - return cpu_to_le32( - *(u32 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET]); + if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) { + version_offset = (u8 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET]; + return le32_to_cpu(*(__le32 *)version_offset); + } - bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off]) - + QLCNIC_UNI_BIOS_VERSION_OFF)); + temp = *((__le32 *)(&fw->data[prd_off]) + QLCNIC_UNI_BIOS_VERSION_OFF); + bios_ver = le32_to_cpu(temp); return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24); } @@ -1131,24 +1136,24 @@ static const char *fw_name[] = { int qlcnic_load_firmware(struct qlcnic_adapter *adapter) { - u64 *ptr64; + __le64 *ptr64; u32 i, flashaddr, size; const struct firmware *fw = adapter->fw; struct pci_dev *pdev = adapter->pdev; dev_info(&pdev->dev, "loading firmware from %s\n", - fw_name[adapter->fw_type]); + fw_name[adapter->ahw->fw_type]); if (fw) { - __le64 data; + u64 data; size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8; - ptr64 = (u64 *)qlcnic_get_bootld_offs(adapter); + ptr64 = (__le64 *)qlcnic_get_bootld_offs(adapter); flashaddr = QLCNIC_BOOTLD_START; for (i = 0; i < size; i++) { - data = cpu_to_le64(ptr64[i]); + data = le64_to_cpu(ptr64[i]); if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data)) return -EIO; @@ -1156,13 +1161,13 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter) flashaddr += 8; } - size = (__force u32)qlcnic_get_fw_size(adapter) / 8; + size = qlcnic_get_fw_size(adapter) / 8; - ptr64 = (u64 *)qlcnic_get_fw_offs(adapter); + ptr64 = (__le64 *)qlcnic_get_fw_offs(adapter); flashaddr = QLCNIC_IMAGE_START; for (i = 0; i < size; i++) { - data = cpu_to_le64(ptr64[i]); + data = le64_to_cpu(ptr64[i]); if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data)) @@ -1171,9 +1176,9 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter) flashaddr += 8; } - size = (__force u32)qlcnic_get_fw_size(adapter) % 8; + size = qlcnic_get_fw_size(adapter) % 8; if (size) { - data = cpu_to_le64(ptr64[i]); + data = le64_to_cpu(ptr64[i]); if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data)) @@ -1225,11 +1230,11 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter) static int qlcnic_validate_firmware(struct qlcnic_adapter *adapter) { - __le32 val; + u32 val; u32 ver, bios, min_size; struct pci_dev *pdev = adapter->pdev; const struct firmware *fw = adapter->fw; - u8 fw_type = adapter->fw_type; + u8 fw_type = adapter->ahw->fw_type; if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) { if (qlcnic_validate_unified_romimage(adapter)) @@ -1237,8 +1242,8 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter) min_size = QLCNIC_UNI_FW_MIN_SIZE; } else { - val = cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]); - if ((__force u32)val != QLCNIC_BDINFO_MAGIC) + val = le32_to_cpu(*(__le32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]); + if (val != QLCNIC_BDINFO_MAGIC) return -EINVAL; min_size = QLCNIC_FW_MIN_SIZE; @@ -1259,7 +1264,7 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter) val = qlcnic_get_bios_version(adapter); qlcnic_rom_fast_read(adapter, QLCNIC_BIOS_VERSION_OFFSET, (int *)&bios); - if ((__force u32)val != bios) { + if (val != bios) { dev_err(&pdev->dev, "%s: firmware bios is incompatible\n", fw_name[fw_type]); return -EINVAL; @@ -1274,7 +1279,7 @@ qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter) { u8 fw_type; - switch (adapter->fw_type) { + switch (adapter->ahw->fw_type) { case QLCNIC_UNKNOWN_ROMIMAGE: fw_type = QLCNIC_UNIFIED_ROMIMAGE; break; @@ -1285,7 +1290,7 @@ qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter) break; } - adapter->fw_type = fw_type; + adapter->ahw->fw_type = fw_type; } @@ -1295,16 +1300,17 @@ void qlcnic_request_firmware(struct qlcnic_adapter *adapter) struct pci_dev *pdev = adapter->pdev; int rc; - adapter->fw_type = QLCNIC_UNKNOWN_ROMIMAGE; + adapter->ahw->fw_type = QLCNIC_UNKNOWN_ROMIMAGE; next: qlcnic_get_next_fwtype(adapter); - if (adapter->fw_type == QLCNIC_FLASH_ROMIMAGE) { + if (adapter->ahw->fw_type == QLCNIC_FLASH_ROMIMAGE) { adapter->fw = NULL; } else { rc = request_firmware(&adapter->fw, - fw_name[adapter->fw_type], &pdev->dev); + fw_name[adapter->ahw->fw_type], + &pdev->dev); if (rc != 0) goto next; @@ -1324,633 +1330,3 @@ qlcnic_release_firmware(struct qlcnic_adapter *adapter) release_firmware(adapter->fw); adapter->fw = NULL; } - -static void -qlcnic_handle_linkevent(struct qlcnic_adapter *adapter, - struct qlcnic_fw_msg *msg) -{ - u32 cable_OUI; - u16 cable_len; - u16 link_speed; - u8 link_status, module, duplex, autoneg; - u8 lb_status = 0; - struct net_device *netdev = adapter->netdev; - - adapter->has_link_events = 1; - - cable_OUI = msg->body[1] & 0xffffffff; - cable_len = (msg->body[1] >> 32) & 0xffff; - link_speed = (msg->body[1] >> 48) & 0xffff; - - link_status = msg->body[2] & 0xff; - duplex = (msg->body[2] >> 16) & 0xff; - autoneg = (msg->body[2] >> 24) & 0xff; - lb_status = (msg->body[2] >> 32) & 0x3; - - module = (msg->body[2] >> 8) & 0xff; - if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) - dev_info(&netdev->dev, "unsupported cable: OUI 0x%x, " - "length %d\n", cable_OUI, cable_len); - else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) - dev_info(&netdev->dev, "unsupported cable length %d\n", - cable_len); - - if (!link_status && (lb_status == QLCNIC_ILB_MODE || - lb_status == QLCNIC_ELB_MODE)) - adapter->ahw->loopback_state |= QLCNIC_LINKEVENT; - - qlcnic_advert_link_change(adapter, link_status); - - if (duplex == LINKEVENT_FULL_DUPLEX) - adapter->link_duplex = DUPLEX_FULL; - else - adapter->link_duplex = DUPLEX_HALF; - - adapter->module_type = module; - adapter->link_autoneg = autoneg; - - if (link_status) { - adapter->link_speed = link_speed; - } else { - adapter->link_speed = SPEED_UNKNOWN; - adapter->link_duplex = DUPLEX_UNKNOWN; - } -} - -static void -qlcnic_handle_fw_message(int desc_cnt, int index, - struct qlcnic_host_sds_ring *sds_ring) -{ - struct qlcnic_fw_msg msg; - struct status_desc *desc; - struct qlcnic_adapter *adapter; - struct device *dev; - int i = 0, opcode, ret; - - while (desc_cnt > 0 && i < 8) { - desc = &sds_ring->desc_head[index]; - msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]); - msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]); - - index = get_next_index(index, sds_ring->num_desc); - desc_cnt--; - } - - adapter = sds_ring->adapter; - dev = &adapter->pdev->dev; - opcode = qlcnic_get_nic_msg_opcode(msg.body[0]); - - switch (opcode) { - case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE: - qlcnic_handle_linkevent(adapter, &msg); - break; - case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK: - ret = (u32)(msg.body[1]); - switch (ret) { - case 0: - adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE; - break; - case 1: - dev_info(dev, "loopback already in progress\n"); - adapter->diag_cnt = -QLCNIC_TEST_IN_PROGRESS; - break; - case 2: - dev_info(dev, "loopback cable is not connected\n"); - adapter->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN; - break; - default: - dev_info(dev, "loopback configure request failed," - " ret %x\n", ret); - adapter->diag_cnt = -QLCNIC_UNDEFINED_ERROR; - break; - } - break; - default: - break; - } -} - -static int -qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, - struct qlcnic_host_rds_ring *rds_ring, - struct qlcnic_rx_buffer *buffer) -{ - struct sk_buff *skb; - dma_addr_t dma; - struct pci_dev *pdev = adapter->pdev; - - skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size); - if (!skb) { - adapter->stats.skb_alloc_failure++; - return -ENOMEM; - } - - skb_reserve(skb, NET_IP_ALIGN); - - dma = pci_map_single(pdev, skb->data, - rds_ring->dma_size, PCI_DMA_FROMDEVICE); - - if (pci_dma_mapping_error(pdev, dma)) { - adapter->stats.rx_dma_map_error++; - dev_kfree_skb_any(skb); - return -ENOMEM; - } - - buffer->skb = skb; - buffer->dma = dma; - - return 0; -} - -static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, - struct qlcnic_host_rds_ring *rds_ring, u16 index, u16 cksum) -{ - struct qlcnic_rx_buffer *buffer; - struct sk_buff *skb; - - buffer = &rds_ring->rx_buf_arr[index]; - - if (unlikely(buffer->skb == NULL)) { - WARN_ON(1); - return NULL; - } - - pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size, - PCI_DMA_FROMDEVICE); - - skb = buffer->skb; - - if (likely((adapter->netdev->features & NETIF_F_RXCSUM) && - (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) { - adapter->stats.csummed++; - skb->ip_summed = CHECKSUM_UNNECESSARY; - } else { - skb_checksum_none_assert(skb); - } - - buffer->skb = NULL; - - return skb; -} - -static inline int -qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb, - u16 *vlan_tag) -{ - struct ethhdr *eth_hdr; - - if (!__vlan_get_tag(skb, vlan_tag)) { - eth_hdr = (struct ethhdr *) skb->data; - memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2); - skb_pull(skb, VLAN_HLEN); - } - if (!adapter->pvid) - return 0; - - if (*vlan_tag == adapter->pvid) { - /* Outer vlan tag. Packet should follow non-vlan path */ - *vlan_tag = 0xffff; - return 0; - } - if (adapter->flags & QLCNIC_TAGGING_ENABLED) - return 0; - - return -EINVAL; -} - -static struct qlcnic_rx_buffer * -qlcnic_process_rcv(struct qlcnic_adapter *adapter, - struct qlcnic_host_sds_ring *sds_ring, - int ring, u64 sts_data0) -{ - struct net_device *netdev = adapter->netdev; - struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; - struct qlcnic_rx_buffer *buffer; - struct sk_buff *skb; - struct qlcnic_host_rds_ring *rds_ring; - int index, length, cksum, pkt_offset; - u16 vid = 0xffff; - - if (unlikely(ring >= adapter->max_rds_rings)) - return NULL; - - rds_ring = &recv_ctx->rds_rings[ring]; - - index = qlcnic_get_sts_refhandle(sts_data0); - if (unlikely(index >= rds_ring->num_desc)) - return NULL; - - buffer = &rds_ring->rx_buf_arr[index]; - - length = qlcnic_get_sts_totallength(sts_data0); - cksum = qlcnic_get_sts_status(sts_data0); - pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0); - - skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum); - if (!skb) - return buffer; - - if (length > rds_ring->skb_size) - skb_put(skb, rds_ring->skb_size); - else - skb_put(skb, length); - - if (pkt_offset) - skb_pull(skb, pkt_offset); - - if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { - adapter->stats.rxdropped++; - dev_kfree_skb(skb); - return buffer; - } - - skb->protocol = eth_type_trans(skb, netdev); - - if (vid != 0xffff) - __vlan_hwaccel_put_tag(skb, vid); - - napi_gro_receive(&sds_ring->napi, skb); - - adapter->stats.rx_pkts++; - adapter->stats.rxbytes += length; - - return buffer; -} - -#define QLC_TCP_HDR_SIZE 20 -#define QLC_TCP_TS_OPTION_SIZE 12 -#define QLC_TCP_TS_HDR_SIZE (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE) - -static struct qlcnic_rx_buffer * -qlcnic_process_lro(struct qlcnic_adapter *adapter, - struct qlcnic_host_sds_ring *sds_ring, - int ring, u64 sts_data0, u64 sts_data1) -{ - struct net_device *netdev = adapter->netdev; - struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; - struct qlcnic_rx_buffer *buffer; - struct sk_buff *skb; - struct qlcnic_host_rds_ring *rds_ring; - struct iphdr *iph; - struct tcphdr *th; - bool push, timestamp; - int l2_hdr_offset, l4_hdr_offset; - int index; - u16 lro_length, length, data_offset; - u32 seq_number; - u16 vid = 0xffff; - - if (unlikely(ring > adapter->max_rds_rings)) - return NULL; - - rds_ring = &recv_ctx->rds_rings[ring]; - - index = qlcnic_get_lro_sts_refhandle(sts_data0); - if (unlikely(index > rds_ring->num_desc)) - return NULL; - - buffer = &rds_ring->rx_buf_arr[index]; - - timestamp = qlcnic_get_lro_sts_timestamp(sts_data0); - lro_length = qlcnic_get_lro_sts_length(sts_data0); - l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0); - l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0); - push = qlcnic_get_lro_sts_push_flag(sts_data0); - seq_number = qlcnic_get_lro_sts_seq_number(sts_data1); - - skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK); - if (!skb) - return buffer; - - if (timestamp) - data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE; - else - data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE; - - skb_put(skb, lro_length + data_offset); - - skb_pull(skb, l2_hdr_offset); - - if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { - adapter->stats.rxdropped++; - dev_kfree_skb(skb); - return buffer; - } - - skb->protocol = eth_type_trans(skb, netdev); - - iph = (struct iphdr *)skb->data; - th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); - - length = (iph->ihl << 2) + (th->doff << 2) + lro_length; - iph->tot_len = htons(length); - iph->check = 0; - iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); - th->psh = push; - th->seq = htonl(seq_number); - - length = skb->len; - - if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) - skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1); - - if (vid != 0xffff) - __vlan_hwaccel_put_tag(skb, vid); - netif_receive_skb(skb); - - adapter->stats.lro_pkts++; - adapter->stats.lrobytes += length; - - return buffer; -} - -int -qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) -{ - struct qlcnic_adapter *adapter = sds_ring->adapter; - struct list_head *cur; - struct status_desc *desc; - struct qlcnic_rx_buffer *rxbuf; - u64 sts_data0, sts_data1; - - int count = 0; - int opcode, ring, desc_cnt; - u32 consumer = sds_ring->consumer; - - while (count < max) { - desc = &sds_ring->desc_head[consumer]; - sts_data0 = le64_to_cpu(desc->status_desc_data[0]); - - if (!(sts_data0 & STATUS_OWNER_HOST)) - break; - - desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); - opcode = qlcnic_get_sts_opcode(sts_data0); - - switch (opcode) { - case QLCNIC_RXPKT_DESC: - case QLCNIC_OLD_RXPKT_DESC: - case QLCNIC_SYN_OFFLOAD: - ring = qlcnic_get_sts_type(sts_data0); - rxbuf = qlcnic_process_rcv(adapter, sds_ring, - ring, sts_data0); - break; - case QLCNIC_LRO_DESC: - ring = qlcnic_get_lro_sts_type(sts_data0); - sts_data1 = le64_to_cpu(desc->status_desc_data[1]); - rxbuf = qlcnic_process_lro(adapter, sds_ring, - ring, sts_data0, sts_data1); - break; - case QLCNIC_RESPONSE_DESC: - qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring); - default: - goto skip; - } - - WARN_ON(desc_cnt > 1); - - if (likely(rxbuf)) - list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); - else - adapter->stats.null_rxbuf++; - -skip: - for (; desc_cnt > 0; desc_cnt--) { - desc = &sds_ring->desc_head[consumer]; - desc->status_desc_data[0] = - cpu_to_le64(STATUS_OWNER_PHANTOM); - consumer = get_next_index(consumer, sds_ring->num_desc); - } - count++; - } - - for (ring = 0; ring < adapter->max_rds_rings; ring++) { - struct qlcnic_host_rds_ring *rds_ring = - &adapter->recv_ctx->rds_rings[ring]; - - if (!list_empty(&sds_ring->free_list[ring])) { - list_for_each(cur, &sds_ring->free_list[ring]) { - rxbuf = list_entry(cur, - struct qlcnic_rx_buffer, list); - qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf); - } - spin_lock(&rds_ring->lock); - list_splice_tail_init(&sds_ring->free_list[ring], - &rds_ring->free_list); - spin_unlock(&rds_ring->lock); - } - - qlcnic_post_rx_buffers_nodb(adapter, rds_ring); - } - - if (count) { - sds_ring->consumer = consumer; - writel(consumer, sds_ring->crb_sts_consumer); - } - - return count; -} - -void -qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, - struct qlcnic_host_rds_ring *rds_ring) -{ - struct rcv_desc *pdesc; - struct qlcnic_rx_buffer *buffer; - int count = 0; - u32 producer; - struct list_head *head; - - producer = rds_ring->producer; - - head = &rds_ring->free_list; - while (!list_empty(head)) { - - buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); - - if (!buffer->skb) { - if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) - break; - } - - count++; - list_del(&buffer->list); - - /* make a rcv descriptor */ - pdesc = &rds_ring->desc_head[producer]; - pdesc->addr_buffer = cpu_to_le64(buffer->dma); - pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); - pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); - - producer = get_next_index(producer, rds_ring->num_desc); - } - - if (count) { - rds_ring->producer = producer; - writel((producer-1) & (rds_ring->num_desc-1), - rds_ring->crb_rcv_producer); - } -} - -static void -qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, - struct qlcnic_host_rds_ring *rds_ring) -{ - struct rcv_desc *pdesc; - struct qlcnic_rx_buffer *buffer; - int count = 0; - uint32_t producer; - struct list_head *head; - - if (!spin_trylock(&rds_ring->lock)) - return; - - producer = rds_ring->producer; - - head = &rds_ring->free_list; - while (!list_empty(head)) { - - buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); - - if (!buffer->skb) { - if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) - break; - } - - count++; - list_del(&buffer->list); - - /* make a rcv descriptor */ - pdesc = &rds_ring->desc_head[producer]; - pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); - pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); - pdesc->addr_buffer = cpu_to_le64(buffer->dma); - - producer = get_next_index(producer, rds_ring->num_desc); - } - - if (count) { - rds_ring->producer = producer; - writel((producer - 1) & (rds_ring->num_desc - 1), - rds_ring->crb_rcv_producer); - } - spin_unlock(&rds_ring->lock); -} - -static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter) -{ - int i; - unsigned char *data = skb->data; - - printk(KERN_INFO "\n"); - for (i = 0; i < skb->len; i++) { - QLCDB(adapter, DRV, "%02x ", data[i]); - if ((i & 0x0f) == 8) - printk(KERN_INFO "\n"); - } -} - -void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, - struct qlcnic_host_sds_ring *sds_ring, - int ring, u64 sts_data0) -{ - struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; - struct sk_buff *skb; - struct qlcnic_host_rds_ring *rds_ring; - int index, length, cksum, pkt_offset; - - if (unlikely(ring >= adapter->max_rds_rings)) - return; - - rds_ring = &recv_ctx->rds_rings[ring]; - - index = qlcnic_get_sts_refhandle(sts_data0); - length = qlcnic_get_sts_totallength(sts_data0); - if (unlikely(index >= rds_ring->num_desc)) - return; - - cksum = qlcnic_get_sts_status(sts_data0); - pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0); - - skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum); - if (!skb) - return; - - if (length > rds_ring->skb_size) - skb_put(skb, rds_ring->skb_size); - else - skb_put(skb, length); - - if (pkt_offset) - skb_pull(skb, pkt_offset); - - if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr)) - adapter->diag_cnt++; - else - dump_skb(skb, adapter); - - dev_kfree_skb_any(skb); - adapter->stats.rx_pkts++; - adapter->stats.rxbytes += length; - - return; -} - -void -qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) -{ - struct qlcnic_adapter *adapter = sds_ring->adapter; - struct status_desc *desc; - u64 sts_data0; - int ring, opcode, desc_cnt; - - u32 consumer = sds_ring->consumer; - - desc = &sds_ring->desc_head[consumer]; - sts_data0 = le64_to_cpu(desc->status_desc_data[0]); - - if (!(sts_data0 & STATUS_OWNER_HOST)) - return; - - desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); - opcode = qlcnic_get_sts_opcode(sts_data0); - switch (opcode) { - case QLCNIC_RESPONSE_DESC: - qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring); - break; - default: - ring = qlcnic_get_sts_type(sts_data0); - qlcnic_process_rcv_diag(adapter, sds_ring, ring, sts_data0); - break; - } - - for (; desc_cnt > 0; desc_cnt--) { - desc = &sds_ring->desc_head[consumer]; - desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM); - consumer = get_next_index(consumer, sds_ring->num_desc); - } - - sds_ring->consumer = consumer; - writel(consumer, sds_ring->crb_sts_consumer); -} - -void -qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2, - u8 alt_mac, u8 *mac) -{ - u32 mac_low, mac_high; - int i; - - mac_low = off1; - mac_high = off2; - - if (alt_mac) { - mac_low |= (mac_low >> 16) | (mac_high << 16); - mac_high >>= 16; - } - - for (i = 0; i < 2; i++) - mac[i] = (u8)(mac_high >> ((1 - i) * 8)); - for (i = 2; i < 6; i++) - mac[i] = (u8)(mac_low >> ((5 - i) * 8)); -} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c new file mode 100644 index 000000000000..6f82812d0fab --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c @@ -0,0 +1,1309 @@ +#include <linux/netdevice.h> +#include <linux/if_vlan.h> +#include <net/ip.h> +#include <linux/ipv6.h> + +#include "qlcnic.h" + +#define QLCNIC_MAC_HASH(MAC)\ + ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25)) + +#define TX_ETHER_PKT 0x01 +#define TX_TCP_PKT 0x02 +#define TX_UDP_PKT 0x03 +#define TX_IP_PKT 0x04 +#define TX_TCP_LSO 0x05 +#define TX_TCP_LSO6 0x06 +#define TX_TCPV6_PKT 0x0b +#define TX_UDPV6_PKT 0x0c +#define FLAGS_VLAN_TAGGED 0x10 +#define FLAGS_VLAN_OOB 0x40 + +#define qlcnic_set_tx_vlan_tci(cmd_desc, v) \ + (cmd_desc)->vlan_TCI = cpu_to_le16(v); +#define qlcnic_set_cmd_desc_port(cmd_desc, var) \ + ((cmd_desc)->port_ctxid |= ((var) & 0x0F)) +#define qlcnic_set_cmd_desc_ctxid(cmd_desc, var) \ + ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0)) + +#define qlcnic_set_tx_port(_desc, _port) \ + ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)) + +#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \ + ((_desc)->flags_opcode |= \ + cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))) + +#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \ + ((_desc)->nfrags__length = \ + cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8))) + +/* owner bits of status_desc */ +#define STATUS_OWNER_HOST (0x1ULL << 56) +#define STATUS_OWNER_PHANTOM (0x2ULL << 56) + +/* Status descriptor: + 0-3 port, 4-7 status, 8-11 type, 12-27 total_length + 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset + 53-55 desc_cnt, 56-57 owner, 58-63 opcode + */ +#define qlcnic_get_sts_port(sts_data) \ + ((sts_data) & 0x0F) +#define qlcnic_get_sts_status(sts_data) \ + (((sts_data) >> 4) & 0x0F) +#define qlcnic_get_sts_type(sts_data) \ + (((sts_data) >> 8) & 0x0F) +#define qlcnic_get_sts_totallength(sts_data) \ + (((sts_data) >> 12) & 0xFFFF) +#define qlcnic_get_sts_refhandle(sts_data) \ + (((sts_data) >> 28) & 0xFFFF) +#define qlcnic_get_sts_prot(sts_data) \ + (((sts_data) >> 44) & 0x0F) +#define qlcnic_get_sts_pkt_offset(sts_data) \ + (((sts_data) >> 48) & 0x1F) +#define qlcnic_get_sts_desc_cnt(sts_data) \ + (((sts_data) >> 53) & 0x7) +#define qlcnic_get_sts_opcode(sts_data) \ + (((sts_data) >> 58) & 0x03F) + +#define qlcnic_get_lro_sts_refhandle(sts_data) \ + ((sts_data) & 0x07FFF) +#define qlcnic_get_lro_sts_length(sts_data) \ + (((sts_data) >> 16) & 0x0FFFF) +#define qlcnic_get_lro_sts_l2_hdr_offset(sts_data) \ + (((sts_data) >> 32) & 0x0FF) +#define qlcnic_get_lro_sts_l4_hdr_offset(sts_data) \ + (((sts_data) >> 40) & 0x0FF) +#define qlcnic_get_lro_sts_timestamp(sts_data) \ + (((sts_data) >> 48) & 0x1) +#define qlcnic_get_lro_sts_type(sts_data) \ + (((sts_data) >> 49) & 0x7) +#define qlcnic_get_lro_sts_push_flag(sts_data) \ + (((sts_data) >> 52) & 0x1) +#define qlcnic_get_lro_sts_seq_number(sts_data) \ + ((sts_data) & 0x0FFFFFFFF) +#define qlcnic_get_lro_sts_mss(sts_data1) \ + ((sts_data1 >> 32) & 0x0FFFF) + +/* opcode field in status_desc */ +#define QLCNIC_SYN_OFFLOAD 0x03 +#define QLCNIC_RXPKT_DESC 0x04 +#define QLCNIC_OLD_RXPKT_DESC 0x3f +#define QLCNIC_RESPONSE_DESC 0x05 +#define QLCNIC_LRO_DESC 0x12 + +/* for status field in status_desc */ +#define STATUS_CKSUM_LOOP 0 +#define STATUS_CKSUM_OK 2 + +static void qlcnic_change_filter(struct qlcnic_adapter *adapter, + u64 uaddr, __le16 vlan_id, + struct qlcnic_host_tx_ring *tx_ring) +{ + struct cmd_desc_type0 *hwdesc; + struct qlcnic_nic_req *req; + struct qlcnic_mac_req *mac_req; + struct qlcnic_vlan_req *vlan_req; + u32 producer; + u64 word; + + producer = tx_ring->producer; + hwdesc = &tx_ring->desc_head[tx_ring->producer]; + + req = (struct qlcnic_nic_req *)hwdesc; + memset(req, 0, sizeof(struct qlcnic_nic_req)); + req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23); + + word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16); + req->req_hdr = cpu_to_le64(word); + + mac_req = (struct qlcnic_mac_req *)&(req->words[0]); + mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD; + memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN); + + vlan_req = (struct qlcnic_vlan_req *)&req->words[1]; + vlan_req->vlan_id = vlan_id; + + tx_ring->producer = get_next_index(producer, tx_ring->num_desc); + smp_mb(); +} + +static void qlcnic_send_filter(struct qlcnic_adapter *adapter, + struct qlcnic_host_tx_ring *tx_ring, + struct cmd_desc_type0 *first_desc, + struct sk_buff *skb) +{ + struct ethhdr *phdr = (struct ethhdr *)(skb->data); + struct qlcnic_filter *fil, *tmp_fil; + struct hlist_node *tmp_hnode, *n; + struct hlist_head *head; + u64 src_addr = 0; + __le16 vlan_id = 0; + u8 hindex; + + if (ether_addr_equal(phdr->h_source, adapter->mac_addr)) + return; + + if (adapter->fhash.fnum >= adapter->fhash.fmax) + return; + + /* Only NPAR capable devices support vlan based learning*/ + if (adapter->flags & QLCNIC_ESWITCH_ENABLED) + vlan_id = first_desc->vlan_TCI; + memcpy(&src_addr, phdr->h_source, ETH_ALEN); + hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1); + head = &(adapter->fhash.fhead[hindex]); + + hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { + if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) && + tmp_fil->vlan_id == vlan_id) { + + if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime)) + qlcnic_change_filter(adapter, src_addr, vlan_id, + tx_ring); + tmp_fil->ftime = jiffies; + return; + } + } + + fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC); + if (!fil) + return; + + qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring); + + fil->ftime = jiffies; + fil->vlan_id = vlan_id; + memcpy(fil->faddr, &src_addr, ETH_ALEN); + + spin_lock(&adapter->mac_learn_lock); + + hlist_add_head(&(fil->fnode), head); + adapter->fhash.fnum++; + + spin_unlock(&adapter->mac_learn_lock); +} + +static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter, + struct cmd_desc_type0 *first_desc, struct sk_buff *skb) +{ + u8 l4proto, opcode = 0, hdr_len = 0; + u16 flags = 0, vlan_tci = 0; + int copied, offset, copy_len, size; + struct cmd_desc_type0 *hwdesc; + struct vlan_ethhdr *vh; + struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; + u16 protocol = ntohs(skb->protocol); + u32 producer = tx_ring->producer; + + if (protocol == ETH_P_8021Q) { + vh = (struct vlan_ethhdr *)skb->data; + flags = FLAGS_VLAN_TAGGED; + vlan_tci = ntohs(vh->h_vlan_TCI); + protocol = ntohs(vh->h_vlan_encapsulated_proto); + } else if (vlan_tx_tag_present(skb)) { + flags = FLAGS_VLAN_OOB; + vlan_tci = vlan_tx_tag_get(skb); + } + if (unlikely(adapter->pvid)) { + if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED)) + return -EIO; + if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED)) + goto set_flags; + + flags = FLAGS_VLAN_OOB; + vlan_tci = adapter->pvid; + } +set_flags: + qlcnic_set_tx_vlan_tci(first_desc, vlan_tci); + qlcnic_set_tx_flags_opcode(first_desc, flags, opcode); + + if (*(skb->data) & BIT_0) { + flags |= BIT_0; + memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN); + } + opcode = TX_ETHER_PKT; + if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && + skb_shinfo(skb)->gso_size > 0) { + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); + first_desc->total_hdr_length = hdr_len; + opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO; + + /* For LSO, we need to copy the MAC/IP/TCP headers into + * the descriptor ring */ + copied = 0; + offset = 2; + + if (flags & FLAGS_VLAN_OOB) { + first_desc->total_hdr_length += VLAN_HLEN; + first_desc->tcp_hdr_offset = VLAN_HLEN; + first_desc->ip_hdr_offset = VLAN_HLEN; + + /* Only in case of TSO on vlan device */ + flags |= FLAGS_VLAN_TAGGED; + + /* Create a TSO vlan header template for firmware */ + hwdesc = &tx_ring->desc_head[producer]; + tx_ring->cmd_buf_arr[producer].skb = NULL; + + copy_len = min((int)sizeof(struct cmd_desc_type0) - + offset, hdr_len + VLAN_HLEN); + + vh = (struct vlan_ethhdr *)((char *) hwdesc + 2); + skb_copy_from_linear_data(skb, vh, 12); + vh->h_vlan_proto = htons(ETH_P_8021Q); + vh->h_vlan_TCI = htons(vlan_tci); + + skb_copy_from_linear_data_offset(skb, 12, + (char *)vh + 16, + copy_len - 16); + copied = copy_len - VLAN_HLEN; + offset = 0; + producer = get_next_index(producer, tx_ring->num_desc); + } + + while (copied < hdr_len) { + size = (int)sizeof(struct cmd_desc_type0) - offset; + copy_len = min(size, (hdr_len - copied)); + hwdesc = &tx_ring->desc_head[producer]; + tx_ring->cmd_buf_arr[producer].skb = NULL; + skb_copy_from_linear_data_offset(skb, copied, + (char *)hwdesc + + offset, copy_len); + copied += copy_len; + offset = 0; + producer = get_next_index(producer, tx_ring->num_desc); + } + + tx_ring->producer = producer; + smp_mb(); + adapter->stats.lso_frames++; + + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (protocol == ETH_P_IP) { + l4proto = ip_hdr(skb)->protocol; + + if (l4proto == IPPROTO_TCP) + opcode = TX_TCP_PKT; + else if (l4proto == IPPROTO_UDP) + opcode = TX_UDP_PKT; + } else if (protocol == ETH_P_IPV6) { + l4proto = ipv6_hdr(skb)->nexthdr; + + if (l4proto == IPPROTO_TCP) + opcode = TX_TCPV6_PKT; + else if (l4proto == IPPROTO_UDP) + opcode = TX_UDPV6_PKT; + } + } + first_desc->tcp_hdr_offset += skb_transport_offset(skb); + first_desc->ip_hdr_offset += skb_network_offset(skb); + qlcnic_set_tx_flags_opcode(first_desc, flags, opcode); + + return 0; +} + +static int qlcnic_map_tx_skb(struct pci_dev *pdev, struct sk_buff *skb, + struct qlcnic_cmd_buffer *pbuf) +{ + struct qlcnic_skb_frag *nf; + struct skb_frag_struct *frag; + int i, nr_frags; + dma_addr_t map; + + nr_frags = skb_shinfo(skb)->nr_frags; + nf = &pbuf->frag_array[0]; + + map = pci_map_single(pdev, skb->data, skb_headlen(skb), + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, map)) + goto out_err; + + nf->dma = map; + nf->length = skb_headlen(skb); + + for (i = 0; i < nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + nf = &pbuf->frag_array[i+1]; + map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag), + DMA_TO_DEVICE); + if (dma_mapping_error(&pdev->dev, map)) + goto unwind; + + nf->dma = map; + nf->length = skb_frag_size(frag); + } + + return 0; + +unwind: + while (--i >= 0) { + nf = &pbuf->frag_array[i+1]; + pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); + } + + nf = &pbuf->frag_array[0]; + pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); + +out_err: + return -ENOMEM; +} + +static void qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb, + struct qlcnic_cmd_buffer *pbuf) +{ + struct qlcnic_skb_frag *nf = &pbuf->frag_array[0]; + int i, nr_frags = skb_shinfo(skb)->nr_frags; + + for (i = 0; i < nr_frags; i++) { + nf = &pbuf->frag_array[i+1]; + pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); + } + + nf = &pbuf->frag_array[0]; + pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); + pbuf->skb = NULL; +} + +static inline void qlcnic_clear_cmddesc(u64 *desc) +{ + desc[0] = 0ULL; + desc[2] = 0ULL; + desc[7] = 0ULL; +} + +netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; + struct qlcnic_cmd_buffer *pbuf; + struct qlcnic_skb_frag *buffrag; + struct cmd_desc_type0 *hwdesc, *first_desc; + struct pci_dev *pdev; + struct ethhdr *phdr; + int i, k, frag_count, delta = 0; + u32 producer, num_txd; + + num_txd = tx_ring->num_desc; + + if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { + netif_stop_queue(netdev); + return NETDEV_TX_BUSY; + } + + if (adapter->flags & QLCNIC_MACSPOOF) { + phdr = (struct ethhdr *)skb->data; + if (!ether_addr_equal(phdr->h_source, adapter->mac_addr)) + goto drop_packet; + } + + frag_count = skb_shinfo(skb)->nr_frags + 1; + /* 14 frags supported for normal packet and + * 32 frags supported for TSO packet + */ + if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) { + for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++) + delta += skb_frag_size(&skb_shinfo(skb)->frags[i]); + + if (!__pskb_pull_tail(skb, delta)) + goto drop_packet; + + frag_count = 1 + skb_shinfo(skb)->nr_frags; + } + + if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) { + netif_stop_queue(netdev); + if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { + netif_start_queue(netdev); + } else { + adapter->stats.xmit_off++; + return NETDEV_TX_BUSY; + } + } + + producer = tx_ring->producer; + pbuf = &tx_ring->cmd_buf_arr[producer]; + pdev = adapter->pdev; + first_desc = &tx_ring->desc_head[producer]; + hwdesc = &tx_ring->desc_head[producer]; + qlcnic_clear_cmddesc((u64 *)hwdesc); + + if (qlcnic_map_tx_skb(pdev, skb, pbuf)) { + adapter->stats.tx_dma_map_error++; + goto drop_packet; + } + + pbuf->skb = skb; + pbuf->frag_count = frag_count; + + qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len); + qlcnic_set_tx_port(first_desc, adapter->portnum); + + for (i = 0; i < frag_count; i++) { + k = i % 4; + + if ((k == 0) && (i > 0)) { + /* move to next desc.*/ + producer = get_next_index(producer, num_txd); + hwdesc = &tx_ring->desc_head[producer]; + qlcnic_clear_cmddesc((u64 *)hwdesc); + tx_ring->cmd_buf_arr[producer].skb = NULL; + } + + buffrag = &pbuf->frag_array[i]; + hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length); + switch (k) { + case 0: + hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); + break; + case 1: + hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma); + break; + case 2: + hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma); + break; + case 3: + hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma); + break; + } + } + + tx_ring->producer = get_next_index(producer, num_txd); + smp_mb(); + + if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb))) + goto unwind_buff; + + if (adapter->mac_learn) + qlcnic_send_filter(adapter, tx_ring, first_desc, skb); + + adapter->stats.txbytes += skb->len; + adapter->stats.xmitcalled++; + + qlcnic_update_cmd_producer(tx_ring); + + return NETDEV_TX_OK; + +unwind_buff: + qlcnic_unmap_buffers(pdev, skb, pbuf); +drop_packet: + adapter->stats.txdropped++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} + +void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup) +{ + struct net_device *netdev = adapter->netdev; + + if (adapter->ahw->linkup && !linkup) { + netdev_info(netdev, "NIC Link is down\n"); + adapter->ahw->linkup = 0; + if (netif_running(netdev)) { + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + } else if (!adapter->ahw->linkup && linkup) { + netdev_info(netdev, "NIC Link is up\n"); + adapter->ahw->linkup = 1; + if (netif_running(netdev)) { + netif_carrier_on(netdev); + netif_wake_queue(netdev); + } + } +} + +static int qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, + struct qlcnic_host_rds_ring *rds_ring, + struct qlcnic_rx_buffer *buffer) +{ + struct sk_buff *skb; + dma_addr_t dma; + struct pci_dev *pdev = adapter->pdev; + + skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size); + if (!skb) { + adapter->stats.skb_alloc_failure++; + return -ENOMEM; + } + + skb_reserve(skb, NET_IP_ALIGN); + dma = pci_map_single(pdev, skb->data, rds_ring->dma_size, + PCI_DMA_FROMDEVICE); + + if (pci_dma_mapping_error(pdev, dma)) { + adapter->stats.rx_dma_map_error++; + dev_kfree_skb_any(skb); + return -ENOMEM; + } + + buffer->skb = skb; + buffer->dma = dma; + + return 0; +} + +static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, + struct qlcnic_host_rds_ring *rds_ring) +{ + struct rcv_desc *pdesc; + struct qlcnic_rx_buffer *buffer; + int count = 0; + uint32_t producer; + struct list_head *head; + + if (!spin_trylock(&rds_ring->lock)) + return; + + producer = rds_ring->producer; + head = &rds_ring->free_list; + + while (!list_empty(head)) { + buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); + + if (!buffer->skb) { + if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) + break; + } + + count++; + list_del(&buffer->list); + + /* make a rcv descriptor */ + pdesc = &rds_ring->desc_head[producer]; + pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); + pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); + pdesc->addr_buffer = cpu_to_le64(buffer->dma); + producer = get_next_index(producer, rds_ring->num_desc); + } + + if (count) { + rds_ring->producer = producer; + writel((producer - 1) & (rds_ring->num_desc - 1), + rds_ring->crb_rcv_producer); + } + + spin_unlock(&rds_ring->lock); +} + +static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) +{ + u32 sw_consumer, hw_consumer; + int i, done, count = 0; + struct qlcnic_cmd_buffer *buffer; + struct pci_dev *pdev = adapter->pdev; + struct net_device *netdev = adapter->netdev; + struct qlcnic_skb_frag *frag; + struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; + + if (!spin_trylock(&adapter->tx_clean_lock)) + return 1; + + sw_consumer = tx_ring->sw_consumer; + hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); + + while (sw_consumer != hw_consumer) { + buffer = &tx_ring->cmd_buf_arr[sw_consumer]; + if (buffer->skb) { + frag = &buffer->frag_array[0]; + pci_unmap_single(pdev, frag->dma, frag->length, + PCI_DMA_TODEVICE); + frag->dma = 0ULL; + for (i = 1; i < buffer->frag_count; i++) { + frag++; + pci_unmap_page(pdev, frag->dma, frag->length, + PCI_DMA_TODEVICE); + frag->dma = 0ULL; + } + + adapter->stats.xmitfinished++; + dev_kfree_skb_any(buffer->skb); + buffer->skb = NULL; + } + + sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc); + if (++count >= MAX_STATUS_HANDLE) + break; + } + + if (count && netif_running(netdev)) { + tx_ring->sw_consumer = sw_consumer; + + smp_mb(); + + if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { + if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { + netif_wake_queue(netdev); + adapter->stats.xmit_on++; + } + } + adapter->tx_timeo_cnt = 0; + } + /* + * If everything is freed up to consumer then check if the ring is full + * If the ring is full then check if more needs to be freed and + * schedule the call back again. + * + * This happens when there are 2 CPUs. One could be freeing and the + * other filling it. If the ring is full when we get out of here and + * the card has already interrupted the host then the host can miss the + * interrupt. + * + * There is still a possible race condition and the host could miss an + * interrupt. The card has to take care of this. + */ + hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); + done = (sw_consumer == hw_consumer); + + spin_unlock(&adapter->tx_clean_lock); + + return done; +} + +static int qlcnic_poll(struct napi_struct *napi, int budget) +{ + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_adapter *adapter; + int tx_complete, work_done; + + sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); + adapter = sds_ring->adapter; + + tx_complete = qlcnic_process_cmd_ring(adapter); + work_done = qlcnic_process_rcv_ring(sds_ring, budget); + + if ((work_done < budget) && tx_complete) { + napi_complete(&sds_ring->napi); + if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) + qlcnic_enable_int(sds_ring); + } + + return work_done; +} + +static int qlcnic_rx_poll(struct napi_struct *napi, int budget) +{ + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_adapter *adapter; + int work_done; + + sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); + adapter = sds_ring->adapter; + + work_done = qlcnic_process_rcv_ring(sds_ring, budget); + + if (work_done < budget) { + napi_complete(&sds_ring->napi); + if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) + qlcnic_enable_int(sds_ring); + } + + return work_done; +} + +static void qlcnic_handle_linkevent(struct qlcnic_adapter *adapter, + struct qlcnic_fw_msg *msg) +{ + u32 cable_OUI; + u16 cable_len, link_speed; + u8 link_status, module, duplex, autoneg, lb_status = 0; + struct net_device *netdev = adapter->netdev; + + adapter->ahw->has_link_events = 1; + + cable_OUI = msg->body[1] & 0xffffffff; + cable_len = (msg->body[1] >> 32) & 0xffff; + link_speed = (msg->body[1] >> 48) & 0xffff; + + link_status = msg->body[2] & 0xff; + duplex = (msg->body[2] >> 16) & 0xff; + autoneg = (msg->body[2] >> 24) & 0xff; + lb_status = (msg->body[2] >> 32) & 0x3; + + module = (msg->body[2] >> 8) & 0xff; + if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) + dev_info(&netdev->dev, + "unsupported cable: OUI 0x%x, length %d\n", + cable_OUI, cable_len); + else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) + dev_info(&netdev->dev, "unsupported cable length %d\n", + cable_len); + + if (!link_status && (lb_status == QLCNIC_ILB_MODE || + lb_status == QLCNIC_ELB_MODE)) + adapter->ahw->loopback_state |= QLCNIC_LINKEVENT; + + qlcnic_advert_link_change(adapter, link_status); + + if (duplex == LINKEVENT_FULL_DUPLEX) + adapter->ahw->link_duplex = DUPLEX_FULL; + else + adapter->ahw->link_duplex = DUPLEX_HALF; + + adapter->ahw->module_type = module; + adapter->ahw->link_autoneg = autoneg; + + if (link_status) { + adapter->ahw->link_speed = link_speed; + } else { + adapter->ahw->link_speed = SPEED_UNKNOWN; + adapter->ahw->link_duplex = DUPLEX_UNKNOWN; + } +} + +static void qlcnic_handle_fw_message(int desc_cnt, int index, + struct qlcnic_host_sds_ring *sds_ring) +{ + struct qlcnic_fw_msg msg; + struct status_desc *desc; + struct qlcnic_adapter *adapter; + struct device *dev; + int i = 0, opcode, ret; + + while (desc_cnt > 0 && i < 8) { + desc = &sds_ring->desc_head[index]; + msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]); + msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]); + + index = get_next_index(index, sds_ring->num_desc); + desc_cnt--; + } + + adapter = sds_ring->adapter; + dev = &adapter->pdev->dev; + opcode = qlcnic_get_nic_msg_opcode(msg.body[0]); + + switch (opcode) { + case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE: + qlcnic_handle_linkevent(adapter, &msg); + break; + case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK: + ret = (u32)(msg.body[1]); + switch (ret) { + case 0: + adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE; + break; + case 1: + dev_info(dev, "loopback already in progress\n"); + adapter->ahw->diag_cnt = -QLCNIC_TEST_IN_PROGRESS; + break; + case 2: + dev_info(dev, "loopback cable is not connected\n"); + adapter->ahw->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN; + break; + default: + dev_info(dev, + "loopback configure request failed, err %x\n", + ret); + adapter->ahw->diag_cnt = -QLCNIC_UNDEFINED_ERROR; + break; + } + break; + default: + break; + } +} + +static struct sk_buff * +qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, + struct qlcnic_host_rds_ring *rds_ring, u16 index, + u16 cksum) +{ + struct qlcnic_rx_buffer *buffer; + struct sk_buff *skb; + + buffer = &rds_ring->rx_buf_arr[index]; + + if (unlikely(buffer->skb == NULL)) { + WARN_ON(1); + return NULL; + } + + pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size, + PCI_DMA_FROMDEVICE); + + skb = buffer->skb; + + if (likely((adapter->netdev->features & NETIF_F_RXCSUM) && + (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) { + adapter->stats.csummed++; + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + skb_checksum_none_assert(skb); + } + + buffer->skb = NULL; + + return skb; +} + +static inline int qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, + struct sk_buff *skb, u16 *vlan_tag) +{ + struct ethhdr *eth_hdr; + + if (!__vlan_get_tag(skb, vlan_tag)) { + eth_hdr = (struct ethhdr *)skb->data; + memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2); + skb_pull(skb, VLAN_HLEN); + } + if (!adapter->pvid) + return 0; + + if (*vlan_tag == adapter->pvid) { + /* Outer vlan tag. Packet should follow non-vlan path */ + *vlan_tag = 0xffff; + return 0; + } + if (adapter->flags & QLCNIC_TAGGING_ENABLED) + return 0; + + return -EINVAL; +} + +static struct qlcnic_rx_buffer * +qlcnic_process_rcv(struct qlcnic_adapter *adapter, + struct qlcnic_host_sds_ring *sds_ring, int ring, + u64 sts_data0) +{ + struct net_device *netdev = adapter->netdev; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; + struct qlcnic_rx_buffer *buffer; + struct sk_buff *skb; + struct qlcnic_host_rds_ring *rds_ring; + int index, length, cksum, pkt_offset; + u16 vid = 0xffff; + + if (unlikely(ring >= adapter->max_rds_rings)) + return NULL; + + rds_ring = &recv_ctx->rds_rings[ring]; + + index = qlcnic_get_sts_refhandle(sts_data0); + if (unlikely(index >= rds_ring->num_desc)) + return NULL; + + buffer = &rds_ring->rx_buf_arr[index]; + length = qlcnic_get_sts_totallength(sts_data0); + cksum = qlcnic_get_sts_status(sts_data0); + pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0); + + skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum); + if (!skb) + return buffer; + + if (length > rds_ring->skb_size) + skb_put(skb, rds_ring->skb_size); + else + skb_put(skb, length); + + if (pkt_offset) + skb_pull(skb, pkt_offset); + + if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { + adapter->stats.rxdropped++; + dev_kfree_skb(skb); + return buffer; + } + + skb->protocol = eth_type_trans(skb, netdev); + + if (vid != 0xffff) + __vlan_hwaccel_put_tag(skb, vid); + + napi_gro_receive(&sds_ring->napi, skb); + + adapter->stats.rx_pkts++; + adapter->stats.rxbytes += length; + + return buffer; +} + +#define QLC_TCP_HDR_SIZE 20 +#define QLC_TCP_TS_OPTION_SIZE 12 +#define QLC_TCP_TS_HDR_SIZE (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE) + +static struct qlcnic_rx_buffer * +qlcnic_process_lro(struct qlcnic_adapter *adapter, + int ring, u64 sts_data0, u64 sts_data1) +{ + struct net_device *netdev = adapter->netdev; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; + struct qlcnic_rx_buffer *buffer; + struct sk_buff *skb; + struct qlcnic_host_rds_ring *rds_ring; + struct iphdr *iph; + struct tcphdr *th; + bool push, timestamp; + int index, l2_hdr_offset, l4_hdr_offset; + u16 lro_length, length, data_offset, vid = 0xffff; + u32 seq_number; + + if (unlikely(ring > adapter->max_rds_rings)) + return NULL; + + rds_ring = &recv_ctx->rds_rings[ring]; + + index = qlcnic_get_lro_sts_refhandle(sts_data0); + if (unlikely(index > rds_ring->num_desc)) + return NULL; + + buffer = &rds_ring->rx_buf_arr[index]; + + timestamp = qlcnic_get_lro_sts_timestamp(sts_data0); + lro_length = qlcnic_get_lro_sts_length(sts_data0); + l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0); + l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0); + push = qlcnic_get_lro_sts_push_flag(sts_data0); + seq_number = qlcnic_get_lro_sts_seq_number(sts_data1); + + skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK); + if (!skb) + return buffer; + + if (timestamp) + data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE; + else + data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE; + + skb_put(skb, lro_length + data_offset); + skb_pull(skb, l2_hdr_offset); + + if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { + adapter->stats.rxdropped++; + dev_kfree_skb(skb); + return buffer; + } + + skb->protocol = eth_type_trans(skb, netdev); + iph = (struct iphdr *)skb->data; + th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); + length = (iph->ihl << 2) + (th->doff << 2) + lro_length; + iph->tot_len = htons(length); + iph->check = 0; + iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); + th->psh = push; + th->seq = htonl(seq_number); + length = skb->len; + + if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) + skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1); + + if (vid != 0xffff) + __vlan_hwaccel_put_tag(skb, vid); + netif_receive_skb(skb); + + adapter->stats.lro_pkts++; + adapter->stats.lrobytes += length; + + return buffer; +} + +int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) +{ + struct qlcnic_host_rds_ring *rds_ring; + struct qlcnic_adapter *adapter = sds_ring->adapter; + struct list_head *cur; + struct status_desc *desc; + struct qlcnic_rx_buffer *rxbuf; + u64 sts_data0, sts_data1; + __le64 owner_phantom = cpu_to_le64(STATUS_OWNER_PHANTOM); + int opcode, ring, desc_cnt, count = 0; + u32 consumer = sds_ring->consumer; + + while (count < max) { + desc = &sds_ring->desc_head[consumer]; + sts_data0 = le64_to_cpu(desc->status_desc_data[0]); + + if (!(sts_data0 & STATUS_OWNER_HOST)) + break; + + desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); + opcode = qlcnic_get_sts_opcode(sts_data0); + + switch (opcode) { + case QLCNIC_RXPKT_DESC: + case QLCNIC_OLD_RXPKT_DESC: + case QLCNIC_SYN_OFFLOAD: + ring = qlcnic_get_sts_type(sts_data0); + rxbuf = qlcnic_process_rcv(adapter, sds_ring, ring, + sts_data0); + break; + case QLCNIC_LRO_DESC: + ring = qlcnic_get_lro_sts_type(sts_data0); + sts_data1 = le64_to_cpu(desc->status_desc_data[1]); + rxbuf = qlcnic_process_lro(adapter, ring, sts_data0, + sts_data1); + break; + case QLCNIC_RESPONSE_DESC: + qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring); + default: + goto skip; + } + + WARN_ON(desc_cnt > 1); + + if (likely(rxbuf)) + list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); + else + adapter->stats.null_rxbuf++; + +skip: + for (; desc_cnt > 0; desc_cnt--) { + desc = &sds_ring->desc_head[consumer]; + desc->status_desc_data[0] = owner_phantom; + consumer = get_next_index(consumer, sds_ring->num_desc); + } + count++; + } + + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &adapter->recv_ctx->rds_rings[ring]; + + if (!list_empty(&sds_ring->free_list[ring])) { + list_for_each(cur, &sds_ring->free_list[ring]) { + rxbuf = list_entry(cur, struct qlcnic_rx_buffer, + list); + qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf); + } + spin_lock(&rds_ring->lock); + list_splice_tail_init(&sds_ring->free_list[ring], + &rds_ring->free_list); + spin_unlock(&rds_ring->lock); + } + + qlcnic_post_rx_buffers_nodb(adapter, rds_ring); + } + + if (count) { + sds_ring->consumer = consumer; + writel(consumer, sds_ring->crb_sts_consumer); + } + + return count; +} + +void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, + struct qlcnic_host_rds_ring *rds_ring) +{ + struct rcv_desc *pdesc; + struct qlcnic_rx_buffer *buffer; + int count = 0; + u32 producer; + struct list_head *head; + + producer = rds_ring->producer; + head = &rds_ring->free_list; + + while (!list_empty(head)) { + + buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); + + if (!buffer->skb) { + if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) + break; + } + + count++; + list_del(&buffer->list); + + /* make a rcv descriptor */ + pdesc = &rds_ring->desc_head[producer]; + pdesc->addr_buffer = cpu_to_le64(buffer->dma); + pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); + pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); + producer = get_next_index(producer, rds_ring->num_desc); + } + + if (count) { + rds_ring->producer = producer; + writel((producer-1) & (rds_ring->num_desc-1), + rds_ring->crb_rcv_producer); + } +} + +static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter) +{ + int i; + unsigned char *data = skb->data; + + pr_info(KERN_INFO "\n"); + for (i = 0; i < skb->len; i++) { + QLCDB(adapter, DRV, "%02x ", data[i]); + if ((i & 0x0f) == 8) + pr_info(KERN_INFO "\n"); + } +} + +static void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, int ring, + u64 sts_data0) +{ + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; + struct sk_buff *skb; + struct qlcnic_host_rds_ring *rds_ring; + int index, length, cksum, pkt_offset; + + if (unlikely(ring >= adapter->max_rds_rings)) + return; + + rds_ring = &recv_ctx->rds_rings[ring]; + + index = qlcnic_get_sts_refhandle(sts_data0); + length = qlcnic_get_sts_totallength(sts_data0); + if (unlikely(index >= rds_ring->num_desc)) + return; + + cksum = qlcnic_get_sts_status(sts_data0); + pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0); + + skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum); + if (!skb) + return; + + if (length > rds_ring->skb_size) + skb_put(skb, rds_ring->skb_size); + else + skb_put(skb, length); + + if (pkt_offset) + skb_pull(skb, pkt_offset); + + if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr)) + adapter->ahw->diag_cnt++; + else + dump_skb(skb, adapter); + + dev_kfree_skb_any(skb); + adapter->stats.rx_pkts++; + adapter->stats.rxbytes += length; + + return; +} + +void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) +{ + struct qlcnic_adapter *adapter = sds_ring->adapter; + struct status_desc *desc; + u64 sts_data0; + int ring, opcode, desc_cnt; + + u32 consumer = sds_ring->consumer; + + desc = &sds_ring->desc_head[consumer]; + sts_data0 = le64_to_cpu(desc->status_desc_data[0]); + + if (!(sts_data0 & STATUS_OWNER_HOST)) + return; + + desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); + opcode = qlcnic_get_sts_opcode(sts_data0); + switch (opcode) { + case QLCNIC_RESPONSE_DESC: + qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring); + break; + default: + ring = qlcnic_get_sts_type(sts_data0); + qlcnic_process_rcv_diag(adapter, ring, sts_data0); + break; + } + + for (; desc_cnt > 0; desc_cnt--) { + desc = &sds_ring->desc_head[consumer]; + desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM); + consumer = get_next_index(consumer, sds_ring->num_desc); + } + + sds_ring->consumer = consumer; + writel(consumer, sds_ring->crb_sts_consumer); +} + +void qlcnic_fetch_mac(u32 off1, u32 off2, u8 alt_mac, u8 *mac) +{ + u32 mac_low, mac_high; + int i; + + mac_low = off1; + mac_high = off2; + + if (alt_mac) { + mac_low |= (mac_low >> 16) | (mac_high << 16); + mac_high >>= 16; + } + + for (i = 0; i < 2; i++) + mac[i] = (u8)(mac_high >> ((1 - i) * 8)); + for (i = 2; i < 6; i++) + mac[i] = (u8)(mac_low >> ((5 - i) * 8)); +} + +int qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev) +{ + int ring, max_sds_rings; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; + + if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) + return -ENOMEM; + + max_sds_rings = adapter->max_sds_rings; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + + if (ring == max_sds_rings - 1) + netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll, + QLCNIC_NETDEV_WEIGHT / max_sds_rings); + else + netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll, + QLCNIC_NETDEV_WEIGHT*2); + } + + return 0; +} + +void qlcnic_napi_del(struct qlcnic_adapter *adapter) +{ + int ring; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + netif_napi_del(&sds_ring->napi); + } + + qlcnic_free_sds_rings(adapter->recv_ctx); +} + +void qlcnic_napi_enable(struct qlcnic_adapter *adapter) +{ + int ring; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; + + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + return; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + napi_enable(&sds_ring->napi); + qlcnic_enable_int(sds_ring); + } +} + +void qlcnic_napi_disable(struct qlcnic_adapter *adapter) +{ + int ring; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; + + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + return; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + qlcnic_disable_int(sds_ring); + napi_synchronize(&sds_ring->napi); + napi_disable(&sds_ring->napi); + } +} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 4c3b67c13047..b30af2b1cd28 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -34,29 +34,28 @@ static int qlcnic_mac_learn; module_param(qlcnic_mac_learn, int, 0444); MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)"); -static int use_msi = 1; -module_param(use_msi, int, 0444); +static int qlcnic_use_msi = 1; MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled"); +module_param_named(use_msi, qlcnic_use_msi, int, 0444); -static int use_msi_x = 1; -module_param(use_msi_x, int, 0444); +static int qlcnic_use_msi_x = 1; MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled"); +module_param_named(use_msi_x, qlcnic_use_msi_x, int, 0444); -static int auto_fw_reset = 1; -module_param(auto_fw_reset, int, 0644); +static int qlcnic_auto_fw_reset = 1; MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled"); +module_param_named(auto_fw_reset, qlcnic_auto_fw_reset, int, 0644); -static int load_fw_file; -module_param(load_fw_file, int, 0444); +static int qlcnic_load_fw_file; MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file"); +module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444); static int qlcnic_config_npars; module_param(qlcnic_config_npars, int, 0444); MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled"); -static int __devinit qlcnic_probe(struct pci_dev *pdev, - const struct pci_device_id *ent); -static void __devexit qlcnic_remove(struct pci_dev *pdev); +static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); +static void qlcnic_remove(struct pci_dev *pdev); static int qlcnic_open(struct net_device *netdev); static int qlcnic_close(struct net_device *netdev); static void qlcnic_tx_timeout(struct net_device *netdev); @@ -66,17 +65,10 @@ static void qlcnic_fw_poll_work(struct work_struct *work); static void qlcnic_schedule_work(struct qlcnic_adapter *adapter, work_func_t func, int delay); static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter); -static int qlcnic_poll(struct napi_struct *napi, int budget); -static int qlcnic_rx_poll(struct napi_struct *napi, int budget); #ifdef CONFIG_NET_POLL_CONTROLLER static void qlcnic_poll_controller(struct net_device *netdev); #endif -static void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter); -static void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter); -static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter); -static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); - static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding); static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8); static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); @@ -92,14 +84,15 @@ static int qlcnic_start_firmware(struct qlcnic_adapter *); static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter); static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *); -static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); -static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); static int qlcnicvf_start_firmware(struct qlcnic_adapter *); static void qlcnic_set_netdev_features(struct qlcnic_adapter *, struct qlcnic_esw_func_cfg *); static int qlcnic_vlan_rx_add(struct net_device *, u16); static int qlcnic_vlan_rx_del(struct net_device *, u16); +#define QLCNIC_IS_TSO_CAPABLE(adapter) \ + ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) + /* PCI Device ID Table */ #define ENTRY(device) \ {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ @@ -115,9 +108,7 @@ static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = { MODULE_DEVICE_TABLE(pci, qlcnic_pci_tbl); -inline void -qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, - struct qlcnic_host_tx_ring *tx_ring) +inline void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *tx_ring) { writel(tx_ring->producer, tx_ring->crb_cmd_producer); } @@ -129,26 +120,34 @@ static const u32 msi_tgt_status[8] = { ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7 }; -static const -struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG; - -static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring) -{ - writel(0, sds_ring->crb_intr_mask); -} - -static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring) -{ - struct qlcnic_adapter *adapter = sds_ring->adapter; +static const struct qlcnic_board_info qlcnic_boards[] = { + {0x1077, 0x8020, 0x1077, 0x203, + "8200 Series Single Port 10GbE Converged Network Adapter" + "(TCP/IP Networking)"}, + {0x1077, 0x8020, 0x1077, 0x207, + "8200 Series Dual Port 10GbE Converged Network Adapter" + "(TCP/IP Networking)"}, + {0x1077, 0x8020, 0x1077, 0x20b, + "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"}, + {0x1077, 0x8020, 0x1077, 0x20c, + "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"}, + {0x1077, 0x8020, 0x1077, 0x20f, + "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"}, + {0x1077, 0x8020, 0x103c, 0x3733, + "NC523SFP 10Gb 2-port Server Adapter"}, + {0x1077, 0x8020, 0x103c, 0x3346, + "CN1000Q Dual Port Converged Network Adapter"}, + {0x1077, 0x8020, 0x1077, 0x210, + "QME8242-k 10GbE Dual Port Mezzanine Card"}, + {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"}, +}; - writel(0x1, sds_ring->crb_intr_mask); +#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards) - if (!QLCNIC_IS_MSI_FAMILY(adapter)) - writel(0xfbff, adapter->tgt_mask_reg); -} +static const +struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG; -static int -qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count) +int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count) { int size = sizeof(struct qlcnic_host_sds_ring) * count; @@ -157,8 +156,7 @@ qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count) return recv_ctx->sds_rings == NULL; } -static void -qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx) +void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx) { if (recv_ctx->sds_rings != NULL) kfree(recv_ctx->sds_rings); @@ -166,80 +164,6 @@ qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx) recv_ctx->sds_rings = NULL; } -static int -qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev) -{ - int ring; - struct qlcnic_host_sds_ring *sds_ring; - struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; - - if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) - return -ENOMEM; - - for (ring = 0; ring < adapter->max_sds_rings; ring++) { - sds_ring = &recv_ctx->sds_rings[ring]; - - if (ring == adapter->max_sds_rings - 1) - netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll, - QLCNIC_NETDEV_WEIGHT/adapter->max_sds_rings); - else - netif_napi_add(netdev, &sds_ring->napi, - qlcnic_rx_poll, QLCNIC_NETDEV_WEIGHT*2); - } - - return 0; -} - -static void -qlcnic_napi_del(struct qlcnic_adapter *adapter) -{ - int ring; - struct qlcnic_host_sds_ring *sds_ring; - struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; - - for (ring = 0; ring < adapter->max_sds_rings; ring++) { - sds_ring = &recv_ctx->sds_rings[ring]; - netif_napi_del(&sds_ring->napi); - } - - qlcnic_free_sds_rings(adapter->recv_ctx); -} - -static void -qlcnic_napi_enable(struct qlcnic_adapter *adapter) -{ - int ring; - struct qlcnic_host_sds_ring *sds_ring; - struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; - - if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) - return; - - for (ring = 0; ring < adapter->max_sds_rings; ring++) { - sds_ring = &recv_ctx->sds_rings[ring]; - napi_enable(&sds_ring->napi); - qlcnic_enable_int(sds_ring); - } -} - -static void -qlcnic_napi_disable(struct qlcnic_adapter *adapter) -{ - int ring; - struct qlcnic_host_sds_ring *sds_ring; - struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; - - if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) - return; - - for (ring = 0; ring < adapter->max_sds_rings; ring++) { - sds_ring = &recv_ctx->sds_rings[ring]; - qlcnic_disable_int(sds_ring); - napi_synchronize(&sds_ring->napi); - napi_disable(&sds_ring->napi); - } -} - static void qlcnic_clear_stats(struct qlcnic_adapter *adapter) { memset(&adapter->stats, 0, sizeof(adapter->stats)); @@ -363,7 +287,7 @@ static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED); qlcnic_set_msix_bit(pdev, 0); - if (adapter->msix_supported) { + if (adapter->ahw->msix_supported) { enable_msix: qlcnic_init_msix_entries(adapter, num_msix); err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); @@ -385,32 +309,31 @@ static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) return err; } - static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) { + u32 offset, mask_reg; const struct qlcnic_legacy_intr_set *legacy_intrp; + struct qlcnic_hardware_context *ahw = adapter->ahw; struct pci_dev *pdev = adapter->pdev; - if (use_msi && !pci_enable_msi(pdev)) { + if (qlcnic_use_msi && !pci_enable_msi(pdev)) { adapter->flags |= QLCNIC_MSI_ENABLED; - adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter, - msi_tgt_status[adapter->ahw->pci_func]); + offset = msi_tgt_status[adapter->ahw->pci_func]; + adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter->ahw, + offset); dev_info(&pdev->dev, "using msi interrupts\n"); adapter->msix_entries[0].vector = pdev->irq; return; } legacy_intrp = &legacy_intr[adapter->ahw->pci_func]; - - adapter->int_vec_bit = legacy_intrp->int_vec_bit; - adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter, - legacy_intrp->tgt_status_reg); - adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter, - legacy_intrp->tgt_mask_reg); - adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR); - - adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter, - ISR_INT_STATE_REG); + adapter->ahw->int_vec_bit = legacy_intrp->int_vec_bit; + offset = legacy_intrp->tgt_status_reg; + adapter->tgt_status_reg = qlcnic_get_ioaddr(ahw, offset); + mask_reg = legacy_intrp->tgt_mask_reg; + adapter->tgt_mask_reg = qlcnic_get_ioaddr(ahw, mask_reg); + adapter->isr_int_vec = qlcnic_get_ioaddr(ahw, ISR_INT_VECTOR); + adapter->crb_int_state_reg = qlcnic_get_ioaddr(ahw, ISR_INT_STATE_REG); dev_info(&pdev->dev, "using legacy interrupts\n"); adapter->msix_entries[0].vector = pdev->irq; } @@ -420,7 +343,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter) { int num_msix; - if (adapter->msix_supported) { + if (adapter->ahw->msix_supported) { num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(), QLCNIC_DEF_NUM_STS_DESC_RINGS)); } else @@ -448,19 +371,25 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter) iounmap(adapter->ahw->pci_base0); } -static int -qlcnic_init_pci_info(struct qlcnic_adapter *adapter) +static int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) { struct qlcnic_pci_info *pci_info; - int i, ret = 0; + int i, ret = 0, j = 0; + u16 act_pci_func; u8 pfn; pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); if (!pci_info) return -ENOMEM; + ret = qlcnic_get_pci_info(adapter, pci_info); + if (ret) + goto err_pci_info; + + act_pci_func = adapter->ahw->act_pci_func; + adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) * - QLCNIC_MAX_PCI_FUNC, GFP_KERNEL); + act_pci_func, GFP_KERNEL); if (!adapter->npars) { ret = -ENOMEM; goto err_pci_info; @@ -473,21 +402,25 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter) goto err_npars; } - ret = qlcnic_get_pci_info(adapter, pci_info); - if (ret) - goto err_eswitch; - for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { pfn = pci_info[i].id; + if (pfn >= QLCNIC_MAX_PCI_FUNC) { ret = QL_STATUS_INVALID_PARAM; goto err_eswitch; } - adapter->npars[pfn].active = (u8)pci_info[i].active; - adapter->npars[pfn].type = (u8)pci_info[i].type; - adapter->npars[pfn].phy_port = (u8)pci_info[i].default_port; - adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw; - adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw; + + if (!pci_info[i].active || + (pci_info[i].type != QLCNIC_TYPE_NIC)) + continue; + + adapter->npars[j].pci_func = pfn; + adapter->npars[j].active = (u8)pci_info[i].active; + adapter->npars[j].type = (u8)pci_info[i].type; + adapter->npars[j].phy_port = (u8)pci_info[i].default_port; + adapter->npars[j].min_bw = pci_info[i].tx_min_bw; + adapter->npars[j].max_bw = pci_info[i].tx_max_bw; + j++; } for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) @@ -512,33 +445,29 @@ static int qlcnic_set_function_modes(struct qlcnic_adapter *adapter) { u8 id; - u32 ref_count; int i, ret = 1; u32 data = QLCNIC_MGMT_FUNC; - void __iomem *priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE; + struct qlcnic_hardware_context *ahw = adapter->ahw; - /* If other drivers are not in use set their privilege level */ - ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); ret = qlcnic_api_lock(adapter); if (ret) goto err_lock; if (qlcnic_config_npars) { - for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { - id = i; - if (adapter->npars[i].type != QLCNIC_TYPE_NIC || - id == adapter->ahw->pci_func) + for (i = 0; i < ahw->act_pci_func; i++) { + id = adapter->npars[i].pci_func; + if (id == ahw->pci_func) continue; data |= (qlcnic_config_npars & QLC_DEV_SET_DRV(0xf, id)); } } else { - data = readl(priv_op); - data = (data & ~QLC_DEV_SET_DRV(0xf, adapter->ahw->pci_func)) | + data = QLCRD32(adapter, QLCNIC_DRV_OP_MODE); + data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) | (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, - adapter->ahw->pci_func)); + ahw->pci_func)); } - writel(data, priv_op); + QLCWR32(adapter, QLCNIC_DRV_OP_MODE, data); qlcnic_api_unlock(adapter); err_lock: return ret; @@ -554,8 +483,8 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter) u32 op_mode, priv_level; /* Determine FW API version */ - adapter->fw_hal_version = readl(adapter->ahw->pci_base0 + - QLCNIC_FW_API); + adapter->ahw->fw_hal_version = readl(adapter->ahw->pci_base0 + + QLCNIC_FW_API); /* Find PCI function number */ pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func); @@ -573,29 +502,39 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter) priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func); if (priv_level == QLCNIC_NON_PRIV_FUNC) { - adapter->op_mode = QLCNIC_NON_PRIV_FUNC; + adapter->ahw->op_mode = QLCNIC_NON_PRIV_FUNC; dev_info(&adapter->pdev->dev, "HAL Version: %d Non Privileged function\n", - adapter->fw_hal_version); + adapter->ahw->fw_hal_version); adapter->nic_ops = &qlcnic_vf_ops; } else adapter->nic_ops = &qlcnic_ops; } -static int -qlcnic_setup_pci_map(struct qlcnic_adapter *adapter) +#define QLCNIC_82XX_BAR0_LENGTH 0x00200000UL +static void qlcnic_get_bar_length(u32 dev_id, ulong *bar) { - void __iomem *mem_ptr0 = NULL; - resource_size_t mem_base; - unsigned long mem_len, pci_len0 = 0; + switch (dev_id) { + case PCI_DEVICE_ID_QLOGIC_QLE824X: + *bar = QLCNIC_82XX_BAR0_LENGTH; + break; + default: + *bar = 0; + } +} - struct pci_dev *pdev = adapter->pdev; +static int qlcnic_setup_pci_map(struct pci_dev *pdev, + struct qlcnic_hardware_context *ahw) +{ + u32 offset; + void __iomem *mem_ptr0 = NULL; + unsigned long mem_len, pci_len0 = 0, bar0_len; /* remap phys address */ - mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ mem_len = pci_resource_len(pdev, 0); - if (mem_len == QLCNIC_PCI_2MB_SIZE) { + qlcnic_get_bar_length(pdev->device, &bar0_len); + if (mem_len >= bar0_len) { mem_ptr0 = pci_ioremap_bar(pdev, 0); if (mem_ptr0 == NULL) { @@ -608,20 +547,15 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter) } dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20)); - - adapter->ahw->pci_base0 = mem_ptr0; - adapter->ahw->pci_len0 = pci_len0; - - qlcnic_check_vf(adapter); - - adapter->ahw->ocm_win_crb = qlcnic_get_ioaddr(adapter, - QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG( - adapter->ahw->pci_func))); + ahw->pci_base0 = mem_ptr0; + ahw->pci_len0 = pci_len0; + offset = QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(ahw->pci_func)); + qlcnic_get_ioaddr(ahw, offset); return 0; } -static void get_brd_name(struct qlcnic_adapter *adapter, char *name) +static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name) { struct pci_dev *pdev = adapter->pdev; int i, found = 0; @@ -659,7 +593,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build); - if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC) { + if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC) { if (fw_dump->tmpl_hdr == NULL || adapter->fw_version > prev_fw_version) { if (fw_dump->tmpl_hdr) @@ -691,7 +625,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G; } - adapter->msix_supported = !!use_msi_x; + adapter->ahw->msix_supported = !!qlcnic_use_msi_x; adapter->num_txd = MAX_CMD_DESCRIPTORS; @@ -704,19 +638,20 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter) int err; struct qlcnic_info nic_info; + memset(&nic_info, 0, sizeof(struct qlcnic_info)); err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func); if (err) return err; - adapter->physical_port = (u8)nic_info.phys_port; - adapter->switch_mode = nic_info.switch_mode; - adapter->max_tx_ques = nic_info.max_tx_ques; - adapter->max_rx_ques = nic_info.max_rx_ques; - adapter->capabilities = nic_info.capabilities; - adapter->max_mac_filters = nic_info.max_mac_filters; - adapter->max_mtu = nic_info.max_mtu; + adapter->ahw->physical_port = (u8)nic_info.phys_port; + adapter->ahw->switch_mode = nic_info.switch_mode; + adapter->ahw->max_tx_ques = nic_info.max_tx_ques; + adapter->ahw->max_rx_ques = nic_info.max_rx_ques; + adapter->ahw->capabilities = nic_info.capabilities; + adapter->ahw->max_mac_filters = nic_info.max_mac_filters; + adapter->ahw->max_mtu = nic_info.max_mtu; - if (adapter->capabilities & BIT_6) + if (adapter->ahw->capabilities & BIT_6) adapter->flags |= QLCNIC_ESWITCH_ENABLED; else adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; @@ -724,9 +659,8 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter) return err; } -static void -qlcnic_set_vlan_config(struct qlcnic_adapter *adapter, - struct qlcnic_esw_func_cfg *esw_cfg) +void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter, + struct qlcnic_esw_func_cfg *esw_cfg) { if (esw_cfg->discard_tagged) adapter->flags &= ~QLCNIC_TAGGING_ENABLED; @@ -757,9 +691,8 @@ qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid) return 0; } -static void -qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, - struct qlcnic_esw_func_cfg *esw_cfg) +void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, + struct qlcnic_esw_func_cfg *esw_cfg) { adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED | QLCNIC_PROMISC_DISABLED); @@ -776,8 +709,7 @@ qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, qlcnic_set_netdev_features(adapter, esw_cfg); } -static int -qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) +static int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) { struct qlcnic_esw_func_cfg esw_cfg; @@ -805,7 +737,7 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER); - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) { + if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) { features |= (NETIF_F_TSO | NETIF_F_TSO6); vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6); } @@ -851,7 +783,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter) if (adapter->flags & QLCNIC_ESWITCH_ENABLED) { if (priv_level == QLCNIC_MGMT_FUNC) { - adapter->op_mode = QLCNIC_MGMT_FUNC; + adapter->ahw->op_mode = QLCNIC_MGMT_FUNC; err = qlcnic_init_pci_info(adapter); if (err) return err; @@ -859,12 +791,12 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter) qlcnic_set_function_modes(adapter); dev_info(&adapter->pdev->dev, "HAL Version: %d, Management function\n", - adapter->fw_hal_version); + adapter->ahw->fw_hal_version); } else if (priv_level == QLCNIC_PRIV_FUNC) { - adapter->op_mode = QLCNIC_PRIV_FUNC; + adapter->ahw->op_mode = QLCNIC_PRIV_FUNC; dev_info(&adapter->pdev->dev, "HAL Version: %d, Privileged function\n", - adapter->fw_hal_version); + adapter->ahw->fw_hal_version); } } @@ -873,8 +805,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter) return err; } -static int -qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) +static int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) { struct qlcnic_esw_func_cfg esw_cfg; struct qlcnic_npar_info *npar; @@ -883,16 +814,16 @@ qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) if (adapter->need_fw_reset) return 0; - for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { - if (adapter->npars[i].type != QLCNIC_TYPE_NIC) - continue; + for (i = 0; i < adapter->ahw->act_pci_func; i++) { memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg)); - esw_cfg.pci_func = i; - esw_cfg.offload_flags = BIT_0; + esw_cfg.pci_func = adapter->npars[i].pci_func; esw_cfg.mac_override = BIT_0; esw_cfg.promisc_mode = BIT_0; - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) - esw_cfg.offload_flags |= (BIT_1 | BIT_2); + if (qlcnic_82xx_check(adapter)) { + esw_cfg.offload_flags = BIT_0; + if (QLCNIC_IS_TSO_CAPABLE(adapter)) + esw_cfg.offload_flags |= (BIT_1 | BIT_2); + } if (qlcnic_config_switch_port(adapter, &esw_cfg)) return -EIO; npar = &adapter->npars[i]; @@ -930,22 +861,24 @@ qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter, return 0; } -static int -qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) +static int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) { int i, err; struct qlcnic_npar_info *npar; struct qlcnic_info nic_info; + u8 pci_func; - if (!adapter->need_fw_reset) - return 0; + if (qlcnic_82xx_check(adapter)) + if (!adapter->need_fw_reset) + return 0; /* Set the NPAR config data after FW reset */ - for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { + for (i = 0; i < adapter->ahw->act_pci_func; i++) { npar = &adapter->npars[i]; - if (npar->type != QLCNIC_TYPE_NIC) - continue; - err = qlcnic_get_nic_info(adapter, &nic_info, i); + pci_func = npar->pci_func; + memset(&nic_info, 0, sizeof(struct qlcnic_info)); + err = qlcnic_get_nic_info(adapter, + &nic_info, pci_func); if (err) return err; nic_info.min_tx_bw = npar->min_bw; @@ -956,11 +889,12 @@ qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) if (npar->enable_pm) { err = qlcnic_config_port_mirroring(adapter, - npar->dest_npar, 1, i); + npar->dest_npar, 1, + pci_func); if (err) return err; } - err = qlcnic_reset_eswitch_config(adapter, npar, i); + err = qlcnic_reset_eswitch_config(adapter, npar, pci_func); if (err) return err; } @@ -972,7 +906,7 @@ static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter) u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO; u32 npar_state; - if (adapter->op_mode == QLCNIC_MGMT_FUNC) + if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) return 0; npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); @@ -994,7 +928,7 @@ qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter) int err; if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) || - adapter->op_mode != QLCNIC_MGMT_FUNC) + adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) return 0; err = qlcnic_set_default_offload_settings(adapter); @@ -1021,14 +955,14 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter) else if (!err) goto check_fw_status; - if (load_fw_file) + if (qlcnic_load_fw_file) qlcnic_request_firmware(adapter); else { err = qlcnic_check_flash_fw_ver(adapter); if (err) goto err_out; - adapter->fw_type = QLCNIC_FLASH_ROMIMAGE; + adapter->ahw->fw_type = QLCNIC_FLASH_ROMIMAGE; } err = qlcnic_need_fw_reset(adapter); @@ -1089,7 +1023,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) struct net_device *netdev = adapter->netdev; struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; - if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { + if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { handler = qlcnic_tmp_intr; if (!QLCNIC_IS_MSI_FAMILY(adapter)) flags |= IRQF_SHARED; @@ -1148,7 +1082,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) if (qlcnic_set_eswitch_port_config(adapter)) return -EIO; - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) { + if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) { capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2); if (capab2 & QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG) adapter->flags |= QLCNIC_FW_LRO_MSS_CAP; @@ -1179,7 +1113,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) qlcnic_linkevent_request(adapter, 1); - adapter->reset_context = 0; + adapter->ahw->reset_context = 0; set_bit(__QLCNIC_DEV_UP, &adapter->state); return 0; } @@ -1312,7 +1246,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings) int ring; clear_bit(__QLCNIC_DEV_UP, &adapter->state); - if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { + if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &adapter->recv_ctx->sds_rings[ring]; qlcnic_disable_int(sds_ring); @@ -1323,7 +1257,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings) qlcnic_detach(adapter); - adapter->diag_test = 0; + adapter->ahw->diag_test = 0; adapter->max_sds_rings = max_sds_rings; if (qlcnic_attach(adapter)) @@ -1393,7 +1327,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) qlcnic_detach(adapter); adapter->max_sds_rings = 1; - adapter->diag_test = test; + adapter->ahw->diag_test = test; ret = qlcnic_attach(adapter); if (ret) { @@ -1413,14 +1347,14 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) qlcnic_post_rx_buffers(adapter, rds_ring); } - if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { + if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &adapter->recv_ctx->sds_rings[ring]; qlcnic_enable_int(sds_ring); } } - if (adapter->diag_test == QLCNIC_LOOPBACK_TEST) { + if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) { adapter->ahw->loopback_state = 0; qlcnic_linkevent_request(adapter, 1); } @@ -1485,14 +1419,14 @@ qlcnic_reset_context(struct qlcnic_adapter *adapter) } static int -qlcnic_setup_netdev(struct qlcnic_adapter *adapter, - struct net_device *netdev, u8 pci_using_dac) +qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, + int pci_using_dac) { int err; struct pci_dev *pdev = adapter->pdev; - adapter->mc_enabled = 0; - adapter->max_mc_count = 38; + adapter->ahw->mc_enabled = 0; + adapter->ahw->max_mc_count = 38; netdev->netdev_ops = &qlcnic_netdev_ops; netdev->watchdog_timeo = 5*HZ; @@ -1504,16 +1438,16 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) + if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; - if (pci_using_dac) + if (pci_using_dac == 1) netdev->hw_features |= NETIF_F_HIGHDMA; netdev->vlan_features = netdev->hw_features; - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX) + if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX) netdev->hw_features |= NETIF_F_HW_VLAN_TX; - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) + if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) netdev->hw_features |= NETIF_F_LRO; netdev->features |= netdev->hw_features | @@ -1530,7 +1464,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, return 0; } -static int qlcnic_set_dma_mask(struct pci_dev *pdev, u8 *pci_using_dac) +static int qlcnic_set_dma_mask(struct pci_dev *pdev, int *pci_using_dac) { if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) @@ -1559,15 +1493,14 @@ qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count) return -ENOMEM; } -static int __devinit +static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev = NULL; struct qlcnic_adapter *adapter = NULL; - int err; + int err, pci_using_dac = -1; uint8_t revision_id; - uint8_t pci_using_dac; - char brd_name[QLCNIC_MAX_BOARD_NAME_LEN]; + char board_name[QLCNIC_MAX_BOARD_NAME_LEN]; err = pci_enable_device(pdev); if (err) @@ -1616,9 +1549,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) spin_lock_init(&adapter->tx_clean_lock); INIT_LIST_HEAD(&adapter->mac_list); - err = qlcnic_setup_pci_map(adapter); + err = qlcnic_setup_pci_map(pdev, adapter->ahw); if (err) goto err_out_free_hw; + qlcnic_check_vf(adapter); /* This will be reset for mezz cards */ adapter->portnum = adapter->ahw->pci_func; @@ -1646,16 +1580,15 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_warn(&pdev->dev, "failed to read mac addr\n"); if (adapter->portnum == 0) { - get_brd_name(adapter, brd_name); - + qlcnic_get_board_name(adapter, board_name); pr_info("%s: %s Board Chip rev 0x%x\n", - module_name(THIS_MODULE), - brd_name, adapter->ahw->revision_id); + module_name(THIS_MODULE), + board_name, adapter->ahw->revision_id); } qlcnic_clear_stats(adapter); - err = qlcnic_alloc_msix_entries(adapter, adapter->max_rx_ques); + err = qlcnic_alloc_msix_entries(adapter, adapter->ahw->max_rx_ques); if (err) goto err_out_decr_ref; @@ -1667,7 +1600,9 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, adapter); - qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); + if (qlcnic_82xx_check(adapter)) + qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, + FW_POLL_DELAY); switch (adapter->ahw->port_type) { case QLCNIC_GBE: @@ -1724,7 +1659,7 @@ err_out_maintenance_mode: return 0; } -static void __devexit qlcnic_remove(struct pci_dev *pdev) +static void qlcnic_remove(struct pci_dev *pdev) { struct qlcnic_adapter *adapter; struct net_device *netdev; @@ -1746,7 +1681,8 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev) if (adapter->eswitch != NULL) kfree(adapter->eswitch); - qlcnic_clr_all_drv_state(adapter, 0); + if (qlcnic_82xx_check(adapter)) + qlcnic_clr_all_drv_state(adapter, 0); clear_bit(__QLCNIC_RESETTING, &adapter->state); @@ -1782,7 +1718,8 @@ static int __qlcnic_shutdown(struct pci_dev *pdev) if (netif_running(netdev)) qlcnic_down(adapter, netdev); - qlcnic_clr_all_drv_state(adapter, 0); + if (qlcnic_82xx_check(adapter)) + qlcnic_clr_all_drv_state(adapter, 0); clear_bit(__QLCNIC_RESETTING, &adapter->state); @@ -1790,9 +1727,11 @@ static int __qlcnic_shutdown(struct pci_dev *pdev) if (retval) return retval; - if (qlcnic_wol_supported(adapter)) { - pci_enable_wake(pdev, PCI_D3cold, 1); - pci_enable_wake(pdev, PCI_D3hot, 1); + if (qlcnic_82xx_check(adapter)) { + if (qlcnic_wol_supported(adapter)) { + pci_enable_wake(pdev, PCI_D3cold, 1); + pci_enable_wake(pdev, PCI_D3hot, 1); + } } return 0; @@ -1927,435 +1866,14 @@ static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter) adapter->fhash.fmax = 0; } -static void qlcnic_change_filter(struct qlcnic_adapter *adapter, - u64 uaddr, __le16 vlan_id, struct qlcnic_host_tx_ring *tx_ring) -{ - struct cmd_desc_type0 *hwdesc; - struct qlcnic_nic_req *req; - struct qlcnic_mac_req *mac_req; - struct qlcnic_vlan_req *vlan_req; - u32 producer; - u64 word; - - producer = tx_ring->producer; - hwdesc = &tx_ring->desc_head[tx_ring->producer]; - - req = (struct qlcnic_nic_req *)hwdesc; - memset(req, 0, sizeof(struct qlcnic_nic_req)); - req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23); - - word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16); - req->req_hdr = cpu_to_le64(word); - - mac_req = (struct qlcnic_mac_req *)&(req->words[0]); - mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD; - memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN); - - vlan_req = (struct qlcnic_vlan_req *)&req->words[1]; - vlan_req->vlan_id = vlan_id; - - tx_ring->producer = get_next_index(producer, tx_ring->num_desc); - smp_mb(); -} - -#define QLCNIC_MAC_HASH(MAC)\ - ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25)) - -static void -qlcnic_send_filter(struct qlcnic_adapter *adapter, - struct qlcnic_host_tx_ring *tx_ring, - struct cmd_desc_type0 *first_desc, - struct sk_buff *skb) -{ - struct ethhdr *phdr = (struct ethhdr *)(skb->data); - struct qlcnic_filter *fil, *tmp_fil; - struct hlist_node *tmp_hnode, *n; - struct hlist_head *head; - u64 src_addr = 0; - __le16 vlan_id = 0; - u8 hindex; - - if (ether_addr_equal(phdr->h_source, adapter->mac_addr)) - return; - - if (adapter->fhash.fnum >= adapter->fhash.fmax) - return; - - /* Only NPAR capable devices support vlan based learning*/ - if (adapter->flags & QLCNIC_ESWITCH_ENABLED) - vlan_id = first_desc->vlan_TCI; - memcpy(&src_addr, phdr->h_source, ETH_ALEN); - hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1); - head = &(adapter->fhash.fhead[hindex]); - - hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { - if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) && - tmp_fil->vlan_id == vlan_id) { - - if (jiffies > - (QLCNIC_READD_AGE * HZ + tmp_fil->ftime)) - qlcnic_change_filter(adapter, src_addr, vlan_id, - tx_ring); - tmp_fil->ftime = jiffies; - return; - } - } - - fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC); - if (!fil) - return; - - qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring); - - fil->ftime = jiffies; - fil->vlan_id = vlan_id; - memcpy(fil->faddr, &src_addr, ETH_ALEN); - spin_lock(&adapter->mac_learn_lock); - hlist_add_head(&(fil->fnode), head); - adapter->fhash.fnum++; - spin_unlock(&adapter->mac_learn_lock); -} - -static int -qlcnic_tx_pkt(struct qlcnic_adapter *adapter, - struct cmd_desc_type0 *first_desc, - struct sk_buff *skb) -{ - u8 opcode = 0, hdr_len = 0; - u16 flags = 0, vlan_tci = 0; - int copied, offset, copy_len; - struct cmd_desc_type0 *hwdesc; - struct vlan_ethhdr *vh; - struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; - u16 protocol = ntohs(skb->protocol); - u32 producer = tx_ring->producer; - - if (protocol == ETH_P_8021Q) { - vh = (struct vlan_ethhdr *)skb->data; - flags = FLAGS_VLAN_TAGGED; - vlan_tci = vh->h_vlan_TCI; - protocol = ntohs(vh->h_vlan_encapsulated_proto); - } else if (vlan_tx_tag_present(skb)) { - flags = FLAGS_VLAN_OOB; - vlan_tci = vlan_tx_tag_get(skb); - } - if (unlikely(adapter->pvid)) { - if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED)) - return -EIO; - if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED)) - goto set_flags; - - flags = FLAGS_VLAN_OOB; - vlan_tci = adapter->pvid; - } -set_flags: - qlcnic_set_tx_vlan_tci(first_desc, vlan_tci); - qlcnic_set_tx_flags_opcode(first_desc, flags, opcode); - - if (*(skb->data) & BIT_0) { - flags |= BIT_0; - memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN); - } - opcode = TX_ETHER_PKT; - if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && - skb_shinfo(skb)->gso_size > 0) { - - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - - first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); - first_desc->total_hdr_length = hdr_len; - - opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO; - - /* For LSO, we need to copy the MAC/IP/TCP headers into - * the descriptor ring */ - copied = 0; - offset = 2; - - if (flags & FLAGS_VLAN_OOB) { - first_desc->total_hdr_length += VLAN_HLEN; - first_desc->tcp_hdr_offset = VLAN_HLEN; - first_desc->ip_hdr_offset = VLAN_HLEN; - /* Only in case of TSO on vlan device */ - flags |= FLAGS_VLAN_TAGGED; - - /* Create a TSO vlan header template for firmware */ - - hwdesc = &tx_ring->desc_head[producer]; - tx_ring->cmd_buf_arr[producer].skb = NULL; - - copy_len = min((int)sizeof(struct cmd_desc_type0) - - offset, hdr_len + VLAN_HLEN); - - vh = (struct vlan_ethhdr *)((char *) hwdesc + 2); - skb_copy_from_linear_data(skb, vh, 12); - vh->h_vlan_proto = htons(ETH_P_8021Q); - vh->h_vlan_TCI = htons(vlan_tci); - - skb_copy_from_linear_data_offset(skb, 12, - (char *)vh + 16, copy_len - 16); - - copied = copy_len - VLAN_HLEN; - offset = 0; - - producer = get_next_index(producer, tx_ring->num_desc); - } - - while (copied < hdr_len) { - - copy_len = min((int)sizeof(struct cmd_desc_type0) - - offset, (hdr_len - copied)); - - hwdesc = &tx_ring->desc_head[producer]; - tx_ring->cmd_buf_arr[producer].skb = NULL; - - skb_copy_from_linear_data_offset(skb, copied, - (char *) hwdesc + offset, copy_len); - - copied += copy_len; - offset = 0; - - producer = get_next_index(producer, tx_ring->num_desc); - } - - tx_ring->producer = producer; - smp_mb(); - adapter->stats.lso_frames++; - - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - u8 l4proto; - - if (protocol == ETH_P_IP) { - l4proto = ip_hdr(skb)->protocol; - - if (l4proto == IPPROTO_TCP) - opcode = TX_TCP_PKT; - else if (l4proto == IPPROTO_UDP) - opcode = TX_UDP_PKT; - } else if (protocol == ETH_P_IPV6) { - l4proto = ipv6_hdr(skb)->nexthdr; - - if (l4proto == IPPROTO_TCP) - opcode = TX_TCPV6_PKT; - else if (l4proto == IPPROTO_UDP) - opcode = TX_UDPV6_PKT; - } - } - first_desc->tcp_hdr_offset += skb_transport_offset(skb); - first_desc->ip_hdr_offset += skb_network_offset(skb); - qlcnic_set_tx_flags_opcode(first_desc, flags, opcode); - - return 0; -} - -static int -qlcnic_map_tx_skb(struct pci_dev *pdev, - struct sk_buff *skb, struct qlcnic_cmd_buffer *pbuf) -{ - struct qlcnic_skb_frag *nf; - struct skb_frag_struct *frag; - int i, nr_frags; - dma_addr_t map; - - nr_frags = skb_shinfo(skb)->nr_frags; - nf = &pbuf->frag_array[0]; - - map = pci_map_single(pdev, skb->data, - skb_headlen(skb), PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(pdev, map)) - goto out_err; - - nf->dma = map; - nf->length = skb_headlen(skb); - - for (i = 0; i < nr_frags; i++) { - frag = &skb_shinfo(skb)->frags[i]; - nf = &pbuf->frag_array[i+1]; - - map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag), - DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, map)) - goto unwind; - - nf->dma = map; - nf->length = skb_frag_size(frag); - } - - return 0; - -unwind: - while (--i >= 0) { - nf = &pbuf->frag_array[i+1]; - pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); - } - - nf = &pbuf->frag_array[0]; - pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); - -out_err: - return -ENOMEM; -} - -static void -qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb, - struct qlcnic_cmd_buffer *pbuf) -{ - struct qlcnic_skb_frag *nf = &pbuf->frag_array[0]; - int nr_frags = skb_shinfo(skb)->nr_frags; - int i; - - for (i = 0; i < nr_frags; i++) { - nf = &pbuf->frag_array[i+1]; - pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); - } - - nf = &pbuf->frag_array[0]; - pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); - pbuf->skb = NULL; -} - -static inline void -qlcnic_clear_cmddesc(u64 *desc) -{ - desc[0] = 0ULL; - desc[2] = 0ULL; - desc[7] = 0ULL; -} - -netdev_tx_t -qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct qlcnic_adapter *adapter = netdev_priv(netdev); - struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; - struct qlcnic_cmd_buffer *pbuf; - struct qlcnic_skb_frag *buffrag; - struct cmd_desc_type0 *hwdesc, *first_desc; - struct pci_dev *pdev; - struct ethhdr *phdr; - int delta = 0; - int i, k; - - u32 producer; - int frag_count; - u32 num_txd = tx_ring->num_desc; - - if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { - netif_stop_queue(netdev); - return NETDEV_TX_BUSY; - } - - if (adapter->flags & QLCNIC_MACSPOOF) { - phdr = (struct ethhdr *)skb->data; - if (!ether_addr_equal(phdr->h_source, adapter->mac_addr)) - goto drop_packet; - } - - frag_count = skb_shinfo(skb)->nr_frags + 1; - /* 14 frags supported for normal packet and - * 32 frags supported for TSO packet - */ - if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) { - - for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++) - delta += skb_frag_size(&skb_shinfo(skb)->frags[i]); - - if (!__pskb_pull_tail(skb, delta)) - goto drop_packet; - - frag_count = 1 + skb_shinfo(skb)->nr_frags; - } - - if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) { - netif_stop_queue(netdev); - if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) - netif_start_queue(netdev); - else { - adapter->stats.xmit_off++; - return NETDEV_TX_BUSY; - } - } - - producer = tx_ring->producer; - pbuf = &tx_ring->cmd_buf_arr[producer]; - - pdev = adapter->pdev; - - first_desc = hwdesc = &tx_ring->desc_head[producer]; - qlcnic_clear_cmddesc((u64 *)hwdesc); - - if (qlcnic_map_tx_skb(pdev, skb, pbuf)) { - adapter->stats.tx_dma_map_error++; - goto drop_packet; - } - - pbuf->skb = skb; - pbuf->frag_count = frag_count; - - qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len); - qlcnic_set_tx_port(first_desc, adapter->portnum); - - for (i = 0; i < frag_count; i++) { - - k = i % 4; - - if ((k == 0) && (i > 0)) { - /* move to next desc.*/ - producer = get_next_index(producer, num_txd); - hwdesc = &tx_ring->desc_head[producer]; - qlcnic_clear_cmddesc((u64 *)hwdesc); - tx_ring->cmd_buf_arr[producer].skb = NULL; - } - - buffrag = &pbuf->frag_array[i]; - - hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length); - switch (k) { - case 0: - hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); - break; - case 1: - hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma); - break; - case 2: - hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma); - break; - case 3: - hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma); - break; - } - } - - tx_ring->producer = get_next_index(producer, num_txd); - smp_mb(); - - if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb))) - goto unwind_buff; - - if (adapter->mac_learn) - qlcnic_send_filter(adapter, tx_ring, first_desc, skb); - - adapter->stats.txbytes += skb->len; - adapter->stats.xmitcalled++; - - qlcnic_update_cmd_producer(adapter, tx_ring); - - return NETDEV_TX_OK; - -unwind_buff: - qlcnic_unmap_buffers(pdev, skb, pbuf); -drop_packet: - adapter->stats.txdropped++; - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} - static int qlcnic_check_temp(struct qlcnic_adapter *adapter) { struct net_device *netdev = adapter->netdev; - u32 temp, temp_state, temp_val; + u32 temp_state, temp_val, temp = 0; int rv = 0; - temp = QLCRD32(adapter, CRB_TEMP_STATE); + if (qlcnic_82xx_check(adapter)) + temp = QLCRD32(adapter, CRB_TEMP_STATE); temp_state = qlcnic_get_temp_state(temp); temp_val = qlcnic_get_temp_val(temp); @@ -2367,7 +1885,7 @@ static int qlcnic_check_temp(struct qlcnic_adapter *adapter) temp_val); rv = 1; } else if (temp_state == QLCNIC_TEMP_WARN) { - if (adapter->temp == QLCNIC_TEMP_NORMAL) { + if (adapter->ahw->temp == QLCNIC_TEMP_NORMAL) { dev_err(&netdev->dev, "Device temperature %d degrees C " "exceeds operating range." @@ -2375,37 +1893,16 @@ static int qlcnic_check_temp(struct qlcnic_adapter *adapter) temp_val); } } else { - if (adapter->temp == QLCNIC_TEMP_WARN) { + if (adapter->ahw->temp == QLCNIC_TEMP_WARN) { dev_info(&netdev->dev, "Device temperature is now %d degrees C" " in normal range.\n", temp_val); } } - adapter->temp = temp_state; + adapter->ahw->temp = temp_state; return rv; } -void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup) -{ - struct net_device *netdev = adapter->netdev; - - if (adapter->ahw->linkup && !linkup) { - netdev_info(netdev, "NIC Link is down\n"); - adapter->ahw->linkup = 0; - if (netif_running(netdev)) { - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } - } else if (!adapter->ahw->linkup && linkup) { - netdev_info(netdev, "NIC Link is up\n"); - adapter->ahw->linkup = 1; - if (netif_running(netdev)) { - netif_carrier_on(netdev); - netif_wake_queue(netdev); - } - } -} - static void qlcnic_tx_timeout(struct net_device *netdev) { struct qlcnic_adapter *adapter = netdev_priv(netdev); @@ -2418,7 +1915,7 @@ static void qlcnic_tx_timeout(struct net_device *netdev) if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) adapter->need_fw_reset = 1; else - adapter->reset_context = 1; + adapter->ahw->reset_context = 1; } static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) @@ -2442,7 +1939,7 @@ static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter) status = readl(adapter->isr_int_vec); - if (!(status & adapter->int_vec_bit)) + if (!(status & adapter->ahw->int_vec_bit)) return IRQ_NONE; /* check interrupt state machine, to be sure */ @@ -2474,7 +1971,7 @@ static irqreturn_t qlcnic_tmp_intr(int irq, void *data) return IRQ_NONE; done: - adapter->diag_cnt++; + adapter->ahw->diag_cnt++; qlcnic_enable_int(sds_ring); return IRQ_HANDLED; } @@ -2512,122 +2009,6 @@ static irqreturn_t qlcnic_msix_intr(int irq, void *data) return IRQ_HANDLED; } -static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) -{ - u32 sw_consumer, hw_consumer; - int count = 0, i; - struct qlcnic_cmd_buffer *buffer; - struct pci_dev *pdev = adapter->pdev; - struct net_device *netdev = adapter->netdev; - struct qlcnic_skb_frag *frag; - int done; - struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; - - if (!spin_trylock(&adapter->tx_clean_lock)) - return 1; - - sw_consumer = tx_ring->sw_consumer; - hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); - - while (sw_consumer != hw_consumer) { - buffer = &tx_ring->cmd_buf_arr[sw_consumer]; - if (buffer->skb) { - frag = &buffer->frag_array[0]; - pci_unmap_single(pdev, frag->dma, frag->length, - PCI_DMA_TODEVICE); - frag->dma = 0ULL; - for (i = 1; i < buffer->frag_count; i++) { - frag++; - pci_unmap_page(pdev, frag->dma, frag->length, - PCI_DMA_TODEVICE); - frag->dma = 0ULL; - } - - adapter->stats.xmitfinished++; - dev_kfree_skb_any(buffer->skb); - buffer->skb = NULL; - } - - sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc); - if (++count >= MAX_STATUS_HANDLE) - break; - } - - if (count && netif_running(netdev)) { - tx_ring->sw_consumer = sw_consumer; - - smp_mb(); - - if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { - if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { - netif_wake_queue(netdev); - adapter->stats.xmit_on++; - } - } - adapter->tx_timeo_cnt = 0; - } - /* - * If everything is freed up to consumer then check if the ring is full - * If the ring is full then check if more needs to be freed and - * schedule the call back again. - * - * This happens when there are 2 CPUs. One could be freeing and the - * other filling it. If the ring is full when we get out of here and - * the card has already interrupted the host then the host can miss the - * interrupt. - * - * There is still a possible race condition and the host could miss an - * interrupt. The card has to take care of this. - */ - hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); - done = (sw_consumer == hw_consumer); - spin_unlock(&adapter->tx_clean_lock); - - return done; -} - -static int qlcnic_poll(struct napi_struct *napi, int budget) -{ - struct qlcnic_host_sds_ring *sds_ring = - container_of(napi, struct qlcnic_host_sds_ring, napi); - - struct qlcnic_adapter *adapter = sds_ring->adapter; - - int tx_complete; - int work_done; - - tx_complete = qlcnic_process_cmd_ring(adapter); - - work_done = qlcnic_process_rcv_ring(sds_ring, budget); - - if ((work_done < budget) && tx_complete) { - napi_complete(&sds_ring->napi); - if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) - qlcnic_enable_int(sds_ring); - } - - return work_done; -} - -static int qlcnic_rx_poll(struct napi_struct *napi, int budget) -{ - struct qlcnic_host_sds_ring *sds_ring = - container_of(napi, struct qlcnic_host_sds_ring, napi); - - struct qlcnic_adapter *adapter = sds_ring->adapter; - int work_done; - - work_done = qlcnic_process_rcv_ring(sds_ring, budget); - - if (work_done < budget) { - napi_complete(&sds_ring->napi); - if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) - qlcnic_enable_int(sds_ring); - } - - return work_done; -} - #ifdef CONFIG_NET_POLL_CONTROLLER static void qlcnic_poll_controller(struct net_device *netdev) { @@ -2871,7 +2252,7 @@ qlcnic_fwinit_work(struct work_struct *work) return; } - if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { + if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { qlcnic_api_unlock(adapter); goto wait_npar; } @@ -2987,9 +2368,9 @@ qlcnic_detach_work(struct work_struct *work) goto err_ret; } - if (adapter->temp == QLCNIC_TEMP_PANIC) { + if (adapter->ahw->temp == QLCNIC_TEMP_PANIC) { dev_err(&adapter->pdev->dev, "Detaching the device: temp=%d\n", - adapter->temp); + adapter->ahw->temp); goto err_ret; } @@ -3114,7 +2495,7 @@ qlcnic_attach_work(struct work_struct *work) struct net_device *netdev = adapter->netdev; u32 npar_state; - if (adapter->op_mode != QLCNIC_MGMT_FUNC) { + if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) { npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO) qlcnic_clr_all_drv_state(adapter, 0); @@ -3171,7 +2552,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter) if (adapter->need_fw_reset) goto detach; - if (adapter->reset_context && auto_fw_reset) { + if (adapter->ahw->reset_context && qlcnic_auto_fw_reset) { qlcnic_reset_hw_context(adapter); adapter->netdev->trans_start = jiffies; } @@ -3186,7 +2567,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter) qlcnic_dev_request_reset(adapter); - if (auto_fw_reset) + if (qlcnic_auto_fw_reset) clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state); dev_err(&adapter->pdev->dev, "firmware hang detected\n"); @@ -3211,8 +2592,8 @@ detach: adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state : QLCNIC_DEV_NEED_RESET; - if (auto_fw_reset && - !test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) { + if (qlcnic_auto_fw_reset && !test_and_set_bit(__QLCNIC_RESETTING, + &adapter->state)) { qlcnic_schedule_work(adapter, qlcnic_detach_work, 0); QLCDB(adapter, DRV, "fw recovery scheduled.\n"); @@ -3283,7 +2664,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev) if (qlcnic_api_lock(adapter)) return -EINVAL; - if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) { + if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) { adapter->need_fw_reset = 1; set_bit(__QLCNIC_START_FW, &adapter->state); QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING); @@ -3395,96 +2776,9 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) return err; } -static int -qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable) -{ - return -EOPNOTSUPP; -} - -static int -qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) -{ - return -EOPNOTSUPP; -} - -static ssize_t -qlcnic_store_bridged_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - unsigned long new; - int ret = -EINVAL; - - if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)) - goto err_out; - - if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) - goto err_out; - - if (strict_strtoul(buf, 2, &new)) - goto err_out; - - if (!adapter->nic_ops->config_bridged_mode(adapter, !!new)) - ret = len; - -err_out: - return ret; -} - -static ssize_t -qlcnic_show_bridged_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - int bridged_mode = 0; - - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) - bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED); - - return sprintf(buf, "%d\n", bridged_mode); -} - -static struct device_attribute dev_attr_bridged_mode = { - .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)}, - .show = qlcnic_show_bridged_mode, - .store = qlcnic_store_bridged_mode, -}; - -static ssize_t -qlcnic_store_diag_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - unsigned long new; - - if (strict_strtoul(buf, 2, &new)) - return -EINVAL; - - if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED)) - adapter->flags ^= QLCNIC_DIAG_ENABLED; - - return len; -} - -static ssize_t -qlcnic_show_diag_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", - !!(adapter->flags & QLCNIC_DIAG_ENABLED)); -} - -static struct device_attribute dev_attr_diag_mode = { - .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)}, - .show = qlcnic_show_diag_mode, - .store = qlcnic_store_diag_mode, -}; - int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val) { - if (!use_msi_x && !use_msi) { + if (!qlcnic_use_msi_x && !qlcnic_use_msi) { netdev_info(netdev, "no msix or msi support, hence no rss\n"); return -EINVAL; } @@ -3532,859 +2826,6 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data) return err; } -static int -qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, u8 *state, - u8 *rate) -{ - *rate = LSB(beacon); - *state = MSB(beacon); - - QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state); - - if (!*state) { - *rate = __QLCNIC_MAX_LED_RATE; - return 0; - } else if (*state > __QLCNIC_MAX_LED_STATE) - return -EINVAL; - - if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE)) - return -EINVAL; - - return 0; -} - -static ssize_t -qlcnic_store_beacon(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - int max_sds_rings = adapter->max_sds_rings; - u16 beacon; - u8 b_state, b_rate; - int err; - - if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { - dev_warn(dev, "LED test not supported for non " - "privilege function\n"); - return -EOPNOTSUPP; - } - - if (len != sizeof(u16)) - return QL_STATUS_INVALID_PARAM; - - memcpy(&beacon, buf, sizeof(u16)); - err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate); - if (err) - return err; - - if (adapter->ahw->beacon_state == b_state) - return len; - - rtnl_lock(); - - if (!adapter->ahw->beacon_state) - if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) { - rtnl_unlock(); - return -EBUSY; - } - - if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { - err = -EIO; - goto out; - } - - if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { - err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST); - if (err) - goto out; - set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); - } - - err = qlcnic_config_led(adapter, b_state, b_rate); - - if (!err) { - err = len; - adapter->ahw->beacon_state = b_state; - } - - if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) - qlcnic_diag_free_res(adapter->netdev, max_sds_rings); - - out: - if (!adapter->ahw->beacon_state) - clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); - rtnl_unlock(); - - return err; -} - -static ssize_t -qlcnic_show_beacon(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", adapter->ahw->beacon_state); -} - -static struct device_attribute dev_attr_beacon = { - .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)}, - .show = qlcnic_show_beacon, - .store = qlcnic_store_beacon, -}; - -static int -qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter, - loff_t offset, size_t size) -{ - size_t crb_size = 4; - - if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) - return -EIO; - - if (offset < QLCNIC_PCI_CRBSPACE) { - if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, - QLCNIC_PCI_CAMQM_END)) - crb_size = 8; - else - return -EINVAL; - } - - if ((size != crb_size) || (offset & (crb_size-1))) - return -EINVAL; - - return 0; -} - -static ssize_t -qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - u32 data; - u64 qmdata; - int ret; - - ret = qlcnic_sysfs_validate_crb(adapter, offset, size); - if (ret != 0) - return ret; - - if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { - qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata); - memcpy(buf, &qmdata, size); - } else { - data = QLCRD32(adapter, offset); - memcpy(buf, &data, size); - } - return size; -} - -static ssize_t -qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - u32 data; - u64 qmdata; - int ret; - - ret = qlcnic_sysfs_validate_crb(adapter, offset, size); - if (ret != 0) - return ret; - - if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { - memcpy(&qmdata, buf, size); - qlcnic_pci_camqm_write_2M(adapter, offset, qmdata); - } else { - memcpy(&data, buf, size); - QLCWR32(adapter, offset, data); - } - return size; -} - -static int -qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter, - loff_t offset, size_t size) -{ - if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) - return -EIO; - - if ((size != 8) || (offset & 0x7)) - return -EIO; - - return 0; -} - -static ssize_t -qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - u64 data; - int ret; - - ret = qlcnic_sysfs_validate_mem(adapter, offset, size); - if (ret != 0) - return ret; - - if (qlcnic_pci_mem_read_2M(adapter, offset, &data)) - return -EIO; - - memcpy(buf, &data, size); - - return size; -} - -static ssize_t -qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - u64 data; - int ret; - - ret = qlcnic_sysfs_validate_mem(adapter, offset, size); - if (ret != 0) - return ret; - - memcpy(&data, buf, size); - - if (qlcnic_pci_mem_write_2M(adapter, offset, data)) - return -EIO; - - return size; -} - -static struct bin_attribute bin_attr_crb = { - .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)}, - .size = 0, - .read = qlcnic_sysfs_read_crb, - .write = qlcnic_sysfs_write_crb, -}; - -static struct bin_attribute bin_attr_mem = { - .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)}, - .size = 0, - .read = qlcnic_sysfs_read_mem, - .write = qlcnic_sysfs_write_mem, -}; - -static int -validate_pm_config(struct qlcnic_adapter *adapter, - struct qlcnic_pm_func_cfg *pm_cfg, int count) -{ - - u8 src_pci_func, s_esw_id, d_esw_id; - u8 dest_pci_func; - int i; - - for (i = 0; i < count; i++) { - src_pci_func = pm_cfg[i].pci_func; - dest_pci_func = pm_cfg[i].dest_npar; - if (src_pci_func >= QLCNIC_MAX_PCI_FUNC - || dest_pci_func >= QLCNIC_MAX_PCI_FUNC) - return QL_STATUS_INVALID_PARAM; - - if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC) - return QL_STATUS_INVALID_PARAM; - - if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC) - return QL_STATUS_INVALID_PARAM; - - s_esw_id = adapter->npars[src_pci_func].phy_port; - d_esw_id = adapter->npars[dest_pci_func].phy_port; - - if (s_esw_id != d_esw_id) - return QL_STATUS_INVALID_PARAM; - - } - return 0; - -} - -static ssize_t -qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - struct qlcnic_pm_func_cfg *pm_cfg; - u32 id, action, pci_func; - int count, rem, i, ret; - - count = size / sizeof(struct qlcnic_pm_func_cfg); - rem = size % sizeof(struct qlcnic_pm_func_cfg); - if (rem) - return QL_STATUS_INVALID_PARAM; - - pm_cfg = (struct qlcnic_pm_func_cfg *) buf; - - ret = validate_pm_config(adapter, pm_cfg, count); - if (ret) - return ret; - for (i = 0; i < count; i++) { - pci_func = pm_cfg[i].pci_func; - action = !!pm_cfg[i].action; - id = adapter->npars[pci_func].phy_port; - ret = qlcnic_config_port_mirroring(adapter, id, - action, pci_func); - if (ret) - return ret; - } - - for (i = 0; i < count; i++) { - pci_func = pm_cfg[i].pci_func; - id = adapter->npars[pci_func].phy_port; - adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action; - adapter->npars[pci_func].dest_npar = id; - } - return size; -} - -static ssize_t -qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC]; - int i; - - if (size != sizeof(pm_cfg)) - return QL_STATUS_INVALID_PARAM; - - for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { - if (adapter->npars[i].type != QLCNIC_TYPE_NIC) - continue; - pm_cfg[i].action = adapter->npars[i].enable_pm; - pm_cfg[i].dest_npar = 0; - pm_cfg[i].pci_func = i; - } - memcpy(buf, &pm_cfg, size); - - return size; -} - -static int -validate_esw_config(struct qlcnic_adapter *adapter, - struct qlcnic_esw_func_cfg *esw_cfg, int count) -{ - u32 op_mode; - u8 pci_func; - int i; - - op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE); - - for (i = 0; i < count; i++) { - pci_func = esw_cfg[i].pci_func; - if (pci_func >= QLCNIC_MAX_PCI_FUNC) - return QL_STATUS_INVALID_PARAM; - - if (adapter->op_mode == QLCNIC_MGMT_FUNC) - if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) - return QL_STATUS_INVALID_PARAM; - - switch (esw_cfg[i].op_mode) { - case QLCNIC_PORT_DEFAULTS: - if (QLC_DEV_GET_DRV(op_mode, pci_func) != - QLCNIC_NON_PRIV_FUNC) { - if (esw_cfg[i].mac_anti_spoof != 0) - return QL_STATUS_INVALID_PARAM; - if (esw_cfg[i].mac_override != 1) - return QL_STATUS_INVALID_PARAM; - if (esw_cfg[i].promisc_mode != 1) - return QL_STATUS_INVALID_PARAM; - } - break; - case QLCNIC_ADD_VLAN: - if (!IS_VALID_VLAN(esw_cfg[i].vlan_id)) - return QL_STATUS_INVALID_PARAM; - if (!esw_cfg[i].op_type) - return QL_STATUS_INVALID_PARAM; - break; - case QLCNIC_DEL_VLAN: - if (!esw_cfg[i].op_type) - return QL_STATUS_INVALID_PARAM; - break; - default: - return QL_STATUS_INVALID_PARAM; - } - } - return 0; -} - -static ssize_t -qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - struct qlcnic_esw_func_cfg *esw_cfg; - struct qlcnic_npar_info *npar; - int count, rem, i, ret; - u8 pci_func, op_mode = 0; - - count = size / sizeof(struct qlcnic_esw_func_cfg); - rem = size % sizeof(struct qlcnic_esw_func_cfg); - if (rem) - return QL_STATUS_INVALID_PARAM; - - esw_cfg = (struct qlcnic_esw_func_cfg *) buf; - ret = validate_esw_config(adapter, esw_cfg, count); - if (ret) - return ret; - - for (i = 0; i < count; i++) { - if (adapter->op_mode == QLCNIC_MGMT_FUNC) - if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) - return QL_STATUS_INVALID_PARAM; - - if (adapter->ahw->pci_func != esw_cfg[i].pci_func) - continue; - - op_mode = esw_cfg[i].op_mode; - qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]); - esw_cfg[i].op_mode = op_mode; - esw_cfg[i].pci_func = adapter->ahw->pci_func; - - switch (esw_cfg[i].op_mode) { - case QLCNIC_PORT_DEFAULTS: - qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]); - break; - case QLCNIC_ADD_VLAN: - qlcnic_set_vlan_config(adapter, &esw_cfg[i]); - break; - case QLCNIC_DEL_VLAN: - esw_cfg[i].vlan_id = 0; - qlcnic_set_vlan_config(adapter, &esw_cfg[i]); - break; - } - } - - if (adapter->op_mode != QLCNIC_MGMT_FUNC) - goto out; - - for (i = 0; i < count; i++) { - pci_func = esw_cfg[i].pci_func; - npar = &adapter->npars[pci_func]; - switch (esw_cfg[i].op_mode) { - case QLCNIC_PORT_DEFAULTS: - npar->promisc_mode = esw_cfg[i].promisc_mode; - npar->mac_override = esw_cfg[i].mac_override; - npar->offload_flags = esw_cfg[i].offload_flags; - npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof; - npar->discard_tagged = esw_cfg[i].discard_tagged; - break; - case QLCNIC_ADD_VLAN: - npar->pvid = esw_cfg[i].vlan_id; - break; - case QLCNIC_DEL_VLAN: - npar->pvid = 0; - break; - } - } -out: - return size; -} - -static ssize_t -qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC]; - u8 i; - - if (size != sizeof(esw_cfg)) - return QL_STATUS_INVALID_PARAM; - - for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { - if (adapter->npars[i].type != QLCNIC_TYPE_NIC) - continue; - esw_cfg[i].pci_func = i; - if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i])) - return QL_STATUS_INVALID_PARAM; - } - memcpy(buf, &esw_cfg, size); - - return size; -} - -static int -validate_npar_config(struct qlcnic_adapter *adapter, - struct qlcnic_npar_func_cfg *np_cfg, int count) -{ - u8 pci_func, i; - - for (i = 0; i < count; i++) { - pci_func = np_cfg[i].pci_func; - if (pci_func >= QLCNIC_MAX_PCI_FUNC) - return QL_STATUS_INVALID_PARAM; - - if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) - return QL_STATUS_INVALID_PARAM; - - if (!IS_VALID_BW(np_cfg[i].min_bw) || - !IS_VALID_BW(np_cfg[i].max_bw)) - return QL_STATUS_INVALID_PARAM; - } - return 0; -} - -static ssize_t -qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - struct qlcnic_info nic_info; - struct qlcnic_npar_func_cfg *np_cfg; - int i, count, rem, ret; - u8 pci_func; - - count = size / sizeof(struct qlcnic_npar_func_cfg); - rem = size % sizeof(struct qlcnic_npar_func_cfg); - if (rem) - return QL_STATUS_INVALID_PARAM; - - np_cfg = (struct qlcnic_npar_func_cfg *) buf; - ret = validate_npar_config(adapter, np_cfg, count); - if (ret) - return ret; - - for (i = 0; i < count ; i++) { - pci_func = np_cfg[i].pci_func; - ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func); - if (ret) - return ret; - nic_info.pci_func = pci_func; - nic_info.min_tx_bw = np_cfg[i].min_bw; - nic_info.max_tx_bw = np_cfg[i].max_bw; - ret = qlcnic_set_nic_info(adapter, &nic_info); - if (ret) - return ret; - adapter->npars[i].min_bw = nic_info.min_tx_bw; - adapter->npars[i].max_bw = nic_info.max_tx_bw; - } - - return size; - -} -static ssize_t -qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - struct qlcnic_info nic_info; - struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC]; - int i, ret; - - if (size != sizeof(np_cfg)) - return QL_STATUS_INVALID_PARAM; - - for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) { - if (adapter->npars[i].type != QLCNIC_TYPE_NIC) - continue; - ret = qlcnic_get_nic_info(adapter, &nic_info, i); - if (ret) - return ret; - - np_cfg[i].pci_func = i; - np_cfg[i].op_mode = (u8)nic_info.op_mode; - np_cfg[i].port_num = nic_info.phys_port; - np_cfg[i].fw_capab = nic_info.capabilities; - np_cfg[i].min_bw = nic_info.min_tx_bw ; - np_cfg[i].max_bw = nic_info.max_tx_bw; - np_cfg[i].max_tx_queues = nic_info.max_tx_ques; - np_cfg[i].max_rx_queues = nic_info.max_rx_ques; - } - memcpy(buf, &np_cfg, size); - return size; -} - -static ssize_t -qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - struct qlcnic_esw_statistics port_stats; - int ret; - - if (size != sizeof(struct qlcnic_esw_statistics)) - return QL_STATUS_INVALID_PARAM; - - if (offset >= QLCNIC_MAX_PCI_FUNC) - return QL_STATUS_INVALID_PARAM; - - memset(&port_stats, 0, size); - ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER, - &port_stats.rx); - if (ret) - return ret; - - ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER, - &port_stats.tx); - if (ret) - return ret; - - memcpy(buf, &port_stats, size); - return size; -} - -static ssize_t -qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - struct qlcnic_esw_statistics esw_stats; - int ret; - - if (size != sizeof(struct qlcnic_esw_statistics)) - return QL_STATUS_INVALID_PARAM; - - if (offset >= QLCNIC_NIU_MAX_XG_PORTS) - return QL_STATUS_INVALID_PARAM; - - memset(&esw_stats, 0, size); - ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER, - &esw_stats.rx); - if (ret) - return ret; - - ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER, - &esw_stats.tx); - if (ret) - return ret; - - memcpy(buf, &esw_stats, size); - return size; -} - -static ssize_t -qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - int ret; - - if (offset >= QLCNIC_NIU_MAX_XG_PORTS) - return QL_STATUS_INVALID_PARAM; - - ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset, - QLCNIC_QUERY_RX_COUNTER); - if (ret) - return ret; - - ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset, - QLCNIC_QUERY_TX_COUNTER); - if (ret) - return ret; - - return size; -} - -static ssize_t -qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t offset, size_t size) -{ - - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - int ret; - - if (offset >= QLCNIC_MAX_PCI_FUNC) - return QL_STATUS_INVALID_PARAM; - - ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, - QLCNIC_QUERY_RX_COUNTER); - if (ret) - return ret; - - ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, - QLCNIC_QUERY_TX_COUNTER); - if (ret) - return ret; - - return size; -} - -static ssize_t -qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t offset, size_t size) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC]; - struct qlcnic_pci_info *pci_info; - int i, ret; - - if (size != sizeof(pci_cfg)) - return QL_STATUS_INVALID_PARAM; - - pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); - if (!pci_info) - return -ENOMEM; - - ret = qlcnic_get_pci_info(adapter, pci_info); - if (ret) { - kfree(pci_info); - return ret; - } - - for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) { - pci_cfg[i].pci_func = pci_info[i].id; - pci_cfg[i].func_type = pci_info[i].type; - pci_cfg[i].port_num = pci_info[i].default_port; - pci_cfg[i].min_bw = pci_info[i].tx_min_bw; - pci_cfg[i].max_bw = pci_info[i].tx_max_bw; - memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN); - } - memcpy(buf, &pci_cfg, size); - kfree(pci_info); - return size; -} -static struct bin_attribute bin_attr_npar_config = { - .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)}, - .size = 0, - .read = qlcnic_sysfs_read_npar_config, - .write = qlcnic_sysfs_write_npar_config, -}; - -static struct bin_attribute bin_attr_pci_config = { - .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)}, - .size = 0, - .read = qlcnic_sysfs_read_pci_config, - .write = NULL, -}; - -static struct bin_attribute bin_attr_port_stats = { - .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)}, - .size = 0, - .read = qlcnic_sysfs_get_port_stats, - .write = qlcnic_sysfs_clear_port_stats, -}; - -static struct bin_attribute bin_attr_esw_stats = { - .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)}, - .size = 0, - .read = qlcnic_sysfs_get_esw_stats, - .write = qlcnic_sysfs_clear_esw_stats, -}; - -static struct bin_attribute bin_attr_esw_config = { - .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)}, - .size = 0, - .read = qlcnic_sysfs_read_esw_config, - .write = qlcnic_sysfs_write_esw_config, -}; - -static struct bin_attribute bin_attr_pm_config = { - .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)}, - .size = 0, - .read = qlcnic_sysfs_read_pm_config, - .write = qlcnic_sysfs_write_pm_config, -}; - -static void -qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter) -{ - struct device *dev = &adapter->pdev->dev; - - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) - if (device_create_file(dev, &dev_attr_bridged_mode)) - dev_warn(dev, - "failed to create bridged_mode sysfs entry\n"); -} - -static void -qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter) -{ - struct device *dev = &adapter->pdev->dev; - - if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) - device_remove_file(dev, &dev_attr_bridged_mode); -} - -static void -qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) -{ - struct device *dev = &adapter->pdev->dev; - u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); - - if (device_create_bin_file(dev, &bin_attr_port_stats)) - dev_info(dev, "failed to create port stats sysfs entry"); - - if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) - return; - if (device_create_file(dev, &dev_attr_diag_mode)) - dev_info(dev, "failed to create diag_mode sysfs entry\n"); - if (device_create_bin_file(dev, &bin_attr_crb)) - dev_info(dev, "failed to create crb sysfs entry\n"); - if (device_create_bin_file(dev, &bin_attr_mem)) - dev_info(dev, "failed to create mem sysfs entry\n"); - - if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) - return; - - if (device_create_bin_file(dev, &bin_attr_pci_config)) - dev_info(dev, "failed to create pci config sysfs entry"); - if (device_create_file(dev, &dev_attr_beacon)) - dev_info(dev, "failed to create beacon sysfs entry"); - - if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) - return; - if (device_create_bin_file(dev, &bin_attr_esw_config)) - dev_info(dev, "failed to create esw config sysfs entry"); - if (adapter->op_mode != QLCNIC_MGMT_FUNC) - return; - if (device_create_bin_file(dev, &bin_attr_npar_config)) - dev_info(dev, "failed to create npar config sysfs entry"); - if (device_create_bin_file(dev, &bin_attr_pm_config)) - dev_info(dev, "failed to create pm config sysfs entry"); - if (device_create_bin_file(dev, &bin_attr_esw_stats)) - dev_info(dev, "failed to create eswitch stats sysfs entry"); -} - -static void -qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) -{ - struct device *dev = &adapter->pdev->dev; - u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); - - device_remove_bin_file(dev, &bin_attr_port_stats); - - if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) - return; - device_remove_file(dev, &dev_attr_diag_mode); - device_remove_bin_file(dev, &bin_attr_crb); - device_remove_bin_file(dev, &bin_attr_mem); - if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) - return; - device_remove_bin_file(dev, &bin_attr_pci_config); - device_remove_file(dev, &dev_attr_beacon); - if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) - return; - device_remove_bin_file(dev, &bin_attr_esw_config); - if (adapter->op_mode != QLCNIC_MGMT_FUNC) - return; - device_remove_bin_file(dev, &bin_attr_npar_config); - device_remove_bin_file(dev, &bin_attr_pm_config); - device_remove_bin_file(dev, &bin_attr_esw_stats); -} - #ifdef CONFIG_INET #define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops) @@ -4523,7 +2964,7 @@ static void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event) { } #endif -static const struct pci_error_handlers qlcnic_err_handler = { +static struct pci_error_handlers qlcnic_err_handler = { .error_detected = qlcnic_io_error_detected, .slot_reset = qlcnic_io_slot_reset, .resume = qlcnic_io_resume, @@ -4533,7 +2974,7 @@ static struct pci_driver qlcnic_driver = { .name = qlcnic_driver_name, .id_table = qlcnic_pci_tbl, .probe = qlcnic_probe, - .remove = __devexit_p(qlcnic_remove), + .remove = qlcnic_remove, #ifdef CONFIG_PM .suspend = qlcnic_suspend, .resume = qlcnic_resume, diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c new file mode 100644 index 000000000000..0b8d8625834c --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c @@ -0,0 +1,628 @@ +#include "qlcnic.h" +#include "qlcnic_hdr.h" + +#include <net/ip.h> + +#define QLCNIC_DUMP_WCRB BIT_0 +#define QLCNIC_DUMP_RWCRB BIT_1 +#define QLCNIC_DUMP_ANDCRB BIT_2 +#define QLCNIC_DUMP_ORCRB BIT_3 +#define QLCNIC_DUMP_POLLCRB BIT_4 +#define QLCNIC_DUMP_RD_SAVE BIT_5 +#define QLCNIC_DUMP_WRT_SAVED BIT_6 +#define QLCNIC_DUMP_MOD_SAVE_ST BIT_7 +#define QLCNIC_DUMP_SKIP BIT_7 + +#define QLCNIC_DUMP_MASK_MAX 0xff + +struct qlcnic_common_entry_hdr { + u32 type; + u32 offset; + u32 cap_size; + u8 mask; + u8 rsvd[2]; + u8 flags; +} __packed; + +struct __crb { + u32 addr; + u8 stride; + u8 rsvd1[3]; + u32 data_size; + u32 no_ops; + u32 rsvd2[4]; +} __packed; + +struct __ctrl { + u32 addr; + u8 stride; + u8 index_a; + u16 timeout; + u32 data_size; + u32 no_ops; + u8 opcode; + u8 index_v; + u8 shl_val; + u8 shr_val; + u32 val1; + u32 val2; + u32 val3; +} __packed; + +struct __cache { + u32 addr; + u16 stride; + u16 init_tag_val; + u32 size; + u32 no_ops; + u32 ctrl_addr; + u32 ctrl_val; + u32 read_addr; + u8 read_addr_stride; + u8 read_addr_num; + u8 rsvd1[2]; +} __packed; + +struct __ocm { + u8 rsvd[8]; + u32 size; + u32 no_ops; + u8 rsvd1[8]; + u32 read_addr; + u32 read_addr_stride; +} __packed; + +struct __mem { + u8 rsvd[24]; + u32 addr; + u32 size; +} __packed; + +struct __mux { + u32 addr; + u8 rsvd[4]; + u32 size; + u32 no_ops; + u32 val; + u32 val_stride; + u32 read_addr; + u8 rsvd2[4]; +} __packed; + +struct __queue { + u32 sel_addr; + u16 stride; + u8 rsvd[2]; + u32 size; + u32 no_ops; + u8 rsvd2[8]; + u32 read_addr; + u8 read_addr_stride; + u8 read_addr_cnt; + u8 rsvd3[2]; +} __packed; + +struct qlcnic_dump_entry { + struct qlcnic_common_entry_hdr hdr; + union { + struct __crb crb; + struct __cache cache; + struct __ocm ocm; + struct __mem mem; + struct __mux mux; + struct __queue que; + struct __ctrl ctrl; + } region; +} __packed; + +enum qlcnic_minidump_opcode { + QLCNIC_DUMP_NOP = 0, + QLCNIC_DUMP_READ_CRB = 1, + QLCNIC_DUMP_READ_MUX = 2, + QLCNIC_DUMP_QUEUE = 3, + QLCNIC_DUMP_BRD_CONFIG = 4, + QLCNIC_DUMP_READ_OCM = 6, + QLCNIC_DUMP_PEG_REG = 7, + QLCNIC_DUMP_L1_DTAG = 8, + QLCNIC_DUMP_L1_ITAG = 9, + QLCNIC_DUMP_L1_DATA = 11, + QLCNIC_DUMP_L1_INST = 12, + QLCNIC_DUMP_L2_DTAG = 21, + QLCNIC_DUMP_L2_ITAG = 22, + QLCNIC_DUMP_L2_DATA = 23, + QLCNIC_DUMP_L2_INST = 24, + QLCNIC_DUMP_READ_ROM = 71, + QLCNIC_DUMP_READ_MEM = 72, + QLCNIC_DUMP_READ_CTRL = 98, + QLCNIC_DUMP_TLHDR = 99, + QLCNIC_DUMP_RDEND = 255 +}; + +struct qlcnic_dump_operations { + enum qlcnic_minidump_opcode opcode; + u32 (*handler)(struct qlcnic_adapter *, struct qlcnic_dump_entry *, + __le32 *); +}; + +static void qlcnic_read_dump_reg(u32 addr, void __iomem *bar0, u32 *data) +{ + u32 dest; + void __iomem *window_reg; + + dest = addr & 0xFFFF0000; + window_reg = bar0 + QLCNIC_FW_DUMP_REG1; + writel(dest, window_reg); + readl(window_reg); + window_reg = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr); + *data = readl(window_reg); +} + +static void qlcnic_write_dump_reg(u32 addr, void __iomem *bar0, u32 data) +{ + u32 dest; + void __iomem *window_reg; + + dest = addr & 0xFFFF0000; + window_reg = bar0 + QLCNIC_FW_DUMP_REG1; + writel(dest, window_reg); + readl(window_reg); + window_reg = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr); + writel(data, window_reg); + readl(window_reg); +} + +/* FW dump related functions */ +static u32 qlcnic_dump_crb(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, __le32 *buffer) +{ + int i; + u32 addr, data; + struct __crb *crb = &entry->region.crb; + void __iomem *base = adapter->ahw->pci_base0; + + addr = crb->addr; + + for (i = 0; i < crb->no_ops; i++) { + qlcnic_read_dump_reg(addr, base, &data); + *buffer++ = cpu_to_le32(addr); + *buffer++ = cpu_to_le32(data); + addr += crb->stride; + } + return crb->no_ops * 2 * sizeof(u32); +} + +static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, __le32 *buffer) +{ + int i, k, timeout = 0; + void __iomem *base = adapter->ahw->pci_base0; + u32 addr, data; + u8 no_ops; + struct __ctrl *ctr = &entry->region.ctrl; + struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr; + + addr = ctr->addr; + no_ops = ctr->no_ops; + + for (i = 0; i < no_ops; i++) { + k = 0; + for (k = 0; k < 8; k++) { + if (!(ctr->opcode & (1 << k))) + continue; + switch (1 << k) { + case QLCNIC_DUMP_WCRB: + qlcnic_write_dump_reg(addr, base, ctr->val1); + break; + case QLCNIC_DUMP_RWCRB: + qlcnic_read_dump_reg(addr, base, &data); + qlcnic_write_dump_reg(addr, base, data); + break; + case QLCNIC_DUMP_ANDCRB: + qlcnic_read_dump_reg(addr, base, &data); + qlcnic_write_dump_reg(addr, base, + data & ctr->val2); + break; + case QLCNIC_DUMP_ORCRB: + qlcnic_read_dump_reg(addr, base, &data); + qlcnic_write_dump_reg(addr, base, + data | ctr->val3); + break; + case QLCNIC_DUMP_POLLCRB: + while (timeout <= ctr->timeout) { + qlcnic_read_dump_reg(addr, base, &data); + if ((data & ctr->val2) == ctr->val1) + break; + msleep(1); + timeout++; + } + if (timeout > ctr->timeout) { + dev_info(&adapter->pdev->dev, + "Timed out, aborting poll CRB\n"); + return -EINVAL; + } + break; + case QLCNIC_DUMP_RD_SAVE: + if (ctr->index_a) + addr = t_hdr->saved_state[ctr->index_a]; + qlcnic_read_dump_reg(addr, base, &data); + t_hdr->saved_state[ctr->index_v] = data; + break; + case QLCNIC_DUMP_WRT_SAVED: + if (ctr->index_v) + data = t_hdr->saved_state[ctr->index_v]; + else + data = ctr->val1; + if (ctr->index_a) + addr = t_hdr->saved_state[ctr->index_a]; + qlcnic_write_dump_reg(addr, base, data); + break; + case QLCNIC_DUMP_MOD_SAVE_ST: + data = t_hdr->saved_state[ctr->index_v]; + data <<= ctr->shl_val; + data >>= ctr->shr_val; + if (ctr->val2) + data &= ctr->val2; + data |= ctr->val3; + data += ctr->val1; + t_hdr->saved_state[ctr->index_v] = data; + break; + default: + dev_info(&adapter->pdev->dev, + "Unknown opcode\n"); + break; + } + } + addr += ctr->stride; + } + return 0; +} + +static u32 qlcnic_dump_mux(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, __le32 *buffer) +{ + int loop; + u32 val, data = 0; + struct __mux *mux = &entry->region.mux; + void __iomem *base = adapter->ahw->pci_base0; + + val = mux->val; + for (loop = 0; loop < mux->no_ops; loop++) { + qlcnic_write_dump_reg(mux->addr, base, val); + qlcnic_read_dump_reg(mux->read_addr, base, &data); + *buffer++ = cpu_to_le32(val); + *buffer++ = cpu_to_le32(data); + val += mux->val_stride; + } + return 2 * mux->no_ops * sizeof(u32); +} + +static u32 qlcnic_dump_que(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, __le32 *buffer) +{ + int i, loop; + u32 cnt, addr, data, que_id = 0; + void __iomem *base = adapter->ahw->pci_base0; + struct __queue *que = &entry->region.que; + + addr = que->read_addr; + cnt = que->read_addr_cnt; + + for (loop = 0; loop < que->no_ops; loop++) { + qlcnic_write_dump_reg(que->sel_addr, base, que_id); + addr = que->read_addr; + for (i = 0; i < cnt; i++) { + qlcnic_read_dump_reg(addr, base, &data); + *buffer++ = cpu_to_le32(data); + addr += que->read_addr_stride; + } + que_id += que->stride; + } + return que->no_ops * cnt * sizeof(u32); +} + +static u32 qlcnic_dump_ocm(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, __le32 *buffer) +{ + int i; + u32 data; + void __iomem *addr; + struct __ocm *ocm = &entry->region.ocm; + + addr = adapter->ahw->pci_base0 + ocm->read_addr; + for (i = 0; i < ocm->no_ops; i++) { + data = readl(addr); + *buffer++ = cpu_to_le32(data); + addr += ocm->read_addr_stride; + } + return ocm->no_ops * sizeof(u32); +} + +static u32 qlcnic_read_rom(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, __le32 *buffer) +{ + int i, count = 0; + u32 fl_addr, size, val, lck_val, addr; + struct __mem *rom = &entry->region.mem; + void __iomem *base = adapter->ahw->pci_base0; + + fl_addr = rom->addr; + size = rom->size/4; +lock_try: + lck_val = readl(base + QLCNIC_FLASH_SEM2_LK); + if (!lck_val && count < MAX_CTL_CHECK) { + msleep(10); + count++; + goto lock_try; + } + writel(adapter->ahw->pci_func, (base + QLCNIC_FLASH_LOCK_ID)); + for (i = 0; i < size; i++) { + addr = fl_addr & 0xFFFF0000; + qlcnic_write_dump_reg(FLASH_ROM_WINDOW, base, addr); + addr = LSW(fl_addr) + FLASH_ROM_DATA; + qlcnic_read_dump_reg(addr, base, &val); + fl_addr += 4; + *buffer++ = cpu_to_le32(val); + } + readl(base + QLCNIC_FLASH_SEM2_ULK); + return rom->size; +} + +static u32 qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, __le32 *buffer) +{ + int i; + u32 cnt, val, data, addr; + void __iomem *base = adapter->ahw->pci_base0; + struct __cache *l1 = &entry->region.cache; + + val = l1->init_tag_val; + + for (i = 0; i < l1->no_ops; i++) { + qlcnic_write_dump_reg(l1->addr, base, val); + qlcnic_write_dump_reg(l1->ctrl_addr, base, LSW(l1->ctrl_val)); + addr = l1->read_addr; + cnt = l1->read_addr_num; + while (cnt) { + qlcnic_read_dump_reg(addr, base, &data); + *buffer++ = cpu_to_le32(data); + addr += l1->read_addr_stride; + cnt--; + } + val += l1->stride; + } + return l1->no_ops * l1->read_addr_num * sizeof(u32); +} + +static u32 qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, __le32 *buffer) +{ + int i; + u32 cnt, val, data, addr; + u8 poll_mask, poll_to, time_out = 0; + void __iomem *base = adapter->ahw->pci_base0; + struct __cache *l2 = &entry->region.cache; + + val = l2->init_tag_val; + poll_mask = LSB(MSW(l2->ctrl_val)); + poll_to = MSB(MSW(l2->ctrl_val)); + + for (i = 0; i < l2->no_ops; i++) { + qlcnic_write_dump_reg(l2->addr, base, val); + if (LSW(l2->ctrl_val)) + qlcnic_write_dump_reg(l2->ctrl_addr, base, + LSW(l2->ctrl_val)); + if (!poll_mask) + goto skip_poll; + do { + qlcnic_read_dump_reg(l2->ctrl_addr, base, &data); + if (!(data & poll_mask)) + break; + msleep(1); + time_out++; + } while (time_out <= poll_to); + + if (time_out > poll_to) { + dev_err(&adapter->pdev->dev, + "Timeout exceeded in %s, aborting dump\n", + __func__); + return -EINVAL; + } +skip_poll: + addr = l2->read_addr; + cnt = l2->read_addr_num; + while (cnt) { + qlcnic_read_dump_reg(addr, base, &data); + *buffer++ = cpu_to_le32(data); + addr += l2->read_addr_stride; + cnt--; + } + val += l2->stride; + } + return l2->no_ops * l2->read_addr_num * sizeof(u32); +} + +static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, __le32 *buffer) +{ + u32 addr, data, test, ret = 0; + int i, reg_read; + struct __mem *mem = &entry->region.mem; + void __iomem *base = adapter->ahw->pci_base0; + + reg_read = mem->size; + addr = mem->addr; + /* check for data size of multiple of 16 and 16 byte alignment */ + if ((addr & 0xf) || (reg_read%16)) { + dev_info(&adapter->pdev->dev, + "Unaligned memory addr:0x%x size:0x%x\n", + addr, reg_read); + return -EINVAL; + } + + mutex_lock(&adapter->ahw->mem_lock); + + while (reg_read != 0) { + qlcnic_write_dump_reg(MIU_TEST_ADDR_LO, base, addr); + qlcnic_write_dump_reg(MIU_TEST_ADDR_HI, base, 0); + qlcnic_write_dump_reg(MIU_TEST_CTR, base, + TA_CTL_ENABLE | TA_CTL_START); + + for (i = 0; i < MAX_CTL_CHECK; i++) { + qlcnic_read_dump_reg(MIU_TEST_CTR, base, &test); + if (!(test & TA_CTL_BUSY)) + break; + } + if (i == MAX_CTL_CHECK) { + if (printk_ratelimit()) { + dev_err(&adapter->pdev->dev, + "failed to read through agent\n"); + ret = -EINVAL; + goto out; + } + } + for (i = 0; i < 4; i++) { + qlcnic_read_dump_reg(MIU_TEST_READ_DATA[i], base, + &data); + *buffer++ = cpu_to_le32(data); + } + addr += 16; + reg_read -= 16; + ret += 16; + } +out: + mutex_unlock(&adapter->ahw->mem_lock); + return mem->size; +} + +static u32 qlcnic_dump_nop(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, __le32 *buffer) +{ + entry->hdr.flags |= QLCNIC_DUMP_SKIP; + return 0; +} + +static const struct qlcnic_dump_operations fw_dump_ops[] = { + { QLCNIC_DUMP_NOP, qlcnic_dump_nop }, + { QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb }, + { QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux }, + { QLCNIC_DUMP_QUEUE, qlcnic_dump_que }, + { QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom }, + { QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm }, + { QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl }, + { QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache }, + { QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache }, + { QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache }, + { QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache }, + { QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache }, + { QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache }, + { QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache }, + { QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache }, + { QLCNIC_DUMP_READ_ROM, qlcnic_read_rom }, + { QLCNIC_DUMP_READ_MEM, qlcnic_read_memory }, + { QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl }, + { QLCNIC_DUMP_TLHDR, qlcnic_dump_nop }, + { QLCNIC_DUMP_RDEND, qlcnic_dump_nop }, +}; + +/* Walk the template and collect dump for each entry in the dump template */ +static int +qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry, + u32 size) +{ + int ret = 1; + if (size != entry->hdr.cap_size) { + dev_info(dev, + "Invalid dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n", + entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size); + dev_info(dev, "Aborting further dump capture\n"); + ret = 0; + } + return ret; +} + +int qlcnic_dump_fw(struct qlcnic_adapter *adapter) +{ + __le32 *buffer; + char mesg[64]; + char *msg[] = {mesg, NULL}; + int i, k, ops_cnt, ops_index, dump_size = 0; + u32 entry_offset, dump, no_entries, buf_offset = 0; + struct qlcnic_dump_entry *entry; + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr; + + if (fw_dump->clr) { + dev_info(&adapter->pdev->dev, + "Previous dump not cleared, not capturing dump\n"); + return -EIO; + } + /* Calculate the size for dump data area only */ + for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++) + if (i & tmpl_hdr->drv_cap_mask) + dump_size += tmpl_hdr->cap_sizes[k]; + if (!dump_size) + return -EIO; + + fw_dump->data = vzalloc(dump_size); + if (!fw_dump->data) { + dev_info(&adapter->pdev->dev, + "Unable to allocate (%d KB) for fw dump\n", + dump_size / 1024); + return -ENOMEM; + } + buffer = fw_dump->data; + fw_dump->size = dump_size; + no_entries = tmpl_hdr->num_entries; + ops_cnt = ARRAY_SIZE(fw_dump_ops); + entry_offset = tmpl_hdr->offset; + tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION; + tmpl_hdr->sys_info[1] = adapter->fw_version; + + for (i = 0; i < no_entries; i++) { + entry = (void *)tmpl_hdr + entry_offset; + if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) { + entry->hdr.flags |= QLCNIC_DUMP_SKIP; + entry_offset += entry->hdr.offset; + continue; + } + /* Find the handler for this entry */ + ops_index = 0; + while (ops_index < ops_cnt) { + if (entry->hdr.type == fw_dump_ops[ops_index].opcode) + break; + ops_index++; + } + if (ops_index == ops_cnt) { + dev_info(&adapter->pdev->dev, + "Invalid entry type %d, exiting dump\n", + entry->hdr.type); + goto error; + } + /* Collect dump for this entry */ + dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer); + if (dump && !qlcnic_valid_dump_entry(&adapter->pdev->dev, entry, + dump)) + entry->hdr.flags |= QLCNIC_DUMP_SKIP; + buf_offset += entry->hdr.cap_size; + entry_offset += entry->hdr.offset; + buffer = fw_dump->data + buf_offset; + } + if (dump_size != buf_offset) { + dev_info(&adapter->pdev->dev, + "Captured(%d) and expected size(%d) do not match\n", + buf_offset, dump_size); + goto error; + } else { + fw_dump->clr = 1; + snprintf(mesg, sizeof(mesg), "FW_DUMP=%s", + adapter->netdev->name); + dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n", + fw_dump->size); + /* Send a udev event to notify availability of FW dump */ + kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg); + return 0; + } +error: + vfree(fw_dump->data); + return -EINVAL; +} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c new file mode 100644 index 000000000000..341d37c867ff --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c @@ -0,0 +1,960 @@ +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/interrupt.h> + +#include "qlcnic.h" + +#include <linux/swab.h> +#include <linux/dma-mapping.h> +#include <net/ip.h> +#include <linux/ipv6.h> +#include <linux/inetdevice.h> +#include <linux/sysfs.h> +#include <linux/aer.h> +#include <linux/log2.h> + +int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable) +{ + return -EOPNOTSUPP; +} + +int qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) +{ + return -EOPNOTSUPP; +} + +static ssize_t qlcnic_store_bridged_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + unsigned long new; + int ret = -EINVAL; + + if (!(adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)) + goto err_out; + + if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) + goto err_out; + + if (strict_strtoul(buf, 2, &new)) + goto err_out; + + if (!adapter->nic_ops->config_bridged_mode(adapter, !!new)) + ret = len; + +err_out: + return ret; +} + +static ssize_t qlcnic_show_bridged_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + int bridged_mode = 0; + + if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG) + bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED); + + return sprintf(buf, "%d\n", bridged_mode); +} + +static ssize_t qlcnic_store_diag_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + unsigned long new; + + if (strict_strtoul(buf, 2, &new)) + return -EINVAL; + + if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED)) + adapter->flags ^= QLCNIC_DIAG_ENABLED; + + return len; +} + +static ssize_t qlcnic_show_diag_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", + !!(adapter->flags & QLCNIC_DIAG_ENABLED)); +} + +static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, + u8 *state, u8 *rate) +{ + *rate = LSB(beacon); + *state = MSB(beacon); + + QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state); + + if (!*state) { + *rate = __QLCNIC_MAX_LED_RATE; + return 0; + } else if (*state > __QLCNIC_MAX_LED_STATE) { + return -EINVAL; + } + + if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE)) + return -EINVAL; + + return 0; +} + +static ssize_t qlcnic_store_beacon(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + int max_sds_rings = adapter->max_sds_rings; + u16 beacon; + u8 b_state, b_rate; + int err; + + if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { + dev_warn(dev, + "LED test not supported in non privileged mode\n"); + return -EOPNOTSUPP; + } + + if (len != sizeof(u16)) + return QL_STATUS_INVALID_PARAM; + + memcpy(&beacon, buf, sizeof(u16)); + err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate); + if (err) + return err; + + if (adapter->ahw->beacon_state == b_state) + return len; + + rtnl_lock(); + + if (!adapter->ahw->beacon_state) + if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) { + rtnl_unlock(); + return -EBUSY; + } + + if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { + err = -EIO; + goto out; + } + + if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { + err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST); + if (err) + goto out; + set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); + } + + err = qlcnic_config_led(adapter, b_state, b_rate); + + if (!err) { + err = len; + adapter->ahw->beacon_state = b_state; + } + + if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) + qlcnic_diag_free_res(adapter->netdev, max_sds_rings); + + out: + if (!adapter->ahw->beacon_state) + clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); + rtnl_unlock(); + + return err; +} + +static ssize_t qlcnic_show_beacon(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", adapter->ahw->beacon_state); +} + +static int qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter, + loff_t offset, size_t size) +{ + size_t crb_size = 4; + + if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) + return -EIO; + + if (offset < QLCNIC_PCI_CRBSPACE) { + if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, + QLCNIC_PCI_CAMQM_END)) + crb_size = 8; + else + return -EINVAL; + } + + if ((size != crb_size) || (offset & (crb_size-1))) + return -EINVAL; + + return 0; +} + +static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t offset, size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + u32 data; + u64 qmdata; + int ret; + + ret = qlcnic_sysfs_validate_crb(adapter, offset, size); + if (ret != 0) + return ret; + + if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { + qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata); + memcpy(buf, &qmdata, size); + } else { + data = QLCRD32(adapter, offset); + memcpy(buf, &data, size); + } + return size; +} + +static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t offset, size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + u32 data; + u64 qmdata; + int ret; + + ret = qlcnic_sysfs_validate_crb(adapter, offset, size); + if (ret != 0) + return ret; + + if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { + memcpy(&qmdata, buf, size); + qlcnic_pci_camqm_write_2M(adapter, offset, qmdata); + } else { + memcpy(&data, buf, size); + QLCWR32(adapter, offset, data); + } + return size; +} + +static int qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter, + loff_t offset, size_t size) +{ + if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) + return -EIO; + + if ((size != 8) || (offset & 0x7)) + return -EIO; + + return 0; +} + +static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t offset, size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + u64 data; + int ret; + + ret = qlcnic_sysfs_validate_mem(adapter, offset, size); + if (ret != 0) + return ret; + + if (qlcnic_pci_mem_read_2M(adapter, offset, &data)) + return -EIO; + + memcpy(buf, &data, size); + + return size; +} + +static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t offset, size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + u64 data; + int ret; + + ret = qlcnic_sysfs_validate_mem(adapter, offset, size); + if (ret != 0) + return ret; + + memcpy(&data, buf, size); + + if (qlcnic_pci_mem_write_2M(adapter, offset, data)) + return -EIO; + + return size; +} + +static int validate_pm_config(struct qlcnic_adapter *adapter, + struct qlcnic_pm_func_cfg *pm_cfg, int count) +{ + u8 src_pci_func, s_esw_id, d_esw_id, dest_pci_func; + int i; + + for (i = 0; i < count; i++) { + src_pci_func = pm_cfg[i].pci_func; + dest_pci_func = pm_cfg[i].dest_npar; + if (src_pci_func >= QLCNIC_MAX_PCI_FUNC || + dest_pci_func >= QLCNIC_MAX_PCI_FUNC) + return QL_STATUS_INVALID_PARAM; + + if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC) + return QL_STATUS_INVALID_PARAM; + + if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC) + return QL_STATUS_INVALID_PARAM; + + s_esw_id = adapter->npars[src_pci_func].phy_port; + d_esw_id = adapter->npars[dest_pci_func].phy_port; + + if (s_esw_id != d_esw_id) + return QL_STATUS_INVALID_PARAM; + } + return 0; + +} + +static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t offset, + size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + struct qlcnic_pm_func_cfg *pm_cfg; + u32 id, action, pci_func; + int count, rem, i, ret; + + count = size / sizeof(struct qlcnic_pm_func_cfg); + rem = size % sizeof(struct qlcnic_pm_func_cfg); + if (rem) + return QL_STATUS_INVALID_PARAM; + + pm_cfg = (struct qlcnic_pm_func_cfg *)buf; + + ret = validate_pm_config(adapter, pm_cfg, count); + if (ret) + return ret; + for (i = 0; i < count; i++) { + pci_func = pm_cfg[i].pci_func; + action = !!pm_cfg[i].action; + id = adapter->npars[pci_func].phy_port; + ret = qlcnic_config_port_mirroring(adapter, id, action, + pci_func); + if (ret) + return ret; + } + + for (i = 0; i < count; i++) { + pci_func = pm_cfg[i].pci_func; + id = adapter->npars[pci_func].phy_port; + adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action; + adapter->npars[pci_func].dest_npar = id; + } + return size; +} + +static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t offset, + size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC]; + int i; + + if (size != sizeof(pm_cfg)) + return QL_STATUS_INVALID_PARAM; + + for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { + if (adapter->npars[i].type != QLCNIC_TYPE_NIC) + continue; + pm_cfg[i].action = adapter->npars[i].enable_pm; + pm_cfg[i].dest_npar = 0; + pm_cfg[i].pci_func = i; + } + memcpy(buf, &pm_cfg, size); + + return size; +} + +static int validate_esw_config(struct qlcnic_adapter *adapter, + struct qlcnic_esw_func_cfg *esw_cfg, int count) +{ + u32 op_mode; + u8 pci_func; + int i; + + op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE); + + for (i = 0; i < count; i++) { + pci_func = esw_cfg[i].pci_func; + if (pci_func >= QLCNIC_MAX_PCI_FUNC) + return QL_STATUS_INVALID_PARAM; + + if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) { + if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) + return QL_STATUS_INVALID_PARAM; + } + + switch (esw_cfg[i].op_mode) { + case QLCNIC_PORT_DEFAULTS: + if (QLC_DEV_GET_DRV(op_mode, pci_func) != + QLCNIC_NON_PRIV_FUNC) { + if (esw_cfg[i].mac_anti_spoof != 0) + return QL_STATUS_INVALID_PARAM; + if (esw_cfg[i].mac_override != 1) + return QL_STATUS_INVALID_PARAM; + if (esw_cfg[i].promisc_mode != 1) + return QL_STATUS_INVALID_PARAM; + } + break; + case QLCNIC_ADD_VLAN: + if (!IS_VALID_VLAN(esw_cfg[i].vlan_id)) + return QL_STATUS_INVALID_PARAM; + if (!esw_cfg[i].op_type) + return QL_STATUS_INVALID_PARAM; + break; + case QLCNIC_DEL_VLAN: + if (!esw_cfg[i].op_type) + return QL_STATUS_INVALID_PARAM; + break; + default: + return QL_STATUS_INVALID_PARAM; + } + } + return 0; +} + +static ssize_t qlcnic_sysfs_write_esw_config(struct file *file, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t offset, + size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + struct qlcnic_esw_func_cfg *esw_cfg; + struct qlcnic_npar_info *npar; + int count, rem, i, ret; + u8 pci_func, op_mode = 0; + + count = size / sizeof(struct qlcnic_esw_func_cfg); + rem = size % sizeof(struct qlcnic_esw_func_cfg); + if (rem) + return QL_STATUS_INVALID_PARAM; + + esw_cfg = (struct qlcnic_esw_func_cfg *)buf; + ret = validate_esw_config(adapter, esw_cfg, count); + if (ret) + return ret; + + for (i = 0; i < count; i++) { + if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) { + if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) + return QL_STATUS_INVALID_PARAM; + } + + if (adapter->ahw->pci_func != esw_cfg[i].pci_func) + continue; + + op_mode = esw_cfg[i].op_mode; + qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]); + esw_cfg[i].op_mode = op_mode; + esw_cfg[i].pci_func = adapter->ahw->pci_func; + + switch (esw_cfg[i].op_mode) { + case QLCNIC_PORT_DEFAULTS: + qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]); + break; + case QLCNIC_ADD_VLAN: + qlcnic_set_vlan_config(adapter, &esw_cfg[i]); + break; + case QLCNIC_DEL_VLAN: + esw_cfg[i].vlan_id = 0; + qlcnic_set_vlan_config(adapter, &esw_cfg[i]); + break; + } + } + + if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) + goto out; + + for (i = 0; i < count; i++) { + pci_func = esw_cfg[i].pci_func; + npar = &adapter->npars[pci_func]; + switch (esw_cfg[i].op_mode) { + case QLCNIC_PORT_DEFAULTS: + npar->promisc_mode = esw_cfg[i].promisc_mode; + npar->mac_override = esw_cfg[i].mac_override; + npar->offload_flags = esw_cfg[i].offload_flags; + npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof; + npar->discard_tagged = esw_cfg[i].discard_tagged; + break; + case QLCNIC_ADD_VLAN: + npar->pvid = esw_cfg[i].vlan_id; + break; + case QLCNIC_DEL_VLAN: + npar->pvid = 0; + break; + } + } +out: + return size; +} + +static ssize_t qlcnic_sysfs_read_esw_config(struct file *file, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t offset, + size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC]; + u8 i; + + if (size != sizeof(esw_cfg)) + return QL_STATUS_INVALID_PARAM; + + for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { + if (adapter->npars[i].type != QLCNIC_TYPE_NIC) + continue; + esw_cfg[i].pci_func = i; + if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i])) + return QL_STATUS_INVALID_PARAM; + } + memcpy(buf, &esw_cfg, size); + + return size; +} + +static int validate_npar_config(struct qlcnic_adapter *adapter, + struct qlcnic_npar_func_cfg *np_cfg, + int count) +{ + u8 pci_func, i; + + for (i = 0; i < count; i++) { + pci_func = np_cfg[i].pci_func; + if (pci_func >= QLCNIC_MAX_PCI_FUNC) + return QL_STATUS_INVALID_PARAM; + + if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) + return QL_STATUS_INVALID_PARAM; + + if (!IS_VALID_BW(np_cfg[i].min_bw) || + !IS_VALID_BW(np_cfg[i].max_bw)) + return QL_STATUS_INVALID_PARAM; + } + return 0; +} + +static ssize_t qlcnic_sysfs_write_npar_config(struct file *file, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t offset, + size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + struct qlcnic_info nic_info; + struct qlcnic_npar_func_cfg *np_cfg; + int i, count, rem, ret; + u8 pci_func; + + count = size / sizeof(struct qlcnic_npar_func_cfg); + rem = size % sizeof(struct qlcnic_npar_func_cfg); + if (rem) + return QL_STATUS_INVALID_PARAM; + + np_cfg = (struct qlcnic_npar_func_cfg *)buf; + ret = validate_npar_config(adapter, np_cfg, count); + if (ret) + return ret; + + for (i = 0; i < count ; i++) { + pci_func = np_cfg[i].pci_func; + ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func); + if (ret) + return ret; + nic_info.pci_func = pci_func; + nic_info.min_tx_bw = np_cfg[i].min_bw; + nic_info.max_tx_bw = np_cfg[i].max_bw; + ret = qlcnic_set_nic_info(adapter, &nic_info); + if (ret) + return ret; + adapter->npars[i].min_bw = nic_info.min_tx_bw; + adapter->npars[i].max_bw = nic_info.max_tx_bw; + } + + return size; + +} + +static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t offset, + size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + struct qlcnic_info nic_info; + struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC]; + int i, ret; + + if (size != sizeof(np_cfg)) + return QL_STATUS_INVALID_PARAM; + + for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { + if (adapter->npars[i].type != QLCNIC_TYPE_NIC) + continue; + ret = qlcnic_get_nic_info(adapter, &nic_info, i); + if (ret) + return ret; + + np_cfg[i].pci_func = i; + np_cfg[i].op_mode = (u8)nic_info.op_mode; + np_cfg[i].port_num = nic_info.phys_port; + np_cfg[i].fw_capab = nic_info.capabilities; + np_cfg[i].min_bw = nic_info.min_tx_bw; + np_cfg[i].max_bw = nic_info.max_tx_bw; + np_cfg[i].max_tx_queues = nic_info.max_tx_ques; + np_cfg[i].max_rx_queues = nic_info.max_rx_ques; + } + memcpy(buf, &np_cfg, size); + return size; +} + +static ssize_t qlcnic_sysfs_get_port_stats(struct file *file, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t offset, + size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + struct qlcnic_esw_statistics port_stats; + int ret; + + if (size != sizeof(struct qlcnic_esw_statistics)) + return QL_STATUS_INVALID_PARAM; + + if (offset >= QLCNIC_MAX_PCI_FUNC) + return QL_STATUS_INVALID_PARAM; + + memset(&port_stats, 0, size); + ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER, + &port_stats.rx); + if (ret) + return ret; + + ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER, + &port_stats.tx); + if (ret) + return ret; + + memcpy(buf, &port_stats, size); + return size; +} + +static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t offset, + size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + struct qlcnic_esw_statistics esw_stats; + int ret; + + if (size != sizeof(struct qlcnic_esw_statistics)) + return QL_STATUS_INVALID_PARAM; + + if (offset >= QLCNIC_NIU_MAX_XG_PORTS) + return QL_STATUS_INVALID_PARAM; + + memset(&esw_stats, 0, size); + ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER, + &esw_stats.rx); + if (ret) + return ret; + + ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER, + &esw_stats.tx); + if (ret) + return ret; + + memcpy(buf, &esw_stats, size); + return size; +} + +static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t offset, + size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + int ret; + + if (offset >= QLCNIC_NIU_MAX_XG_PORTS) + return QL_STATUS_INVALID_PARAM; + + ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset, + QLCNIC_QUERY_RX_COUNTER); + if (ret) + return ret; + + ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset, + QLCNIC_QUERY_TX_COUNTER); + if (ret) + return ret; + + return size; +} + +static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t offset, + size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + int ret; + + if (offset >= QLCNIC_MAX_PCI_FUNC) + return QL_STATUS_INVALID_PARAM; + + ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, + QLCNIC_QUERY_RX_COUNTER); + if (ret) + return ret; + + ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, + QLCNIC_QUERY_TX_COUNTER); + if (ret) + return ret; + + return size; +} + +static ssize_t qlcnic_sysfs_read_pci_config(struct file *file, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t offset, + size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC]; + struct qlcnic_pci_info *pci_info; + int i, ret; + + if (size != sizeof(pci_cfg)) + return QL_STATUS_INVALID_PARAM; + + pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); + if (!pci_info) + return -ENOMEM; + + ret = qlcnic_get_pci_info(adapter, pci_info); + if (ret) { + kfree(pci_info); + return ret; + } + + for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) { + pci_cfg[i].pci_func = pci_info[i].id; + pci_cfg[i].func_type = pci_info[i].type; + pci_cfg[i].port_num = pci_info[i].default_port; + pci_cfg[i].min_bw = pci_info[i].tx_min_bw; + pci_cfg[i].max_bw = pci_info[i].tx_max_bw; + memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN); + } + memcpy(buf, &pci_cfg, size); + kfree(pci_info); + return size; +} + +static struct device_attribute dev_attr_bridged_mode = { + .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)}, + .show = qlcnic_show_bridged_mode, + .store = qlcnic_store_bridged_mode, +}; + +static struct device_attribute dev_attr_diag_mode = { + .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)}, + .show = qlcnic_show_diag_mode, + .store = qlcnic_store_diag_mode, +}; + +static struct device_attribute dev_attr_beacon = { + .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)}, + .show = qlcnic_show_beacon, + .store = qlcnic_store_beacon, +}; + +static struct bin_attribute bin_attr_crb = { + .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_read_crb, + .write = qlcnic_sysfs_write_crb, +}; + +static struct bin_attribute bin_attr_mem = { + .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_read_mem, + .write = qlcnic_sysfs_write_mem, +}; + +static struct bin_attribute bin_attr_npar_config = { + .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_read_npar_config, + .write = qlcnic_sysfs_write_npar_config, +}; + +static struct bin_attribute bin_attr_pci_config = { + .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_read_pci_config, + .write = NULL, +}; + +static struct bin_attribute bin_attr_port_stats = { + .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_get_port_stats, + .write = qlcnic_sysfs_clear_port_stats, +}; + +static struct bin_attribute bin_attr_esw_stats = { + .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_get_esw_stats, + .write = qlcnic_sysfs_clear_esw_stats, +}; + +static struct bin_attribute bin_attr_esw_config = { + .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_read_esw_config, + .write = qlcnic_sysfs_write_esw_config, +}; + +static struct bin_attribute bin_attr_pm_config = { + .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_read_pm_config, + .write = qlcnic_sysfs_write_pm_config, +}; + +void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter) +{ + struct device *dev = &adapter->pdev->dev; + + if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG) + if (device_create_file(dev, &dev_attr_bridged_mode)) + dev_warn(dev, + "failed to create bridged_mode sysfs entry\n"); +} + +void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter) +{ + struct device *dev = &adapter->pdev->dev; + + if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG) + device_remove_file(dev, &dev_attr_bridged_mode); +} + +void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) +{ + struct device *dev = &adapter->pdev->dev; + u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); + + if (device_create_bin_file(dev, &bin_attr_port_stats)) + dev_info(dev, "failed to create port stats sysfs entry"); + + if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) + return; + if (device_create_file(dev, &dev_attr_diag_mode)) + dev_info(dev, "failed to create diag_mode sysfs entry\n"); + if (device_create_bin_file(dev, &bin_attr_crb)) + dev_info(dev, "failed to create crb sysfs entry\n"); + if (device_create_bin_file(dev, &bin_attr_mem)) + dev_info(dev, "failed to create mem sysfs entry\n"); + + if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) + return; + + if (device_create_bin_file(dev, &bin_attr_pci_config)) + dev_info(dev, "failed to create pci config sysfs entry"); + if (device_create_file(dev, &dev_attr_beacon)) + dev_info(dev, "failed to create beacon sysfs entry"); + + if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) + return; + if (device_create_bin_file(dev, &bin_attr_esw_config)) + dev_info(dev, "failed to create esw config sysfs entry"); + if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) + return; + if (device_create_bin_file(dev, &bin_attr_npar_config)) + dev_info(dev, "failed to create npar config sysfs entry"); + if (device_create_bin_file(dev, &bin_attr_pm_config)) + dev_info(dev, "failed to create pm config sysfs entry"); + if (device_create_bin_file(dev, &bin_attr_esw_stats)) + dev_info(dev, "failed to create eswitch stats sysfs entry"); +} + +void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) +{ + struct device *dev = &adapter->pdev->dev; + u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); + + device_remove_bin_file(dev, &bin_attr_port_stats); + + if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) + return; + device_remove_file(dev, &dev_attr_diag_mode); + device_remove_bin_file(dev, &bin_attr_crb); + device_remove_bin_file(dev, &bin_attr_mem); + if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) + return; + device_remove_bin_file(dev, &bin_attr_pci_config); + device_remove_file(dev, &dev_attr_beacon); + if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) + return; + device_remove_bin_file(dev, &bin_attr_esw_config); + if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) + return; + device_remove_bin_file(dev, &bin_attr_npar_config); + device_remove_bin_file(dev, &bin_attr_pm_config); + device_remove_bin_file(dev, &bin_attr_esw_stats); +} diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c index 58185b604b72..10093f0c4c0f 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c @@ -86,7 +86,7 @@ exit: } /* Read out the SERDES registers */ -static int ql_read_serdes_reg(struct ql_adapter *qdev, u32 reg, u32 * data) +static int ql_read_serdes_reg(struct ql_adapter *qdev, u32 reg, u32 *data) { int status; @@ -364,7 +364,7 @@ exit: /* Read the 400 xgmac control/statistics registers * skipping unused locations. */ -static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 * buf, +static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 *buf, unsigned int other_function) { int status = 0; @@ -405,7 +405,7 @@ static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 * buf, return status; } -static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf) +static int ql_get_ets_regs(struct ql_adapter *qdev, u32 *buf) { int status = 0; int i; @@ -423,7 +423,7 @@ static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf) return status; } -static void ql_get_intr_states(struct ql_adapter *qdev, u32 * buf) +static void ql_get_intr_states(struct ql_adapter *qdev, u32 *buf) { int i; @@ -434,7 +434,7 @@ static void ql_get_intr_states(struct ql_adapter *qdev, u32 * buf) } } -static int ql_get_cam_entries(struct ql_adapter *qdev, u32 * buf) +static int ql_get_cam_entries(struct ql_adapter *qdev, u32 *buf) { int i, status; u32 value[3]; @@ -471,7 +471,7 @@ err: return status; } -static int ql_get_routing_entries(struct ql_adapter *qdev, u32 * buf) +static int ql_get_routing_entries(struct ql_adapter *qdev, u32 *buf) { int status; u32 value, i; @@ -496,7 +496,7 @@ err: } /* Read the MPI Processor shadow registers */ -static int ql_get_mpi_shadow_regs(struct ql_adapter *qdev, u32 * buf) +static int ql_get_mpi_shadow_regs(struct ql_adapter *qdev, u32 *buf) { u32 i; int status; @@ -515,7 +515,7 @@ end: } /* Read the MPI Processor core registers */ -static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 * buf, +static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 *buf, u32 offset, u32 count) { int i, status = 0; diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index b262d6156816..3e73742024b0 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -4491,8 +4491,8 @@ static void ql_release_all(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } -static int __devinit ql_init_device(struct pci_dev *pdev, - struct net_device *ndev, int cards_found) +static int ql_init_device(struct pci_dev *pdev, struct net_device *ndev, + int cards_found) { struct ql_adapter *qdev = netdev_priv(ndev); int err = 0; @@ -4656,8 +4656,8 @@ static void ql_timer(unsigned long data) mod_timer(&qdev->timer, jiffies + (5*HZ)); } -static int __devinit qlge_probe(struct pci_dev *pdev, - const struct pci_device_id *pci_entry) +static int qlge_probe(struct pci_dev *pdev, + const struct pci_device_id *pci_entry) { struct net_device *ndev = NULL; struct ql_adapter *qdev = NULL; @@ -4678,7 +4678,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev, qdev = netdev_priv(ndev); SET_NETDEV_DEV(ndev, &pdev->dev); ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN | + NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM; ndev->features = ndev->hw_features | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; @@ -4729,7 +4729,7 @@ int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget) return ql_clean_inbound_rx_ring(rx_ring, budget); } -static void __devexit qlge_remove(struct pci_dev *pdev) +static void qlge_remove(struct pci_dev *pdev) { struct net_device *ndev = pci_get_drvdata(pdev); struct ql_adapter *qdev = netdev_priv(ndev); @@ -4921,7 +4921,7 @@ static struct pci_driver qlge_driver = { .name = DRV_NAME, .id_table = qlge_pci_tbl, .probe = qlge_probe, - .remove = __devexit_p(qlge_remove), + .remove = qlge_remove, #ifdef CONFIG_PM .suspend = qlge_suspend, .resume = qlge_resume, diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c index 557a26545d75..63c13125db6c 100644 --- a/drivers/net/ethernet/rdc/r6040.c +++ b/drivers/net/ethernet/rdc/r6040.c @@ -206,7 +206,7 @@ struct r6040_private { int old_duplex; }; -static char version[] __devinitdata = DRV_NAME +static char version[] = DRV_NAME ": RDC R6040 NAPI net driver," "version "DRV_VERSION " (" DRV_RELDATE ")"; @@ -1073,8 +1073,7 @@ static int r6040_mii_probe(struct net_device *dev) return 0; } -static int __devinit r6040_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int r6040_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; struct r6040_private *lp; @@ -1246,7 +1245,7 @@ err_out: return err; } -static void __devexit r6040_remove_one(struct pci_dev *pdev) +static void r6040_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct r6040_private *lp = netdev_priv(dev); @@ -1274,7 +1273,7 @@ static struct pci_driver r6040_driver = { .name = DRV_NAME, .id_table = r6040_pci_tbl, .probe = r6040_init_one, - .remove = __devexit_p(r6040_remove_one), + .remove = r6040_remove_one, }; module_pci_driver(r6040_driver); diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 1c818254b7be..5ac93323a40c 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -577,28 +577,30 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) { struct net_device *dev = dev_instance; struct cp_private *cp; + int handled = 0; u16 status; if (unlikely(dev == NULL)) return IRQ_NONE; cp = netdev_priv(dev); + spin_lock(&cp->lock); + status = cpr16(IntrStatus); if (!status || (status == 0xFFFF)) - return IRQ_NONE; + goto out_unlock; + + handled = 1; netif_dbg(cp, intr, dev, "intr, status %04x cmd %02x cpcmd %04x\n", status, cpr8(Cmd), cpr16(CpCmd)); cpw16(IntrStatus, status & ~cp_rx_intr_mask); - spin_lock(&cp->lock); - /* close possible race's with dev_close */ if (unlikely(!netif_running(dev))) { cpw16(IntrMask, 0); - spin_unlock(&cp->lock); - return IRQ_HANDLED; + goto out_unlock; } if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) @@ -612,7 +614,6 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) if (status & LinkChg) mii_check_media(&cp->mii_if, netif_msg_link(cp), false); - spin_unlock(&cp->lock); if (status & PciErr) { u16 pci_status; @@ -625,7 +626,10 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) /* TODO: reset hardware */ } - return IRQ_HANDLED; +out_unlock: + spin_unlock(&cp->lock); + + return IRQ_RETVAL(handled); } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -648,6 +652,7 @@ static void cp_tx (struct cp_private *cp) { unsigned tx_head = cp->tx_head; unsigned tx_tail = cp->tx_tail; + unsigned bytes_compl = 0, pkts_compl = 0; while (tx_tail != tx_head) { struct cp_desc *txd = cp->tx_ring + tx_tail; @@ -666,6 +671,9 @@ static void cp_tx (struct cp_private *cp) le32_to_cpu(txd->opts1) & 0xffff, PCI_DMA_TODEVICE); + bytes_compl += skb->len; + pkts_compl++; + if (status & LastFrag) { if (status & (TxError | TxFIFOUnder)) { netif_dbg(cp, tx_err, cp->dev, @@ -697,6 +705,7 @@ static void cp_tx (struct cp_private *cp) cp->tx_tail = tx_tail; + netdev_completed_queue(cp->dev, pkts_compl, bytes_compl); if (TX_BUFFS_AVAIL(cp) > (MAX_SKB_FRAGS + 1)) netif_wake_queue(cp->dev); } @@ -843,6 +852,8 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, wmb(); } cp->tx_head = entry; + + netdev_sent_queue(dev, skb->len); netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n", entry, skb->len); if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1)) @@ -937,6 +948,8 @@ static void cp_stop_hw (struct cp_private *cp) cp->rx_tail = 0; cp->tx_head = cp->tx_tail = 0; + + netdev_reset_queue(cp->dev); } static void cp_reset_hw (struct cp_private *cp) @@ -957,8 +970,38 @@ static void cp_reset_hw (struct cp_private *cp) static inline void cp_start_hw (struct cp_private *cp) { + dma_addr_t ring_dma; + cpw16(CpCmd, cp->cpcmd); + + /* + * These (at least TxRingAddr) need to be configured after the + * corresponding bits in CpCmd are enabled. Datasheet v1.6 §6.33 + * (C+ Command Register) recommends that these and more be configured + * *after* the [RT]xEnable bits in CpCmd are set. And on some hardware + * it's been observed that the TxRingAddr is actually reset to garbage + * when C+ mode Tx is enabled in CpCmd. + */ + cpw32_f(HiTxRingAddr, 0); + cpw32_f(HiTxRingAddr + 4, 0); + + ring_dma = cp->ring_dma; + cpw32_f(RxRingAddr, ring_dma & 0xffffffff); + cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); + + ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; + cpw32_f(TxRingAddr, ring_dma & 0xffffffff); + cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); + + /* + * Strictly speaking, the datasheet says this should be enabled + * *before* setting the descriptor addresses. But what, then, would + * prevent it from doing DMA to random unconfigured addresses? + * This variant appears to work fine. + */ cpw8(Cmd, RxOn | TxOn); + + netdev_reset_queue(cp->dev); } static void cp_enable_irq(struct cp_private *cp) @@ -969,7 +1012,6 @@ static void cp_enable_irq(struct cp_private *cp) static void cp_init_hw (struct cp_private *cp) { struct net_device *dev = cp->dev; - dma_addr_t ring_dma; cp_reset_hw(cp); @@ -979,17 +1021,6 @@ static void cp_init_hw (struct cp_private *cp) cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); - cpw32_f(HiTxRingAddr, 0); - cpw32_f(HiTxRingAddr + 4, 0); - - ring_dma = cp->ring_dma; - cpw32_f(RxRingAddr, ring_dma & 0xffffffff); - cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); - - ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; - cpw32_f(TxRingAddr, ring_dma & 0xffffffff); - cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); - cp_start_hw(cp); cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ @@ -1060,17 +1091,22 @@ static int cp_init_rings (struct cp_private *cp) static int cp_alloc_rings (struct cp_private *cp) { + struct device *d = &cp->pdev->dev; void *mem; + int rc; - mem = dma_alloc_coherent(&cp->pdev->dev, CP_RING_BYTES, - &cp->ring_dma, GFP_KERNEL); + mem = dma_alloc_coherent(d, CP_RING_BYTES, &cp->ring_dma, GFP_KERNEL); if (!mem) return -ENOMEM; cp->rx_ring = mem; cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE]; - return cp_init_rings(cp); + rc = cp_init_rings(cp); + if (rc < 0) + dma_free_coherent(d, CP_RING_BYTES, cp->rx_ring, cp->ring_dma); + + return rc; } static void cp_clean_rings (struct cp_private *cp) @@ -1192,18 +1228,16 @@ static void cp_tx_timeout(struct net_device *dev) cp_clean_rings(cp); rc = cp_init_rings(cp); cp_start_hw(cp); + cp_enable_irq(cp); netif_wake_queue(dev); spin_unlock_irqrestore(&cp->lock, flags); } -#ifdef BROKEN static int cp_change_mtu(struct net_device *dev, int new_mtu) { struct cp_private *cp = netdev_priv(dev); - int rc; - unsigned long flags; /* check for invalid MTU, according to hardware limits */ if (new_mtu < CP_MIN_MTU || new_mtu > CP_MAX_MTU) @@ -1216,22 +1250,12 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu) return 0; } - spin_lock_irqsave(&cp->lock, flags); - - cp_stop_hw(cp); /* stop h/w and free rings */ - cp_clean_rings(cp); - + /* network IS up, close it, reset MTU, and come up again. */ + cp_close(dev); dev->mtu = new_mtu; - cp_set_rxbufsize(cp); /* set new rx buf size */ - - rc = cp_init_rings(cp); /* realloc and restart h/w */ - cp_start_hw(cp); - - spin_unlock_irqrestore(&cp->lock, flags); - - return rc; + cp_set_rxbufsize(cp); + return cp_open(dev); } -#endif /* BROKEN */ static const char mii_2_8139_map[8] = { BasicModeCtrl, @@ -1807,9 +1831,7 @@ static const struct net_device_ops cp_netdev_ops = { .ndo_start_xmit = cp_start_xmit, .ndo_tx_timeout = cp_tx_timeout, .ndo_set_features = cp_set_features, -#ifdef BROKEN .ndo_change_mtu = cp_change_mtu, -#endif #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = cp_poll_controller, diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c index 3ed7add23c12..5dc161630127 100644 --- a/drivers/net/ethernet/realtek/8139too.c +++ b/drivers/net/ethernet/realtek/8139too.c @@ -228,7 +228,7 @@ typedef enum { static const struct { const char *name; u32 hw_flags; -} board_info[] __devinitconst = { +} board_info[] = { { "RealTek RTL8139", RTL8139_CAPS }, { "RealTek RTL8129", RTL8129_CAPS }, }; @@ -748,7 +748,7 @@ static void rtl8139_chip_reset (void __iomem *ioaddr) } -static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev) +static struct net_device *rtl8139_init_board(struct pci_dev *pdev) { struct device *d = &pdev->dev; void __iomem *ioaddr; @@ -935,8 +935,8 @@ static const struct net_device_ops rtl8139_netdev_ops = { .ndo_set_features = rtl8139_set_features, }; -static int __devinit rtl8139_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int rtl8139_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct net_device *dev = NULL; struct rtl8139_private *tp; @@ -1103,7 +1103,7 @@ err_out: } -static void __devexit rtl8139_remove_one (struct pci_dev *pdev) +static void rtl8139_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); struct rtl8139_private *tp = netdev_priv(dev); @@ -1141,7 +1141,7 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev) #define EE_READ_CMD (6) #define EE_ERASE_CMD (7) -static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len) +static int read_eeprom(void __iomem *ioaddr, int location, int addr_len) { int i; unsigned retval = 0; @@ -2652,7 +2652,7 @@ static struct pci_driver rtl8139_pci_driver = { .name = DRV_NAME, .id_table = rtl8139_pci_tbl, .probe = rtl8139_init_one, - .remove = __devexit_p(rtl8139_remove_one), + .remove = rtl8139_remove_one, #ifdef CONFIG_PM .suspend = rtl8139_suspend, .resume = rtl8139_resume, diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c index e02f04d7f3ad..9f2d416de750 100644 --- a/drivers/net/ethernet/realtek/atp.c +++ b/drivers/net/ethernet/realtek/atp.c @@ -175,8 +175,7 @@ struct net_local { unsigned int tx_unit_busy:1; unsigned char re_tx, /* Number of packet retransmissions. */ addr_mode, /* Current Rx filter e.g. promiscuous, etc. */ - pac_cnt_in_tx_buf, - chip_type; + pac_cnt_in_tx_buf; }; /* This code, written by wwc@super.org, resets the adapter every @@ -339,7 +338,6 @@ static int __init atp_probe1(long ioaddr) write_reg_high(ioaddr, CMR1, CMR1h_RESET | CMR1h_MUX); lp = netdev_priv(dev); - lp->chip_type = RTL8002; lp->addr_mode = CMR2h_Normal; spin_lock_init(&lp->lock); @@ -852,7 +850,7 @@ net_close(struct net_device *dev) * Set or clear the multicast filter for this adapter. */ -static void set_rx_mode_8002(struct net_device *dev) +static void set_rx_mode(struct net_device *dev) { struct net_local *lp = netdev_priv(dev); long ioaddr = dev->base_addr; @@ -864,58 +862,6 @@ static void set_rx_mode_8002(struct net_device *dev) write_reg_high(ioaddr, CMR2, lp->addr_mode); } -static void set_rx_mode_8012(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - long ioaddr = dev->base_addr; - unsigned char new_mode, mc_filter[8]; /* Multicast hash filter */ - int i; - - if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ - new_mode = CMR2h_PROMISC; - } else if ((netdev_mc_count(dev) > 1000) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - memset(mc_filter, 0xff, sizeof(mc_filter)); - new_mode = CMR2h_Normal; - } else { - struct netdev_hw_addr *ha; - - memset(mc_filter, 0, sizeof(mc_filter)); - netdev_for_each_mc_addr(ha, dev) { - int filterbit = ether_crc_le(ETH_ALEN, ha->addr) & 0x3f; - mc_filter[filterbit >> 5] |= 1 << (filterbit & 31); - } - new_mode = CMR2h_Normal; - } - lp->addr_mode = new_mode; - write_reg(ioaddr, CMR2, CMR2_IRQOUT | 0x04); /* Switch to page 1. */ - for (i = 0; i < 8; i++) - write_reg_byte(ioaddr, i, mc_filter[i]); - if (net_debug > 2 || 1) { - lp->addr_mode = 1; - printk(KERN_DEBUG "%s: Mode %d, setting multicast filter to", - dev->name, lp->addr_mode); - for (i = 0; i < 8; i++) - printk(" %2.2x", mc_filter[i]); - printk(".\n"); - } - - write_reg_high(ioaddr, CMR2, lp->addr_mode); - write_reg(ioaddr, CMR2, CMR2_IRQOUT); /* Switch back to page 0 */ -} - -static void set_rx_mode(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - - if (lp->chip_type == RTL8002) - return set_rx_mode_8002(dev); - else - return set_rx_mode_8012(dev); -} - - static int __init atp_init_module(void) { if (debug) /* Emit version even if no cards detected. */ printk(KERN_INFO "%s", version); diff --git a/drivers/net/ethernet/realtek/atp.h b/drivers/net/ethernet/realtek/atp.h index 0edc642c2c2f..040b13739947 100644 --- a/drivers/net/ethernet/realtek/atp.h +++ b/drivers/net/ethernet/realtek/atp.h @@ -16,8 +16,6 @@ struct rx_header { #define PAR_STATUS 1 #define PAR_CONTROL 2 -enum chip_type { RTL8002, RTL8012 }; - #define Ctrl_LNibRead 0x08 /* LP_PSELECP */ #define Ctrl_HNibRead 0 #define Ctrl_LNibWrite 0x08 /* LP_PSELECP */ diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index e7ff886e8047..11702324a071 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -78,24 +78,18 @@ static const int multicast_filter_limit = 32; #define MAX_READ_REQUEST_SHIFT 12 #define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ -#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ #define R8169_REGS_SIZE 256 #define R8169_NAPI_WEIGHT 64 #define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ #define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ -#define RX_BUF_SIZE 1536 /* Rx Buffer size */ #define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) #define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) #define RTL8169_TX_TIMEOUT (6*HZ) #define RTL8169_PHY_TIMEOUT (10*HZ) -#define RTL_EEPROM_SIG cpu_to_le32(0x8129) -#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) -#define RTL_EEPROM_SIG_ADDR 0x0000 - /* write/read MMIO register */ #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) #define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) @@ -456,6 +450,7 @@ enum rtl8168_registers { #define PWM_EN (1 << 22) #define RXDV_GATED_EN (1 << 19) #define EARLY_TALLY_EN (1 << 16) +#define FORCE_CLK (1 << 15) /* force clock request */ }; enum rtl_register_content { @@ -519,6 +514,7 @@ enum rtl_register_content { PMEnable = (1 << 0), /* Power Management Enable */ /* Config2 register p. 25 */ + ClkReqEn = (1 << 7), /* Clock Request Enable */ MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */ PCI_Clock_66MHz = 0x01, PCI_Clock_33MHz = 0x00, @@ -539,6 +535,7 @@ enum rtl_register_content { Spi_en = (1 << 3), LanWake = (1 << 1), /* LanWake enable/disable */ PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ + ASPM_en = (1 << 0), /* ASPM enable */ /* TBICSR p.28 */ TBIReset = 0x80000000, @@ -687,6 +684,7 @@ enum features { RTL_FEATURE_WOL = (1 << 0), RTL_FEATURE_MSI = (1 << 1), RTL_FEATURE_GMII = (1 << 2), + RTL_FEATURE_FW_LOADED = (1 << 3), }; struct rtl8169_counters { @@ -1816,8 +1814,7 @@ static int rtl8169_set_features(struct net_device *dev, } -static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, - struct sk_buff *skb) +static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb) { return (vlan_tx_tag_present(skb)) ? TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; @@ -1829,8 +1826,6 @@ static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb) if (opts2 & RxVlanTag) __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); - - desc->opts2 = 0; } static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) @@ -2394,8 +2389,10 @@ static void rtl_apply_firmware(struct rtl8169_private *tp) struct rtl_fw *rtl_fw = tp->rtl_fw; /* TODO: release firmware once rtl_phy_write_fw signals failures. */ - if (!IS_ERR_OR_NULL(rtl_fw)) + if (!IS_ERR_OR_NULL(rtl_fw)) { rtl_phy_write_fw(tp, rtl_fw); + tp->features |= RTL_FEATURE_FW_LOADED; + } } static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) @@ -2406,6 +2403,31 @@ static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) rtl_apply_firmware(tp); } +static void r810x_aldps_disable(struct rtl8169_private *tp) +{ + rtl_writephy(tp, 0x1f, 0x0000); + rtl_writephy(tp, 0x18, 0x0310); + msleep(100); +} + +static void r810x_aldps_enable(struct rtl8169_private *tp) +{ + if (!(tp->features & RTL_FEATURE_FW_LOADED)) + return; + + rtl_writephy(tp, 0x1f, 0x0000); + rtl_writephy(tp, 0x18, 0x8310); +} + +static void r8168_aldps_enable_1(struct rtl8169_private *tp) +{ + if (!(tp->features & RTL_FEATURE_FW_LOADED)) + return; + + rtl_writephy(tp, 0x1f, 0x0000); + rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000); +} + static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { @@ -3096,6 +3118,23 @@ static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x0d, 0x0000); } +static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr) +{ + const u16 w[] = { + addr[0] | (addr[1] << 8), + addr[2] | (addr[3] << 8), + addr[4] | (addr[5] << 8) + }; + const struct exgmac_reg e[] = { + { .addr = 0xe0, ERIAR_MASK_1111, .val = w[0] | (w[1] << 16) }, + { .addr = 0xe4, ERIAR_MASK_1111, .val = w[2] }, + { .addr = 0xf0, ERIAR_MASK_1111, .val = w[0] << 16 }, + { .addr = 0xf4, ERIAR_MASK_1111, .val = w[1] | (w[2] << 16) } + }; + + rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e)); +} + static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { @@ -3178,6 +3217,11 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001); rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400); rtl_writephy(tp, 0x1f, 0x0000); + + r8168_aldps_enable_1(tp); + + /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */ + rtl_rar_exgmac_set(tp, tp->dev->dev_addr); } static void rtl8168f_hw_phy_config(struct rtl8169_private *tp) @@ -3250,6 +3294,8 @@ static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x05, 0x8b85); rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); + + r8168_aldps_enable_1(tp); } static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp) @@ -3257,6 +3303,8 @@ static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp) rtl_apply_firmware(tp); rtl8168f_hw_phy_config(tp); + + r8168_aldps_enable_1(tp); } static void rtl8411_hw_phy_config(struct rtl8169_private *tp) @@ -3354,6 +3402,8 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp) rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001); rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400); rtl_writephy(tp, 0x1f, 0x0000); + + r8168_aldps_enable_1(tp); } static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) @@ -3439,21 +3489,19 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp) }; /* Disable ALDPS before ram code */ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x18, 0x0310); - msleep(100); + r810x_aldps_disable(tp); rtl_apply_firmware(tp); rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); + + r810x_aldps_enable(tp); } static void rtl8402_hw_phy_config(struct rtl8169_private *tp) { /* Disable ALDPS before setting firmware */ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x18, 0x0310); - msleep(20); + r810x_aldps_disable(tp); rtl_apply_firmware(tp); @@ -3463,6 +3511,8 @@ static void rtl8402_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x10, 0x401f); rtl_writephy(tp, 0x19, 0x7030); rtl_writephy(tp, 0x1f, 0x0000); + + r810x_aldps_enable(tp); } static void rtl8106e_hw_phy_config(struct rtl8169_private *tp) @@ -3475,9 +3525,7 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp) }; /* Disable ALDPS before ram code */ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x18, 0x0310); - msleep(100); + r810x_aldps_disable(tp); rtl_apply_firmware(tp); @@ -3485,6 +3533,8 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp) rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); + + r810x_aldps_enable(tp); } static void rtl_hw_phy_config(struct net_device *dev) @@ -3708,33 +3758,19 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) { void __iomem *ioaddr = tp->mmio_addr; - u32 high; - u32 low; - - low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); - high = addr[4] | (addr[5] << 8); rtl_lock_work(tp); RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W32(MAC4, high); + RTL_W32(MAC4, addr[4] | addr[5] << 8); RTL_R32(MAC4); - RTL_W32(MAC0, low); + RTL_W32(MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24); RTL_R32(MAC0); - if (tp->mac_version == RTL_GIGA_MAC_VER_34) { - const struct exgmac_reg e[] = { - { .addr = 0xe0, ERIAR_MASK_1111, .val = low }, - { .addr = 0xe4, ERIAR_MASK_1111, .val = high }, - { .addr = 0xf0, ERIAR_MASK_1111, .val = low << 16 }, - { .addr = 0xf4, ERIAR_MASK_1111, .val = high << 16 | - low >> 16 }, - }; - - rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e)); - } + if (tp->mac_version == RTL_GIGA_MAC_VER_34) + rtl_rar_exgmac_set(tp, addr); RTL_W8(Cfg9346, Cfg9346_Lock); @@ -3796,7 +3832,7 @@ static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) } } -static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp) +static void rtl_init_mdio_ops(struct rtl8169_private *tp) { struct mdio_ops *ops = &tp->mdio_ops; @@ -3827,6 +3863,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_25: + case RTL_GIGA_MAC_VER_26: case RTL_GIGA_MAC_VER_29: case RTL_GIGA_MAC_VER_30: case RTL_GIGA_MAC_VER_32: @@ -4046,7 +4084,7 @@ static void rtl_pll_power_up(struct rtl8169_private *tp) rtl_generic_op(tp, tp->pll_power_ops.up); } -static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) +static void rtl_init_pll_power_ops(struct rtl8169_private *tp) { struct pll_power_ops *ops = &tp->pll_power_ops; @@ -4240,7 +4278,7 @@ static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp) RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); } -static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp) +static void rtl_init_jumbo_ops(struct rtl8169_private *tp) { struct jumbo_ops *ops = &tp->jumbo_ops; @@ -4519,6 +4557,9 @@ static void rtl_set_rx_mode(struct net_device *dev) mc_filter[1] = swab32(data); } + if (tp->mac_version == RTL_GIGA_MAC_VER_35) + mc_filter[1] = mc_filter[0] = 0xffffffff; + RTL_W32(MAR0 + 4, mc_filter[1]); RTL_W32(MAR0 + 0, mc_filter[0]); @@ -4678,7 +4719,7 @@ static u32 r8402_csi_read(struct rtl8169_private *tp, int addr) RTL_R32(CSIDR) : ~0; } -static void __devinit rtl_init_csi_ops(struct rtl8169_private *tp) +static void rtl_init_csi_ops(struct rtl8169_private *tp) { struct csi_ops *ops = &tp->csi_ops; @@ -5010,8 +5051,6 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) RTL_W8(MaxTxPacketSize, EarlySize); - rtl_disable_clock_request(pdev); - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); @@ -5020,7 +5059,8 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); - RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); + RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en); + RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); } static void rtl_hw_start_8168f(struct rtl8169_private *tp) @@ -5045,13 +5085,12 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp) RTL_W8(MaxTxPacketSize, EarlySize); - rtl_disable_clock_request(pdev); - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); - RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); - RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); + RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK); + RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en); + RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); } static void rtl_hw_start_8168f_1(struct rtl8169_private *tp) @@ -5108,8 +5147,10 @@ static void rtl_hw_start_8168g_1(struct rtl8169_private *tp) rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN); + RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN); RTL_W8(MaxTxPacketSize, EarlySize); + RTL_W8(Config5, RTL_R8(Config5) | ASPM_en); + RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); @@ -5325,6 +5366,9 @@ static void rtl_hw_start_8105e_1(struct rtl8169_private *tp) RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); + RTL_W8(Config5, RTL_R8(Config5) | ASPM_en); + RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); + RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK); rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1)); } @@ -5350,6 +5394,9 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp) RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); + RTL_W8(Config5, RTL_R8(Config5) | ASPM_en); + RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); + RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK); rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402)); @@ -5371,7 +5418,10 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp) /* Force LAN exit from ASPM if Rx/Tx are not idle */ RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); - RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN); + RTL_W32(MISC, + (RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN); + RTL_W8(Config5, RTL_R8(Config5) | ASPM_en); + RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN); } @@ -5769,7 +5819,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, tp->tx_skb[entry].len = len; txd->addr = cpu_to_le64(mapping); - opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); + opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb)); opts[0] = DescOwn; rtl8169_tso_csum(tp, skb, opts); @@ -6012,8 +6062,6 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget !(status & (RxRWT | RxFOVF)) && (dev->features & NETIF_F_RXALL)) goto process_pkt; - - rtl8169_mark_to_asic(desc, rx_buf_sz); } else { struct sk_buff *skb; dma_addr_t addr; @@ -6034,16 +6082,14 @@ process_pkt: if (unlikely(rtl8169_fragmented_frame(status))) { dev->stats.rx_dropped++; dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, rx_buf_sz); - continue; + goto release_descriptor; } skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], tp, pkt_size, addr); - rtl8169_mark_to_asic(desc, rx_buf_sz); if (!skb) { dev->stats.rx_dropped++; - continue; + goto release_descriptor; } rtl8169_rx_csum(skb, status); @@ -6059,13 +6105,10 @@ process_pkt: tp->rx_stats.bytes += pkt_size; u64_stats_update_end(&tp->rx_stats.syncp); } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } +release_descriptor: + desc->opts2 = 0; + wmb(); + rtl8169_mark_to_asic(desc, rx_buf_sz); } count = cur_rx - tp->cur_rx; @@ -6564,7 +6607,7 @@ static void rtl_shutdown(struct pci_dev *pdev) pm_runtime_put_noidle(d); } -static void __devexit rtl_remove_one(struct pci_dev *pdev) +static void rtl_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct rtl8169_private *tp = netdev_priv(dev); @@ -6684,7 +6727,7 @@ DECLARE_RTL_COND(rtl_rxtx_empty_cond) return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY; } -static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp) +static void rtl_hw_init_8168g(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; u32 data; @@ -6718,7 +6761,7 @@ static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp) return; } -static void __devinit rtl_hw_initialize(struct rtl8169_private *tp) +static void rtl_hw_initialize(struct rtl8169_private *tp) { switch (tp->mac_version) { case RTL_GIGA_MAC_VER_40: @@ -6731,7 +6774,7 @@ static void __devinit rtl_hw_initialize(struct rtl8169_private *tp) } } -static int __devinit +static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; @@ -6982,20 +7025,9 @@ static struct pci_driver rtl8169_pci_driver = { .name = MODULENAME, .id_table = rtl8169_pci_tbl, .probe = rtl_init_one, - .remove = __devexit_p(rtl_remove_one), + .remove = rtl_remove_one, .shutdown = rtl_shutdown, .driver.pm = RTL8169_PM_OPS, }; -static int __init rtl8169_init_module(void) -{ - return pci_register_driver(&rtl8169_pci_driver); -} - -static void __exit rtl8169_cleanup_module(void) -{ - pci_unregister_driver(&rtl8169_pci_driver); -} - -module_init(rtl8169_init_module); -module_exit(rtl8169_cleanup_module); +module_pci_driver(rtl8169_pci_driver); diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index c8bfea0524dd..3d705862bd7d 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -2286,7 +2286,7 @@ static int sh_mdio_init(struct net_device *ndev, int id, for (i = 0; i < PHY_MAX_ADDR; i++) mdp->mii_bus->irq[i] = PHY_POLL; - /* regist mdio bus */ + /* register mdio bus */ ret = mdiobus_register(mdp->mii_bus); if (ret) goto out_free_irq; diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c index 2ed3ab4b3c2d..72fc57dd084d 100644 --- a/drivers/net/ethernet/s6gmac.c +++ b/drivers/net/ethernet/s6gmac.c @@ -954,7 +954,7 @@ static struct net_device_stats *s6gmac_stats(struct net_device *dev) return st; } -static int __devinit s6gmac_probe(struct platform_device *pdev) +static int s6gmac_probe(struct platform_device *pdev) { struct net_device *dev; struct s6gmac *pd; @@ -1030,7 +1030,7 @@ errirq: return res; } -static int __devexit s6gmac_remove(struct platform_device *pdev) +static int s6gmac_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); if (dev) { @@ -1046,7 +1046,7 @@ static int __devexit s6gmac_remove(struct platform_device *pdev) static struct platform_driver s6gmac_driver = { .probe = s6gmac_probe, - .remove = __devexit_p(s6gmac_remove), + .remove = s6gmac_remove, .driver = { .name = "s6gmac", .owner = THIS_MODULE, diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c index 6a40dd03a32f..3aca57853ed4 100644 --- a/drivers/net/ethernet/seeq/ether3.c +++ b/drivers/net/ethernet/seeq/ether3.c @@ -67,7 +67,7 @@ #include <asm/ecard.h> #include <asm/io.h> -static char version[] __devinitdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; +static char version[] = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; #include "ether3.h" @@ -194,7 +194,7 @@ static inline void ether3_ledon(struct net_device *dev) * Read the ethernet address string from the on board rom. * This is an ascii string!!! */ -static int __devinit +static int ether3_addr(char *addr, struct expansion_card *ec) { struct in_chunk_dir cd; @@ -219,7 +219,7 @@ ether3_addr(char *addr, struct expansion_card *ec) /* --------------------------------------------------------------------------- */ -static int __devinit +static int ether3_ramtest(struct net_device *dev, unsigned char byte) { unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL); @@ -268,7 +268,7 @@ ether3_ramtest(struct net_device *dev, unsigned char byte) /* ------------------------------------------------------------------------------- */ -static int __devinit ether3_init_2(struct net_device *dev) +static int ether3_init_2(struct net_device *dev) { int i; @@ -399,12 +399,6 @@ ether3_probe_bus_16(struct net_device *dev, int val) static int ether3_open(struct net_device *dev) { - if (!is_valid_ether_addr(dev->dev_addr)) { - printk(KERN_WARNING "%s: invalid ethernet MAC address\n", - dev->name); - return -EINVAL; - } - if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev)) return -EAGAIN; @@ -748,7 +742,7 @@ static void ether3_tx(struct net_device *dev) } } -static void __devinit ether3_banner(void) +static void ether3_banner(void) { static unsigned version_printed = 0; @@ -767,7 +761,7 @@ static const struct net_device_ops ether3_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, }; -static int __devinit +static int ether3_probe(struct expansion_card *ec, const struct ecard_id *id) { const struct ether3_data *data = id->data; @@ -864,7 +858,7 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id) return ret; } -static void __devexit ether3_remove(struct expansion_card *ec) +static void ether3_remove(struct expansion_card *ec) { struct net_device *dev = ecard_get_drvdata(ec); @@ -894,7 +888,7 @@ static const struct ecard_id ether3_ids[] = { static struct ecard_driver ether3_driver = { .probe = ether3_probe, - .remove = __devexit_p(ether3_remove), + .remove = ether3_remove, .id_table = ether3_ids, .drv = { .name = "ether3", diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c index 4d15bf413bdc..0fde9ca28269 100644 --- a/drivers/net/ethernet/seeq/sgiseeq.c +++ b/drivers/net/ethernet/seeq/sgiseeq.c @@ -721,7 +721,7 @@ static const struct net_device_ops sgiseeq_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit sgiseeq_probe(struct platform_device *pdev) +static int sgiseeq_probe(struct platform_device *pdev) { struct sgiseeq_platform_data *pd = pdev->dev.platform_data; struct hpc3_regs *hpcregs = pd->hpc; diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig index 25906c1d1b15..435b4f1e3488 100644 --- a/drivers/net/ethernet/sfc/Kconfig +++ b/drivers/net/ethernet/sfc/Kconfig @@ -1,10 +1,11 @@ config SFC tristate "Solarflare SFC4000/SFC9000-family support" - depends on PCI && INET + depends on PCI select MDIO select CRC32 select I2C select I2C_ALGOBIT + select PTP_1588_CLOCK ---help--- This driver supports 10-gigabit Ethernet cards based on the Solarflare SFC4000 and SFC9000-family controllers. @@ -34,10 +35,3 @@ config SFC_SRIOV This enables support for the SFC9000 I/O Virtualization features, allowing accelerated network performance in virtualized environments. -config SFC_PTP - bool "Solarflare SFC9000-family PTP support" - depends on SFC && PTP_1588_CLOCK && !(SFC=y && PTP_1588_CLOCK=m) - default y - ---help--- - This enables support for the Precision Time Protocol (PTP) - on SFC9000-family NICs diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile index e11f2ecf69d9..945bf06e69ef 100644 --- a/drivers/net/ethernet/sfc/Makefile +++ b/drivers/net/ethernet/sfc/Makefile @@ -2,9 +2,8 @@ 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_mon.o + mcdi.o mcdi_phy.o mcdi_mon.o ptp.o sfc-$(CONFIG_SFC_MTD) += mtd.o sfc-$(CONFIG_SFC_SRIOV) += siena_sriov.o -sfc-$(CONFIG_SFC_PTP) += ptp.o obj-$(CONFIG_SFC) += sfc.o diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 4f86d0cd516a..bf57b3cb16ab 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -106,8 +106,8 @@ static struct workqueue_struct *reset_workqueue; * * This is only used in MSI-X interrupt mode */ -static unsigned int separate_tx_channels; -module_param(separate_tx_channels, uint, 0444); +static bool separate_tx_channels; +module_param(separate_tx_channels, bool, 0444); MODULE_PARM_DESC(separate_tx_channels, "Use separate channels for TX and RX"); @@ -160,8 +160,8 @@ static unsigned int rss_cpus; module_param(rss_cpus, uint, 0444); MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling"); -static int phy_flash_cfg; -module_param(phy_flash_cfg, int, 0644); +static bool phy_flash_cfg; +module_param(phy_flash_cfg, bool, 0644); MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially"); static unsigned irq_adapt_low_thresh = 8000; @@ -2279,7 +2279,7 @@ int efx_reset(struct efx_nic *efx, enum reset_type method) netif_info(efx, drv, efx->net_dev, "resetting (%s)\n", RESET_TYPE(method)); - netif_device_detach(efx->net_dev); + efx_device_detach_sync(efx); efx_reset_down(efx, method); rc = efx->type->reset(efx, method); @@ -2669,8 +2669,8 @@ static int efx_pci_probe_main(struct efx_nic *efx) * transmission; this is left to the first time one of the network * interfaces is brought up (i.e. efx_net_open). */ -static int __devinit efx_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *entry) +static int efx_pci_probe(struct pci_dev *pci_dev, + const struct pci_device_id *entry) { struct net_device *net_dev; struct efx_nic *efx; @@ -2758,7 +2758,7 @@ static int efx_pm_freeze(struct device *dev) if (efx->state != STATE_DISABLED) { efx->state = STATE_UNINIT; - netif_device_detach(efx->net_dev); + efx_device_detach_sync(efx); efx_stop_all(efx); efx_stop_interrupts(efx, false); diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index f11170bc48bf..50247dfe8f57 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -163,4 +163,17 @@ 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); +static inline void efx_device_detach_sync(struct efx_nic *efx) +{ + struct net_device *dev = efx->net_dev; + + /* Lock/freeze all TX queues so that we can be sure the + * TX scheduler is stopped when we're done and before + * netif_device_present() becomes false. + */ + netif_tx_lock(dev); + netif_device_detach(dev); + netif_tx_unlock(dev); +} + #endif /* EFX_EFX_H */ diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 90f078eff8e6..8e61cd06f66a 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -816,6 +816,9 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) /* MAC address mask including only MC flag */ static const u8 mac_addr_mc_mask[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; +#define IP4_ADDR_FULL_MASK ((__force __be32)~0) +#define PORT_FULL_MASK ((__force __be16)~0) + static int efx_ethtool_get_class_rule(struct efx_nic *efx, struct ethtool_rx_flow_spec *rule) { @@ -865,12 +868,12 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, &spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst, &ip_entry->ip4src, &ip_entry->psrc); EFX_WARN_ON_PARANOID(rc); - ip_mask->ip4src = ~0; - ip_mask->psrc = ~0; + ip_mask->ip4src = IP4_ADDR_FULL_MASK; + ip_mask->psrc = PORT_FULL_MASK; } rule->flow_type = (proto == IPPROTO_TCP) ? TCP_V4_FLOW : UDP_V4_FLOW; - ip_mask->ip4dst = ~0; - ip_mask->pdst = ~0; + ip_mask->ip4dst = IP4_ADDR_FULL_MASK; + ip_mask->pdst = PORT_FULL_MASK; return rc; } @@ -971,7 +974,7 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx, /* Check for unsupported extensions */ if ((rule->flow_type & FLOW_EXT) && - (rule->m_ext.vlan_etype | rule->m_ext.data[0] | + (rule->m_ext.vlan_etype || rule->m_ext.data[0] || rule->m_ext.data[1])) return -EINVAL; @@ -986,16 +989,16 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx, IPPROTO_TCP : IPPROTO_UDP); /* Must match all of destination, */ - if ((__force u32)~ip_mask->ip4dst | - (__force u16)~ip_mask->pdst) + if (!(ip_mask->ip4dst == IP4_ADDR_FULL_MASK && + ip_mask->pdst == PORT_FULL_MASK)) return -EINVAL; /* all or none of source, */ - if ((ip_mask->ip4src | ip_mask->psrc) && - ((__force u32)~ip_mask->ip4src | - (__force u16)~ip_mask->psrc)) + if ((ip_mask->ip4src || ip_mask->psrc) && + !(ip_mask->ip4src == IP4_ADDR_FULL_MASK && + ip_mask->psrc == PORT_FULL_MASK)) return -EINVAL; /* and nothing else */ - if (ip_mask->tos | rule->m_ext.vlan_tci) + if (ip_mask->tos || rule->m_ext.vlan_tci) return -EINVAL; if (ip_mask->ip4src) diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 12b573a8e82b..49bcd196e10d 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -1792,6 +1792,7 @@ const struct efx_nic_type falcon_a1_nic_type = { .remove_port = falcon_remove_port, .handle_global_event = falcon_handle_global_event, .prepare_flush = falcon_prepare_flush, + .finish_flush = efx_port_dummy_op_void, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, .stop_stats = falcon_stop_nic_stats, @@ -1834,6 +1835,7 @@ const struct efx_nic_type falcon_b0_nic_type = { .remove_port = falcon_remove_port, .handle_global_event = falcon_handle_global_event, .prepare_flush = falcon_prepare_flush, + .finish_flush = efx_port_dummy_op_void, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, .stop_stats = falcon_stop_nic_stats, diff --git a/drivers/net/ethernet/sfc/io.h b/drivers/net/ethernet/sfc/io.h index 751d1ec112cc..96759aee1c6c 100644 --- a/drivers/net/ethernet/sfc/io.h +++ b/drivers/net/ethernet/sfc/io.h @@ -22,22 +22,21 @@ * * Notes on locking strategy: * - * Most CSRs are 128-bit (oword) and therefore cannot be read or - * written atomically. Access from the host is buffered by the Bus - * Interface Unit (BIU). Whenever the host reads from the lowest - * address of such a register, or from the address of a different such - * register, the BIU latches the register's value. Subsequent reads - * from higher addresses of the same register will read the latched - * value. Whenever the host writes part of such a register, the BIU - * collects the written value and does not write to the underlying - * register until all 4 dwords have been written. A similar buffering - * scheme applies to host access to the NIC's 64-bit SRAM. + * Many CSRs are very wide and cannot be read or written atomically. + * Writes from the host are buffered by the Bus Interface Unit (BIU) + * up to 128 bits. Whenever the host writes part of such a register, + * the BIU collects the written value and does not write to the + * underlying register until all 4 dwords have been written. A + * similar buffering scheme applies to host access to the NIC's 64-bit + * SRAM. * - * Access to different CSRs and 64-bit SRAM words must be serialised, - * since interleaved access can result in lost writes or lost - * information from read-to-clear fields. We use efx_nic::biu_lock - * for this. (We could use separate locks for read and write, but - * this is not normally a performance bottleneck.) + * Writes to different CSRs and 64-bit SRAM words must be serialised, + * since interleaved access can result in lost writes. We use + * efx_nic::biu_lock for this. + * + * We also serialise reads from 128-bit CSRs and SRAM with the same + * spinlock. This may not be necessary, but it doesn't really matter + * as there are no such reads on the fast path. * * The DMA descriptor pointers (RX_DESC_UPD and TX_DESC_UPD) are * 128-bit but are special-cased in the BIU to avoid the need for @@ -204,20 +203,6 @@ static inline void efx_reado_table(struct efx_nic *efx, efx_oword_t *value, efx_reado(efx, value, reg + index * sizeof(efx_oword_t)); } -/* Write a 32-bit CSR forming part of a table, or 32-bit SRAM */ -static inline void efx_writed_table(struct efx_nic *efx, efx_dword_t *value, - unsigned int reg, unsigned int index) -{ - efx_writed(efx, value, reg + index * sizeof(efx_oword_t)); -} - -/* Read a 32-bit CSR forming part of a table, or 32-bit SRAM */ -static inline void efx_readd_table(struct efx_nic *efx, efx_dword_t *value, - unsigned int reg, unsigned int index) -{ - efx_readd(efx, value, reg + index * sizeof(efx_dword_t)); -} - /* Page-mapped register block size */ #define EFX_PAGE_BLOCK_SIZE 0x2000 diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index aea43cbd0520..0095ce95150b 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -22,7 +22,7 @@ ************************************************************************** */ -#define MCDI_RPC_TIMEOUT 10 /*seconds */ +#define MCDI_RPC_TIMEOUT (10 * HZ) #define MCDI_PDU(efx) \ (efx_port_num(efx) ? MC_SMEM_P1_PDU_OFST : MC_SMEM_P0_PDU_OFST) @@ -120,7 +120,7 @@ static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen) static int efx_mcdi_poll(struct efx_nic *efx) { struct efx_mcdi_iface *mcdi = efx_mcdi(efx); - unsigned int time, finish; + unsigned long time, finish; unsigned int respseq, respcmd, error; unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); unsigned int rc, spins; @@ -136,7 +136,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) * and poll once a jiffy (approximately) */ spins = TICK_USEC; - finish = get_seconds() + MCDI_RPC_TIMEOUT; + finish = jiffies + MCDI_RPC_TIMEOUT; while (1) { if (spins != 0) { @@ -146,7 +146,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) schedule_timeout_uninterruptible(1); } - time = get_seconds(); + time = jiffies; rmb(); efx_readd(efx, ®, pdu); @@ -158,7 +158,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) EFX_DWORD_FIELD(reg, MCDI_HEADER_RESPONSE)) break; - if (time >= finish) + if (time_after(time, finish)) return -ETIMEDOUT; } @@ -207,7 +207,9 @@ out: return 0; } -/* Test and clear MC-rebooted flag for this port/function */ +/* Test and clear MC-rebooted flag for this port/function; reset + * software state as necessary. + */ int efx_mcdi_poll_reboot(struct efx_nic *efx) { unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx); @@ -223,6 +225,11 @@ int efx_mcdi_poll_reboot(struct efx_nic *efx) if (value == 0) return 0; + /* MAC statistics have been cleared on the NIC; clear our copy + * so that efx_update_diff_stat() can continue to work. + */ + memset(&efx->mac_stats, 0, sizeof(efx->mac_stats)); + EFX_ZERO_DWORD(reg); efx_writed(efx, ®, addr); @@ -250,7 +257,7 @@ static int efx_mcdi_await_completion(struct efx_nic *efx) if (wait_event_timeout( mcdi->wq, atomic_read(&mcdi->state) == MCDI_STATE_COMPLETED, - msecs_to_jiffies(MCDI_RPC_TIMEOUT * 1000)) == 0) + MCDI_RPC_TIMEOUT) == 0) return -ETIMEDOUT; /* Check if efx_mcdi_set_mode() switched us back to polled completions. @@ -1216,7 +1223,7 @@ int efx_mcdi_flush_rxqs(struct efx_nic *efx) rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, (u8 *)qid, count * sizeof(*qid), NULL, 0, NULL); - WARN_ON(rc > 0); + WARN_ON(rc < 0); kfree(qid); diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 576a31091165..2d756c1d7142 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -200,6 +200,7 @@ struct efx_tx_queue { /* Members shared between paths and sometimes updated */ unsigned int empty_read_count ____cacheline_aligned_in_smp; #define EFX_EMPTY_COUNT_VALID 0x80000000 + atomic_t flush_outstanding; }; /** @@ -868,9 +869,7 @@ struct efx_nic { struct work_struct peer_work; #endif -#ifdef CONFIG_SFC_PTP struct efx_ptp_data *ptp_data; -#endif /* The following fields may be written more often */ @@ -909,6 +908,7 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * @remove_port: Free resources allocated by probe_port() * @handle_global_event: Handle a "global" event (may be %NULL) * @prepare_flush: Prepare the hardware for flushing the DMA queues + * @finish_flush: Clean up after flushing the DMA queues * @update_stats: Update statistics not provided by event handling * @start_stats: Start the regular fetching of statistics * @stop_stats: Stop the regular fetching of statistics @@ -956,6 +956,7 @@ struct efx_nic_type { void (*remove_port)(struct efx_nic *efx); bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *); void (*prepare_flush)(struct efx_nic *efx); + void (*finish_flush)(struct efx_nic *efx); void (*update_stats)(struct efx_nic *efx); void (*start_stats)(struct efx_nic *efx); void (*stop_stats)(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index aab7cacb2e34..0ad790cc473c 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -73,6 +73,8 @@ _EFX_CHANNEL_MAGIC(_EFX_CHANNEL_MAGIC_TX_DRAIN, \ (_tx_queue)->queue) +static void efx_magic_event(struct efx_channel *channel, u32 magic); + /************************************************************************** * * Solarstorm hardware access @@ -255,9 +257,6 @@ static int efx_alloc_special_buffer(struct efx_nic *efx, buffer->entries = len / EFX_BUF_SIZE; BUG_ON(buffer->dma_addr & (EFX_BUF_SIZE - 1)); - /* All zeros is a potentially valid event so memset to 0xff */ - memset(buffer->addr, 0xff, len); - /* Select new buffer ID */ buffer->index = efx->next_buffer_table; efx->next_buffer_table += buffer->entries; @@ -494,6 +493,9 @@ static void efx_flush_tx_queue(struct efx_tx_queue *tx_queue) struct efx_nic *efx = tx_queue->efx; efx_oword_t tx_flush_descq; + WARN_ON(atomic_read(&tx_queue->flush_outstanding)); + atomic_set(&tx_queue->flush_outstanding, 1); + EFX_POPULATE_OWORD_2(tx_flush_descq, FRF_AZ_TX_FLUSH_DESCQ_CMD, 1, FRF_AZ_TX_FLUSH_DESCQ, tx_queue->queue); @@ -669,6 +671,47 @@ static bool efx_flush_wake(struct efx_nic *efx) && atomic_read(&efx->rxq_flush_pending) > 0)); } +static bool efx_check_tx_flush_complete(struct efx_nic *efx) +{ + bool i = true; + efx_oword_t txd_ptr_tbl; + struct efx_channel *channel; + struct efx_tx_queue *tx_queue; + + efx_for_each_channel(channel, efx) { + efx_for_each_channel_tx_queue(tx_queue, channel) { + efx_reado_table(efx, &txd_ptr_tbl, + FR_BZ_TX_DESC_PTR_TBL, tx_queue->queue); + if (EFX_OWORD_FIELD(txd_ptr_tbl, + FRF_AZ_TX_DESCQ_FLUSH) || + EFX_OWORD_FIELD(txd_ptr_tbl, + FRF_AZ_TX_DESCQ_EN)) { + netif_dbg(efx, hw, efx->net_dev, + "flush did not complete on TXQ %d\n", + tx_queue->queue); + i = false; + } else if (atomic_cmpxchg(&tx_queue->flush_outstanding, + 1, 0)) { + /* The flush is complete, but we didn't + * receive a flush completion event + */ + netif_dbg(efx, hw, efx->net_dev, + "flush complete on TXQ %d, so drain " + "the queue\n", tx_queue->queue); + /* Don't need to increment drain_pending as it + * has already been incremented for the queues + * which did not drain + */ + efx_magic_event(channel, + EFX_CHANNEL_MAGIC_TX_DRAIN( + tx_queue)); + } + } + } + + return i; +} + /* Flush all the transmit queues, and continue flushing receive queues until * they're all flushed. Wait for the DRAIN events to be recieved so that there * are no more RX and TX events left on any channel. */ @@ -680,7 +723,6 @@ int efx_nic_flush_queues(struct efx_nic *efx) struct efx_tx_queue *tx_queue; int rc = 0; - efx->fc_disable++; efx->type->prepare_flush(efx); efx_for_each_channel(channel, efx) { @@ -730,7 +772,8 @@ int efx_nic_flush_queues(struct efx_nic *efx) timeout); } - if (atomic_read(&efx->drain_pending)) { + if (atomic_read(&efx->drain_pending) && + !efx_check_tx_flush_complete(efx)) { netif_err(efx, hw, efx->net_dev, "failed to flush %d queues " "(rx %d+%d)\n", atomic_read(&efx->drain_pending), atomic_read(&efx->rxq_flush_outstanding), @@ -742,7 +785,7 @@ int efx_nic_flush_queues(struct efx_nic *efx) atomic_set(&efx->rxq_flush_outstanding, 0); } - efx->fc_disable--; + efx->type->finish_flush(efx); return rc; } @@ -766,8 +809,13 @@ void efx_nic_eventq_read_ack(struct efx_channel *channel) EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR, channel->eventq_read_ptr & channel->eventq_mask); - efx_writed_table(efx, ®, efx->type->evq_rptr_tbl_base, - channel->channel); + + /* For Falcon A1, EVQ_RPTR_KER is documented as having a step size + * of 4 bytes, but it is really 16 bytes just like later revisions. + */ + efx_writed(efx, ®, + efx->type->evq_rptr_tbl_base + + FR_BZ_EVQ_RPTR_STEP * channel->channel); } /* Use HW to insert a SW defined event */ @@ -1017,9 +1065,10 @@ efx_handle_tx_flush_done(struct efx_nic *efx, efx_qword_t *event) if (qid < EFX_TXQ_TYPES * efx->n_tx_channels) { tx_queue = efx_get_tx_queue(efx, qid / EFX_TXQ_TYPES, qid % EFX_TXQ_TYPES); - - efx_magic_event(tx_queue->channel, - EFX_CHANNEL_MAGIC_TX_DRAIN(tx_queue)); + if (atomic_cmpxchg(&tx_queue->flush_outstanding, 1, 0)) { + efx_magic_event(tx_queue->channel, + EFX_CHANNEL_MAGIC_TX_DRAIN(tx_queue)); + } } } @@ -1565,7 +1614,9 @@ void efx_nic_push_rx_indir_table(struct efx_nic *efx) for (i = 0; i < FR_BZ_RX_INDIRECTION_TBL_ROWS; i++) { EFX_POPULATE_DWORD_1(dword, FRF_BZ_IT_QUEUE, efx->rx_indir_table[i]); - efx_writed_table(efx, &dword, FR_BZ_RX_INDIRECTION_TBL, i); + efx_writed(efx, &dword, + FR_BZ_RX_INDIRECTION_TBL + + FR_BZ_RX_INDIRECTION_TBL_STEP * i); } } @@ -2029,15 +2080,15 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf) for (i = 0; i < table->rows; i++) { switch (table->step) { - case 4: /* 32-bit register or SRAM */ - efx_readd_table(efx, buf, table->offset, i); + case 4: /* 32-bit SRAM */ + efx_readd(efx, buf, table->offset + 4 * i); break; case 8: /* 64-bit SRAM */ efx_sram_readq(efx, efx->membase + table->offset, buf, i); break; - case 16: /* 128-bit register */ + case 16: /* 128-bit-readable register */ efx_reado_table(efx, buf, table->offset, i); break; case 32: /* 128-bit register, interleaved */ diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 438cef11f727..1b0003323498 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -252,7 +252,6 @@ extern int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf, bool spoofchk); struct ethtool_ts_info; -#ifdef CONFIG_SFC_PTP extern void efx_ptp_probe(struct efx_nic *efx); extern int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd); extern int efx_ptp_get_ts_info(struct net_device *net_dev, @@ -260,31 +259,6 @@ extern int efx_ptp_get_ts_info(struct net_device *net_dev, extern bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); extern int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); extern void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); -#else -static inline void efx_ptp_probe(struct efx_nic *efx) {} -static inline int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd) -{ - return -EOPNOTSUPP; -} -static inline int efx_ptp_get_ts_info(struct net_device *net_dev, - struct ethtool_ts_info *ts_info) -{ - ts_info->so_timestamping = (SOF_TIMESTAMPING_SOFTWARE | - SOF_TIMESTAMPING_RX_SOFTWARE); - ts_info->phc_index = -1; - - return 0; -} -static inline bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb) -{ - return false; -} -static inline int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb) -{ - return NETDEV_TX_OK; -} -static inline void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev) {} -#endif extern const struct efx_nic_type falcon_a1_nic_type; extern const struct efx_nic_type falcon_b0_nic_type; @@ -370,6 +344,8 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx) /* Global Resources */ extern int efx_nic_flush_queues(struct efx_nic *efx); +extern void siena_prepare_flush(struct efx_nic *efx); +extern void siena_finish_flush(struct efx_nic *efx); extern void falcon_start_nic_stats(struct efx_nic *efx); extern void falcon_stop_nic_stats(struct efx_nic *efx); extern void falcon_setup_xaui(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 9e0ad1b75c33..d780a0d096b4 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -187,7 +187,6 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) struct efx_nic *efx = rx_queue->efx; struct efx_rx_buffer *rx_buf; struct page *page; - void *page_addr; struct efx_rx_page_state *state; dma_addr_t dma_addr; unsigned index, count; @@ -207,12 +206,10 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) __free_pages(page, efx->rx_buffer_order); return -EIO; } - page_addr = page_address(page); - state = page_addr; + state = page_address(page); state->refcnt = 0; state->dma_addr = dma_addr; - page_addr += sizeof(struct efx_rx_page_state); dma_addr += sizeof(struct efx_rx_page_state); split: @@ -230,7 +227,6 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) /* Use the second half of the page */ get_page(page); dma_addr += (PAGE_SIZE >> 1); - page_addr += (PAGE_SIZE >> 1); ++count; goto split; } diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index ce72ae4f399f..2069f51b2aa9 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -373,7 +373,7 @@ static void efx_iterate_state(struct efx_nic *efx) /* saddr set later and used as incrementing count */ payload->ip.daddr = htonl(INADDR_LOOPBACK); payload->ip.ihl = 5; - payload->ip.check = htons(0xdead); + payload->ip.check = (__force __sum16) htons(0xdead); payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr)); payload->ip.version = IPVERSION; payload->ip.protocol = IPPROTO_UDP; @@ -722,7 +722,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, /* Detach the device so the kernel doesn't transmit during the * loopback test and the watchdog timeout doesn't fire. */ - netif_device_detach(efx->net_dev); + efx_device_detach_sync(efx); if (efx->type->test_chip) { rc_reset = efx->type->test_chip(efx, tests); diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 84b41bf08a38..ba40f67e4f05 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -127,6 +127,18 @@ static void siena_remove_port(struct efx_nic *efx) efx_nic_free_buffer(efx, &efx->stats_buffer); } +void siena_prepare_flush(struct efx_nic *efx) +{ + if (efx->fc_disable++ == 0) + efx_mcdi_set_mac(efx); +} + +void siena_finish_flush(struct efx_nic *efx) +{ + if (--efx->fc_disable == 0) + efx_mcdi_set_mac(efx); +} + static const struct efx_nic_register_test siena_register_tests[] = { { FR_AZ_ADR_REGION, EFX_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) }, @@ -158,7 +170,7 @@ static const struct efx_nic_register_test siena_register_tests[] = { static int siena_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) { - enum reset_type reset_method = reset_method; + enum reset_type reset_method = RESET_TYPE_ALL; int rc, rc2; efx_reset_down(efx, reset_method); @@ -659,7 +671,8 @@ const struct efx_nic_type siena_a0_nic_type = { .reset = siena_reset_hw, .probe_port = siena_probe_port, .remove_port = siena_remove_port, - .prepare_flush = efx_port_dummy_op_void, + .prepare_flush = siena_prepare_flush, + .finish_flush = siena_finish_flush, .update_stats = siena_update_nic_stats, .start_stats = siena_start_nic_stats, .stop_stats = siena_stop_nic_stats, diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c index d49b53dc2a50..90f8d1604f5f 100644 --- a/drivers/net/ethernet/sfc/siena_sriov.c +++ b/drivers/net/ethernet/sfc/siena_sriov.c @@ -695,8 +695,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf) return VFDI_RC_ENOMEM; rtnl_lock(); - if (efx->fc_disable++ == 0) - efx_mcdi_set_mac(efx); + siena_prepare_flush(efx); rtnl_unlock(); /* Flush all the initialized queues */ @@ -733,8 +732,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf) } rtnl_lock(); - if (--efx->fc_disable == 0) - efx_mcdi_set_mac(efx); + siena_finish_flush(efx); rtnl_unlock(); /* Irrespective of success/failure, fini the queues */ @@ -995,7 +993,7 @@ static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer) FRF_AZ_EVQ_BUF_BASE_ID, buftbl); efx_writeo_table(efx, ®, FR_BZ_EVQ_PTR_TBL, abs_evq); EFX_POPULATE_DWORD_1(ptr, FRF_AZ_EVQ_RPTR, 0); - efx_writed_table(efx, &ptr, FR_BZ_EVQ_RPTR, abs_evq); + efx_writed(efx, &ptr, FR_BZ_EVQ_RPTR + FR_BZ_EVQ_RPTR_STEP * abs_evq); mutex_unlock(&vf->status_lock); } diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 3e5519a0acc7..dc171b4961e4 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -1143,7 +1143,7 @@ static int ioc3_is_menet(struct pci_dev *pdev) * Can't use UPF_IOREMAP as the whole of IOC3 resources have already been * registered. */ -static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart) +static void ioc3_8250_register(struct ioc3_uartregs __iomem *uart) { #define COSMISC_CONSTANT 6 @@ -1169,7 +1169,7 @@ static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart) serial8250_register_8250_port(&port); } -static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3) +static void ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3) { /* * We need to recognice and treat the fourth MENET serial as it @@ -1229,8 +1229,7 @@ static const struct net_device_ops ioc3_netdev_ops = { .ndo_change_mtu = eth_change_mtu, }; -static int __devinit ioc3_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { unsigned int sw_physid1, sw_physid2; struct net_device *dev = NULL; @@ -1368,7 +1367,7 @@ out: return err; } -static void __devexit ioc3_remove_one (struct pci_dev *pdev) +static void ioc3_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct ioc3_private *ip = netdev_priv(dev); @@ -1396,7 +1395,7 @@ static struct pci_driver ioc3_driver = { .name = "ioc3-eth", .id_table = ioc3_pci_tbl, .probe = ioc3_probe, - .remove = __devexit_p(ioc3_remove_one), + .remove = ioc3_remove_one, }; static int __init ioc3_init_module(void) diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c index 53efe7c7b1c0..79ad9c94a21b 100644 --- a/drivers/net/ethernet/sgi/meth.c +++ b/drivers/net/ethernet/sgi/meth.c @@ -825,7 +825,7 @@ static const struct net_device_ops meth_netdev_ops = { /* * The init function. */ -static int __devinit meth_probe(struct platform_device *pdev) +static int meth_probe(struct platform_device *pdev) { struct net_device *dev; struct meth_private *priv; diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c index 32e55664df6e..b2315324cc6d 100644 --- a/drivers/net/ethernet/silan/sc92031.c +++ b/drivers/net/ethernet/silan/sc92031.c @@ -1395,8 +1395,7 @@ static const struct net_device_ops sc92031_netdev_ops = { #endif }; -static int __devinit sc92031_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int sc92031_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int err; void __iomem* port_base; @@ -1489,7 +1488,7 @@ out_enable_device: return err; } -static void __devexit sc92031_remove(struct pci_dev *pdev) +static void sc92031_remove(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct sc92031_priv *priv = netdev_priv(dev); @@ -1574,7 +1573,7 @@ static struct pci_driver sc92031_pci_driver = { .name = SC92031_NAME, .id_table = sc92031_pci_device_id_table, .probe = sc92031_probe, - .remove = __devexit_p(sc92031_remove), + .remove = sc92031_remove, .suspend = sc92031_suspend, .resume = sc92031_resume, }; diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c index d8166012b7d4..9a9c379420d1 100644 --- a/drivers/net/ethernet/sis/sis190.c +++ b/drivers/net/ethernet/sis/sis190.c @@ -415,7 +415,7 @@ static u16 mdio_read_latched(void __iomem *ioaddr, int phy_id, int reg) return mdio_read(ioaddr, phy_id, reg); } -static u16 __devinit sis190_read_eeprom(void __iomem *ioaddr, u32 reg) +static u16 sis190_read_eeprom(void __iomem *ioaddr, u32 reg) { u16 data = 0xffff; unsigned int i; @@ -1379,7 +1379,7 @@ static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp) * Identify and set current phy if found one, * return error if it failed to found. */ -static int __devinit sis190_mii_probe(struct net_device *dev) +static int sis190_mii_probe(struct net_device *dev) { struct sis190_private *tp = netdev_priv(dev); struct mii_if_info *mii_if = &tp->mii_if; @@ -1451,7 +1451,7 @@ static void sis190_release_board(struct pci_dev *pdev) free_netdev(dev); } -static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev) +static struct net_device *sis190_init_board(struct pci_dev *pdev) { struct sis190_private *tp; struct net_device *dev; @@ -1573,8 +1573,8 @@ static void sis190_set_rgmii(struct sis190_private *tp, u8 reg) tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0; } -static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, - struct net_device *dev) +static int sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, + struct net_device *dev) { struct sis190_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; @@ -1615,10 +1615,10 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, * APC CMOS RAM is accessed through ISA bridge. * MAC address is read into @net_dev->dev_addr. */ -static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev, - struct net_device *dev) +static int sis190_get_mac_addr_from_apc(struct pci_dev *pdev, + struct net_device *dev) { - static const u16 __devinitconst ids[] = { 0x0965, 0x0966, 0x0968 }; + static const u16 ids[] = { 0x0965, 0x0966, 0x0968 }; struct sis190_private *tp = netdev_priv(dev); struct pci_dev *isa_bridge; u8 reg, tmp8; @@ -1693,8 +1693,7 @@ static inline void sis190_init_rxfilter(struct net_device *dev) SIS_PCI_COMMIT(); } -static int __devinit sis190_get_mac_addr(struct pci_dev *pdev, - struct net_device *dev) +static int sis190_get_mac_addr(struct pci_dev *pdev, struct net_device *dev) { int rc; @@ -1845,8 +1844,8 @@ static const struct net_device_ops sis190_netdev_ops = { #endif }; -static int __devinit sis190_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int sis190_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { static int printed_version = 0; struct sis190_private *tp; @@ -1916,7 +1915,7 @@ err_release_board: goto out; } -static void __devexit sis190_remove_one(struct pci_dev *pdev) +static void sis190_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct sis190_private *tp = netdev_priv(dev); @@ -1932,7 +1931,7 @@ static struct pci_driver sis190_pci_driver = { .name = DRV_NAME, .id_table = sis190_pci_tbl, .probe = sis190_init_one, - .remove = __devexit_p(sis190_remove_one), + .remove = sis190_remove_one, }; static int __init sis190_init_module(void) diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index fb9f6b38511f..5bffd9749a58 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -81,7 +81,7 @@ #define SIS900_MODULE_NAME "sis900" #define SIS900_DRV_VERSION "v1.08.10 Apr. 2 2006" -static const char version[] __devinitconst = +static const char version[] = KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n"; static int max_interrupt_work = 40; @@ -251,7 +251,8 @@ static const struct ethtool_ops sis900_ethtool_ops; * @net_dev->perm_addr. */ -static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) +static int sis900_get_mac_addr(struct pci_dev *pci_dev, + struct net_device *net_dev) { struct sis900_private *sis_priv = netdev_priv(net_dev); void __iomem *ioaddr = sis_priv->ioaddr; @@ -287,8 +288,8 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de * @net_dev->perm_addr. */ -static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, - struct net_device *net_dev) +static int sis630e_get_mac_addr(struct pci_dev *pci_dev, + struct net_device *net_dev) { struct pci_dev *isa_bridge = NULL; u8 reg; @@ -330,8 +331,8 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, * @net_dev->dev_addr and @net_dev->perm_addr. */ -static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, - struct net_device *net_dev) +static int sis635_get_mac_addr(struct pci_dev *pci_dev, + struct net_device *net_dev) { struct sis900_private *sis_priv = netdev_priv(net_dev); void __iomem *ioaddr = sis_priv->ioaddr; @@ -377,8 +378,8 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, * MAC address is read into @net_dev->dev_addr and @net_dev->perm_addr. */ -static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev, - struct net_device *net_dev) +static int sis96x_get_mac_addr(struct pci_dev *pci_dev, + struct net_device *net_dev) { struct sis900_private *sis_priv = netdev_priv(net_dev); void __iomem *ioaddr = sis_priv->ioaddr; @@ -433,8 +434,8 @@ static const struct net_device_ops sis900_netdev_ops = { * ie: sis900_open(), sis900_start_xmit(), sis900_close(), etc. */ -static int __devinit sis900_probe(struct pci_dev *pci_dev, - const struct pci_device_id *pci_id) +static int sis900_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_id) { struct sis900_private *sis_priv; struct net_device *net_dev; @@ -605,7 +606,7 @@ err_out_cleardev: * return error if it failed to found. */ -static int __devinit sis900_mii_probe(struct net_device * net_dev) +static int sis900_mii_probe(struct net_device *net_dev) { struct sis900_private *sis_priv = netdev_priv(net_dev); const char *dev_name = pci_name(sis_priv->pci_dev); @@ -824,7 +825,7 @@ static void sis900_set_capability(struct net_device *net_dev, struct mii_phy *ph * Note that location is in word (16 bits) unit */ -static u16 __devinit read_eeprom(void __iomem *ioaddr, int location) +static u16 read_eeprom(void __iomem *ioaddr, int location) { u32 read_cmd = location | EEread; int i; @@ -2410,7 +2411,7 @@ static void sis900_reset(struct net_device *net_dev) * remove and release SiS900 net device */ -static void __devexit sis900_remove(struct pci_dev *pci_dev) +static void sis900_remove(struct pci_dev *pci_dev) { struct net_device *net_dev = pci_get_drvdata(pci_dev); struct sis900_private *sis_priv = netdev_priv(net_dev); @@ -2479,7 +2480,7 @@ static int sis900_resume(struct pci_dev *pci_dev) netif_start_queue(net_dev); /* Workaround for EDB */ - sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); + sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); /* Enable all known interrupts by setting the interrupt mask. */ sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE); @@ -2496,7 +2497,7 @@ static struct pci_driver sis900_pci_driver = { .name = SIS900_MODULE_NAME, .id_table = sis900_pci_tbl, .probe = sis900_probe, - .remove = __devexit_p(sis900_remove), + .remove = sis900_remove, #ifdef CONFIG_PM .suspend = sis900_suspend, .resume = sis900_resume, diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c index d01e59c348ad..03b256af7ed5 100644 --- a/drivers/net/ethernet/smsc/epic100.c +++ b/drivers/net/ethernet/smsc/epic100.c @@ -90,9 +90,9 @@ static int rx_copybreak; #include <asm/byteorder.h> /* These identify the driver base version and may not be removed. */ -static char version[] __devinitdata = +static char version[] = DRV_NAME ".c:v1.11 1/7/2001 Written by Donald Becker <becker@scyld.com>\n"; -static char version2[] __devinitdata = +static char version2[] = " (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); @@ -318,8 +318,7 @@ static const struct net_device_ops epic_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit epic_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int epic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int card_idx = -1; void __iomem *ioaddr; @@ -569,7 +568,7 @@ static inline void epic_napi_irq_on(struct net_device *dev, ew32(INTMASK, ep->irq_mask | EpicNapiEvent); } -static int __devinit read_eeprom(struct epic_private *ep, int location) +static int read_eeprom(struct epic_private *ep, int location) { void __iomem *ioaddr = ep->ioaddr; int i; @@ -1524,7 +1523,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } -static void __devexit epic_remove_one(struct pci_dev *pdev) +static void epic_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct epic_private *ep = netdev_priv(dev); @@ -1577,7 +1576,7 @@ static struct pci_driver epic_driver = { .name = DRV_NAME, .id_table = epic_pci_tbl, .probe = epic_init_one, - .remove = __devexit_p(epic_remove_one), + .remove = epic_remove_one, #ifdef CONFIG_PM .suspend = epic_suspend, .resume = epic_resume, diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c index 8d15f7a74b45..59a6f88da867 100644 --- a/drivers/net/ethernet/smsc/smc911x.c +++ b/drivers/net/ethernet/smsc/smc911x.c @@ -1400,16 +1400,6 @@ smc911x_open(struct net_device *dev) DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); - /* - * Check that the address is valid. If its not, refuse - * to bring the device up. The user must specify an - * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx - */ - if (!is_valid_ether_addr(dev->dev_addr)) { - PRINTK("%s: no valid ethernet hw addr\n", __func__); - return -EINVAL; - } - /* reset the hardware */ smc911x_reset(dev); @@ -1722,7 +1712,7 @@ static const struct ethtool_ops smc911x_ethtool_ops = { * This routine has a simple purpose -- make the SMC chip generate an * interrupt, so an auto-detect routine can detect it, and find the IRQ, */ -static int __devinit smc911x_findirq(struct net_device *dev) +static int smc911x_findirq(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); int timeout = 20; @@ -1800,7 +1790,7 @@ static const struct net_device_ops smc911x_netdev_ops = { * o actually GRAB the irq. * o GRAB the region */ -static int __devinit smc911x_probe(struct net_device *dev) +static int smc911x_probe(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); int i, retval; @@ -2040,7 +2030,7 @@ err_out: * 0 --> there is a device * anything else, error */ -static int __devinit smc911x_drv_probe(struct platform_device *pdev) +static int smc911x_drv_probe(struct platform_device *pdev) { struct net_device *ndev; struct resource *res; @@ -2115,7 +2105,7 @@ out: return ret; } -static int __devexit smc911x_drv_remove(struct platform_device *pdev) +static int smc911x_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct smc911x_local *lp = netdev_priv(ndev); @@ -2186,7 +2176,7 @@ static int smc911x_drv_resume(struct platform_device *dev) static struct platform_driver smc911x_driver = { .probe = smc911x_drv_probe, - .remove = __devexit_p(smc911x_drv_remove), + .remove = smc911x_drv_remove, .suspend = smc911x_drv_suspend, .resume = smc911x_drv_resume, .driver = { diff --git a/drivers/net/ethernet/smsc/smc911x.h b/drivers/net/ethernet/smsc/smc911x.h index 3269292efecc..d51261ba4642 100644 --- a/drivers/net/ethernet/smsc/smc911x.h +++ b/drivers/net/ethernet/smsc/smc911x.h @@ -159,12 +159,12 @@ static inline void SMC_insl(struct smc911x_local *lp, int reg, void __iomem *ioaddr = lp->base + reg; if (lp->cfg.flags & SMC911X_USE_32BIT) { - readsl(ioaddr, addr, count); + ioread32_rep(ioaddr, addr, count); return; } if (lp->cfg.flags & SMC911X_USE_16BIT) { - readsw(ioaddr, addr, count * 2); + ioread16_rep(ioaddr, addr, count * 2); return; } @@ -177,12 +177,12 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg, void __iomem *ioaddr = lp->base + reg; if (lp->cfg.flags & SMC911X_USE_32BIT) { - writesl(ioaddr, addr, count); + iowrite32_rep(ioaddr, addr, count); return; } if (lp->cfg.flags & SMC911X_USE_16BIT) { - writesw(ioaddr, addr, count * 2); + iowrite16_rep(ioaddr, addr, count * 2); return; } @@ -196,14 +196,14 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg, writew(v & 0xFFFF, (lp)->base + (r)); \ writew(v >> 16, (lp)->base + (r) + 2); \ } while (0) -#define SMC_insl(lp, r, p, l) readsw((short*)((lp)->base + (r)), p, l*2) -#define SMC_outsl(lp, r, p, l) writesw((short*)((lp)->base + (r)), p, l*2) +#define SMC_insl(lp, r, p, l) ioread16_rep((short*)((lp)->base + (r)), p, l*2) +#define SMC_outsl(lp, r, p, l) iowrite16_rep((short*)((lp)->base + (r)), p, l*2) #elif SMC_USE_32BIT #define SMC_inl(lp, r) readl((lp)->base + (r)) #define SMC_outl(v, lp, r) writel(v, (lp)->base + (r)) -#define SMC_insl(lp, r, p, l) readsl((int*)((lp)->base + (r)), p, l) -#define SMC_outsl(lp, r, p, l) writesl((int*)((lp)->base + (r)), p, l) +#define SMC_insl(lp, r, p, l) ioread32_rep((int*)((lp)->base + (r)), p, l) +#define SMC_outsl(lp, r, p, l) iowrite32_rep((int*)((lp)->base + (r)), p, l) #endif /* SMC_USE_16BIT */ #endif /* SMC_DYNAMIC_BUS_CONFIG */ diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 318adc935a53..a670d23d9340 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -1474,16 +1474,6 @@ smc_open(struct net_device *dev) DBG(2, "%s: %s\n", dev->name, __func__); - /* - * Check that the address is valid. If its not, refuse - * to bring the device up. The user must specify an - * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx - */ - if (!is_valid_ether_addr(dev->dev_addr)) { - PRINTK("%s: no valid ethernet hw addr\n", __func__); - return -EINVAL; - } - /* Setup the default Register Modes */ lp->tcr_cur_mode = TCR_DEFAULT; lp->rcr_cur_mode = RCR_DEFAULT; @@ -1789,7 +1779,7 @@ static const struct net_device_ops smc_netdev_ops = { * I just deleted auto_irq.c, since it was never built... * --jgarzik */ -static int __devinit smc_findirq(struct smc_local *lp) +static int smc_findirq(struct smc_local *lp) { void __iomem *ioaddr = lp->base; int timeout = 20; @@ -1863,8 +1853,8 @@ static int __devinit smc_findirq(struct smc_local *lp) * o actually GRAB the irq. * o GRAB the region */ -static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr, - unsigned long irq_flags) +static int smc_probe(struct net_device *dev, void __iomem *ioaddr, + unsigned long irq_flags) { struct smc_local *lp = netdev_priv(dev); static int version_printed = 0; @@ -2211,7 +2201,7 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device * * 0 --> there is a device * anything else, error */ -static int __devinit smc_drv_probe(struct platform_device *pdev) +static int smc_drv_probe(struct platform_device *pdev) { struct smc91x_platdata *pd = pdev->dev.platform_data; struct smc_local *lp; @@ -2324,7 +2314,7 @@ static int __devinit smc_drv_probe(struct platform_device *pdev) return ret; } -static int __devexit smc_drv_remove(struct platform_device *pdev) +static int smc_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct smc_local *lp = netdev_priv(ndev); @@ -2396,8 +2386,6 @@ static const struct of_device_id smc91x_match[] = { {}, }; MODULE_DEVICE_TABLE(of, smc91x_match); -#else -#define smc91x_match NULL #endif static struct dev_pm_ops smc_drv_pm_ops = { @@ -2407,12 +2395,12 @@ static struct dev_pm_ops smc_drv_pm_ops = { static struct platform_driver smc_driver = { .probe = smc_drv_probe, - .remove = __devexit_p(smc_drv_remove), + .remove = smc_drv_remove, .driver = { .name = CARDNAME, .owner = THIS_MODULE, .pm = &smc_drv_pm_ops, - .of_match_table = smc91x_match, + .of_match_table = of_match_ptr(smc91x_match), }, }; diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index 5f53fbbf67be..370e13dde115 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -286,16 +286,16 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l) #define SMC_IO_SHIFT (lp->io_shift) -#define SMC_inb(a, r) readb((a) + (r)) -#define SMC_inw(a, r) readw((a) + (r)) -#define SMC_inl(a, r) readl((a) + (r)) -#define SMC_outb(v, a, r) writeb(v, (a) + (r)) -#define SMC_outw(v, a, r) writew(v, (a) + (r)) -#define SMC_outl(v, a, r) writel(v, (a) + (r)) -#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) -#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) -#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) -#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) +#define SMC_inb(a, r) ioread8((a) + (r)) +#define SMC_inw(a, r) ioread16((a) + (r)) +#define SMC_inl(a, r) ioread32((a) + (r)) +#define SMC_outb(v, a, r) iowrite8(v, (a) + (r)) +#define SMC_outw(v, a, r) iowrite16(v, (a) + (r)) +#define SMC_outl(v, a, r) iowrite32(v, (a) + (r)) +#define SMC_insw(a, r, p, l) ioread16_rep((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) iowrite16_rep((a) + (r), p, l) +#define SMC_insl(a, r, p, l) ioread32_rep((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) iowrite32_rep((a) + (r), p, l) #define RPC_LSA_DEFAULT RPC_LED_100_10 #define RPC_LSB_DEFAULT RPC_LED_TX_RX diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 62d1baf111ea..e112877d15d3 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -253,7 +253,7 @@ smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf, } if (pdata->config.flags & SMSC911X_USE_32BIT) { - writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount); + iowrite32_rep(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount); goto out; } @@ -285,7 +285,7 @@ smsc911x_tx_writefifo_shift(struct smsc911x_data *pdata, unsigned int *buf, } if (pdata->config.flags & SMSC911X_USE_32BIT) { - writesl(pdata->ioaddr + __smsc_shift(pdata, + iowrite32_rep(pdata->ioaddr + __smsc_shift(pdata, TX_DATA_FIFO), buf, wordcount); goto out; } @@ -319,7 +319,7 @@ smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf, } if (pdata->config.flags & SMSC911X_USE_32BIT) { - readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount); + ioread32_rep(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount); goto out; } @@ -351,7 +351,7 @@ smsc911x_rx_readfifo_shift(struct smsc911x_data *pdata, unsigned int *buf, } if (pdata->config.flags & SMSC911X_USE_32BIT) { - readsl(pdata->ioaddr + __smsc_shift(pdata, + ioread32_rep(pdata->ioaddr + __smsc_shift(pdata, RX_DATA_FIFO), buf, wordcount); goto out; } @@ -1031,8 +1031,8 @@ static int smsc911x_mii_probe(struct net_device *dev) return 0; } -static int __devinit smsc911x_mii_init(struct platform_device *pdev, - struct net_device *dev) +static int smsc911x_mii_init(struct platform_device *pdev, + struct net_device *dev) { struct smsc911x_data *pdata = netdev_priv(dev); int err = -ENXIO, i; @@ -1463,11 +1463,6 @@ static int smsc911x_open(struct net_device *dev) return -EAGAIN; } - if (!is_valid_ether_addr(dev->dev_addr)) { - SMSC_WARN(pdata, hw, "dev_addr is not a valid MAC address"); - return -EADDRNOTAVAIL; - } - /* Reset the LAN911x */ if (smsc911x_soft_reset(pdata)) { SMSC_WARN(pdata, hw, "soft reset failed"); @@ -2092,7 +2087,7 @@ static const struct net_device_ops smsc911x_netdev_ops = { }; /* copies the current mac address from hardware to dev->dev_addr */ -static void __devinit smsc911x_read_mac_address(struct net_device *dev) +static void smsc911x_read_mac_address(struct net_device *dev) { struct smsc911x_data *pdata = netdev_priv(dev); u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH); @@ -2107,10 +2102,10 @@ static void __devinit smsc911x_read_mac_address(struct net_device *dev) } /* Initializing private device structures, only called from probe */ -static int __devinit smsc911x_init(struct net_device *dev) +static int smsc911x_init(struct net_device *dev) { struct smsc911x_data *pdata = netdev_priv(dev); - unsigned int byte_test; + unsigned int byte_test, mask; unsigned int to = 100; SMSC_TRACE(pdata, probe, "Driver Parameters:"); @@ -2130,9 +2125,22 @@ static int __devinit smsc911x_init(struct net_device *dev) /* * poll the READY bit in PMT_CTRL. Any other access to the device is * forbidden while this bit isn't set. Try for 100ms + * + * Note that this test is done before the WORD_SWAP register is + * programmed. So in some configurations the READY bit is at 16 before + * WORD_SWAP is written to. This issue is worked around by waiting + * until either bit 0 or bit 16 gets set in PMT_CTRL. + * + * SMSC has confirmed that checking bit 16 (marked as reserved in + * the datasheet) is fine since these bits "will either never be set + * or can only go high after READY does (so also indicate the device + * is ready)". */ - while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to) + + mask = PMT_CTRL_READY_ | swahw32(PMT_CTRL_READY_); + while (!(smsc911x_reg_read(pdata, PMT_CTRL) & mask) && --to) udelay(1000); + if (to == 0) { pr_err("Device not READY in 100ms aborting\n"); return -ENODEV; @@ -2231,7 +2239,7 @@ static int __devinit smsc911x_init(struct net_device *dev) return 0; } -static int __devexit smsc911x_drv_remove(struct platform_device *pdev) +static int smsc911x_drv_remove(struct platform_device *pdev) { struct net_device *dev; struct smsc911x_data *pdata; @@ -2288,9 +2296,8 @@ static const struct smsc911x_ops shifted_smsc911x_ops = { }; #ifdef CONFIG_OF -static int __devinit smsc911x_probe_config_dt( - struct smsc911x_platform_config *config, - struct device_node *np) +static int smsc911x_probe_config_dt(struct smsc911x_platform_config *config, + struct device_node *np) { const char *mac; u32 width = 0; @@ -2338,7 +2345,7 @@ static inline int smsc911x_probe_config_dt( } #endif /* CONFIG_OF */ -static int __devinit smsc911x_drv_probe(struct platform_device *pdev) +static int smsc911x_drv_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct net_device *dev; @@ -2568,20 +2575,22 @@ static const struct dev_pm_ops smsc911x_pm_ops = { #define SMSC911X_PM_OPS NULL #endif +#ifdef CONFIG_OF static const struct of_device_id smsc911x_dt_ids[] = { { .compatible = "smsc,lan9115", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, smsc911x_dt_ids); +#endif static struct platform_driver smsc911x_driver = { .probe = smsc911x_drv_probe, - .remove = __devexit_p(smsc911x_drv_remove), + .remove = smsc911x_drv_remove, .driver = { .name = SMSC_CHIPNAME, .owner = THIS_MODULE, .pm = SMSC911X_PM_OPS, - .of_match_table = smsc911x_dt_ids, + .of_match_table = of_match_ptr(smsc911x_dt_ids), }, }; diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c index 1fcd914ec39b..3c586585e1b3 100644 --- a/drivers/net/ethernet/smsc/smsc9420.c +++ b/drivers/net/ethernet/smsc/smsc9420.c @@ -1577,7 +1577,7 @@ static const struct net_device_ops smsc9420_netdev_ops = { #endif /* CONFIG_NET_POLL_CONTROLLER */ }; -static int __devinit +static int smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct net_device *dev; @@ -1702,7 +1702,7 @@ out_0: return -ENODEV; } -static void __devexit smsc9420_remove(struct pci_dev *pdev) +static void smsc9420_remove(struct pci_dev *pdev) { struct net_device *dev; struct smsc9420_pdata *pd; @@ -1736,7 +1736,7 @@ static struct pci_driver smsc9420_driver = { .name = DRV_NAME, .id_table = smsc9420_id_table, .probe = smsc9420_probe, - .remove = __devexit_p(smsc9420_remove), + .remove = smsc9420_remove, #ifdef CONFIG_PM .suspend = smsc9420_suspend, .resume = smsc9420_resume, diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 9f448279e12a..1164930a40a5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -54,31 +54,6 @@ config STMMAC_DA By default, the DMA arbitration scheme is based on Round-robin (rx:tx priority is 1:1). -config STMMAC_TIMER - bool "STMMAC Timer optimisation" - default n - depends on RTC_HCTOSYS_DEVICE - ---help--- - Use an external timer for mitigating the number of network - interrupts. Currently, for SH architectures, it is possible - to use the TMU channel 2 and the SH-RTC device. - -choice - prompt "Select Timer device" - depends on STMMAC_TIMER - -config STMMAC_TMU_TIMER - bool "TMU channel 2" - depends on CPU_SH4 - ---help--- - -config STMMAC_RTC_TIMER - bool "Real time clock" - depends on RTC_CLASS - ---help--- - -endchoice - choice prompt "Select the DMA TX/RX descriptor operating modes" depends on STMMAC_ETH diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index bc965ac9e025..c8e8ea60ac19 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -1,5 +1,4 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o -stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o stmmac-$(CONFIG_STMMAC_RING) += ring_mode.o stmmac-$(CONFIG_STMMAC_CHAINED) += chain_mode.o stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 719be3912aa9..186d14806122 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -48,6 +48,10 @@ #define CHIP_DBG(fmt, args...) do { } while (0) #endif +/* Synopsys Core versions */ +#define DWMAC_CORE_3_40 0x34 +#define DWMAC_CORE_3_50 0x35 + #undef FRAME_FILTER_DEBUG /* #define FRAME_FILTER_DEBUG */ @@ -81,7 +85,7 @@ struct stmmac_extra_stats { unsigned long rx_missed_cntr; unsigned long rx_overflow_cntr; unsigned long rx_vlan; - /* Tx/Rx IRQ errors */ + /* Tx/Rx IRQ error info */ unsigned long tx_undeflow_irq; unsigned long tx_process_stopped_irq; unsigned long tx_jabber_irq; @@ -91,18 +95,23 @@ struct stmmac_extra_stats { unsigned long rx_watchdog_irq; unsigned long tx_early_irq; unsigned long fatal_bus_error_irq; - /* Extra info */ + /* Tx/Rx IRQ Events */ + unsigned long rx_early_irq; unsigned long threshold; unsigned long tx_pkt_n; unsigned long rx_pkt_n; - unsigned long poll_n; - unsigned long sched_timer_n; unsigned long normal_irq_n; + unsigned long rx_normal_irq_n; + unsigned long napi_poll; + unsigned long tx_normal_irq_n; + unsigned long tx_clean; + unsigned long tx_reset_ic_bit; + unsigned long irq_receive_pmt_irq_n; + /* MMC info */ unsigned long mmc_tx_irq_n; unsigned long mmc_rx_irq_n; unsigned long mmc_rx_csum_offload_irq_n; /* EEE */ - unsigned long irq_receive_pmt_irq_n; unsigned long irq_tx_path_in_lpi_mode_n; unsigned long irq_tx_path_exit_lpi_mode_n; unsigned long irq_rx_path_in_lpi_mode_n; @@ -162,6 +171,15 @@ struct stmmac_extra_stats { #define DMA_HW_FEAT_ACTPHYIF 0x70000000 /* Active/selected PHY interface */ #define DEFAULT_DMA_PBL 8 +/* Max/Min RI Watchdog Timer count value */ +#define MAX_DMA_RIWT 0xff +#define MIN_DMA_RIWT 0x20 +/* Tx coalesce parameters */ +#define STMMAC_COAL_TX_TIMER 40000 +#define STMMAC_MAX_COAL_TX_TICK 100000 +#define STMMAC_TX_MAX_FRAMES 256 +#define STMMAC_TX_FRAMES 64 + enum rx_frame_status { /* IPC status */ good_frame = 0, discard_frame = 1, @@ -169,10 +187,11 @@ enum rx_frame_status { /* IPC status */ llc_snap = 4, }; -enum tx_dma_irq_status { - tx_hard_error = 1, - tx_hard_error_bump_tc = 2, - handle_tx_rx = 3, +enum dma_irq_status { + tx_hard_error = 0x1, + tx_hard_error_bump_tc = 0x2, + handle_rx = 0x4, + handle_tx = 0x8, }; enum core_specific_irq_mask { @@ -296,6 +315,8 @@ struct stmmac_dma_ops { struct stmmac_extra_stats *x); /* If supported then get the optional core features */ unsigned int (*get_hw_feature) (void __iomem *ioaddr); + /* Program the HW RX Watchdog */ + void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt); }; struct stmmac_ops { diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h index 0e4cacedc1f0..7ad56afd6324 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h @@ -230,8 +230,5 @@ enum rtc_control { #define GMAC_MMC_TX_INTR 0x108 #define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 -/* Synopsys Core versions */ -#define DWMAC_CORE_3_40 0x34 - extern const struct stmmac_dma_ops dwmac1000_dma_ops; #endif /* __DWMAC1000_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index 033500090f55..bf83c03bfd06 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -174,6 +174,11 @@ static unsigned int dwmac1000_get_hw_feature(void __iomem *ioaddr) return readl(ioaddr + DMA_HW_FEATURE); } +static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt) +{ + writel(riwt, ioaddr + DMA_RX_WATCHDOG); +} + const struct stmmac_dma_ops dwmac1000_dma_ops = { .init = dwmac1000_dma_init, .dump_regs = dwmac1000_dump_dma_regs, @@ -187,4 +192,5 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = { .stop_rx = dwmac_dma_stop_rx, .dma_interrupt = dwmac_dma_interrupt, .get_hw_feature = dwmac1000_get_hw_feature, + .rx_watchdog = dwmac1000_rx_watchdog, }; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h index e49c9a0fd6ff..ab4896ecac1c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h @@ -35,7 +35,10 @@ #define DMA_CONTROL 0x00001018 /* Ctrl (Operational Mode) */ #define DMA_INTR_ENA 0x0000101c /* Interrupt Enable */ #define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */ -#define DMA_AXI_BUS_MODE 0x00001028 /* AXI Bus Mode */ +/* Rx watchdog register */ +#define DMA_RX_WATCHDOG 0x00001024 +/* AXI Bus Mode */ +#define DMA_AXI_BUS_MODE 0x00001028 #define DMA_CUR_TX_BUF_ADDR 0x00001050 /* Current Host Tx Buffer */ #define DMA_CUR_RX_BUF_ADDR 0x00001054 /* Current Host Rx Buffer */ #define DMA_HW_FEATURE 0x00001058 /* HW Feature Register */ @@ -77,8 +80,6 @@ #define DMA_STATUS_GPI 0x10000000 /* PMT interrupt */ #define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */ #define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */ -#define DMA_STATUS_GMI 0x08000000 -#define DMA_STATUS_GLI 0x04000000 #define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */ #define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */ #define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index 4e0e18a44fcc..491d7e930603 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -204,16 +204,28 @@ int dwmac_dma_interrupt(void __iomem *ioaddr, } } /* TX/RX NORMAL interrupts */ - if (intr_status & DMA_STATUS_NIS) { + if (likely(intr_status & DMA_STATUS_NIS)) { x->normal_irq_n++; - if (likely((intr_status & DMA_STATUS_RI) || - (intr_status & (DMA_STATUS_TI)))) - ret = handle_tx_rx; + if (likely(intr_status & DMA_STATUS_RI)) { + u32 value = readl(ioaddr + DMA_INTR_ENA); + /* to schedule NAPI on real RIE event. */ + if (likely(value & DMA_INTR_ENA_RIE)) { + x->rx_normal_irq_n++; + ret |= handle_rx; + } + } + if (likely(intr_status & DMA_STATUS_TI)) { + x->tx_normal_irq_n++; + ret |= handle_tx; + } + if (unlikely(intr_status & DMA_STATUS_ERI)) + x->rx_early_irq++; } /* Optional hardware blocks, interrupts should be disabled */ if (unlikely(intr_status & (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI))) pr_info("%s: unexpected status %08x\n", __func__, intr_status); + /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */ writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 7d51a65ab099..b05df8983be5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -24,16 +24,13 @@ #define __STMMAC_H__ #define STMMAC_RESOURCE_NAME "stmmaceth" -#define DRV_MODULE_VERSION "March_2012" +#define DRV_MODULE_VERSION "Nov_2012" #include <linux/clk.h> #include <linux/stmmac.h> #include <linux/phy.h> #include <linux/pci.h> #include "common.h" -#ifdef CONFIG_STMMAC_TIMER -#include "stmmac_timer.h" -#endif struct stmmac_priv { /* Frequently used values are kept adjacent for cache effect */ @@ -77,9 +74,6 @@ struct stmmac_priv { spinlock_t tx_lock; int wolopts; int wol_irq; -#ifdef CONFIG_STMMAC_TIMER - struct stmmac_timer *tm; -#endif struct plat_stmmacenet_data *plat; struct stmmac_counters mmc; struct dma_features dma_cap; @@ -93,6 +87,12 @@ struct stmmac_priv { int eee_enabled; int eee_active; int tx_lpi_timer; + struct timer_list txtimer; + u32 tx_count_frames; + u32 tx_coal_frames; + u32 tx_coal_timer; + int use_riwt; + u32 rx_riwt; }; extern int phyaddr; @@ -127,14 +127,14 @@ static inline int stmmac_register_platform(void) } static inline void stmmac_unregister_platform(void) { - platform_driver_register(&stmmac_pltfr_driver); + platform_driver_unregister(&stmmac_pltfr_driver); } #else static inline int stmmac_register_platform(void) { pr_debug("stmmac: do not register the platf driver\n"); - return -EINVAL; + return 0; } static inline void stmmac_unregister_platform(void) { @@ -162,7 +162,7 @@ static inline int stmmac_register_pci(void) { pr_debug("stmmac: do not register the PCI driver\n"); - return -EINVAL; + return 0; } static inline void stmmac_unregister_pci(void) { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 76fd61aa005f..1372ce210b58 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -76,7 +76,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = { STMMAC_STAT(rx_missed_cntr), STMMAC_STAT(rx_overflow_cntr), STMMAC_STAT(rx_vlan), - /* Tx/Rx IRQ errors */ + /* Tx/Rx IRQ error info */ STMMAC_STAT(tx_undeflow_irq), STMMAC_STAT(tx_process_stopped_irq), STMMAC_STAT(tx_jabber_irq), @@ -86,18 +86,23 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = { STMMAC_STAT(rx_watchdog_irq), STMMAC_STAT(tx_early_irq), STMMAC_STAT(fatal_bus_error_irq), - /* Extra info */ + /* Tx/Rx IRQ Events */ + STMMAC_STAT(rx_early_irq), STMMAC_STAT(threshold), STMMAC_STAT(tx_pkt_n), STMMAC_STAT(rx_pkt_n), - STMMAC_STAT(poll_n), - STMMAC_STAT(sched_timer_n), - STMMAC_STAT(normal_irq_n), STMMAC_STAT(normal_irq_n), + STMMAC_STAT(rx_normal_irq_n), + STMMAC_STAT(napi_poll), + STMMAC_STAT(tx_normal_irq_n), + STMMAC_STAT(tx_clean), + STMMAC_STAT(tx_reset_ic_bit), + STMMAC_STAT(irq_receive_pmt_irq_n), + /* MMC info */ STMMAC_STAT(mmc_tx_irq_n), STMMAC_STAT(mmc_rx_irq_n), STMMAC_STAT(mmc_rx_csum_offload_irq_n), - STMMAC_STAT(irq_receive_pmt_irq_n), + /* EEE */ STMMAC_STAT(irq_tx_path_in_lpi_mode_n), STMMAC_STAT(irq_tx_path_exit_lpi_mode_n), STMMAC_STAT(irq_rx_path_in_lpi_mode_n), @@ -519,6 +524,87 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev, return phy_ethtool_set_eee(priv->phydev, edata); } +static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv) +{ + unsigned long clk = clk_get_rate(priv->stmmac_clk); + + if (!clk) + return 0; + + return (usec * (clk / 1000000)) / 256; +} + +static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv) +{ + unsigned long clk = clk_get_rate(priv->stmmac_clk); + + if (!clk) + return 0; + + return (riwt * 256) / (clk / 1000000); +} + +static int stmmac_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *ec) +{ + struct stmmac_priv *priv = netdev_priv(dev); + + ec->tx_coalesce_usecs = priv->tx_coal_timer; + ec->tx_max_coalesced_frames = priv->tx_coal_frames; + + if (priv->use_riwt) + ec->rx_coalesce_usecs = stmmac_riwt2usec(priv->rx_riwt, priv); + + return 0; +} + +static int stmmac_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *ec) +{ + struct stmmac_priv *priv = netdev_priv(dev); + unsigned int rx_riwt; + + /* Check not supported parameters */ + if ((ec->rx_max_coalesced_frames) || (ec->rx_coalesce_usecs_irq) || + (ec->rx_max_coalesced_frames_irq) || (ec->tx_coalesce_usecs_irq) || + (ec->use_adaptive_rx_coalesce) || (ec->use_adaptive_tx_coalesce) || + (ec->pkt_rate_low) || (ec->rx_coalesce_usecs_low) || + (ec->rx_max_coalesced_frames_low) || (ec->tx_coalesce_usecs_high) || + (ec->tx_max_coalesced_frames_low) || (ec->pkt_rate_high) || + (ec->tx_coalesce_usecs_low) || (ec->rx_coalesce_usecs_high) || + (ec->rx_max_coalesced_frames_high) || + (ec->tx_max_coalesced_frames_irq) || + (ec->stats_block_coalesce_usecs) || + (ec->tx_max_coalesced_frames_high) || (ec->rate_sample_interval)) + return -EOPNOTSUPP; + + if (ec->rx_coalesce_usecs == 0) + return -EINVAL; + + if ((ec->tx_coalesce_usecs == 0) && + (ec->tx_max_coalesced_frames == 0)) + return -EINVAL; + + if ((ec->tx_coalesce_usecs > STMMAC_COAL_TX_TIMER) || + (ec->tx_max_coalesced_frames > STMMAC_TX_MAX_FRAMES)) + return -EINVAL; + + rx_riwt = stmmac_usec2riwt(ec->rx_coalesce_usecs, priv); + + if ((rx_riwt > MAX_DMA_RIWT) || (rx_riwt < MIN_DMA_RIWT)) + return -EINVAL; + else if (!priv->use_riwt) + return -EOPNOTSUPP; + + /* Only copy relevant parameters, ignore all others. */ + priv->tx_coal_frames = ec->tx_max_coalesced_frames; + priv->tx_coal_timer = ec->tx_coalesce_usecs; + priv->rx_riwt = rx_riwt; + priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt); + + return 0; +} + static const struct ethtool_ops stmmac_ethtool_ops = { .begin = stmmac_check_if_running, .get_drvinfo = stmmac_ethtool_getdrvinfo, @@ -539,6 +625,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = { .set_eee = stmmac_ethtool_op_set_eee, .get_sset_count = stmmac_get_sset_count, .get_ts_info = ethtool_op_get_ts_info, + .get_coalesce = stmmac_get_coalesce, + .set_coalesce = stmmac_set_coalesce, }; void stmmac_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c6cdbc4eb05e..f07c0612abf6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -115,16 +115,6 @@ static int tc = TC_DEFAULT; module_param(tc, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(tc, "DMA threshold control value"); -/* Pay attention to tune this parameter; take care of both - * hardware capability and network stabitily/performance impact. - * Many tests showed that ~4ms latency seems to be good enough. */ -#ifdef CONFIG_STMMAC_TIMER -#define DEFAULT_PERIODIC_RATE 256 -static int tmrate = DEFAULT_PERIODIC_RATE; -module_param(tmrate, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tmrate, "External timer freq. (default: 256Hz)"); -#endif - #define DMA_BUFFER_SIZE BUF_SIZE_2KiB static int buf_sz = DMA_BUFFER_SIZE; module_param(buf_sz, int, S_IRUGO | S_IWUSR); @@ -147,6 +137,8 @@ static int stmmac_init_fs(struct net_device *dev); static void stmmac_exit_fs(void); #endif +#define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x)) + /** * stmmac_verify_args - verify the driver parameters. * Description: it verifies if some wrong parameter is passed to the driver. @@ -536,12 +528,6 @@ static void init_dma_desc_rings(struct net_device *dev) else bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz); -#ifdef CONFIG_STMMAC_TIMER - /* Disable interrupts on completion for the reception if timer is on */ - if (likely(priv->tm->enable)) - dis_ic = 1; -#endif - DBG(probe, INFO, "stmmac: txsize %d, rxsize %d, bfsize %d\n", txsize, rxsize, bfsize); @@ -617,6 +603,8 @@ static void init_dma_desc_rings(struct net_device *dev) priv->dirty_tx = 0; priv->cur_tx = 0; + if (priv->use_riwt) + dis_ic = 1; /* Clear the Rx/Tx descriptors */ priv->hw->desc->init_rx_desc(priv->dma_rx, rxsize, dis_ic); priv->hw->desc->init_tx_desc(priv->dma_tx, txsize); @@ -704,16 +692,18 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) } /** - * stmmac_tx: - * @priv: private driver structure + * stmmac_tx_clean: + * @priv: private data pointer * Description: it reclaims resources after transmission completes. */ -static void stmmac_tx(struct stmmac_priv *priv) +static void stmmac_tx_clean(struct stmmac_priv *priv) { unsigned int txsize = priv->dma_tx_size; spin_lock(&priv->tx_lock); + priv->xstats.tx_clean++; + while (priv->dirty_tx != priv->cur_tx) { int last; unsigned int entry = priv->dirty_tx % txsize; @@ -773,69 +763,16 @@ static void stmmac_tx(struct stmmac_priv *priv) spin_unlock(&priv->tx_lock); } -static inline void stmmac_enable_irq(struct stmmac_priv *priv) -{ -#ifdef CONFIG_STMMAC_TIMER - if (likely(priv->tm->enable)) - priv->tm->timer_start(tmrate); - else -#endif - priv->hw->dma->enable_dma_irq(priv->ioaddr); -} - -static inline void stmmac_disable_irq(struct stmmac_priv *priv) -{ -#ifdef CONFIG_STMMAC_TIMER - if (likely(priv->tm->enable)) - priv->tm->timer_stop(); - else -#endif - priv->hw->dma->disable_dma_irq(priv->ioaddr); -} - -static int stmmac_has_work(struct stmmac_priv *priv) -{ - unsigned int has_work = 0; - int rxret, tx_work = 0; - - rxret = priv->hw->desc->get_rx_owner(priv->dma_rx + - (priv->cur_rx % priv->dma_rx_size)); - - if (priv->dirty_tx != priv->cur_tx) - tx_work = 1; - - if (likely(!rxret || tx_work)) - has_work = 1; - - return has_work; -} - -static inline void _stmmac_schedule(struct stmmac_priv *priv) +static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv) { - if (likely(stmmac_has_work(priv))) { - stmmac_disable_irq(priv); - napi_schedule(&priv->napi); - } + priv->hw->dma->enable_dma_irq(priv->ioaddr); } -#ifdef CONFIG_STMMAC_TIMER -void stmmac_schedule(struct net_device *dev) +static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv) { - struct stmmac_priv *priv = netdev_priv(dev); - - priv->xstats.sched_timer_n++; - - _stmmac_schedule(priv); + priv->hw->dma->disable_dma_irq(priv->ioaddr); } -static void stmmac_no_timer_started(unsigned int x) -{; -}; - -static void stmmac_no_timer_stopped(void) -{; -}; -#endif /** * stmmac_tx_err: @@ -858,16 +795,18 @@ static void stmmac_tx_err(struct stmmac_priv *priv) netif_wake_queue(priv->dev); } - static void stmmac_dma_interrupt(struct stmmac_priv *priv) { int status; status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); - if (likely(status == handle_tx_rx)) - _stmmac_schedule(priv); - - else if (unlikely(status == tx_hard_error_bump_tc)) { + if (likely((status & handle_rx)) || (status & handle_tx)) { + if (likely(napi_schedule_prep(&priv->napi))) { + stmmac_disable_dma_irq(priv); + __napi_schedule(&priv->napi); + } + } + if (unlikely(status & tx_hard_error_bump_tc)) { /* Try to bump up the dma threshold on this failure */ if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) { tc += 64; @@ -983,7 +922,6 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv) /* Alternate (enhanced) DESC mode*/ priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24; - } return hw_cap; @@ -1025,6 +963,38 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) } /** + * stmmac_tx_timer: + * @data: data pointer + * Description: + * This is the timer handler to directly invoke the stmmac_tx_clean. + */ +static void stmmac_tx_timer(unsigned long data) +{ + struct stmmac_priv *priv = (struct stmmac_priv *)data; + + stmmac_tx_clean(priv); +} + +/** + * stmmac_tx_timer: + * @priv: private data structure + * Description: + * This inits the transmit coalesce parameters: i.e. timer rate, + * timer handler and default threshold used for enabling the + * interrupt on completion bit. + */ +static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) +{ + priv->tx_coal_frames = STMMAC_TX_FRAMES; + priv->tx_coal_timer = STMMAC_COAL_TX_TIMER; + init_timer(&priv->txtimer); + priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer); + priv->txtimer.data = (unsigned long)priv; + priv->txtimer.function = stmmac_tx_timer; + add_timer(&priv->txtimer); +} + +/** * stmmac_open - open entry point of the driver * @dev : pointer to the device structure. * Description: @@ -1038,23 +1008,6 @@ static int stmmac_open(struct net_device *dev) struct stmmac_priv *priv = netdev_priv(dev); int ret; -#ifdef CONFIG_STMMAC_TIMER - priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL); - if (unlikely(priv->tm == NULL)) - return -ENOMEM; - - priv->tm->freq = tmrate; - - /* Test if the external timer can be actually used. - * In case of failure continue without timer. */ - if (unlikely((stmmac_open_ext_timer(dev, priv->tm)) < 0)) { - pr_warning("stmmaceth: cannot attach the external timer.\n"); - priv->tm->freq = 0; - priv->tm->timer_start = stmmac_no_timer_started; - priv->tm->timer_stop = stmmac_no_timer_stopped; - } else - priv->tm->enable = 1; -#endif clk_prepare_enable(priv->stmmac_clk); stmmac_check_ether_addr(priv); @@ -1141,10 +1094,6 @@ static int stmmac_open(struct net_device *dev) priv->hw->dma->start_tx(priv->ioaddr); priv->hw->dma->start_rx(priv->ioaddr); -#ifdef CONFIG_STMMAC_TIMER - priv->tm->timer_start(tmrate); -#endif - /* Dump DMA/MAC registers */ if (netif_msg_hw(priv)) { priv->hw->mac->dump_regs(priv->ioaddr); @@ -1157,6 +1106,13 @@ static int stmmac_open(struct net_device *dev) priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER; priv->eee_enabled = stmmac_eee_init(priv); + stmmac_init_tx_coalesce(priv); + + if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { + priv->rx_riwt = MAX_DMA_RIWT; + priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); + } + napi_enable(&priv->napi); netif_start_queue(dev); @@ -1170,9 +1126,6 @@ open_error_wolirq: free_irq(dev->irq, dev); open_error: -#ifdef CONFIG_STMMAC_TIMER - kfree(priv->tm); -#endif if (priv->phydev) phy_disconnect(priv->phydev); @@ -1203,14 +1156,10 @@ static int stmmac_release(struct net_device *dev) netif_stop_queue(dev); -#ifdef CONFIG_STMMAC_TIMER - /* Stop and release the timer */ - stmmac_close_ext_timer(); - if (priv->tm != NULL) - kfree(priv->tm); -#endif napi_disable(&priv->napi); + del_timer_sync(&priv->txtimer); + /* Free the IRQ lines */ free_irq(dev->irq, dev); if (priv->wol_irq != dev->irq) @@ -1273,11 +1222,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) #ifdef STMMAC_XMIT_DEBUG if ((skb->len > ETH_FRAME_LEN) || nfrags) - pr_info("stmmac xmit:\n" - "\tskb addr %p - len: %d - nopaged_len: %d\n" - "\tn_frags: %d - ip_summed: %d - %s gso\n", - skb, skb->len, nopaged_len, nfrags, skb->ip_summed, - !skb_is_gso(skb) ? "isn't" : "is"); + pr_debug("stmmac xmit: [entry %d]\n" + "\tskb addr %p - len: %d - nopaged_len: %d\n" + "\tn_frags: %d - ip_summed: %d - %s gso\n" + "\ttx_count_frames %d\n", entry, + skb, skb->len, nopaged_len, nfrags, skb->ip_summed, + !skb_is_gso(skb) ? "isn't" : "is", + priv->tx_count_frames); #endif csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL); @@ -1287,9 +1238,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) #ifdef STMMAC_XMIT_DEBUG if ((nfrags > 0) || (skb->len > ETH_FRAME_LEN)) - pr_debug("stmmac xmit: skb len: %d, nopaged_len: %d,\n" - "\t\tn_frags: %d, ip_summed: %d\n", - skb->len, nopaged_len, nfrags, skb->ip_summed); + pr_debug("\tskb len: %d, nopaged_len: %d,\n" + "\t\tn_frags: %d, ip_summed: %d\n", + skb->len, nopaged_len, nfrags, skb->ip_summed); #endif priv->tx_skbuff[entry] = skb; @@ -1320,16 +1271,24 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) wmb(); } - /* Interrupt on completition only for the latest segment */ + /* Finalize the latest segment. */ priv->hw->desc->close_tx_desc(desc); -#ifdef CONFIG_STMMAC_TIMER - /* Clean IC while using timer */ - if (likely(priv->tm->enable)) - priv->hw->desc->clear_tx_ic(desc); -#endif - wmb(); + /* According to the coalesce parameter the IC bit for the latest + * segment could be reset and the timer re-started to invoke the + * stmmac_tx function. This approach takes care about the fragments. + */ + priv->tx_count_frames += nfrags + 1; + if (priv->tx_coal_frames > priv->tx_count_frames) { + priv->hw->desc->clear_tx_ic(desc); + priv->xstats.tx_reset_ic_bit++; + TX_DBG("\t[entry %d]: tx_count_frames %d\n", entry, + priv->tx_count_frames); + mod_timer(&priv->txtimer, + STMMAC_COAL_TIMER(priv->tx_coal_timer)); + } else + priv->tx_count_frames = 0; /* To avoid raise condition */ priv->hw->desc->set_tx_owner(first); @@ -1471,14 +1430,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) #endif skb->protocol = eth_type_trans(skb, priv->dev); - if (unlikely(!priv->plat->rx_coe)) { - /* No RX COE for old mac10/100 devices */ + if (unlikely(!priv->plat->rx_coe)) skb_checksum_none_assert(skb); - netif_receive_skb(skb); - } else { + else skb->ip_summed = CHECKSUM_UNNECESSARY; - napi_gro_receive(&priv->napi, skb); - } + + napi_gro_receive(&priv->napi, skb); priv->dev->stats.rx_packets++; priv->dev->stats.rx_bytes += frame_len; @@ -1500,21 +1457,20 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) * @budget : maximum number of packets that the current CPU can receive from * all interfaces. * Description : - * This function implements the the reception process. - * Also it runs the TX completion thread + * To look at the incoming frames and clear the tx resources. */ static int stmmac_poll(struct napi_struct *napi, int budget) { struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi); int work_done = 0; - priv->xstats.poll_n++; - stmmac_tx(priv); - work_done = stmmac_rx(priv, budget); + priv->xstats.napi_poll++; + stmmac_tx_clean(priv); + work_done = stmmac_rx(priv, budget); if (work_done < budget) { napi_complete(napi); - stmmac_enable_irq(priv); + stmmac_enable_dma_irq(priv); } return work_done; } @@ -1523,7 +1479,7 @@ static int stmmac_poll(struct napi_struct *napi, int budget) * stmmac_tx_timeout * @dev : Pointer to net device structure * Description: this function is called when a packet transmission fails to - * complete within a reasonable tmrate. The driver will mark the error in the + * complete within a reasonable time. The driver will mark the error in the * netdev structure and arrange for the device to be reset to a sane state * in order to transmit a new packet. */ @@ -2050,6 +2006,16 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, if (flow_ctrl) priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ + /* Rx Watchdog is available in the COREs newer than the 3.40. + * In some case, for example on bugged HW this feature + * has to be disable and this can be done by passing the + * riwt_off field from the platform. + */ + if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) { + priv->use_riwt = 1; + pr_info(" Enable RX Mitigation via HW Watchdog Timer\n"); + } + netif_napi_add(ndev, &priv->napi, stmmac_poll, 64); spin_lock_init(&priv->lock); @@ -2141,11 +2107,9 @@ int stmmac_suspend(struct net_device *ndev) netif_device_detach(ndev); netif_stop_queue(ndev); -#ifdef CONFIG_STMMAC_TIMER - priv->tm->timer_stop(); - if (likely(priv->tm->enable)) + if (priv->use_riwt) dis_ic = 1; -#endif + napi_disable(&priv->napi); /* Stop TX/RX DMA */ @@ -2196,10 +2160,6 @@ int stmmac_resume(struct net_device *ndev) priv->hw->dma->start_tx(priv->ioaddr); priv->hw->dma->start_rx(priv->ioaddr); -#ifdef CONFIG_STMMAC_TIMER - if (likely(priv->tm->enable)) - priv->tm->timer_start(tmrate); -#endif napi_enable(&priv->napi); netif_start_queue(ndev); @@ -2234,18 +2194,20 @@ int stmmac_restore(struct net_device *ndev) */ static int __init stmmac_init(void) { - int err_plt = 0; - int err_pci = 0; - - err_plt = stmmac_register_platform(); - err_pci = stmmac_register_pci(); - - if ((err_pci) && (err_plt)) { - pr_err("stmmac: driver registration failed\n"); - return -EINVAL; - } + int ret; + ret = stmmac_register_platform(); + if (ret) + goto err; + ret = stmmac_register_pci(); + if (ret) + goto err_pci; return 0; +err_pci: + stmmac_unregister_platform(); +err: + pr_err("stmmac: driver registration failed\n"); + return ret; } static void __exit stmmac_exit(void) @@ -2295,11 +2257,6 @@ static int __init stmmac_cmdline_opt(char *str) } else if (!strncmp(opt, "eee_timer:", 6)) { if (kstrtoint(opt + 10, 0, &eee_timer)) goto err; -#ifdef CONFIG_STMMAC_TIMER - } else if (!strncmp(opt, "tmrate:", 7)) { - if (kstrtoint(opt + 7, 0, &tmrate)) - goto err; -#endif } } return 0; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index 1f069b0f6af5..064eaac9616f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -61,8 +61,8 @@ static void stmmac_default_data(void) * matches the device. The probe functions returns zero when the driver choose * to take "ownership" of the device or an error code(-ve no) otherwise. */ -static int __devinit stmmac_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int stmmac_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) { int ret = 0; void __iomem *addr = NULL; @@ -130,7 +130,7 @@ err_out_req_reg_failed: * Description: this function calls the main to free the net resources * and releases the PCI resources. */ -static void __devexit stmmac_pci_remove(struct pci_dev *pdev) +static void stmmac_pci_remove(struct pci_dev *pdev) { struct net_device *ndev = pci_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(ndev); @@ -182,7 +182,7 @@ struct pci_driver stmmac_pci_driver = { .name = STMMAC_RESOURCE_NAME, .id_table = stmmac_id_table, .probe = stmmac_pci_probe, - .remove = __devexit_p(stmmac_pci_remove), + .remove = stmmac_pci_remove, #ifdef CONFIG_PM .suspend = stmmac_pci_suspend, .resume = stmmac_pci_resume, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index ed112b55ae7f..b43d68b40e50 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -29,9 +29,9 @@ #include "stmmac.h" #ifdef CONFIG_OF -static int __devinit stmmac_probe_config_dt(struct platform_device *pdev, - struct plat_stmmacenet_data *plat, - const char **mac) +static int stmmac_probe_config_dt(struct platform_device *pdev, + struct plat_stmmacenet_data *plat, + const char **mac) { struct device_node *np = pdev->dev.of_node; @@ -59,9 +59,9 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev, return 0; } #else -static int __devinit stmmac_probe_config_dt(struct platform_device *pdev, - struct plat_stmmacenet_data *plat, - const char **mac) +static int stmmac_probe_config_dt(struct platform_device *pdev, + struct plat_stmmacenet_data *plat, + const char **mac) { return -ENOSYS; } @@ -74,7 +74,7 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev, * the necessary resources and invokes the main to init * the net device, register the mdio bus etc. */ -static int __devinit stmmac_pltfr_probe(struct platform_device *pdev) +static int stmmac_pltfr_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c deleted file mode 100644 index 4ccd4e2977b7..000000000000 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c +++ /dev/null @@ -1,134 +0,0 @@ -/******************************************************************************* - STMMAC external timer support. - - Copyright (C) 2007-2009 STMicroelectronics Ltd - - 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". - - Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> -*******************************************************************************/ - -#include <linux/kernel.h> -#include <linux/etherdevice.h> -#include "stmmac_timer.h" - -static void stmmac_timer_handler(void *data) -{ - struct net_device *dev = (struct net_device *)data; - - stmmac_schedule(dev); -} - -#define STMMAC_TIMER_MSG(timer, freq) \ -printk(KERN_INFO "stmmac_timer: %s Timer ON (freq %dHz)\n", timer, freq); - -#if defined(CONFIG_STMMAC_RTC_TIMER) -#include <linux/rtc.h> -static struct rtc_device *stmmac_rtc; -static rtc_task_t stmmac_task; - -static void stmmac_rtc_start(unsigned int new_freq) -{ - rtc_irq_set_freq(stmmac_rtc, &stmmac_task, new_freq); - rtc_irq_set_state(stmmac_rtc, &stmmac_task, 1); -} - -static void stmmac_rtc_stop(void) -{ - rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0); -} - -int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm) -{ - stmmac_task.private_data = dev; - stmmac_task.func = stmmac_timer_handler; - - stmmac_rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); - if (stmmac_rtc == NULL) { - pr_err("open rtc device failed\n"); - return -ENODEV; - } - - rtc_irq_register(stmmac_rtc, &stmmac_task); - - /* Periodic mode is not supported */ - if ((rtc_irq_set_freq(stmmac_rtc, &stmmac_task, tm->freq) < 0)) { - pr_err("set periodic failed\n"); - rtc_irq_unregister(stmmac_rtc, &stmmac_task); - rtc_class_close(stmmac_rtc); - return -1; - } - - STMMAC_TIMER_MSG(CONFIG_RTC_HCTOSYS_DEVICE, tm->freq); - - tm->timer_start = stmmac_rtc_start; - tm->timer_stop = stmmac_rtc_stop; - - return 0; -} - -int stmmac_close_ext_timer(void) -{ - rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0); - rtc_irq_unregister(stmmac_rtc, &stmmac_task); - rtc_class_close(stmmac_rtc); - return 0; -} - -#elif defined(CONFIG_STMMAC_TMU_TIMER) -#include <linux/clk.h> -#define TMU_CHANNEL "tmu2_clk" -static struct clk *timer_clock; - -static void stmmac_tmu_start(unsigned int new_freq) -{ - clk_set_rate(timer_clock, new_freq); - clk_prepare_enable(timer_clock); -} - -static void stmmac_tmu_stop(void) -{ - clk_disable_unprepare(timer_clock); -} - -int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm) -{ - timer_clock = clk_get(NULL, TMU_CHANNEL); - - if (IS_ERR(timer_clock)) - return -1; - - if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) { - timer_clock = NULL; - return -1; - } - - STMMAC_TIMER_MSG("TMU2", tm->freq); - tm->timer_start = stmmac_tmu_start; - tm->timer_stop = stmmac_tmu_stop; - - return 0; -} - -int stmmac_close_ext_timer(void) -{ - clk_disable_unprepare(timer_clock); - tmu2_unregister_user(); - clk_put(timer_clock); - return 0; -} -#endif diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h deleted file mode 100644 index aea9b14cdfbe..000000000000 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - STMMAC external timer Header File. - - Copyright (C) 2007-2009 STMicroelectronics Ltd - - 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". - - Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> -*******************************************************************************/ -#ifndef __STMMAC_TIMER_H__ -#define __STMMAC_TIMER_H__ - -struct stmmac_timer { - void (*timer_start) (unsigned int new_freq); - void (*timer_stop) (void); - unsigned int freq; - unsigned int enable; -}; - -/* Open the HW timer device and return 0 in case of success */ -int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm); -/* Stop the timer and release it */ -int stmmac_close_ext_timer(void); -/* Function used for scheduling task within the stmmac */ -void stmmac_schedule(struct net_device *dev); - -#if defined(CONFIG_STMMAC_TMU_TIMER) -extern int tmu2_register_user(void *fnt, void *data); -extern void tmu2_unregister_user(void); -#endif - -#endif /* __STMMAC_TIMER_H__ */ diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index c8251be104d6..4c682a3d0424 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -185,7 +185,7 @@ #define CAS_RESET_SPARE 3 #endif -static char version[] __devinitdata = +static char version[] = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */ @@ -222,7 +222,7 @@ static int link_transition_timeout; -static u16 link_modes[] __devinitdata = { +static u16 link_modes[] = { BMCR_ANENABLE, /* 0 : autoneg */ 0, /* 1 : 10bt half duplex */ BMCR_SPEED100, /* 2 : 100bt half duplex */ @@ -4820,7 +4820,7 @@ static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) * only subordinate device and we can tweak the bridge settings to * reflect that fact. */ -static void __devinit cas_program_bridge(struct pci_dev *cas_pdev) +static void cas_program_bridge(struct pci_dev *cas_pdev) { struct pci_dev *pdev = cas_pdev->bus->self; u32 val; @@ -4916,8 +4916,7 @@ static const struct net_device_ops cas_netdev_ops = { #endif }; -static int __devinit cas_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int cas_version_printed = 0; unsigned long casreg_len; @@ -5175,7 +5174,7 @@ err_out_disable_pdev: return -ENODEV; } -static void __devexit cas_remove_one(struct pci_dev *pdev) +static void cas_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct cas *cp; @@ -5273,7 +5272,7 @@ static struct pci_driver cas_driver = { .name = DRV_MODULE_NAME, .id_table = cas_pci_tbl, .probe = cas_init_one, - .remove = __devexit_p(cas_remove_one), + .remove = cas_remove_one, #ifdef CONFIG_PM .suspend = cas_suspend, .resume = cas_resume diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 275b430aeb75..a0bdf0779466 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -38,7 +38,7 @@ #define DRV_MODULE_VERSION "1.1" #define DRV_MODULE_RELDATE "Apr 22, 2010" -static char version[] __devinitdata = +static char version[] = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); @@ -7977,7 +7977,7 @@ static int niu_set_ldg_sid(struct niu *np, int ldg, int func, int vector) return 0; } -static int __devinit niu_pci_eeprom_read(struct niu *np, u32 addr) +static int niu_pci_eeprom_read(struct niu *np, u32 addr) { u64 frame, frame_base = (ESPC_PIO_STAT_READ_START | (addr << ESPC_PIO_STAT_ADDR_SHIFT)); @@ -8020,7 +8020,7 @@ static int __devinit niu_pci_eeprom_read(struct niu *np, u32 addr) return (frame & ESPC_PIO_STAT_DATA) >> ESPC_PIO_STAT_DATA_SHIFT; } -static int __devinit niu_pci_eeprom_read16(struct niu *np, u32 off) +static int niu_pci_eeprom_read16(struct niu *np, u32 off) { int err = niu_pci_eeprom_read(np, off); u16 val; @@ -8036,7 +8036,7 @@ static int __devinit niu_pci_eeprom_read16(struct niu *np, u32 off) return val; } -static int __devinit niu_pci_eeprom_read16_swp(struct niu *np, u32 off) +static int niu_pci_eeprom_read16_swp(struct niu *np, u32 off) { int err = niu_pci_eeprom_read(np, off); u16 val; @@ -8054,10 +8054,8 @@ static int __devinit niu_pci_eeprom_read16_swp(struct niu *np, u32 off) return val; } -static int __devinit niu_pci_vpd_get_propname(struct niu *np, - u32 off, - char *namebuf, - int namebuf_len) +static int niu_pci_vpd_get_propname(struct niu *np, u32 off, char *namebuf, + int namebuf_len) { int i; @@ -8075,7 +8073,7 @@ static int __devinit niu_pci_vpd_get_propname(struct niu *np, return i + 1; } -static void __devinit niu_vpd_parse_version(struct niu *np) +static void niu_vpd_parse_version(struct niu *np) { struct niu_vpd *vpd = &np->vpd; int len = strlen(vpd->version) + 1; @@ -8102,8 +8100,7 @@ static void __devinit niu_vpd_parse_version(struct niu *np) } /* ESPC_PIO_EN_ENABLE must be set */ -static int __devinit niu_pci_vpd_scan_props(struct niu *np, - u32 start, u32 end) +static int niu_pci_vpd_scan_props(struct niu *np, u32 start, u32 end) { unsigned int found_mask = 0; #define FOUND_MASK_MODEL 0x00000001 @@ -8189,7 +8186,7 @@ static int __devinit niu_pci_vpd_scan_props(struct niu *np, } /* ESPC_PIO_EN_ENABLE must be set */ -static void __devinit niu_pci_vpd_fetch(struct niu *np, u32 start) +static void niu_pci_vpd_fetch(struct niu *np, u32 start) { u32 offset; int err; @@ -8224,7 +8221,7 @@ static void __devinit niu_pci_vpd_fetch(struct niu *np, u32 start) } /* ESPC_PIO_EN_ENABLE must be set */ -static u32 __devinit niu_pci_vpd_offset(struct niu *np) +static u32 niu_pci_vpd_offset(struct niu *np) { u32 start = 0, end = ESPC_EEPROM_SIZE, ret; int err; @@ -8279,8 +8276,7 @@ static u32 __devinit niu_pci_vpd_offset(struct niu *np) return 0; } -static int __devinit niu_phy_type_prop_decode(struct niu *np, - const char *phy_prop) +static int niu_phy_type_prop_decode(struct niu *np, const char *phy_prop) { if (!strcmp(phy_prop, "mif")) { /* 1G copper, MII */ @@ -8334,7 +8330,7 @@ static int niu_pci_vpd_get_nports(struct niu *np) return ports; } -static void __devinit niu_pci_vpd_validate(struct niu *np) +static void niu_pci_vpd_validate(struct niu *np) { struct net_device *dev = np->dev; struct niu_vpd *vpd = &np->vpd; @@ -8380,7 +8376,7 @@ static void __devinit niu_pci_vpd_validate(struct niu *np) memcpy(dev->dev_addr, dev->perm_addr, dev->addr_len); } -static int __devinit niu_pci_probe_sprom(struct niu *np) +static int niu_pci_probe_sprom(struct niu *np) { struct net_device *dev = np->dev; int len, i; @@ -8538,7 +8534,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) return 0; } -static int __devinit niu_get_and_validate_port(struct niu *np) +static int niu_get_and_validate_port(struct niu *np) { struct niu_parent *parent = np->parent; @@ -8572,10 +8568,8 @@ static int __devinit niu_get_and_validate_port(struct niu *np) return 0; } -static int __devinit phy_record(struct niu_parent *parent, - struct phy_probe_info *p, - int dev_id_1, int dev_id_2, u8 phy_port, - int type) +static int phy_record(struct niu_parent *parent, struct phy_probe_info *p, + int dev_id_1, int dev_id_2, u8 phy_port, int type) { u32 id = (dev_id_1 << 16) | dev_id_2; u8 idx; @@ -8611,7 +8605,7 @@ static int __devinit phy_record(struct niu_parent *parent, return 0; } -static int __devinit port_has_10g(struct phy_probe_info *p, int port) +static int port_has_10g(struct phy_probe_info *p, int port) { int i; @@ -8627,7 +8621,7 @@ static int __devinit port_has_10g(struct phy_probe_info *p, int port) return 0; } -static int __devinit count_10g_ports(struct phy_probe_info *p, int *lowest) +static int count_10g_ports(struct phy_probe_info *p, int *lowest) { int port, cnt; @@ -8644,7 +8638,7 @@ static int __devinit count_10g_ports(struct phy_probe_info *p, int *lowest) return cnt; } -static int __devinit count_1g_ports(struct phy_probe_info *p, int *lowest) +static int count_1g_ports(struct phy_probe_info *p, int *lowest) { *lowest = 32; if (p->cur[PHY_TYPE_MII]) @@ -8653,7 +8647,7 @@ static int __devinit count_1g_ports(struct phy_probe_info *p, int *lowest) return p->cur[PHY_TYPE_MII]; } -static void __devinit niu_n2_divide_channels(struct niu_parent *parent) +static void niu_n2_divide_channels(struct niu_parent *parent) { int num_ports = parent->num_ports; int i; @@ -8669,8 +8663,8 @@ static void __devinit niu_n2_divide_channels(struct niu_parent *parent) } } -static void __devinit niu_divide_channels(struct niu_parent *parent, - int num_10g, int num_1g) +static void niu_divide_channels(struct niu_parent *parent, + int num_10g, int num_1g) { int num_ports = parent->num_ports; int rx_chans_per_10g, rx_chans_per_1g; @@ -8731,8 +8725,8 @@ static void __devinit niu_divide_channels(struct niu_parent *parent, } } -static void __devinit niu_divide_rdc_groups(struct niu_parent *parent, - int num_10g, int num_1g) +static void niu_divide_rdc_groups(struct niu_parent *parent, + int num_10g, int num_1g) { int i, num_ports = parent->num_ports; int rdc_group, rdc_groups_per_port; @@ -8776,9 +8770,8 @@ static void __devinit niu_divide_rdc_groups(struct niu_parent *parent, } } -static int __devinit fill_phy_probe_info(struct niu *np, - struct niu_parent *parent, - struct phy_probe_info *info) +static int fill_phy_probe_info(struct niu *np, struct niu_parent *parent, + struct phy_probe_info *info) { unsigned long flags; int port, err; @@ -8819,7 +8812,7 @@ static int __devinit fill_phy_probe_info(struct niu *np, return err; } -static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) +static int walk_phys(struct niu *np, struct niu_parent *parent) { struct phy_probe_info *info = &parent->phy_probe_info; int lowest_10g, lowest_1g; @@ -8948,7 +8941,7 @@ unknown_vg_1g_port: return -EINVAL; } -static int __devinit niu_probe_ports(struct niu *np) +static int niu_probe_ports(struct niu *np) { struct niu_parent *parent = np->parent; int err, i; @@ -8969,7 +8962,7 @@ static int __devinit niu_probe_ports(struct niu *np) return 0; } -static int __devinit niu_classifier_swstate_init(struct niu *np) +static int niu_classifier_swstate_init(struct niu *np) { struct niu_classifier *cp = &np->clas; @@ -8981,7 +8974,7 @@ static int __devinit niu_classifier_swstate_init(struct niu *np) return fflp_early_init(np); } -static void __devinit niu_link_config_init(struct niu *np) +static void niu_link_config_init(struct niu *np) { struct niu_link_config *lp = &np->link_config; @@ -9006,7 +8999,7 @@ static void __devinit niu_link_config_init(struct niu *np) #endif } -static int __devinit niu_init_mac_ipp_pcs_base(struct niu *np) +static int niu_init_mac_ipp_pcs_base(struct niu *np) { switch (np->port) { case 0: @@ -9045,7 +9038,7 @@ static int __devinit niu_init_mac_ipp_pcs_base(struct niu *np) return 0; } -static void __devinit niu_try_msix(struct niu *np, u8 *ldg_num_map) +static void niu_try_msix(struct niu *np, u8 *ldg_num_map) { struct msix_entry msi_vec[NIU_NUM_LDG]; struct niu_parent *parent = np->parent; @@ -9084,7 +9077,7 @@ retry: np->num_ldg = num_irqs; } -static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map) +static int niu_n2_irq_init(struct niu *np, u8 *ldg_num_map) { #ifdef CONFIG_SPARC64 struct platform_device *op = np->op; @@ -9108,7 +9101,7 @@ static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map) #endif } -static int __devinit niu_ldg_init(struct niu *np) +static int niu_ldg_init(struct niu *np) { struct niu_parent *parent = np->parent; u8 ldg_num_map[NIU_NUM_LDG]; @@ -9225,13 +9218,13 @@ static int __devinit niu_ldg_init(struct niu *np) return 0; } -static void __devexit niu_ldg_free(struct niu *np) +static void niu_ldg_free(struct niu *np) { if (np->flags & NIU_FLAGS_MSIX) pci_disable_msix(np->pdev); } -static int __devinit niu_get_of_props(struct niu *np) +static int niu_get_of_props(struct niu *np) { #ifdef CONFIG_SPARC64 struct net_device *dev = np->dev; @@ -9300,7 +9293,7 @@ static int __devinit niu_get_of_props(struct niu *np) #endif } -static int __devinit niu_get_invariants(struct niu *np) +static int niu_get_invariants(struct niu *np) { int err, have_props; u32 offset; @@ -9479,9 +9472,8 @@ static struct device_attribute niu_parent_attributes[] = { {} }; -static struct niu_parent * __devinit niu_new_parent(struct niu *np, - union niu_parent_id *id, - u8 ptype) +static struct niu_parent *niu_new_parent(struct niu *np, + union niu_parent_id *id, u8 ptype) { struct platform_device *plat_dev; struct niu_parent *p; @@ -9544,9 +9536,8 @@ fail_unregister: return NULL; } -static struct niu_parent * __devinit niu_get_parent(struct niu *np, - union niu_parent_id *id, - u8 ptype) +static struct niu_parent *niu_get_parent(struct niu *np, + union niu_parent_id *id, u8 ptype) { struct niu_parent *p, *tmp; int port = np->port; @@ -9662,7 +9653,7 @@ static const struct niu_ops niu_pci_ops = { .unmap_single = niu_pci_unmap_single, }; -static void __devinit niu_driver_version(void) +static void niu_driver_version(void) { static int niu_version_printed; @@ -9670,10 +9661,10 @@ static void __devinit niu_driver_version(void) pr_info("%s", version); } -static struct net_device * __devinit niu_alloc_and_init( - struct device *gen_dev, struct pci_dev *pdev, - struct platform_device *op, const struct niu_ops *ops, - u8 port) +static struct net_device *niu_alloc_and_init(struct device *gen_dev, + struct pci_dev *pdev, + struct platform_device *op, + const struct niu_ops *ops, u8 port) { struct net_device *dev; struct niu *np; @@ -9714,14 +9705,14 @@ static const struct net_device_ops niu_netdev_ops = { .ndo_change_mtu = niu_change_mtu, }; -static void __devinit niu_assign_netdev_ops(struct net_device *dev) +static void niu_assign_netdev_ops(struct net_device *dev) { dev->netdev_ops = &niu_netdev_ops; dev->ethtool_ops = &niu_ethtool_ops; dev->watchdog_timeo = NIU_TX_TIMEOUT; } -static void __devinit niu_device_announce(struct niu *np) +static void niu_device_announce(struct niu *np) { struct net_device *dev = np->dev; @@ -9750,14 +9741,14 @@ static void __devinit niu_device_announce(struct niu *np) } } -static void __devinit niu_set_basic_features(struct net_device *dev) +static void niu_set_basic_features(struct net_device *dev) { dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXHASH; dev->features |= dev->hw_features | NETIF_F_RXCSUM; } -static int __devinit niu_pci_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int niu_pci_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { union niu_parent_id parent_id; struct net_device *dev; @@ -9895,7 +9886,7 @@ err_out_disable_pdev: return err; } -static void __devexit niu_pci_remove_one(struct pci_dev *pdev) +static void niu_pci_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -9980,7 +9971,7 @@ static struct pci_driver niu_pci_driver = { .name = DRV_MODULE_NAME, .id_table = niu_pci_tbl, .probe = niu_pci_init_one, - .remove = __devexit_p(niu_pci_remove_one), + .remove = niu_pci_remove_one, .suspend = niu_suspend, .resume = niu_resume, }; @@ -10044,7 +10035,7 @@ static const struct niu_ops niu_phys_ops = { .unmap_single = niu_phys_unmap_single, }; -static int __devinit niu_of_probe(struct platform_device *op) +static int niu_of_probe(struct platform_device *op) { union niu_parent_id parent_id; struct net_device *dev; @@ -10158,7 +10149,7 @@ err_out: return err; } -static int __devexit niu_of_remove(struct platform_device *op) +static int niu_of_remove(struct platform_device *op) { struct net_device *dev = dev_get_drvdata(&op->dev); @@ -10211,7 +10202,7 @@ static struct platform_driver niu_of_driver = { .of_match_table = niu_match, }, .probe = niu_of_probe, - .remove = __devexit_p(niu_of_remove), + .remove = niu_of_remove, }; #endif /* CONFIG_SPARC64 */ diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c index c9c977bf02ac..be82f6d13c51 100644 --- a/drivers/net/ethernet/sun/sunbmac.c +++ b/drivers/net/ethernet/sun/sunbmac.c @@ -1074,8 +1074,8 @@ static const struct net_device_ops bigmac_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit bigmac_ether_init(struct platform_device *op, - struct platform_device *qec_op) +static int bigmac_ether_init(struct platform_device *op, + struct platform_device *qec_op) { static int version_printed; struct net_device *dev; @@ -1233,7 +1233,7 @@ fail_and_cleanup: /* QEC can be the parent of either QuadEthernet or a BigMAC. We want * the latter. */ -static int __devinit bigmac_sbus_probe(struct platform_device *op) +static int bigmac_sbus_probe(struct platform_device *op) { struct device *parent = op->dev.parent; struct platform_device *qec_op; @@ -1243,7 +1243,7 @@ static int __devinit bigmac_sbus_probe(struct platform_device *op) return bigmac_ether_init(op, qec_op); } -static int __devexit bigmac_sbus_remove(struct platform_device *op) +static int bigmac_sbus_remove(struct platform_device *op) { struct bigmac *bp = dev_get_drvdata(&op->dev); struct device *parent = op->dev.parent; @@ -1286,7 +1286,7 @@ static struct platform_driver bigmac_sbus_driver = { .of_match_table = bigmac_sbus_match, }, .probe = bigmac_sbus_probe, - .remove = __devexit_p(bigmac_sbus_remove), + .remove = bigmac_sbus_remove, }; module_platform_driver(bigmac_sbus_driver); diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index 6c8695ec7cb9..5f3f9d52757d 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -77,7 +77,7 @@ #define DRV_VERSION "1.0" #define DRV_AUTHOR "David S. Miller <davem@redhat.com>" -static char version[] __devinitdata = +static char version[] = DRV_NAME ".c:v" DRV_VERSION " " DRV_AUTHOR "\n"; MODULE_AUTHOR(DRV_AUTHOR); @@ -2763,7 +2763,7 @@ static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr) } #endif /* not Sparc and not PPC */ -static int __devinit gem_get_device_address(struct gem *gp) +static int gem_get_device_address(struct gem *gp) { #if defined(CONFIG_SPARC) || defined(CONFIG_PPC_PMAC) struct net_device *dev = gp->dev; @@ -2827,8 +2827,7 @@ static const struct net_device_ops gem_netdev_ops = { #endif }; -static int __devinit gem_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { unsigned long gemreg_base, gemreg_len; struct net_device *dev; diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c index 73f341b8befb..a1bff49a8155 100644 --- a/drivers/net/ethernet/sun/sunhme.c +++ b/drivers/net/ethernet/sun/sunhme.c @@ -2499,7 +2499,7 @@ static int hme_version_printed; * * Return NULL on failure. */ -static struct quattro * __devinit quattro_sbus_find(struct platform_device *child) +static struct quattro *quattro_sbus_find(struct platform_device *child) { struct device *parent = child->dev.parent; struct platform_device *op; @@ -2580,7 +2580,7 @@ static void quattro_sbus_free_irqs(void) #endif /* CONFIG_SBUS */ #ifdef CONFIG_PCI -static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev) +static struct quattro *quattro_pci_find(struct pci_dev *pdev) { struct pci_dev *bdev = pdev->bus->self; struct quattro *qp; @@ -2623,7 +2623,7 @@ static const struct net_device_ops hme_netdev_ops = { }; #ifdef CONFIG_SBUS -static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe) +static int happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe) { struct device_node *dp = op->dev.of_node, *sbus_dp; struct quattro *qp = NULL; @@ -2927,8 +2927,8 @@ static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr) } #endif /* !(CONFIG_SPARC) */ -static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int happy_meal_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct quattro *qp = NULL; #ifdef CONFIG_SPARC @@ -3162,7 +3162,7 @@ err_out: return err; } -static void __devexit happy_meal_pci_remove(struct pci_dev *pdev) +static void happy_meal_pci_remove(struct pci_dev *pdev) { struct happy_meal *hp = dev_get_drvdata(&pdev->dev); struct net_device *net_dev = hp->dev; @@ -3190,7 +3190,7 @@ static struct pci_driver hme_pci_driver = { .name = "hme", .id_table = happymeal_pci_ids, .probe = happy_meal_pci_probe, - .remove = __devexit_p(happy_meal_pci_remove), + .remove = happy_meal_pci_remove, }; static int __init happy_meal_pci_init(void) @@ -3216,7 +3216,7 @@ static void happy_meal_pci_exit(void) #ifdef CONFIG_SBUS static const struct of_device_id hme_sbus_match[]; -static int __devinit hme_sbus_probe(struct platform_device *op) +static int hme_sbus_probe(struct platform_device *op) { const struct of_device_id *match; struct device_node *dp = op->dev.of_node; @@ -3234,7 +3234,7 @@ static int __devinit hme_sbus_probe(struct platform_device *op) return happy_meal_sbus_probe_one(op, is_qfe); } -static int __devexit hme_sbus_remove(struct platform_device *op) +static int hme_sbus_remove(struct platform_device *op) { struct happy_meal *hp = dev_get_drvdata(&op->dev); struct net_device *net_dev = hp->dev; @@ -3284,7 +3284,7 @@ static struct platform_driver hme_sbus_driver = { .of_match_table = hme_sbus_match, }, .probe = hme_sbus_probe, - .remove = __devexit_p(hme_sbus_remove), + .remove = hme_sbus_remove, }; static int __init happy_meal_sbus_init(void) diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c index aeded7ff1c8f..1dcee6915843 100644 --- a/drivers/net/ethernet/sun/sunqe.c +++ b/drivers/net/ethernet/sun/sunqe.c @@ -744,7 +744,7 @@ static void qec_init_once(struct sunqec *qecp, struct platform_device *op) qecp->gregs + GLOB_RSIZE); } -static u8 __devinit qec_get_burst(struct device_node *dp) +static u8 qec_get_burst(struct device_node *dp) { u8 bsizes, bsizes_more; @@ -764,7 +764,7 @@ static u8 __devinit qec_get_burst(struct device_node *dp) return bsizes; } -static struct sunqec * __devinit get_qec(struct platform_device *child) +static struct sunqec *get_qec(struct platform_device *child) { struct platform_device *op = to_platform_device(child->dev.parent); struct sunqec *qecp; @@ -830,7 +830,7 @@ static const struct net_device_ops qec_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit qec_ether_init(struct platform_device *op) +static int qec_ether_init(struct platform_device *op) { static unsigned version_printed; struct net_device *dev; @@ -929,12 +929,12 @@ fail: return res; } -static int __devinit qec_sbus_probe(struct platform_device *op) +static int qec_sbus_probe(struct platform_device *op) { return qec_ether_init(op); } -static int __devexit qec_sbus_remove(struct platform_device *op) +static int qec_sbus_remove(struct platform_device *op) { struct sunqe *qp = dev_get_drvdata(&op->dev); struct net_device *net_dev = qp->dev; @@ -971,7 +971,7 @@ static struct platform_driver qec_sbus_driver = { .of_match_table = qec_sbus_match, }, .probe = qec_sbus_probe, - .remove = __devexit_p(qec_sbus_remove), + .remove = qec_sbus_remove, }; static int __init qec_init(void) diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index a108db35924e..e1b895530827 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -25,7 +25,7 @@ #define DRV_MODULE_VERSION "1.0" #define DRV_MODULE_RELDATE "June 25, 2007" -static char version[] __devinitdata = +static char version[] = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); MODULE_DESCRIPTION("Sun LDOM virtual network driver"); @@ -937,7 +937,7 @@ static void vnet_port_free_tx_bufs(struct vnet_port *port) } } -static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port) +static int vnet_port_alloc_tx_bufs(struct vnet_port *port) { struct vio_dring_state *dr; unsigned long len; @@ -1019,7 +1019,7 @@ static const struct net_device_ops vnet_ops = { .ndo_start_xmit = vnet_start_xmit, }; -static struct vnet * __devinit vnet_new(const u64 *local_mac) +static struct vnet *vnet_new(const u64 *local_mac) { struct net_device *dev; struct vnet *vp; @@ -1067,7 +1067,7 @@ err_out_free_dev: return ERR_PTR(err); } -static struct vnet * __devinit vnet_find_or_create(const u64 *local_mac) +static struct vnet *vnet_find_or_create(const u64 *local_mac) { struct vnet *iter, *vp; @@ -1088,7 +1088,7 @@ static struct vnet * __devinit vnet_find_or_create(const u64 *local_mac) static const char *local_mac_prop = "local-mac-address"; -static struct vnet * __devinit vnet_find_parent(struct mdesc_handle *hp, +static struct vnet *vnet_find_parent(struct mdesc_handle *hp, u64 port_node) { const u64 *local_mac = NULL; @@ -1125,15 +1125,14 @@ static struct vio_driver_ops vnet_vio_ops = { .handshake_complete = vnet_handshake_complete, }; -static void __devinit print_version(void) +static void print_version(void) { printk_once(KERN_INFO "%s", version); } const char *remote_macaddr_prop = "remote-mac-address"; -static int __devinit vnet_port_probe(struct vio_dev *vdev, - const struct vio_device_id *id) +static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) { struct mdesc_handle *hp; struct vnet_port *port; diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index 6ce9edd95c04..1e4d743ff03e 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -1914,7 +1914,7 @@ static const struct net_device_ops bdx_netdev_ops = { */ /* TBD: netif_msg should be checked and implemented. I disable it for now */ -static int __devinit +static int bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *ndev; @@ -2427,7 +2427,7 @@ static void bdx_set_ethtool_ops(struct net_device *netdev) * Hot-Plug event, or because the driver is going to be removed from * memory. **/ -static void __devexit bdx_remove(struct pci_dev *pdev) +static void bdx_remove(struct pci_dev *pdev) { struct pci_nic *nic = pci_get_drvdata(pdev); struct net_device *ndev; @@ -2458,7 +2458,7 @@ static struct pci_driver bdx_pci_driver = { .name = BDX_DRV_NAME, .id_table = bdx_pci_tbl, .probe = bdx_probe, - .remove = __devexit_p(bdx_remove), + .remove = bdx_remove, }; /* diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index 2c41894d5472..4426151d4ac9 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@ -60,6 +60,15 @@ config TI_CPSW To compile this driver as a module, choose M here: the module will be called cpsw. +config TI_CPTS + boolean "TI Common Platform Time Sync (CPTS) Support" + depends on TI_CPSW + select PTP_1588_CLOCK + ---help--- + This driver supports the Common Platform Time Sync unit of + the CPSW Ethernet Switch. The unit can time stamp PTP UDP/IPv4 + and Layer 2 packets, and the driver offers a PTP Hardware Clock. + config TLAN tristate "TI ThunderLAN support" depends on (PCI || EISA) diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile index 91bd8bba78ff..c65148e8aa1d 100644 --- a/drivers/net/ethernet/ti/Makefile +++ b/drivers/net/ethernet/ti/Makefile @@ -8,4 +8,4 @@ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o obj-$(CONFIG_TI_CPSW) += ti_cpsw.o -ti_cpsw-y := cpsw_ale.o cpsw.o +ti_cpsw-y := cpsw_ale.o cpsw.o cpts.o diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c index 860c2526f08d..d9625f62b026 100644 --- a/drivers/net/ethernet/ti/cpmac.c +++ b/drivers/net/ethernet/ti/cpmac.c @@ -1110,7 +1110,7 @@ static const struct net_device_ops cpmac_netdev_ops = { static int external_switch; -static int __devinit cpmac_probe(struct platform_device *pdev) +static int cpmac_probe(struct platform_device *pdev) { int rc, phy_id; char mdio_bus_id[MII_BUS_ID_SIZE]; @@ -1204,7 +1204,7 @@ fail: return rc; } -static int __devexit cpmac_remove(struct platform_device *pdev) +static int cpmac_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); unregister_netdev(dev); @@ -1216,10 +1216,10 @@ static struct platform_driver cpmac_driver = { .driver.name = "cpmac", .driver.owner = THIS_MODULE, .probe = cpmac_probe, - .remove = __devexit_p(cpmac_remove), + .remove = cpmac_remove, }; -int __devinit cpmac_init(void) +int cpmac_init(void) { u32 mask; int i, res; @@ -1290,7 +1290,7 @@ fail_alloc: return res; } -void __devexit cpmac_exit(void) +void cpmac_exit(void) { platform_driver_unregister(&cpmac_driver); mdiobus_unregister(cpmac_mii); diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index df55e2403746..40aff684aa23 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -24,6 +24,7 @@ #include <linux/if_ether.h> #include <linux/etherdevice.h> #include <linux/netdevice.h> +#include <linux/net_tstamp.h> #include <linux/phy.h> #include <linux/workqueue.h> #include <linux/delay.h> @@ -35,6 +36,7 @@ #include <linux/platform_data/cpsw.h> #include "cpsw_ale.h" +#include "cpts.h" #include "davinci_cpdma.h" #define CPSW_DEBUG (NETIF_MSG_HW | NETIF_MSG_WOL | \ @@ -70,10 +72,37 @@ do { \ dev_notice(priv->dev, format, ## __VA_ARGS__); \ } while (0) +#define ALE_ALL_PORTS 0x7 + #define CPSW_MAJOR_VERSION(reg) (reg >> 8 & 0x7) #define CPSW_MINOR_VERSION(reg) (reg & 0xff) #define CPSW_RTL_VERSION(reg) ((reg >> 11) & 0x1f) +#define CPSW_VERSION_1 0x19010a +#define CPSW_VERSION_2 0x19010c + +#define HOST_PORT_NUM 0 +#define SLIVER_SIZE 0x40 + +#define CPSW1_HOST_PORT_OFFSET 0x028 +#define CPSW1_SLAVE_OFFSET 0x050 +#define CPSW1_SLAVE_SIZE 0x040 +#define CPSW1_CPDMA_OFFSET 0x100 +#define CPSW1_STATERAM_OFFSET 0x200 +#define CPSW1_CPTS_OFFSET 0x500 +#define CPSW1_ALE_OFFSET 0x600 +#define CPSW1_SLIVER_OFFSET 0x700 + +#define CPSW2_HOST_PORT_OFFSET 0x108 +#define CPSW2_SLAVE_OFFSET 0x200 +#define CPSW2_SLAVE_SIZE 0x100 +#define CPSW2_CPDMA_OFFSET 0x800 +#define CPSW2_STATERAM_OFFSET 0xa00 +#define CPSW2_CPTS_OFFSET 0xc00 +#define CPSW2_ALE_OFFSET 0xd00 +#define CPSW2_SLIVER_OFFSET 0xd80 +#define CPSW2_BD_OFFSET 0x2000 + #define CPDMA_RXTHRESH 0x0c0 #define CPDMA_RXFREE 0x0e0 #define CPDMA_TXHDP 0x00 @@ -81,21 +110,6 @@ do { \ #define CPDMA_TXCP 0x40 #define CPDMA_RXCP 0x60 -#define cpsw_dma_regs(base, offset) \ - (void __iomem *)((base) + (offset)) -#define cpsw_dma_rxthresh(base, offset) \ - (void __iomem *)((base) + (offset) + CPDMA_RXTHRESH) -#define cpsw_dma_rxfree(base, offset) \ - (void __iomem *)((base) + (offset) + CPDMA_RXFREE) -#define cpsw_dma_txhdp(base, offset) \ - (void __iomem *)((base) + (offset) + CPDMA_TXHDP) -#define cpsw_dma_rxhdp(base, offset) \ - (void __iomem *)((base) + (offset) + CPDMA_RXHDP) -#define cpsw_dma_txcp(base, offset) \ - (void __iomem *)((base) + (offset) + CPDMA_TXCP) -#define cpsw_dma_rxcp(base, offset) \ - (void __iomem *)((base) + (offset) + CPDMA_RXCP) - #define CPSW_POLL_WEIGHT 64 #define CPSW_MIN_PACKET_SIZE 60 #define CPSW_MAX_PACKET_SIZE (1500 + 14 + 4 + 4) @@ -129,7 +143,7 @@ static int rx_packet_max = CPSW_MAX_PACKET_SIZE; module_param(rx_packet_max, int, 0); MODULE_PARM_DESC(rx_packet_max, "maximum receive packet size (bytes)"); -struct cpsw_ss_regs { +struct cpsw_wr_regs { u32 id_ver; u32 soft_reset; u32 control; @@ -140,26 +154,98 @@ struct cpsw_ss_regs { u32 misc_en; }; -struct cpsw_regs { +struct cpsw_ss_regs { u32 id_ver; u32 control; u32 soft_reset; u32 stat_port_en; u32 ptype; + u32 soft_idle; + u32 thru_rate; + u32 gap_thresh; + u32 tx_start_wds; + u32 flow_control; + u32 vlan_ltype; + u32 ts_ltype; + u32 dlr_ltype; }; -struct cpsw_slave_regs { - u32 max_blks; - u32 blk_cnt; - u32 flow_thresh; - u32 port_vlan; - u32 tx_pri_map; - u32 ts_ctl; - u32 ts_seq_ltype; - u32 ts_vlan; - u32 sa_lo; - u32 sa_hi; -}; +/* CPSW_PORT_V1 */ +#define CPSW1_MAX_BLKS 0x00 /* Maximum FIFO Blocks */ +#define CPSW1_BLK_CNT 0x04 /* FIFO Block Usage Count (Read Only) */ +#define CPSW1_TX_IN_CTL 0x08 /* Transmit FIFO Control */ +#define CPSW1_PORT_VLAN 0x0c /* VLAN Register */ +#define CPSW1_TX_PRI_MAP 0x10 /* Tx Header Priority to Switch Pri Mapping */ +#define CPSW1_TS_CTL 0x14 /* Time Sync Control */ +#define CPSW1_TS_SEQ_LTYPE 0x18 /* Time Sync Sequence ID Offset and Msg Type */ +#define CPSW1_TS_VLAN 0x1c /* Time Sync VLAN1 and VLAN2 */ + +/* CPSW_PORT_V2 */ +#define CPSW2_CONTROL 0x00 /* Control Register */ +#define CPSW2_MAX_BLKS 0x08 /* Maximum FIFO Blocks */ +#define CPSW2_BLK_CNT 0x0c /* FIFO Block Usage Count (Read Only) */ +#define CPSW2_TX_IN_CTL 0x10 /* Transmit FIFO Control */ +#define CPSW2_PORT_VLAN 0x14 /* VLAN Register */ +#define CPSW2_TX_PRI_MAP 0x18 /* Tx Header Priority to Switch Pri Mapping */ +#define CPSW2_TS_SEQ_MTYPE 0x1c /* Time Sync Sequence ID Offset and Msg Type */ + +/* CPSW_PORT_V1 and V2 */ +#define SA_LO 0x20 /* CPGMAC_SL Source Address Low */ +#define SA_HI 0x24 /* CPGMAC_SL Source Address High */ +#define SEND_PERCENT 0x28 /* Transmit Queue Send Percentages */ + +/* CPSW_PORT_V2 only */ +#define RX_DSCP_PRI_MAP0 0x30 /* Rx DSCP Priority to Rx Packet Mapping */ +#define RX_DSCP_PRI_MAP1 0x34 /* Rx DSCP Priority to Rx Packet Mapping */ +#define RX_DSCP_PRI_MAP2 0x38 /* Rx DSCP Priority to Rx Packet Mapping */ +#define RX_DSCP_PRI_MAP3 0x3c /* Rx DSCP Priority to Rx Packet Mapping */ +#define RX_DSCP_PRI_MAP4 0x40 /* Rx DSCP Priority to Rx Packet Mapping */ +#define RX_DSCP_PRI_MAP5 0x44 /* Rx DSCP Priority to Rx Packet Mapping */ +#define RX_DSCP_PRI_MAP6 0x48 /* Rx DSCP Priority to Rx Packet Mapping */ +#define RX_DSCP_PRI_MAP7 0x4c /* Rx DSCP Priority to Rx Packet Mapping */ + +/* Bit definitions for the CPSW2_CONTROL register */ +#define PASS_PRI_TAGGED (1<<24) /* Pass Priority Tagged */ +#define VLAN_LTYPE2_EN (1<<21) /* VLAN LTYPE 2 enable */ +#define VLAN_LTYPE1_EN (1<<20) /* VLAN LTYPE 1 enable */ +#define DSCP_PRI_EN (1<<16) /* DSCP Priority Enable */ +#define TS_320 (1<<14) /* Time Sync Dest Port 320 enable */ +#define TS_319 (1<<13) /* Time Sync Dest Port 319 enable */ +#define TS_132 (1<<12) /* Time Sync Dest IP Addr 132 enable */ +#define TS_131 (1<<11) /* Time Sync Dest IP Addr 131 enable */ +#define TS_130 (1<<10) /* Time Sync Dest IP Addr 130 enable */ +#define TS_129 (1<<9) /* Time Sync Dest IP Addr 129 enable */ +#define TS_BIT8 (1<<8) /* ts_ttl_nonzero? */ +#define TS_ANNEX_D_EN (1<<4) /* Time Sync Annex D enable */ +#define TS_LTYPE2_EN (1<<3) /* Time Sync LTYPE 2 enable */ +#define TS_LTYPE1_EN (1<<2) /* Time Sync LTYPE 1 enable */ +#define TS_TX_EN (1<<1) /* Time Sync Transmit Enable */ +#define TS_RX_EN (1<<0) /* Time Sync Receive Enable */ + +#define CTRL_TS_BITS \ + (TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 | TS_BIT8 | \ + TS_ANNEX_D_EN | TS_LTYPE1_EN) + +#define CTRL_ALL_TS_MASK (CTRL_TS_BITS | TS_TX_EN | TS_RX_EN) +#define CTRL_TX_TS_BITS (CTRL_TS_BITS | TS_TX_EN) +#define CTRL_RX_TS_BITS (CTRL_TS_BITS | TS_RX_EN) + +/* Bit definitions for the CPSW2_TS_SEQ_MTYPE register */ +#define TS_SEQ_ID_OFFSET_SHIFT (16) /* Time Sync Sequence ID Offset */ +#define TS_SEQ_ID_OFFSET_MASK (0x3f) +#define TS_MSG_TYPE_EN_SHIFT (0) /* Time Sync Message Type Enable */ +#define TS_MSG_TYPE_EN_MASK (0xffff) + +/* The PTP event messages - Sync, Delay_Req, Pdelay_Req, and Pdelay_Resp. */ +#define EVENT_MSG_BITS ((1<<0) | (1<<1) | (1<<2) | (1<<3)) + +/* Bit definitions for the CPSW1_TS_CTL register */ +#define CPSW_V1_TS_RX_EN BIT(0) +#define CPSW_V1_TS_TX_EN BIT(4) +#define CPSW_V1_MSG_TYPE_OFS 16 + +/* Bit definitions for the CPSW1_TS_SEQ_LTYPE register */ +#define CPSW_V1_SEQ_ID_OFS_SHIFT 16 struct cpsw_host_regs { u32 max_blks; @@ -185,7 +271,7 @@ struct cpsw_sliver_regs { }; struct cpsw_slave { - struct cpsw_slave_regs __iomem *regs; + void __iomem *regs; struct cpsw_sliver_regs __iomem *sliver; int slave_num; u32 mac_control; @@ -193,19 +279,30 @@ struct cpsw_slave { struct phy_device *phy; }; +static inline u32 slave_read(struct cpsw_slave *slave, u32 offset) +{ + return __raw_readl(slave->regs + offset); +} + +static inline void slave_write(struct cpsw_slave *slave, u32 val, u32 offset) +{ + __raw_writel(val, slave->regs + offset); +} + struct cpsw_priv { spinlock_t lock; struct platform_device *pdev; struct net_device *ndev; struct resource *cpsw_res; - struct resource *cpsw_ss_res; + struct resource *cpsw_wr_res; struct napi_struct napi; struct device *dev; struct cpsw_platform_data data; - struct cpsw_regs __iomem *regs; - struct cpsw_ss_regs __iomem *ss_regs; + struct cpsw_ss_regs __iomem *regs; + struct cpsw_wr_regs __iomem *wr_regs; struct cpsw_host_regs __iomem *host_port_regs; u32 msg_enable; + u32 version; struct net_device_stats stats; int rx_packet_max; int host_port; @@ -218,6 +315,7 @@ struct cpsw_priv { /* snapshot of IRQ numbers */ u32 irqs_table[4]; u32 num_irqs; + struct cpts cpts; }; #define napi_to_priv(napi) container_of(napi, struct cpsw_priv, napi) @@ -228,10 +326,34 @@ struct cpsw_priv { (func)((priv)->slaves + idx, ##arg); \ } while (0) +static void cpsw_ndo_set_rx_mode(struct net_device *ndev) +{ + struct cpsw_priv *priv = netdev_priv(ndev); + + if (ndev->flags & IFF_PROMISC) { + /* Enable promiscuous mode */ + dev_err(priv->dev, "Ignoring Promiscuous mode\n"); + return; + } + + /* Clear all mcast from ALE */ + cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port); + + if (!netdev_mc_empty(ndev)) { + struct netdev_hw_addr *ha; + + /* program multicast address list into ALE register */ + netdev_for_each_mc_addr(ha, ndev) { + cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr, + ALE_ALL_PORTS << priv->host_port, 0, 0); + } + } +} + static void cpsw_intr_enable(struct cpsw_priv *priv) { - __raw_writel(0xFF, &priv->ss_regs->tx_en); - __raw_writel(0xFF, &priv->ss_regs->rx_en); + __raw_writel(0xFF, &priv->wr_regs->tx_en); + __raw_writel(0xFF, &priv->wr_regs->rx_en); cpdma_ctlr_int_ctrl(priv->dma, true); return; @@ -239,8 +361,8 @@ static void cpsw_intr_enable(struct cpsw_priv *priv) static void cpsw_intr_disable(struct cpsw_priv *priv) { - __raw_writel(0, &priv->ss_regs->tx_en); - __raw_writel(0, &priv->ss_regs->rx_en); + __raw_writel(0, &priv->wr_regs->tx_en); + __raw_writel(0, &priv->wr_regs->rx_en); cpdma_ctlr_int_ctrl(priv->dma, false); return; @@ -254,6 +376,7 @@ void cpsw_tx_handler(void *token, int len, int status) if (unlikely(netif_queue_stopped(ndev))) netif_start_queue(ndev); + cpts_tx_timestamp(&priv->cpts, skb); priv->stats.tx_packets++; priv->stats.tx_bytes += len; dev_kfree_skb_any(skb); @@ -274,6 +397,7 @@ void cpsw_rx_handler(void *token, int len, int status) } if (likely(status >= 0)) { skb_put(skb, len); + cpts_rx_timestamp(&priv->cpts, skb); skb->protocol = eth_type_trans(skb, ndev); netif_receive_skb(skb); priv->stats.rx_bytes += len; @@ -359,8 +483,8 @@ static inline void soft_reset(const char *module, void __iomem *reg) static void cpsw_set_slave_mac(struct cpsw_slave *slave, struct cpsw_priv *priv) { - __raw_writel(mac_hi(priv->mac_addr), &slave->regs->sa_hi); - __raw_writel(mac_lo(priv->mac_addr), &slave->regs->sa_lo); + slave_write(slave, mac_hi(priv->mac_addr), SA_HI); + slave_write(slave, mac_lo(priv->mac_addr), SA_LO); } static void _cpsw_adjust_link(struct cpsw_slave *slave, @@ -446,7 +570,15 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) /* setup priority mapping */ __raw_writel(RX_PRIORITY_MAPPING, &slave->sliver->rx_pri_map); - __raw_writel(TX_PRIORITY_MAPPING, &slave->regs->tx_pri_map); + + switch (priv->version) { + case CPSW_VERSION_1: + slave_write(slave, TX_PRIORITY_MAPPING, CPSW1_TX_PRI_MAP); + break; + case CPSW_VERSION_2: + slave_write(slave, TX_PRIORITY_MAPPING, CPSW2_TX_PRI_MAP); + break; + } /* setup max packet size, and mac address */ __raw_writel(priv->rx_packet_max, &slave->sliver->rx_maxlen); @@ -505,7 +637,7 @@ static int cpsw_ndo_open(struct net_device *ndev) pm_runtime_get_sync(&priv->pdev->dev); - reg = __raw_readl(&priv->regs->id_ver); + reg = priv->version; dev_info(priv->dev, "initializing cpsw version %d.%d (%d)\n", CPSW_MAJOR_VERSION(reg), CPSW_MINOR_VERSION(reg), @@ -566,12 +698,12 @@ static int cpsw_ndo_stop(struct net_device *ndev) struct cpsw_priv *priv = netdev_priv(ndev); cpsw_info(priv, ifdown, "shutting down cpsw device\n"); - cpsw_intr_disable(priv); - cpdma_ctlr_int_ctrl(priv->dma, false); - cpdma_ctlr_stop(priv->dma); netif_stop_queue(priv->ndev); napi_disable(&priv->napi); netif_carrier_off(priv->ndev); + cpsw_intr_disable(priv); + cpdma_ctlr_int_ctrl(priv->dma, false); + cpdma_ctlr_stop(priv->dma); cpsw_ale_stop(priv->ale); for_each_slave(priv, cpsw_slave_stop, priv); pm_runtime_put_sync(&priv->pdev->dev); @@ -592,6 +724,11 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } + if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && priv->cpts.tx_enable) + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + + skb_tx_timestamp(skb); + ret = cpdma_chan_submit(priv->txch, skb, skb->data, skb->len, GFP_KERNEL); if (unlikely(ret != 0)) { @@ -629,6 +766,129 @@ static void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags) dev_err(&ndev->dev, "multicast traffic cannot be filtered!\n"); } +#ifdef CONFIG_TI_CPTS + +static void cpsw_hwtstamp_v1(struct cpsw_priv *priv) +{ + struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave]; + u32 ts_en, seq_id; + + if (!priv->cpts.tx_enable && !priv->cpts.rx_enable) { + slave_write(slave, 0, CPSW1_TS_CTL); + return; + } + + seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588; + ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS; + + if (priv->cpts.tx_enable) + ts_en |= CPSW_V1_TS_TX_EN; + + if (priv->cpts.rx_enable) + ts_en |= CPSW_V1_TS_RX_EN; + + slave_write(slave, ts_en, CPSW1_TS_CTL); + slave_write(slave, seq_id, CPSW1_TS_SEQ_LTYPE); +} + +static void cpsw_hwtstamp_v2(struct cpsw_priv *priv) +{ + struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave]; + u32 ctrl, mtype; + + ctrl = slave_read(slave, CPSW2_CONTROL); + ctrl &= ~CTRL_ALL_TS_MASK; + + if (priv->cpts.tx_enable) + ctrl |= CTRL_TX_TS_BITS; + + if (priv->cpts.rx_enable) + ctrl |= CTRL_RX_TS_BITS; + + mtype = (30 << TS_SEQ_ID_OFFSET_SHIFT) | EVENT_MSG_BITS; + + slave_write(slave, mtype, CPSW2_TS_SEQ_MTYPE); + slave_write(slave, ctrl, CPSW2_CONTROL); + __raw_writel(ETH_P_1588, &priv->regs->ts_ltype); +} + +static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) +{ + struct cpsw_priv *priv = netdev_priv(dev); + struct cpts *cpts = &priv->cpts; + struct hwtstamp_config cfg; + + if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) + return -EFAULT; + + /* reserved for future extensions */ + if (cfg.flags) + return -EINVAL; + + switch (cfg.tx_type) { + case HWTSTAMP_TX_OFF: + cpts->tx_enable = 0; + break; + case HWTSTAMP_TX_ON: + cpts->tx_enable = 1; + break; + default: + return -ERANGE; + } + + switch (cfg.rx_filter) { + case HWTSTAMP_FILTER_NONE: + cpts->rx_enable = 0; + break; + case HWTSTAMP_FILTER_ALL: + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + return -ERANGE; + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + cpts->rx_enable = 1; + cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; + break; + default: + return -ERANGE; + } + + switch (priv->version) { + case CPSW_VERSION_1: + cpsw_hwtstamp_v1(priv); + break; + case CPSW_VERSION_2: + cpsw_hwtstamp_v2(priv); + break; + default: + return -ENOTSUPP; + } + + return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; +} + +#endif /*CONFIG_TI_CPTS*/ + +static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd) +{ + if (!netif_running(dev)) + return -EINVAL; + +#ifdef CONFIG_TI_CPTS + if (cmd == SIOCSHWTSTAMP) + return cpsw_hwtstamp_ioctl(dev, req); +#endif + return -ENOTSUPP; +} + static void cpsw_ndo_tx_timeout(struct net_device *ndev) { struct cpsw_priv *priv = netdev_priv(ndev); @@ -669,10 +929,12 @@ static const struct net_device_ops cpsw_netdev_ops = { .ndo_stop = cpsw_ndo_stop, .ndo_start_xmit = cpsw_ndo_start_xmit, .ndo_change_rx_flags = cpsw_ndo_change_rx_flags, + .ndo_do_ioctl = cpsw_ndo_ioctl, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = eth_change_mtu, .ndo_tx_timeout = cpsw_ndo_tx_timeout, .ndo_get_stats = cpsw_ndo_get_stats, + .ndo_set_rx_mode = cpsw_ndo_set_rx_mode, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = cpsw_ndo_poll_controller, #endif @@ -699,22 +961,56 @@ static void cpsw_set_msglevel(struct net_device *ndev, u32 value) priv->msg_enable = value; } +static int cpsw_get_ts_info(struct net_device *ndev, + struct ethtool_ts_info *info) +{ +#ifdef CONFIG_TI_CPTS + struct cpsw_priv *priv = netdev_priv(ndev); + + info->so_timestamping = + SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + info->phc_index = priv->cpts.phc_index; + info->tx_types = + (1 << HWTSTAMP_TX_OFF) | + (1 << HWTSTAMP_TX_ON); + info->rx_filters = + (1 << HWTSTAMP_FILTER_NONE) | + (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); +#else + info->so_timestamping = + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + info->phc_index = -1; + info->tx_types = 0; + info->rx_filters = 0; +#endif + return 0; +} + static const struct ethtool_ops cpsw_ethtool_ops = { .get_drvinfo = cpsw_get_drvinfo, .get_msglevel = cpsw_get_msglevel, .set_msglevel = cpsw_set_msglevel, .get_link = ethtool_op_get_link, + .get_ts_info = cpsw_get_ts_info, }; -static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv) +static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv, + u32 slave_reg_ofs, u32 sliver_reg_ofs) { void __iomem *regs = priv->regs; int slave_num = slave->slave_num; struct cpsw_slave_data *data = priv->data.slave_data + slave_num; slave->data = data; - slave->regs = regs + data->slave_reg_ofs; - slave->sliver = regs + data->sliver_reg_ofs; + slave->regs = regs + slave_reg_ofs; + slave->sliver = regs + sliver_reg_ofs; } static int cpsw_probe_dt(struct cpsw_platform_data *data, @@ -734,49 +1030,40 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, } data->slaves = prop; - data->slave_data = kzalloc(sizeof(struct cpsw_slave_data) * - data->slaves, GFP_KERNEL); - if (!data->slave_data) { - pr_err("Could not allocate slave memory.\n"); - return -EINVAL; - } - - data->no_bd_ram = of_property_read_bool(node, "no_bd_ram"); - - if (of_property_read_u32(node, "cpdma_channels", &prop)) { - pr_err("Missing cpdma_channels property in the DT.\n"); + if (of_property_read_u32(node, "cpts_active_slave", &prop)) { + pr_err("Missing cpts_active_slave property in the DT.\n"); ret = -EINVAL; goto error_ret; } - data->channels = prop; + data->cpts_active_slave = prop; - if (of_property_read_u32(node, "host_port_no", &prop)) { - pr_err("Missing host_port_no property in the DT.\n"); + if (of_property_read_u32(node, "cpts_clock_mult", &prop)) { + pr_err("Missing cpts_clock_mult property in the DT.\n"); ret = -EINVAL; goto error_ret; } - data->host_port_num = prop; + data->cpts_clock_mult = prop; - if (of_property_read_u32(node, "cpdma_reg_ofs", &prop)) { - pr_err("Missing cpdma_reg_ofs property in the DT.\n"); + if (of_property_read_u32(node, "cpts_clock_shift", &prop)) { + pr_err("Missing cpts_clock_shift property in the DT.\n"); ret = -EINVAL; goto error_ret; } - data->cpdma_reg_ofs = prop; + data->cpts_clock_shift = prop; - if (of_property_read_u32(node, "cpdma_sram_ofs", &prop)) { - pr_err("Missing cpdma_sram_ofs property in the DT.\n"); - ret = -EINVAL; - goto error_ret; + data->slave_data = kzalloc(sizeof(struct cpsw_slave_data) * + data->slaves, GFP_KERNEL); + if (!data->slave_data) { + pr_err("Could not allocate slave memory.\n"); + return -EINVAL; } - data->cpdma_sram_ofs = prop; - if (of_property_read_u32(node, "ale_reg_ofs", &prop)) { - pr_err("Missing ale_reg_ofs property in the DT.\n"); + if (of_property_read_u32(node, "cpdma_channels", &prop)) { + pr_err("Missing cpdma_channels property in the DT.\n"); ret = -EINVAL; goto error_ret; } - data->ale_reg_ofs = prop; + data->channels = prop; if (of_property_read_u32(node, "ale_entries", &prop)) { pr_err("Missing ale_entries property in the DT.\n"); @@ -785,27 +1072,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, } data->ale_entries = prop; - if (of_property_read_u32(node, "host_port_reg_ofs", &prop)) { - pr_err("Missing host_port_reg_ofs property in the DT.\n"); - ret = -EINVAL; - goto error_ret; - } - data->host_port_reg_ofs = prop; - - if (of_property_read_u32(node, "hw_stats_reg_ofs", &prop)) { - pr_err("Missing hw_stats_reg_ofs property in the DT.\n"); - ret = -EINVAL; - goto error_ret; - } - data->hw_stats_reg_ofs = prop; - - if (of_property_read_u32(node, "bd_ram_ofs", &prop)) { - pr_err("Missing bd_ram_ofs property in the DT.\n"); - ret = -EINVAL; - goto error_ret; - } - data->bd_ram_ofs = prop; - if (of_property_read_u32(node, "bd_ram_size", &prop)) { pr_err("Missing bd_ram_size property in the DT.\n"); ret = -EINVAL; @@ -827,33 +1093,34 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, } data->mac_control = prop; - for_each_child_of_node(node, slave_node) { + /* + * Populate all the child nodes here... + */ + ret = of_platform_populate(node, NULL, NULL, &pdev->dev); + /* We do not want to force this, as in some cases may not have child */ + if (ret) + pr_warn("Doesn't have any child node\n"); + + for_each_node_by_name(slave_node, "slave") { struct cpsw_slave_data *slave_data = data->slave_data + i; - const char *phy_id = NULL; const void *mac_addr = NULL; - - if (of_property_read_string(slave_node, "phy_id", &phy_id)) { + u32 phyid; + int lenp; + const __be32 *parp; + struct device_node *mdio_node; + struct platform_device *mdio; + + parp = of_get_property(slave_node, "phy_id", &lenp); + if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) { pr_err("Missing slave[%d] phy_id property\n", i); ret = -EINVAL; goto error_ret; } - slave_data->phy_id = phy_id; - - if (of_property_read_u32(slave_node, "slave_reg_ofs", &prop)) { - pr_err("Missing slave[%d] slave_reg_ofs property\n", i); - ret = -EINVAL; - goto error_ret; - } - slave_data->slave_reg_ofs = prop; - - if (of_property_read_u32(slave_node, "sliver_reg_ofs", - &prop)) { - pr_err("Missing slave[%d] sliver_reg_ofs property\n", - i); - ret = -EINVAL; - goto error_ret; - } - slave_data->sliver_reg_ofs = prop; + mdio_node = of_find_node_by_phandle(be32_to_cpup(parp)); + phyid = be32_to_cpup(parp+1); + mdio = of_find_device_by_node(mdio_node); + snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), + PHY_ID_FMT, mdio->name, phyid); mac_addr = of_get_mac_address(slave_node); if (mac_addr) @@ -869,15 +1136,16 @@ error_ret: return ret; } -static int __devinit cpsw_probe(struct platform_device *pdev) +static int cpsw_probe(struct platform_device *pdev) { struct cpsw_platform_data *data = pdev->dev.platform_data; struct net_device *ndev; struct cpsw_priv *priv; struct cpdma_params dma_params; struct cpsw_ale_params ale_params; - void __iomem *regs; + void __iomem *ss_regs, *wr_regs; struct resource *res; + u32 slave_offset, sliver_offset, slave_size; int ret = 0, i, k = 0; ndev = alloc_etherdev(sizeof(struct cpsw_priv)); @@ -895,6 +1163,11 @@ static int __devinit cpsw_probe(struct platform_device *pdev) priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG); priv->rx_packet_max = max(rx_packet_max, 128); + /* + * This may be required here for child devices. + */ + pm_runtime_enable(&pdev->dev); + if (cpsw_probe_dt(&priv->data, pdev)) { pr_err("cpsw: platform data missing\n"); ret = -ENODEV; @@ -921,7 +1194,6 @@ static int __devinit cpsw_probe(struct platform_device *pdev) for (i = 0; i < data->slaves; i++) priv->slaves[i].slave_num = i; - pm_runtime_enable(&pdev->dev); priv->clk = clk_get(&pdev->dev, "fck"); if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "fck is not found\n"); @@ -935,63 +1207,86 @@ static int __devinit cpsw_probe(struct platform_device *pdev) ret = -ENOENT; goto clean_clk_ret; } - if (!request_mem_region(priv->cpsw_res->start, resource_size(priv->cpsw_res), ndev->name)) { dev_err(priv->dev, "failed request i/o region\n"); ret = -ENXIO; goto clean_clk_ret; } - - regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res)); - if (!regs) { + ss_regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res)); + if (!ss_regs) { dev_err(priv->dev, "unable to map i/o region\n"); goto clean_cpsw_iores_ret; } - priv->regs = regs; - priv->host_port = data->host_port_num; - priv->host_port_regs = regs + data->host_port_reg_ofs; + priv->regs = ss_regs; + priv->version = __raw_readl(&priv->regs->id_ver); + priv->host_port = HOST_PORT_NUM; - priv->cpsw_ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!priv->cpsw_ss_res) { + priv->cpsw_wr_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!priv->cpsw_wr_res) { dev_err(priv->dev, "error getting i/o resource\n"); ret = -ENOENT; - goto clean_clk_ret; + goto clean_iomap_ret; } - - if (!request_mem_region(priv->cpsw_ss_res->start, - resource_size(priv->cpsw_ss_res), ndev->name)) { + if (!request_mem_region(priv->cpsw_wr_res->start, + resource_size(priv->cpsw_wr_res), ndev->name)) { dev_err(priv->dev, "failed request i/o region\n"); ret = -ENXIO; - goto clean_clk_ret; + goto clean_iomap_ret; } - - regs = ioremap(priv->cpsw_ss_res->start, - resource_size(priv->cpsw_ss_res)); - if (!regs) { + wr_regs = ioremap(priv->cpsw_wr_res->start, + resource_size(priv->cpsw_wr_res)); + if (!wr_regs) { dev_err(priv->dev, "unable to map i/o region\n"); - goto clean_cpsw_ss_iores_ret; + goto clean_cpsw_wr_iores_ret; } - priv->ss_regs = regs; - - for_each_slave(priv, cpsw_slave_init, priv); + priv->wr_regs = wr_regs; memset(&dma_params, 0, sizeof(dma_params)); + memset(&ale_params, 0, sizeof(ale_params)); + + switch (priv->version) { + case CPSW_VERSION_1: + priv->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET; + priv->cpts.reg = ss_regs + CPSW1_CPTS_OFFSET; + dma_params.dmaregs = ss_regs + CPSW1_CPDMA_OFFSET; + dma_params.txhdp = ss_regs + CPSW1_STATERAM_OFFSET; + ale_params.ale_regs = ss_regs + CPSW1_ALE_OFFSET; + slave_offset = CPSW1_SLAVE_OFFSET; + slave_size = CPSW1_SLAVE_SIZE; + sliver_offset = CPSW1_SLIVER_OFFSET; + dma_params.desc_mem_phys = 0; + break; + case CPSW_VERSION_2: + priv->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET; + priv->cpts.reg = ss_regs + CPSW2_CPTS_OFFSET; + dma_params.dmaregs = ss_regs + CPSW2_CPDMA_OFFSET; + dma_params.txhdp = ss_regs + CPSW2_STATERAM_OFFSET; + ale_params.ale_regs = ss_regs + CPSW2_ALE_OFFSET; + slave_offset = CPSW2_SLAVE_OFFSET; + slave_size = CPSW2_SLAVE_SIZE; + sliver_offset = CPSW2_SLIVER_OFFSET; + dma_params.desc_mem_phys = + (u32 __force) priv->cpsw_res->start + CPSW2_BD_OFFSET; + break; + default: + dev_err(priv->dev, "unknown version 0x%08x\n", priv->version); + ret = -ENODEV; + goto clean_cpsw_wr_iores_ret; + } + for (i = 0; i < priv->data.slaves; i++) { + struct cpsw_slave *slave = &priv->slaves[i]; + cpsw_slave_init(slave, priv, slave_offset, sliver_offset); + slave_offset += slave_size; + sliver_offset += SLIVER_SIZE; + } + dma_params.dev = &pdev->dev; - dma_params.dmaregs = cpsw_dma_regs((u32)priv->regs, - data->cpdma_reg_ofs); - dma_params.rxthresh = cpsw_dma_rxthresh((u32)priv->regs, - data->cpdma_reg_ofs); - dma_params.rxfree = cpsw_dma_rxfree((u32)priv->regs, - data->cpdma_reg_ofs); - dma_params.txhdp = cpsw_dma_txhdp((u32)priv->regs, - data->cpdma_sram_ofs); - dma_params.rxhdp = cpsw_dma_rxhdp((u32)priv->regs, - data->cpdma_sram_ofs); - dma_params.txcp = cpsw_dma_txcp((u32)priv->regs, - data->cpdma_sram_ofs); - dma_params.rxcp = cpsw_dma_rxcp((u32)priv->regs, - data->cpdma_sram_ofs); + dma_params.rxthresh = dma_params.dmaregs + CPDMA_RXTHRESH; + dma_params.rxfree = dma_params.dmaregs + CPDMA_RXFREE; + dma_params.rxhdp = dma_params.txhdp + CPDMA_RXHDP; + dma_params.txcp = dma_params.txhdp + CPDMA_TXCP; + dma_params.rxcp = dma_params.txhdp + CPDMA_RXCP; dma_params.num_chan = data->channels; dma_params.has_soft_reset = true; @@ -999,16 +1294,13 @@ static int __devinit cpsw_probe(struct platform_device *pdev) dma_params.desc_mem_size = data->bd_ram_size; dma_params.desc_align = 16; dma_params.has_ext_regs = true; - dma_params.desc_mem_phys = data->no_bd_ram ? 0 : - (u32 __force)priv->cpsw_res->start + data->bd_ram_ofs; - dma_params.desc_hw_addr = data->hw_ram_addr ? - data->hw_ram_addr : dma_params.desc_mem_phys ; + dma_params.desc_hw_addr = dma_params.desc_mem_phys; priv->dma = cpdma_ctlr_create(&dma_params); if (!priv->dma) { dev_err(priv->dev, "error initializing dma\n"); ret = -ENOMEM; - goto clean_iomap_ret; + goto clean_wr_iomap_ret; } priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0), @@ -1022,10 +1314,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev) goto clean_dma_ret; } - memset(&ale_params, 0, sizeof(ale_params)); ale_params.dev = &ndev->dev; - ale_params.ale_regs = (void *)((u32)priv->regs) + - ((u32)data->ale_reg_ofs); ale_params.ale_ageout = ale_ageout; ale_params.ale_entries = data->ale_entries; ale_params.ale_ports = data->slaves; @@ -1072,6 +1361,10 @@ static int __devinit cpsw_probe(struct platform_device *pdev) goto clean_irq_ret; } + if (cpts_register(&pdev->dev, &priv->cpts, + data->cpts_clock_mult, data->cpts_clock_shift)) + dev_err(priv->dev, "error registering cpts device\n"); + cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n", priv->cpsw_res->start, ndev->irq); @@ -1085,11 +1378,13 @@ clean_dma_ret: cpdma_chan_destroy(priv->txch); cpdma_chan_destroy(priv->rxch); cpdma_ctlr_destroy(priv->dma); +clean_wr_iomap_ret: + iounmap(priv->wr_regs); +clean_cpsw_wr_iores_ret: + release_mem_region(priv->cpsw_wr_res->start, + resource_size(priv->cpsw_wr_res)); clean_iomap_ret: iounmap(priv->regs); -clean_cpsw_ss_iores_ret: - release_mem_region(priv->cpsw_ss_res->start, - resource_size(priv->cpsw_ss_res)); clean_cpsw_iores_ret: release_mem_region(priv->cpsw_res->start, resource_size(priv->cpsw_res)); @@ -1103,7 +1398,7 @@ clean_ndev_ret: return ret; } -static int __devexit cpsw_remove(struct platform_device *pdev) +static int cpsw_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct cpsw_priv *priv = netdev_priv(ndev); @@ -1111,6 +1406,7 @@ static int __devexit cpsw_remove(struct platform_device *pdev) pr_info("removing device"); platform_set_drvdata(pdev, NULL); + cpts_unregister(&priv->cpts); free_irq(ndev->irq, priv); cpsw_ale_destroy(priv->ale); cpdma_chan_destroy(priv->txch); @@ -1119,8 +1415,9 @@ static int __devexit cpsw_remove(struct platform_device *pdev) iounmap(priv->regs); release_mem_region(priv->cpsw_res->start, resource_size(priv->cpsw_res)); - release_mem_region(priv->cpsw_ss_res->start, - resource_size(priv->cpsw_ss_res)); + iounmap(priv->wr_regs); + release_mem_region(priv->cpsw_wr_res->start, + resource_size(priv->cpsw_wr_res)); pm_runtime_disable(&pdev->dev); clk_put(priv->clk); kfree(priv->slaves); @@ -1170,7 +1467,7 @@ static struct platform_driver cpsw_driver = { .of_match_table = of_match_ptr(cpsw_of_mtable), }, .probe = cpsw_probe, - .remove = __devexit_p(cpsw_remove), + .remove = cpsw_remove, }; static int __init cpsw_init(void) diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c index ca0d48a7e508..0e9ccc2cf91f 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.c +++ b/drivers/net/ethernet/ti/cpsw_ale.c @@ -20,6 +20,7 @@ #include <linux/io.h> #include <linux/stat.h> #include <linux/sysfs.h> +#include <linux/etherdevice.h> #include "cpsw_ale.h" @@ -211,10 +212,34 @@ static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry, mask &= ~port_mask; /* free if only remaining port is host port */ - if (mask == BIT(ale->params.ale_ports)) - cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); - else + if (mask) cpsw_ale_set_port_mask(ale_entry, mask); + else + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); +} + +int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask) +{ + u32 ale_entry[ALE_ENTRY_WORDS]; + int ret, idx; + + for (idx = 0; idx < ale->params.ale_entries; idx++) { + cpsw_ale_read(ale, idx, ale_entry); + ret = cpsw_ale_get_entry_type(ale_entry); + if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR) + continue; + + if (cpsw_ale_get_mcast(ale_entry)) { + u8 addr[6]; + + cpsw_ale_get_addr(ale_entry, addr); + if (!is_broadcast_ether_addr(addr)) + cpsw_ale_flush_mcast(ale, ale_entry, port_mask); + } + + cpsw_ale_write(ale, idx, ale_entry); + } + return 0; } static void cpsw_ale_flush_ucast(struct cpsw_ale *ale, u32 *ale_entry, diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h index a95b37beb02d..2bd09cbce522 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.h +++ b/drivers/net/ethernet/ti/cpsw_ale.h @@ -80,6 +80,7 @@ void cpsw_ale_stop(struct cpsw_ale *ale); int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout); int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask); +int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask); int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags); int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port); int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask, diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c new file mode 100644 index 000000000000..463597f919f1 --- /dev/null +++ b/drivers/net/ethernet/ti/cpts.c @@ -0,0 +1,424 @@ +/* + * TI Common Platform Time Sync + * + * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 + */ +#include <linux/err.h> +#include <linux/if.h> +#include <linux/hrtimer.h> +#include <linux/module.h> +#include <linux/net_tstamp.h> +#include <linux/ptp_classify.h> +#include <linux/time.h> +#include <linux/uaccess.h> +#include <linux/workqueue.h> + +#include "cpts.h" + +#ifdef CONFIG_TI_CPTS + +static struct sock_filter ptp_filter[] = { + PTP_FILTER +}; + +#define cpts_read32(c, r) __raw_readl(&c->reg->r) +#define cpts_write32(c, v, r) __raw_writel(v, &c->reg->r) + +static int event_expired(struct cpts_event *event) +{ + return time_after(jiffies, event->tmo); +} + +static int event_type(struct cpts_event *event) +{ + return (event->high >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; +} + +static int cpts_fifo_pop(struct cpts *cpts, u32 *high, u32 *low) +{ + u32 r = cpts_read32(cpts, intstat_raw); + + if (r & TS_PEND_RAW) { + *high = cpts_read32(cpts, event_high); + *low = cpts_read32(cpts, event_low); + cpts_write32(cpts, EVENT_POP, event_pop); + return 0; + } + return -1; +} + +/* + * Returns zero if matching event type was found. + */ +static int cpts_fifo_read(struct cpts *cpts, int match) +{ + int i, type = -1; + u32 hi, lo; + struct cpts_event *event; + + for (i = 0; i < CPTS_FIFO_DEPTH; i++) { + if (cpts_fifo_pop(cpts, &hi, &lo)) + break; + if (list_empty(&cpts->pool)) { + pr_err("cpts: event pool is empty\n"); + return -1; + } + event = list_first_entry(&cpts->pool, struct cpts_event, list); + event->tmo = jiffies + 2; + event->high = hi; + event->low = lo; + type = event_type(event); + switch (type) { + case CPTS_EV_PUSH: + case CPTS_EV_RX: + case CPTS_EV_TX: + list_del_init(&event->list); + list_add_tail(&event->list, &cpts->events); + break; + case CPTS_EV_ROLL: + case CPTS_EV_HALF: + case CPTS_EV_HW: + break; + default: + pr_err("cpts: unkown event type\n"); + break; + } + if (type == match) + break; + } + return type == match ? 0 : -1; +} + +static cycle_t cpts_systim_read(const struct cyclecounter *cc) +{ + u64 val = 0; + struct cpts_event *event; + struct list_head *this, *next; + struct cpts *cpts = container_of(cc, struct cpts, cc); + + cpts_write32(cpts, TS_PUSH, ts_push); + if (cpts_fifo_read(cpts, CPTS_EV_PUSH)) + pr_err("cpts: unable to obtain a time stamp\n"); + + list_for_each_safe(this, next, &cpts->events) { + event = list_entry(this, struct cpts_event, list); + if (event_type(event) == CPTS_EV_PUSH) { + list_del_init(&event->list); + list_add(&event->list, &cpts->pool); + val = event->low; + break; + } + } + + return val; +} + +/* PTP clock operations */ + +static int cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) +{ + u64 adj; + u32 diff, mult; + int neg_adj = 0; + unsigned long flags; + struct cpts *cpts = container_of(ptp, struct cpts, info); + + if (ppb < 0) { + neg_adj = 1; + ppb = -ppb; + } + mult = cpts->cc_mult; + adj = mult; + adj *= ppb; + diff = div_u64(adj, 1000000000ULL); + + spin_lock_irqsave(&cpts->lock, flags); + + timecounter_read(&cpts->tc); + + cpts->cc.mult = neg_adj ? mult - diff : mult + diff; + + spin_unlock_irqrestore(&cpts->lock, flags); + + return 0; +} + +static int cpts_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + s64 now; + unsigned long flags; + struct cpts *cpts = container_of(ptp, struct cpts, info); + + spin_lock_irqsave(&cpts->lock, flags); + now = timecounter_read(&cpts->tc); + now += delta; + timecounter_init(&cpts->tc, &cpts->cc, now); + spin_unlock_irqrestore(&cpts->lock, flags); + + return 0; +} + +static int cpts_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts) +{ + u64 ns; + u32 remainder; + unsigned long flags; + struct cpts *cpts = container_of(ptp, struct cpts, info); + + spin_lock_irqsave(&cpts->lock, flags); + ns = timecounter_read(&cpts->tc); + spin_unlock_irqrestore(&cpts->lock, flags); + + ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); + ts->tv_nsec = remainder; + + return 0; +} + +static int cpts_ptp_settime(struct ptp_clock_info *ptp, + const struct timespec *ts) +{ + u64 ns; + unsigned long flags; + struct cpts *cpts = container_of(ptp, struct cpts, info); + + ns = ts->tv_sec * 1000000000ULL; + ns += ts->tv_nsec; + + spin_lock_irqsave(&cpts->lock, flags); + timecounter_init(&cpts->tc, &cpts->cc, ns); + spin_unlock_irqrestore(&cpts->lock, flags); + + return 0; +} + +static int cpts_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + return -EOPNOTSUPP; +} + +static struct ptp_clock_info cpts_info = { + .owner = THIS_MODULE, + .name = "CTPS timer", + .max_adj = 1000000, + .n_ext_ts = 0, + .pps = 0, + .adjfreq = cpts_ptp_adjfreq, + .adjtime = cpts_ptp_adjtime, + .gettime = cpts_ptp_gettime, + .settime = cpts_ptp_settime, + .enable = cpts_ptp_enable, +}; + +static void cpts_overflow_check(struct work_struct *work) +{ + struct timespec ts; + struct cpts *cpts = container_of(work, struct cpts, overflow_work.work); + + cpts_write32(cpts, CPTS_EN, control); + cpts_write32(cpts, TS_PEND_EN, int_enable); + cpts_ptp_gettime(&cpts->info, &ts); + pr_debug("cpts overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec); + schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD); +} + +#define CPTS_REF_CLOCK_NAME "cpsw_cpts_rft_clk" + +static void cpts_clk_init(struct cpts *cpts) +{ + cpts->refclk = clk_get(NULL, CPTS_REF_CLOCK_NAME); + if (IS_ERR(cpts->refclk)) { + pr_err("Failed to clk_get %s\n", CPTS_REF_CLOCK_NAME); + cpts->refclk = NULL; + return; + } + clk_prepare_enable(cpts->refclk); +} + +static void cpts_clk_release(struct cpts *cpts) +{ + clk_disable(cpts->refclk); + clk_put(cpts->refclk); +} + +static int cpts_match(struct sk_buff *skb, unsigned int ptp_class, + u16 ts_seqid, u8 ts_msgtype) +{ + u16 *seqid; + unsigned int offset; + u8 *msgtype, *data = skb->data; + + switch (ptp_class) { + case PTP_CLASS_V1_IPV4: + case PTP_CLASS_V2_IPV4: + offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN; + break; + case PTP_CLASS_V1_IPV6: + case PTP_CLASS_V2_IPV6: + offset = OFF_PTP6; + break; + case PTP_CLASS_V2_L2: + offset = ETH_HLEN; + break; + case PTP_CLASS_V2_VLAN: + offset = ETH_HLEN + VLAN_HLEN; + break; + default: + return 0; + } + + if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid)) + return 0; + + if (unlikely(ptp_class & PTP_CLASS_V1)) + msgtype = data + offset + OFF_PTP_CONTROL; + else + msgtype = data + offset; + + seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID); + + return (ts_msgtype == (*msgtype & 0xf) && ts_seqid == ntohs(*seqid)); +} + +static u64 cpts_find_ts(struct cpts *cpts, struct sk_buff *skb, int ev_type) +{ + u64 ns = 0; + struct cpts_event *event; + struct list_head *this, *next; + unsigned int class = sk_run_filter(skb, ptp_filter); + unsigned long flags; + u16 seqid; + u8 mtype; + + if (class == PTP_CLASS_NONE) + return 0; + + spin_lock_irqsave(&cpts->lock, flags); + cpts_fifo_read(cpts, CPTS_EV_PUSH); + list_for_each_safe(this, next, &cpts->events) { + event = list_entry(this, struct cpts_event, list); + if (event_expired(event)) { + list_del_init(&event->list); + list_add(&event->list, &cpts->pool); + continue; + } + mtype = (event->high >> MESSAGE_TYPE_SHIFT) & MESSAGE_TYPE_MASK; + seqid = (event->high >> SEQUENCE_ID_SHIFT) & SEQUENCE_ID_MASK; + if (ev_type == event_type(event) && + cpts_match(skb, class, seqid, mtype)) { + ns = timecounter_cyc2time(&cpts->tc, event->low); + list_del_init(&event->list); + list_add(&event->list, &cpts->pool); + break; + } + } + spin_unlock_irqrestore(&cpts->lock, flags); + + return ns; +} + +void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb) +{ + u64 ns; + struct skb_shared_hwtstamps *ssh; + + if (!cpts->rx_enable) + return; + ns = cpts_find_ts(cpts, skb, CPTS_EV_RX); + if (!ns) + return; + ssh = skb_hwtstamps(skb); + memset(ssh, 0, sizeof(*ssh)); + ssh->hwtstamp = ns_to_ktime(ns); +} + +void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb) +{ + u64 ns; + struct skb_shared_hwtstamps ssh; + + if (!(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) + return; + ns = cpts_find_ts(cpts, skb, CPTS_EV_TX); + if (!ns) + return; + memset(&ssh, 0, sizeof(ssh)); + ssh.hwtstamp = ns_to_ktime(ns); + skb_tstamp_tx(skb, &ssh); +} + +#endif /*CONFIG_TI_CPTS*/ + +int cpts_register(struct device *dev, struct cpts *cpts, + u32 mult, u32 shift) +{ +#ifdef CONFIG_TI_CPTS + int err, i; + unsigned long flags; + + if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) { + pr_err("cpts: bad ptp filter\n"); + return -EINVAL; + } + cpts->info = cpts_info; + cpts->clock = ptp_clock_register(&cpts->info, dev); + if (IS_ERR(cpts->clock)) { + err = PTR_ERR(cpts->clock); + cpts->clock = NULL; + return err; + } + spin_lock_init(&cpts->lock); + + cpts->cc.read = cpts_systim_read; + cpts->cc.mask = CLOCKSOURCE_MASK(32); + cpts->cc_mult = mult; + cpts->cc.mult = mult; + cpts->cc.shift = shift; + + INIT_LIST_HEAD(&cpts->events); + INIT_LIST_HEAD(&cpts->pool); + for (i = 0; i < CPTS_MAX_EVENTS; i++) + list_add(&cpts->pool_data[i].list, &cpts->pool); + + cpts_clk_init(cpts); + cpts_write32(cpts, CPTS_EN, control); + cpts_write32(cpts, TS_PEND_EN, int_enable); + + spin_lock_irqsave(&cpts->lock, flags); + timecounter_init(&cpts->tc, &cpts->cc, ktime_to_ns(ktime_get_real())); + spin_unlock_irqrestore(&cpts->lock, flags); + + INIT_DELAYED_WORK(&cpts->overflow_work, cpts_overflow_check); + schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD); + + cpts->phc_index = ptp_clock_index(cpts->clock); +#endif + return 0; +} + +void cpts_unregister(struct cpts *cpts) +{ +#ifdef CONFIG_TI_CPTS + if (cpts->clock) { + ptp_clock_unregister(cpts->clock); + cancel_delayed_work_sync(&cpts->overflow_work); + } + if (cpts->refclk) + cpts_clk_release(cpts); +#endif +} diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h new file mode 100644 index 000000000000..fe993cdd7e23 --- /dev/null +++ b/drivers/net/ethernet/ti/cpts.h @@ -0,0 +1,145 @@ +/* + * TI Common Platform Time Sync + * + * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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 + */ +#ifndef _TI_CPTS_H_ +#define _TI_CPTS_H_ + +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/clocksource.h> +#include <linux/device.h> +#include <linux/list.h> +#include <linux/ptp_clock_kernel.h> +#include <linux/skbuff.h> + +struct cpsw_cpts { + u32 idver; /* Identification and version */ + u32 control; /* Time sync control */ + u32 res1; + u32 ts_push; /* Time stamp event push */ + u32 ts_load_val; /* Time stamp load value */ + u32 ts_load_en; /* Time stamp load enable */ + u32 res2[2]; + u32 intstat_raw; /* Time sync interrupt status raw */ + u32 intstat_masked; /* Time sync interrupt status masked */ + u32 int_enable; /* Time sync interrupt enable */ + u32 res3; + u32 event_pop; /* Event interrupt pop */ + u32 event_low; /* 32 Bit Event Time Stamp */ + u32 event_high; /* Event Type Fields */ +}; + +/* Bit definitions for the IDVER register */ +#define TX_IDENT_SHIFT (16) /* TX Identification Value */ +#define TX_IDENT_MASK (0xffff) +#define RTL_VER_SHIFT (11) /* RTL Version Value */ +#define RTL_VER_MASK (0x1f) +#define MAJOR_VER_SHIFT (8) /* Major Version Value */ +#define MAJOR_VER_MASK (0x7) +#define MINOR_VER_SHIFT (0) /* Minor Version Value */ +#define MINOR_VER_MASK (0xff) + +/* Bit definitions for the CONTROL register */ +#define HW4_TS_PUSH_EN (1<<11) /* Hardware push 4 enable */ +#define HW3_TS_PUSH_EN (1<<10) /* Hardware push 3 enable */ +#define HW2_TS_PUSH_EN (1<<9) /* Hardware push 2 enable */ +#define HW1_TS_PUSH_EN (1<<8) /* Hardware push 1 enable */ +#define INT_TEST (1<<1) /* Interrupt Test */ +#define CPTS_EN (1<<0) /* Time Sync Enable */ + +/* + * Definitions for the single bit resisters: + * TS_PUSH TS_LOAD_EN INTSTAT_RAW INTSTAT_MASKED INT_ENABLE EVENT_POP + */ +#define TS_PUSH (1<<0) /* Time stamp event push */ +#define TS_LOAD_EN (1<<0) /* Time Stamp Load */ +#define TS_PEND_RAW (1<<0) /* int read (before enable) */ +#define TS_PEND (1<<0) /* masked interrupt read (after enable) */ +#define TS_PEND_EN (1<<0) /* masked interrupt enable */ +#define EVENT_POP (1<<0) /* writing discards one event */ + +/* Bit definitions for the EVENT_HIGH register */ +#define PORT_NUMBER_SHIFT (24) /* Indicates Ethernet port or HW pin */ +#define PORT_NUMBER_MASK (0x1f) +#define EVENT_TYPE_SHIFT (20) /* Time sync event type */ +#define EVENT_TYPE_MASK (0xf) +#define MESSAGE_TYPE_SHIFT (16) /* PTP message type */ +#define MESSAGE_TYPE_MASK (0xf) +#define SEQUENCE_ID_SHIFT (0) /* PTP message sequence ID */ +#define SEQUENCE_ID_MASK (0xffff) + +enum { + CPTS_EV_PUSH, /* Time Stamp Push Event */ + CPTS_EV_ROLL, /* Time Stamp Rollover Event */ + CPTS_EV_HALF, /* Time Stamp Half Rollover Event */ + CPTS_EV_HW, /* Hardware Time Stamp Push Event */ + CPTS_EV_RX, /* Ethernet Receive Event */ + CPTS_EV_TX, /* Ethernet Transmit Event */ +}; + +/* This covers any input clock up to about 500 MHz. */ +#define CPTS_OVERFLOW_PERIOD (HZ * 8) + +#define CPTS_FIFO_DEPTH 16 +#define CPTS_MAX_EVENTS 32 + +struct cpts_event { + struct list_head list; + unsigned long tmo; + u32 high; + u32 low; +}; + +struct cpts { + struct cpsw_cpts __iomem *reg; + int tx_enable; + int rx_enable; +#ifdef CONFIG_TI_CPTS + struct ptp_clock_info info; + struct ptp_clock *clock; + spinlock_t lock; /* protects time registers */ + u32 cc_mult; /* for the nominal frequency */ + struct cyclecounter cc; + struct timecounter tc; + struct delayed_work overflow_work; + int phc_index; + struct clk *refclk; + struct list_head events; + struct list_head pool; + struct cpts_event pool_data[CPTS_MAX_EVENTS]; +#endif +}; + +#ifdef CONFIG_TI_CPTS +extern void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb); +extern void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb); +#else +static inline void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb) +{ +} +static inline void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb) +{ +} +#endif + +extern int cpts_register(struct device *dev, struct cpts *cpts, + u32 mult, u32 shift); +extern void cpts_unregister(struct cpts *cpts); + +#endif diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index fce89a0ab06e..2a3e2c56bc60 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1850,7 +1850,7 @@ static struct emac_platform_data * resource information from platform init and register a network device * and allocate resources necessary for driver to perform */ -static int __devinit davinci_emac_probe(struct platform_device *pdev) +static int davinci_emac_probe(struct platform_device *pdev) { int rc = 0; struct resource *res; @@ -2039,7 +2039,7 @@ no_ndev: * Called when removing the device driver. We disable clock usage and release * the resources taken up by the driver and unregister network device */ -static int __devexit davinci_emac_remove(struct platform_device *pdev) +static int davinci_emac_remove(struct platform_device *pdev) { struct resource *res; struct net_device *ndev = platform_get_drvdata(pdev); @@ -2107,7 +2107,7 @@ static struct platform_driver davinci_emac_driver = { .of_match_table = of_match_ptr(davinci_emac_of_match), }, .probe = davinci_emac_probe, - .remove = __devexit_p(davinci_emac_remove), + .remove = davinci_emac_remove, }; /** diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index 51a96dbee9ac..cca25509b039 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -310,7 +310,7 @@ static int davinci_mdio_probe_dt(struct mdio_platform_data *data, } -static int __devinit davinci_mdio_probe(struct platform_device *pdev) +static int davinci_mdio_probe(struct platform_device *pdev) { struct mdio_platform_data *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; @@ -416,7 +416,7 @@ bail_out: return ret; } -static int __devexit davinci_mdio_remove(struct platform_device *pdev) +static int davinci_mdio_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct davinci_mdio_data *data = dev_get_drvdata(dev); @@ -465,7 +465,7 @@ static int davinci_mdio_resume(struct device *dev) u32 ctrl; spin_lock(&data->lock); - pm_runtime_put_sync(data->dev); + pm_runtime_get_sync(data->dev); /* restart the scan state machine */ ctrl = __raw_readl(&data->regs->control); @@ -496,7 +496,7 @@ static struct platform_driver davinci_mdio_driver = { .of_match_table = of_match_ptr(davinci_mdio_of_mtable), }, .probe = davinci_mdio_probe, - .remove = __devexit_p(davinci_mdio_remove), + .remove = davinci_mdio_remove, }; static int __init davinci_mdio_init(void) diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c index 3e6abf0f2771..22725386c5de 100644 --- a/drivers/net/ethernet/ti/tlan.c +++ b/drivers/net/ethernet/ti/tlan.c @@ -300,7 +300,7 @@ these functions are more or less common to all linux network drivers. **************************************************************/ -static void __devexit tlan_remove_one(struct pci_dev *pdev) +static void tlan_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct tlan_priv *priv = netdev_priv(dev); @@ -392,7 +392,7 @@ static struct pci_driver tlan_driver = { .name = "tlan", .id_table = tlan_pci_tbl, .probe = tlan_init_one, - .remove = __devexit_p(tlan_remove_one), + .remove = tlan_remove_one, .suspend = tlan_suspend, .resume = tlan_resume, }; @@ -434,7 +434,7 @@ err_out_pci_free: } -static int __devinit tlan_init_one(struct pci_dev *pdev, +static int tlan_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { return tlan_probe1(pdev, -1, -1, 0, ent); @@ -460,9 +460,8 @@ static int __devinit tlan_init_one(struct pci_dev *pdev, * **************************************************************/ -static int __devinit tlan_probe1(struct pci_dev *pdev, - long ioaddr, int irq, int rev, - const struct pci_device_id *ent) +static int tlan_probe1(struct pci_dev *pdev, long ioaddr, int irq, int rev, + const struct pci_device_id *ent) { struct net_device *dev; diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 4e9810013850..66e025ad5df1 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c @@ -917,7 +917,7 @@ static int tile_net_setup_interrupts(struct net_device *dev) ingress_irq = rc; tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU); rc = request_irq(ingress_irq, tile_net_handle_ingress_irq, - 0, NULL, NULL); + 0, "tile_net", NULL); if (rc != 0) { netdev_err(dev, "request_irq failed: %d\n", rc); destroy_irq(ingress_irq); diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c index 5ee82a77723b..e321d0b6fc88 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c @@ -234,10 +234,9 @@ static void gelic_card_free_chain(struct gelic_card *card, * * returns 0 on success, <0 on failure */ -static int __devinit gelic_card_init_chain(struct gelic_card *card, - struct gelic_descr_chain *chain, - struct gelic_descr *start_descr, - int no) +static int gelic_card_init_chain(struct gelic_card *card, + struct gelic_descr_chain *chain, + struct gelic_descr *start_descr, int no) { int i; struct gelic_descr *descr; @@ -428,7 +427,7 @@ rewind: * * returns 0 on success, < 0 on failure */ -static int __devinit gelic_card_alloc_rx_skbs(struct gelic_card *card) +static int gelic_card_alloc_rx_skbs(struct gelic_card *card) { struct gelic_descr_chain *chain; int ret; @@ -1468,8 +1467,8 @@ static const struct net_device_ops gelic_netdevice_ops = { * * fills out function pointers in the net_device structure */ -static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev, - struct napi_struct *napi) +static void gelic_ether_setup_netdev_ops(struct net_device *netdev, + struct napi_struct *napi) { netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; /* NAPI */ @@ -1489,8 +1488,7 @@ static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev, * gelic_ether_setup_netdev initializes the net_device structure * and register it. **/ -int __devinit gelic_net_setup_netdev(struct net_device *netdev, - struct gelic_card *card) +int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card) { int status; u64 v1, v2; @@ -1542,7 +1540,7 @@ int __devinit gelic_net_setup_netdev(struct net_device *netdev, * the card and net_device structures are linked to each other */ #define GELIC_ALIGN (32) -static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **netdev) +static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev) { struct gelic_card *card; struct gelic_port *port; @@ -1593,7 +1591,7 @@ static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **ne return card; } -static void __devinit gelic_card_get_vlan_info(struct gelic_card *card) +static void gelic_card_get_vlan_info(struct gelic_card *card) { u64 v1, v2; int status; @@ -1667,7 +1665,7 @@ static void __devinit gelic_card_get_vlan_info(struct gelic_card *card) /** * ps3_gelic_driver_probe - add a device to the control of this driver */ -static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) +static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) { struct gelic_card *card; struct net_device *netdev; diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c index 961c8321451f..d568af1eb4f4 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c @@ -452,7 +452,7 @@ static size_t gelic_wl_synthesize_ie(u8 *buf, if (rsn) *buf++ = WLAN_EID_RSN; else - *buf++ = WLAN_EID_GENERIC; + *buf++ = WLAN_EID_VENDOR_SPECIFIC; /* length filed; set later */ buf++; @@ -540,7 +540,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len, break; switch (item_id) { - case WLAN_EID_GENERIC: + case WLAN_EID_VENDOR_SPECIFIC: if ((OUI_LEN + 1 <= item_len) && !memcmp(pos, wpa_oui, OUI_LEN) && pos[OUI_LEN] == 0x01) { @@ -2305,7 +2305,7 @@ static const struct iw_handler_def gelic_wl_wext_handler_def = { .get_wireless_stats = gelic_wl_get_wireless_stats, }; -static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card) +static struct net_device *gelic_wl_alloc(struct gelic_card *card) { struct net_device *netdev; struct gelic_port *port; @@ -2582,7 +2582,7 @@ static const struct ethtool_ops gelic_wl_ethtool_ops = { .get_link = gelic_wl_get_link, }; -static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev) +static void gelic_wl_setup_netdev_ops(struct net_device *netdev) { struct gelic_wl_info *wl; wl = port_wl(netdev_priv(netdev)); @@ -2598,7 +2598,7 @@ static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev) /* * driver probe/remove */ -int __devinit gelic_wl_driver_probe(struct gelic_card *card) +int gelic_wl_driver_probe(struct gelic_card *card) { int ret; struct net_device *netdev; diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c index c1ebfe9efcb3..f1b91fd7e41c 100644 --- a/drivers/net/ethernet/toshiba/spider_net.c +++ b/drivers/net/ethernet/toshiba/spider_net.c @@ -2492,7 +2492,7 @@ out_disable_dev: * spider_net_probe initializes pdev and registers a net_device * structure for it. After that, the device can be ifconfig'ed up **/ -static int __devinit +static int spider_net_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = -EIO; @@ -2531,7 +2531,7 @@ out: * spider_net_remove is called to remove the device and unregisters the * net_device **/ -static void __devexit +static void spider_net_remove(struct pci_dev *pdev) { struct net_device *netdev; @@ -2559,7 +2559,7 @@ static struct pci_driver spider_net_driver = { .name = spider_net_driver_name, .id_table = spider_net_pci_tbl, .probe = spider_net_probe, - .remove = __devexit_p(spider_net_remove) + .remove = spider_net_remove }; /** diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c index 651a70c55e6e..9819349eaa1e 100644 --- a/drivers/net/ethernet/toshiba/tc35815.c +++ b/drivers/net/ethernet/toshiba/tc35815.c @@ -60,7 +60,7 @@ enum tc35815_chiptype { /* indexed by tc35815_chiptype, above */ static const struct { const char *name; -} chip_info[] __devinitdata = { +} chip_info[] = { { "TOSHIBA TC35815CF 10/100BaseTX" }, { "TOSHIBA TC35815 with Wake on LAN" }, { "TOSHIBA TC35815/TX4939" }, @@ -719,7 +719,7 @@ err_out: * should provide a "tc35815-mac" device with a MAC address in its * platform_data. */ -static int __devinit tc35815_mac_match(struct device *dev, void *data) +static int tc35815_mac_match(struct device *dev, void *data) { struct platform_device *plat_dev = to_platform_device(dev); struct pci_dev *pci_dev = data; @@ -727,7 +727,7 @@ static int __devinit tc35815_mac_match(struct device *dev, void *data) return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id; } -static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev) +static int tc35815_read_plat_dev_addr(struct net_device *dev) { struct tc35815_local *lp = netdev_priv(dev); struct device *pd = bus_find_device(&platform_bus_type, NULL, @@ -741,13 +741,13 @@ static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev) return -ENODEV; } #else -static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev) +static int tc35815_read_plat_dev_addr(struct net_device *dev) { return -ENODEV; } #endif -static int __devinit tc35815_init_dev_addr(struct net_device *dev) +static int tc35815_init_dev_addr(struct net_device *dev) { struct tc35815_regs __iomem *tr = (struct tc35815_regs __iomem *)dev->base_addr; @@ -785,8 +785,8 @@ static const struct net_device_ops tc35815_netdev_ops = { #endif }; -static int __devinit tc35815_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int tc35815_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { void __iomem *ioaddr = NULL; struct net_device *dev; @@ -878,7 +878,7 @@ err_out: } -static void __devexit tc35815_remove_one(struct pci_dev *pdev) +static void tc35815_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct tc35815_local *lp = netdev_priv(dev); @@ -2198,7 +2198,7 @@ static struct pci_driver tc35815_pci_driver = { .name = MODNAME, .id_table = tc35815_pci_tbl, .probe = tc35815_init_one, - .remove = __devexit_p(tc35815_remove_one), + .remove = tc35815_remove_one, #ifdef CONFIG_PM .suspend = tc35815_suspend, .resume = tc35815_resume, diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 0459c096629f..7992b3e05d3d 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -113,7 +113,7 @@ static const int multicast_filter_limit = 32; #include <linux/dmi.h> /* These identify the driver base version and may not be removed. */ -static const char version[] __devinitconst = +static const char version[] = "v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker"; /* This driver was written to use PCI memory space. Some early versions @@ -657,7 +657,7 @@ static void enable_mmio(long pioaddr, u32 quirks) * Loads bytes 0x00-0x05, 0x6E-0x6F, 0x78-0x7B from EEPROM * (plus 0x6C for Rhine-I/II) */ -static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev) +static void rhine_reload_eeprom(long pioaddr, struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; @@ -823,7 +823,7 @@ static int rhine_napipoll(struct napi_struct *napi, int budget) return work_done; } -static void __devinit rhine_hw_init(struct net_device *dev, long pioaddr) +static void rhine_hw_init(struct net_device *dev, long pioaddr) { struct rhine_private *rp = netdev_priv(dev); @@ -856,8 +856,7 @@ static const struct net_device_ops rhine_netdev_ops = { #endif }; -static int __devinit rhine_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int rhine_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; struct rhine_private *rp; @@ -2232,7 +2231,7 @@ static int rhine_close(struct net_device *dev) } -static void __devexit rhine_remove_one(struct pci_dev *pdev) +static void rhine_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct rhine_private *rp = netdev_priv(dev); @@ -2359,7 +2358,7 @@ static struct pci_driver rhine_driver = { .name = DRV_NAME, .id_table = rhine_pci_tbl, .probe = rhine_init_one, - .remove = __devexit_p(rhine_remove_one), + .remove = rhine_remove_one, .shutdown = rhine_shutdown, .driver.pm = RHINE_PM_OPS, }; diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index a46c19859683..1bc7f9fd2583 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -375,7 +375,7 @@ MODULE_DEVICE_TABLE(pci, velocity_id_table); * Given a chip identifier return a suitable description. Returns * a pointer a static string valid while the driver is loaded. */ -static const char __devinit *get_chip_name(enum chip_type chip_id) +static const char *get_chip_name(enum chip_type chip_id) { int i; for (i = 0; chip_info_table[i].name != NULL; i++) @@ -392,7 +392,7 @@ static const char __devinit *get_chip_name(enum chip_type chip_id) * unload for each active device that is present. Disconnects * the device from the network layer and frees all the resources */ -static void __devexit velocity_remove1(struct pci_dev *pdev) +static void velocity_remove1(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct velocity_info *vptr = netdev_priv(dev); @@ -421,7 +421,8 @@ static void __devexit velocity_remove1(struct pci_dev *pdev) * all the verification and checking as well as reporting so that * we don't duplicate code for each option. */ -static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, const char *devname) +static void velocity_set_int_opt(int *opt, int val, int min, int max, int def, + char *name, const char *devname) { if (val == -1) *opt = def; @@ -449,7 +450,8 @@ static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, * all the verification and checking as well as reporting so that * we don't duplicate code for each option. */ -static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag, char *name, const char *devname) +static void velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag, + char *name, const char *devname) { (*opt) &= (~flag); if (val == -1) @@ -474,7 +476,8 @@ static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag * Turn the module and command options into a single structure * for the current device */ -static void __devinit velocity_get_options(struct velocity_opt *opts, int index, const char *devname) +static void velocity_get_options(struct velocity_opt *opts, int index, + const char *devname) { velocity_set_int_opt(&opts->rx_thresh, rx_thresh[index], RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh", devname); @@ -2627,9 +2630,8 @@ static const struct net_device_ops velocity_netdev_ops = { * Set up the initial velocity_info struct for the device that has been * discovered. */ -static void __devinit velocity_init_info(struct pci_dev *pdev, - struct velocity_info *vptr, - const struct velocity_info_tbl *info) +static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, + const struct velocity_info_tbl *info) { memset(vptr, 0, sizeof(struct velocity_info)); @@ -2648,7 +2650,8 @@ static void __devinit velocity_init_info(struct pci_dev *pdev, * Retrieve the PCI configuration space data that interests us from * the kernel PCI layer */ -static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev) +static int velocity_get_pci_info(struct velocity_info *vptr, + struct pci_dev *pdev) { vptr->rev_id = pdev->revision; @@ -2685,7 +2688,7 @@ static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pc * Print per driver data as the kernel driver finds Velocity * hardware */ -static void __devinit velocity_print_info(struct velocity_info *vptr) +static void velocity_print_info(struct velocity_info *vptr) { struct net_device *dev = vptr->dev; @@ -2709,7 +2712,8 @@ static u32 velocity_get_link(struct net_device *dev) * Configure a discovered adapter from scratch. Return a negative * errno error code on failure paths. */ -static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent) +static int velocity_found1(struct pci_dev *pdev, + const struct pci_device_id *ent) { static int first = 1; struct net_device *dev; @@ -3108,7 +3112,7 @@ static struct pci_driver velocity_driver = { .name = VELOCITY_NAME, .id_table = velocity_id_table, .probe = velocity_found1, - .remove = __devexit_p(velocity_remove1), + .remove = velocity_remove1, #ifdef CONFIG_PM .suspend = velocity_suspend, .resume = velocity_resume, diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c index 2c08bf6e7bf3..352383890326 100644 --- a/drivers/net/ethernet/wiznet/w5100.c +++ b/drivers/net/ethernet/wiznet/w5100.c @@ -580,8 +580,6 @@ static int w5100_open(struct net_device *ndev) struct w5100_priv *priv = netdev_priv(ndev); netif_info(priv, ifup, ndev, "enabling\n"); - if (!is_valid_ether_addr(ndev->dev_addr)) - return -EINVAL; w5100_hw_start(priv); napi_enable(&priv->napi); netif_start_queue(ndev); @@ -623,7 +621,7 @@ static const struct net_device_ops w5100_netdev_ops = { .ndo_change_mtu = eth_change_mtu, }; -static int __devinit w5100_hw_probe(struct platform_device *pdev) +static int w5100_hw_probe(struct platform_device *pdev) { struct wiznet_platform_data *data = pdev->dev.platform_data; struct net_device *ndev = platform_get_drvdata(pdev); @@ -698,7 +696,7 @@ static int __devinit w5100_hw_probe(struct platform_device *pdev) return 0; } -static int __devinit w5100_probe(struct platform_device *pdev) +static int w5100_probe(struct platform_device *pdev) { struct w5100_priv *priv; struct net_device *ndev; @@ -741,7 +739,7 @@ err_register: return err; } -static int __devexit w5100_remove(struct platform_device *pdev) +static int w5100_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct w5100_priv *priv = netdev_priv(ndev); @@ -801,7 +799,7 @@ static struct platform_driver w5100_driver = { .pm = &w5100_pm_ops, }, .probe = w5100_probe, - .remove = __devexit_p(w5100_remove), + .remove = w5100_remove, }; module_platform_driver(w5100_driver); diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c index 88943d90c765..9d1d986f8d40 100644 --- a/drivers/net/ethernet/wiznet/w5300.c +++ b/drivers/net/ethernet/wiznet/w5300.c @@ -500,8 +500,6 @@ static int w5300_open(struct net_device *ndev) struct w5300_priv *priv = netdev_priv(ndev); netif_info(priv, ifup, ndev, "enabling\n"); - if (!is_valid_ether_addr(ndev->dev_addr)) - return -EINVAL; w5300_hw_start(priv); napi_enable(&priv->napi); netif_start_queue(ndev); @@ -543,7 +541,7 @@ static const struct net_device_ops w5300_netdev_ops = { .ndo_change_mtu = eth_change_mtu, }; -static int __devinit w5300_hw_probe(struct platform_device *pdev) +static int w5300_hw_probe(struct platform_device *pdev) { struct wiznet_platform_data *data = pdev->dev.platform_data; struct net_device *ndev = platform_get_drvdata(pdev); @@ -610,7 +608,7 @@ static int __devinit w5300_hw_probe(struct platform_device *pdev) return 0; } -static int __devinit w5300_probe(struct platform_device *pdev) +static int w5300_probe(struct platform_device *pdev) { struct w5300_priv *priv; struct net_device *ndev; @@ -653,7 +651,7 @@ err_register: return err; } -static int __devexit w5300_remove(struct platform_device *pdev) +static int w5300_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct w5300_priv *priv = netdev_priv(ndev); @@ -713,7 +711,7 @@ static struct platform_driver w5300_driver = { .pm = &w5300_pm_ops, }, .probe = w5300_probe, - .remove = __devexit_p(w5300_remove), + .remove = w5300_remove, }; module_platform_driver(w5300_driver); diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig index 5778a4ae1164..122d60c0481b 100644 --- a/drivers/net/ethernet/xilinx/Kconfig +++ b/drivers/net/ethernet/xilinx/Kconfig @@ -27,7 +27,7 @@ config XILINX_EMACLITE config XILINX_AXI_EMAC tristate "Xilinx 10/100/1000 AXI Ethernet support" - depends on (PPC32 || MICROBLAZE) + depends on MICROBLAZE select PHYLIB ---help--- This driver supports the 10/100/1000 Ethernet from Xilinx for the diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index f8e351880119..aad909d793d7 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -1002,7 +1002,7 @@ static const struct ethtool_ops temac_ethtool_ops = { .get_ts_info = ethtool_op_get_ts_info, }; -static int __devinit temac_of_probe(struct platform_device *op) +static int temac_of_probe(struct platform_device *op) { struct device_node *np; struct temac_local *lp; @@ -1144,7 +1144,7 @@ static int __devinit temac_of_probe(struct platform_device *op) return rc; } -static int __devexit temac_of_remove(struct platform_device *op) +static int temac_of_remove(struct platform_device *op) { struct net_device *ndev = dev_get_drvdata(&op->dev); struct temac_local *lp = netdev_priv(ndev); @@ -1163,7 +1163,7 @@ static int __devexit temac_of_remove(struct platform_device *op) return 0; } -static struct of_device_id temac_of_match[] __devinitdata = { +static struct of_device_id temac_of_match[] = { { .compatible = "xlnx,xps-ll-temac-1.01.b", }, { .compatible = "xlnx,xps-ll-temac-2.00.a", }, { .compatible = "xlnx,xps-ll-temac-2.02.a", }, @@ -1174,7 +1174,7 @@ MODULE_DEVICE_TABLE(of, temac_of_match); static struct platform_driver temac_of_driver = { .probe = temac_of_probe, - .remove = __devexit_p(temac_of_remove), + .remove = temac_of_remove, .driver = { .owner = THIS_MODULE, .name = "xilinx_temac", diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 0793299bd39e..6f47100e58d7 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -48,7 +48,7 @@ #define AXIENET_REGS_N 32 /* Match table for of_platform binding */ -static struct of_device_id axienet_of_match[] __devinitdata = { +static struct of_device_id axienet_of_match[] = { { .compatible = "xlnx,axi-ethernet-1.00.a", }, { .compatible = "xlnx,axi-ethernet-1.01.a", }, { .compatible = "xlnx,axi-ethernet-2.01.a", }, @@ -894,6 +894,8 @@ out: return IRQ_HANDLED; } +static void axienet_dma_err_handler(unsigned long data); + /** * axienet_open - Driver open routine. * @ndev: Pointer to net_device structure @@ -942,6 +944,10 @@ static int axienet_open(struct net_device *ndev) phy_start(lp->phy_dev); } + /* Enable tasklets for Axi DMA error handling */ + tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler, + (unsigned long) lp); + /* Enable interrupts for Axi DMA Tx */ ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev); if (ret) @@ -950,8 +956,7 @@ static int axienet_open(struct net_device *ndev) 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: @@ -960,6 +965,7 @@ err_tx_irq: if (lp->phy_dev) phy_disconnect(lp->phy_dev); lp->phy_dev = NULL; + tasklet_kill(&lp->dma_err_tasklet); dev_err(lp->dev, "request_irq() failed\n"); return ret; } @@ -990,7 +996,7 @@ static int axienet_stop(struct net_device *ndev) axienet_setoptions(ndev, lp->options & ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); - tasklet_disable(&lp->dma_err_tasklet); + tasklet_kill(&lp->dma_err_tasklet); free_irq(lp->tx_irq, ndev); free_irq(lp->rx_irq, ndev); @@ -1476,7 +1482,7 @@ static void axienet_dma_err_handler(unsigned long data) * 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) +static int axienet_of_probe(struct platform_device *op) { __be32 *p; int size, ret = 0; @@ -1584,7 +1590,7 @@ static int __devinit axienet_of_probe(struct platform_device *op) 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)) { + if ((lp->rx_irq <= 0) || (lp->tx_irq <= 0)) { dev_err(&op->dev, "could not determine irqs\n"); ret = -ENOMEM; goto err_iounmap_2; @@ -1613,10 +1619,6 @@ static int __devinit axienet_of_probe(struct platform_device *op) 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: @@ -1630,7 +1632,7 @@ nodev: return ret; } -static int __devexit axienet_of_remove(struct platform_device *op) +static int axienet_of_remove(struct platform_device *op) { struct net_device *ndev = dev_get_drvdata(&op->dev); struct axienet_local *lp = netdev_priv(ndev); @@ -1654,7 +1656,7 @@ static int __devexit axienet_of_remove(struct platform_device *op) static struct platform_driver axienet_of_driver = { .probe = axienet_of_probe, - .remove = __devexit_p(axienet_of_remove), + .remove = axienet_of_remove, .driver = { .owner = THIS_MODULE, .name = "xilinx_axienet", diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 77cfe5110318..919b983114e9 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -1107,7 +1107,7 @@ static struct net_device_ops xemaclite_netdev_ops; * Return: 0, if the driver is bound to the Emaclite device, or * a negative error if there is failure. */ -static int __devinit xemaclite_of_probe(struct platform_device *ofdev) +static int xemaclite_of_probe(struct platform_device *ofdev) { struct resource r_irq; /* Interrupt resources */ struct resource r_mem; /* IO mem resources */ @@ -1229,7 +1229,7 @@ error2: * * Return: 0, always. */ -static int __devexit xemaclite_of_remove(struct platform_device *of_dev) +static int xemaclite_of_remove(struct platform_device *of_dev) { struct device *dev = &of_dev->dev; struct net_device *ndev = dev_get_drvdata(dev); @@ -1280,7 +1280,7 @@ static struct net_device_ops xemaclite_netdev_ops = { }; /* Match table for OF platform binding */ -static struct of_device_id xemaclite_of_match[] __devinitdata = { +static struct of_device_id xemaclite_of_match[] = { { .compatible = "xlnx,opb-ethernetlite-1.01.a", }, { .compatible = "xlnx,opb-ethernetlite-1.01.b", }, { .compatible = "xlnx,xps-ethernetlite-1.00.a", }, @@ -1298,7 +1298,7 @@ static struct platform_driver xemaclite_of_driver = { .of_match_table = xemaclite_of_match, }, .probe = xemaclite_of_probe, - .remove = __devexit_p(xemaclite_of_remove), + .remove = xemaclite_of_remove, }; module_platform_driver(xemaclite_of_driver); diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index 98934bdf6acf..d3ebb73277be 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -1102,10 +1102,12 @@ static int init_queues(struct port *port) { int i; - if (!ports_open) - if (!(dma_pool = dma_pool_create(DRV_NAME, NULL, - POOL_ALLOC_SIZE, 32, 0))) + if (!ports_open) { + dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev, + POOL_ALLOC_SIZE, 32, 0); + if (!dma_pool) return -ENOMEM; + } if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL, &port->desc_tab_phys))) @@ -1377,7 +1379,7 @@ static const struct net_device_ops ixp4xx_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit eth_init_one(struct platform_device *pdev) +static int eth_init_one(struct platform_device *pdev) { struct port *port; struct net_device *dev; @@ -1478,7 +1480,7 @@ err_free: return err; } -static int __devexit eth_remove_one(struct platform_device *pdev) +static int eth_remove_one(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct port *port = netdev_priv(dev); |