aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/3com/3c501.c2
-rw-r--r--drivers/net/ethernet/3com/3c509.c2
-rw-r--r--drivers/net/ethernet/3com/3c515.c10
-rw-r--r--drivers/net/ethernet/3com/3c574_cs.c2
-rw-r--r--drivers/net/ethernet/3com/3c589_cs.c2
-rw-r--r--drivers/net/ethernet/3com/3c59x.c10
-rw-r--r--drivers/net/ethernet/3com/Kconfig2
-rw-r--r--drivers/net/ethernet/3com/typhoon.c19
-rw-r--r--drivers/net/ethernet/8390/ax88796.c2
-rw-r--r--drivers/net/ethernet/8390/axnet_cs.c4
-rw-r--r--drivers/net/ethernet/8390/lib8390.c2
-rw-r--r--drivers/net/ethernet/8390/pcnet_cs.c2
-rw-r--r--drivers/net/ethernet/adaptec/starfire.c13
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.c27
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.h2
-rw-r--r--drivers/net/ethernet/aeroflex/greth.c5
-rw-r--r--drivers/net/ethernet/alteon/acenic.c5
-rw-r--r--drivers/net/ethernet/amd/7990.c2
-rw-r--r--drivers/net/ethernet/amd/Kconfig2
-rw-r--r--drivers/net/ethernet/amd/a2065.c2
-rw-r--r--drivers/net/ethernet/amd/am79c961a.c4
-rw-r--r--drivers/net/ethernet/amd/am79c961a.h2
-rw-r--r--drivers/net/ethernet/amd/amd8111e.c7
-rw-r--r--drivers/net/ethernet/amd/ariadne.c2
-rw-r--r--drivers/net/ethernet/amd/atarilance.c2
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.c12
-rw-r--r--drivers/net/ethernet/amd/declance.c4
-rw-r--r--drivers/net/ethernet/amd/depca.c2
-rw-r--r--drivers/net/ethernet/amd/hplance.c10
-rw-r--r--drivers/net/ethernet/amd/ni65.c6
-rw-r--r--drivers/net/ethernet/amd/nmclan_cs.c2
-rw-r--r--drivers/net/ethernet/amd/pcnet32.c16
-rw-r--r--drivers/net/ethernet/amd/sun3lance.c2
-rw-r--r--drivers/net/ethernet/amd/sunlance.c4
-rw-r--r--drivers/net/ethernet/apple/bmac.c19
-rw-r--r--drivers/net/ethernet/apple/mace.c9
-rw-r--r--drivers/net/ethernet/apple/macmace.c2
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.c2
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c12
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_main.c1
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c12
-rw-r--r--drivers/net/ethernet/atheros/atlx/atlx.c1
-rw-r--r--drivers/net/ethernet/broadcom/b44.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c108
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.h3
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h33
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c261
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h122
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c100
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h59
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h55
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c324
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h6
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c365
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h21
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c6
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h7
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c342
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h154
-rw-r--r--drivers/net/ethernet/broadcom/cnic.c42
-rw-r--r--drivers/net/ethernet/broadcom/cnic_defs.h27
-rw-r--r--drivers/net/ethernet/broadcom/cnic_if.h4
-rw-r--r--drivers/net/ethernet/broadcom/sb1250-mac.c2
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c1516
-rw-r--r--drivers/net/ethernet/broadcom/tg3.h14
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_cee.c8
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_defs.h1
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.c2
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c1
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_debugfs.c21
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_ethtool.c42
-rw-r--r--drivers/net/ethernet/cadence/at91_ether.c2
-rw-r--r--drivers/net/ethernet/cadence/macb.c8
-rw-r--r--drivers/net/ethernet/calxeda/xgmac.c3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/version.h4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c4
-rw-r--r--drivers/net/ethernet/cirrus/cs89x0.c4
-rw-r--r--drivers/net/ethernet/cirrus/ep93xx_eth.c4
-rw-r--r--drivers/net/ethernet/cirrus/mac89x0.c12
-rw-r--r--drivers/net/ethernet/cisco/enic/enic.h4
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c50
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_pp.c4
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_res.c2
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_dev.c76
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_dev.h3
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_devcmd.h11
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_rq.c4
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_wq.c4
-rw-r--r--drivers/net/ethernet/davicom/dm9000.c8
-rw-r--r--drivers/net/ethernet/dec/ewrk3.c4
-rw-r--r--drivers/net/ethernet/dec/tulip/21142.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/de2104x.c6
-rw-r--r--drivers/net/ethernet/dec/tulip/de4x5.c10
-rw-r--r--drivers/net/ethernet/dec/tulip/dmfe.c20
-rw-r--r--drivers/net/ethernet/dec/tulip/eeprom.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/interrupt.c10
-rw-r--r--drivers/net/ethernet/dec/tulip/media.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/pnic.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/pnic2.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/timer.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/tulip.h2
-rw-r--r--drivers/net/ethernet/dec/tulip/tulip_core.c9
-rw-r--r--drivers/net/ethernet/dec/tulip/uli526x.c21
-rw-r--r--drivers/net/ethernet/dec/tulip/winbond-840.c6
-rw-r--r--drivers/net/ethernet/dec/tulip/xircom_cb.c7
-rw-r--r--drivers/net/ethernet/dlink/de600.c2
-rw-r--r--drivers/net/ethernet/dlink/de620.c2
-rw-r--r--drivers/net/ethernet/dlink/sundance.c11
-rw-r--r--drivers/net/ethernet/dnet.c8
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h74
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c107
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h54
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c160
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c948
-rw-r--r--drivers/net/ethernet/ethoc.c23
-rw-r--r--drivers/net/ethernet/faraday/ftgmac100.c2
-rw-r--r--drivers/net/ethernet/faraday/ftmac100.c2
-rw-r--r--drivers/net/ethernet/fealnx.c8
-rw-r--r--drivers/net/ethernet/freescale/fec.c21
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.c4
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.h2
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c12
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c2
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h2
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c2
-rw-r--r--drivers/net/ethernet/freescale/gianfar_sysfs.c2
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.c7
-rw-r--r--drivers/net/ethernet/fujitsu/at1700.c2
-rw-r--r--drivers/net/ethernet/fujitsu/eth16i.c2
-rw-r--r--drivers/net/ethernet/fujitsu/fmvj18x_cs.c2
-rw-r--r--drivers/net/ethernet/hp/hp100.c6
-rw-r--r--drivers/net/ethernet/i825xx/3c505.c2
-rw-r--r--drivers/net/ethernet/i825xx/3c507.c2
-rw-r--r--drivers/net/ethernet/i825xx/3c523.c2
-rw-r--r--drivers/net/ethernet/i825xx/3c527.c4
-rw-r--r--drivers/net/ethernet/i825xx/82596.c8
-rw-r--r--drivers/net/ethernet/i825xx/eepro.c2
-rw-r--r--drivers/net/ethernet/i825xx/eexpress.c2
-rw-r--r--drivers/net/ethernet/i825xx/ether1.c2
-rw-r--r--drivers/net/ethernet/i825xx/lp486e.c4
-rw-r--r--drivers/net/ethernet/i825xx/ni52.c2
-rw-r--r--drivers/net/ethernet/i825xx/sun3_82586.c27
-rw-r--r--drivers/net/ethernet/i825xx/znet.c2
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea.h2
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_ethtool.c2
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_hw.h2
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_main.c3
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_phyp.c2
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_phyp.h2
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_qmr.c2
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_qmr.h2
-rw-r--r--drivers/net/ethernet/ibm/emac/core.c8
-rw-r--r--drivers/net/ethernet/ibm/emac/core.h2
-rw-r--r--drivers/net/ethernet/ibm/emac/debug.c2
-rw-r--r--drivers/net/ethernet/ibm/emac/debug.h2
-rw-r--r--drivers/net/ethernet/ibm/emac/emac.h2
-rw-r--r--drivers/net/ethernet/ibm/emac/mal.c2
-rw-r--r--drivers/net/ethernet/ibm/emac/mal.h2
-rw-r--r--drivers/net/ethernet/ibm/emac/phy.c2
-rw-r--r--drivers/net/ethernet/ibm/emac/phy.h2
-rw-r--r--drivers/net/ethernet/ibm/emac/rgmii.c7
-rw-r--r--drivers/net/ethernet/ibm/emac/rgmii.h2
-rw-r--r--drivers/net/ethernet/ibm/emac/tah.c7
-rw-r--r--drivers/net/ethernet/ibm/emac/tah.h2
-rw-r--r--drivers/net/ethernet/ibm/emac/zmii.c7
-rw-r--r--drivers/net/ethernet/ibm/emac/zmii.h2
-rw-r--r--drivers/net/ethernet/ibm/iseries_veth.c4
-rw-r--r--drivers/net/ethernet/icplus/ipg.c4
-rw-r--r--drivers/net/ethernet/intel/e100.c5
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000.h1
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_hw.c156
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_hw.h10
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c249
-rw-r--r--drivers/net/ethernet/intel/e1000e/80003es2lan.c99
-rw-r--r--drivers/net/ethernet/intel/e1000e/82571.c133
-rw-r--r--drivers/net/ethernet/intel/e1000e/Makefile5
-rw-r--r--drivers/net/ethernet/intel/e1000e/defines.h11
-rw-r--r--drivers/net/ethernet/intel/e1000e/e1000.h52
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c207
-rw-r--r--drivers/net/ethernet/intel/e1000e/hw.h13
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c423
-rw-r--r--drivers/net/ethernet/intel/e1000e/mac.c (renamed from drivers/net/ethernet/intel/e1000e/lib.c)1130
-rw-r--r--drivers/net/ethernet/intel/e1000e/manage.c367
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c710
-rw-r--r--drivers/net/ethernet/intel/e1000e/nvm.c643
-rw-r--r--drivers/net/ethernet/intel/e1000e/param.c55
-rw-r--r--drivers/net/ethernet/intel/e1000e/phy.c264
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c4
-rw-r--r--drivers/net/ethernet/intel/igbvf/ethtool.c19
-rw-r--r--drivers/net/ethernet/intel/igbvf/igbvf.h27
-rw-r--r--drivers/net/ethernet/intel/igbvf/netdev.c143
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_ee.c12
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_main.c4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h29
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c59
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c694
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c14
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h1
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c42
-rw-r--r--drivers/net/ethernet/jme.c1
-rw-r--r--drivers/net/ethernet/korina.c6
-rw-r--r--drivers/net/ethernet/lantiq_etop.c15
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c4
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c17
-rw-r--r--drivers/net/ethernet/marvell/skge.c4
-rw-r--r--drivers/net/ethernet/marvell/sky2.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c21
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mcg.c38
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c2
-rw-r--r--drivers/net/ethernet/micrel/ks8695net.c8
-rw-r--r--drivers/net/ethernet/micrel/ks8842.c3
-rw-r--r--drivers/net/ethernet/micrel/ks8851.c11
-rw-r--r--drivers/net/ethernet/micrel/ks8851.h2
-rw-r--r--drivers/net/ethernet/micrel/ks8851_mll.c11
-rw-r--r--drivers/net/ethernet/micrel/ksz884x.c8
-rw-r--r--drivers/net/ethernet/microchip/enc28j60.c9
-rw-r--r--drivers/net/ethernet/mipsnet.c4
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c4
-rw-r--r--drivers/net/ethernet/natsemi/ibmlana.c2
-rw-r--r--drivers/net/ethernet/natsemi/macsonic.c2
-rw-r--r--drivers/net/ethernet/natsemi/natsemi.c5
-rw-r--r--drivers/net/ethernet/natsemi/sonic.c4
-rw-r--r--drivers/net/ethernet/neterion/s2io.c9
-rw-r--r--drivers/net/ethernet/netx-eth.c5
-rw-r--r--drivers/net/ethernet/nuvoton/w90p910_ether.c2
-rw-r--r--drivers/net/ethernet/nvidia/forcedeth.c11
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c13
-rw-r--r--drivers/net/ethernet/packetengines/hamachi.c8
-rw-r--r--drivers/net/ethernet/packetengines/yellowfin.c13
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac.c6
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic.h437
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c296
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c109
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h1
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c629
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c17
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c134
-rw-r--r--drivers/net/ethernet/qlogic/qla3xxx.c1
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c14
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c10
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c19
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge.h2
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_dbg.c4
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_main.c86
-rw-r--r--drivers/net/ethernet/racal/ni5010.c2
-rw-r--r--drivers/net/ethernet/rdc/r6040.c3
-rw-r--r--drivers/net/ethernet/realtek/8139too.c63
-rw-r--r--drivers/net/ethernet/realtek/Kconfig10
-rw-r--r--drivers/net/ethernet/realtek/atp.c2
-rw-r--r--drivers/net/ethernet/realtek/r8169.c616
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c439
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.h15
-rw-r--r--drivers/net/ethernet/s6gmac.c15
-rw-r--r--drivers/net/ethernet/seeq/ether3.c2
-rw-r--r--drivers/net/ethernet/seeq/seeq8005.c2
-rw-r--r--drivers/net/ethernet/seeq/sgiseeq.c1
-rw-r--r--drivers/net/ethernet/sfc/Kconfig21
-rw-r--r--drivers/net/ethernet/sfc/Makefile3
-rw-r--r--drivers/net/ethernet/sfc/bitfield.h22
-rw-r--r--drivers/net/ethernet/sfc/efx.c868
-rw-r--r--drivers/net/ethernet/sfc/efx.h11
-rw-r--r--drivers/net/ethernet/sfc/ethtool.c200
-rw-r--r--drivers/net/ethernet/sfc/falcon.c54
-rw-r--r--drivers/net/ethernet/sfc/falcon_boards.c12
-rw-r--r--drivers/net/ethernet/sfc/falcon_xmac.c15
-rw-r--r--drivers/net/ethernet/sfc/filter.c255
-rw-r--r--drivers/net/ethernet/sfc/filter.h20
-rw-r--r--drivers/net/ethernet/sfc/mac.h21
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c149
-rw-r--r--drivers/net/ethernet/sfc/mcdi.h36
-rw-r--r--drivers/net/ethernet/sfc/mcdi_mac.c65
-rw-r--r--drivers/net/ethernet/sfc/mcdi_mon.c415
-rw-r--r--drivers/net/ethernet/sfc/mcdi_pcol.h3542
-rw-r--r--drivers/net/ethernet/sfc/mcdi_phy.c36
-rw-r--r--drivers/net/ethernet/sfc/mdio_10g.c2
-rw-r--r--drivers/net/ethernet/sfc/mtd.c15
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h321
-rw-r--r--drivers/net/ethernet/sfc/nic.c593
-rw-r--r--drivers/net/ethernet/sfc/nic.h122
-rw-r--r--drivers/net/ethernet/sfc/qt202x_phy.c6
-rw-r--r--drivers/net/ethernet/sfc/regs.h20
-rw-r--r--drivers/net/ethernet/sfc/rx.c126
-rw-r--r--drivers/net/ethernet/sfc/selftest.c110
-rw-r--r--drivers/net/ethernet/sfc/selftest.h1
-rw-r--r--drivers/net/ethernet/sfc/siena.c47
-rw-r--r--drivers/net/ethernet/sfc/siena_sriov.c1643
-rw-r--r--drivers/net/ethernet/sfc/spi.h2
-rw-r--r--drivers/net/ethernet/sfc/tenxpress.c2
-rw-r--r--drivers/net/ethernet/sfc/tx.c8
-rw-r--r--drivers/net/ethernet/sfc/txc43128_phy.c2
-rw-r--r--drivers/net/ethernet/sfc/vfdi.h255
-rw-r--r--drivers/net/ethernet/sis/sis190.c2
-rw-r--r--drivers/net/ethernet/sis/sis900.c9
-rw-r--r--drivers/net/ethernet/smsc/epic100.c11
-rw-r--r--drivers/net/ethernet/smsc/smc911x.c3
-rw-r--r--drivers/net/ethernet/smsc/smc9194.c2
-rw-r--r--drivers/net/ethernet/smsc/smc91c92_cs.c2
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c3
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.c4
-rw-r--r--drivers/net/ethernet/smsc/smsc9420.c11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c2
-rw-r--r--drivers/net/ethernet/sun/cassini.c4
-rw-r--r--drivers/net/ethernet/sun/niu.c6
-rw-r--r--drivers/net/ethernet/sun/sunbmac.c2
-rw-r--r--drivers/net/ethernet/sun/sungem.c1
-rw-r--r--drivers/net/ethernet/sun/sunhme.c2
-rw-r--r--drivers/net/ethernet/sun/sunqe.c12
-rw-r--r--drivers/net/ethernet/sun/sunvnet.c13
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.c8
-rw-r--r--drivers/net/ethernet/ti/cpmac.c5
-rw-r--r--drivers/net/ethernet/ti/davinci_cpdma.c2
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c11
-rw-r--r--drivers/net/ethernet/ti/davinci_mdio.c2
-rw-r--r--drivers/net/ethernet/ti/tlan.c1
-rw-r--r--drivers/net/ethernet/tile/tilepro.c9
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.c5
-rw-r--r--drivers/net/ethernet/toshiba/tc35815.c9
-rw-r--r--drivers/net/ethernet/tundra/tsi108_eth.c6
-rw-r--r--drivers/net/ethernet/via/via-rhine.c5
-rw-r--r--drivers/net/ethernet/via/via-velocity.c6
-rw-r--r--drivers/net/ethernet/xilinx/Kconfig8
-rw-r--r--drivers/net/ethernet/xilinx/Makefile2
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c9
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet.h508
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c1669
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c238
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_emaclite.c6
-rw-r--r--drivers/net/ethernet/xircom/xirc2ps_cs.c3
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixpdev.c7
348 files changed, 17602 insertions, 8661 deletions
diff --git a/drivers/net/ethernet/3com/3c501.c b/drivers/net/ethernet/3com/3c501.c
index 68da81d476f3..bf73e1a02293 100644
--- a/drivers/net/ethernet/3com/3c501.c
+++ b/drivers/net/ethernet/3com/3c501.c
@@ -702,7 +702,7 @@ static void el_receive(struct net_device *dev)
*/
outb(AX_SYS, AX_CMD);
- skb = dev_alloc_skb(pkt_len+2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
/*
* Start of frame
diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c
index 92053e6fc980..41719da2e178 100644
--- a/drivers/net/ethernet/3com/3c509.c
+++ b/drivers/net/ethernet/3com/3c509.c
@@ -1066,7 +1066,7 @@ el3_rx(struct net_device *dev)
short pkt_len = rx_status & 0x7ff;
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len+5);
+ skb = netdev_alloc_skb(dev, pkt_len + 5);
if (el3_debug > 4)
pr_debug("Receiving packet size %d status %4.4x.\n",
pkt_len, rx_status);
diff --git a/drivers/net/ethernet/3com/3c515.c b/drivers/net/ethernet/3com/3c515.c
index f67a5d3a200c..59e1e001bc3f 100644
--- a/drivers/net/ethernet/3com/3c515.c
+++ b/drivers/net/ethernet/3com/3c515.c
@@ -826,11 +826,10 @@ static int corkscrew_open(struct net_device *dev)
vp->rx_ring[i].next = 0;
vp->rx_ring[i].status = 0; /* Clear complete bit. */
vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000;
- skb = dev_alloc_skb(PKT_BUF_SZ);
+ skb = netdev_alloc_skb(dev, PKT_BUF_SZ);
vp->rx_skbuff[i] = skb;
if (skb == NULL)
break; /* Bad news! */
- skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
vp->rx_ring[i].addr = isa_virt_to_bus(skb->data);
}
@@ -1295,7 +1294,7 @@ static int corkscrew_rx(struct net_device *dev)
short pkt_len = rx_status & 0x1fff;
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len + 5 + 2);
+ skb = netdev_alloc_skb(dev, pkt_len + 5 + 2);
if (corkscrew_debug > 4)
pr_debug("Receiving packet size %d status %4.4x.\n",
pkt_len, rx_status);
@@ -1368,7 +1367,7 @@ static int boomerang_rx(struct net_device *dev)
/* Check if the packet is long enough to just accept without
copying to a properly sized skbuff. */
if (pkt_len < rx_copybreak &&
- (skb = dev_alloc_skb(pkt_len + 4)) != NULL) {
+ (skb = netdev_alloc_skb(dev, pkt_len + 4)) != NULL) {
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
/* 'skb_put()' points to the start of sk_buff data area. */
memcpy(skb_put(skb, pkt_len),
@@ -1403,10 +1402,9 @@ static int boomerang_rx(struct net_device *dev)
struct sk_buff *skb;
entry = vp->dirty_rx % RX_RING_SIZE;
if (vp->rx_skbuff[entry] == NULL) {
- skb = dev_alloc_skb(PKT_BUF_SZ);
+ skb = netdev_alloc_skb(dev, PKT_BUF_SZ);
if (skb == NULL)
break; /* Bad news! */
- skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
vp->rx_ring[entry].addr = isa_virt_to_bus(skb->data);
vp->rx_skbuff[entry] = skb;
diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c
index 9c01bc9235b3..e61b2f82ba3a 100644
--- a/drivers/net/ethernet/3com/3c574_cs.c
+++ b/drivers/net/ethernet/3com/3c574_cs.c
@@ -1012,7 +1012,7 @@ static int el3_rx(struct net_device *dev, int worklimit)
short pkt_len = rx_status & 0x7ff;
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len+5);
+ skb = netdev_alloc_skb(dev, pkt_len + 5);
pr_debug(" Receiving packet size %d status %4.4x.\n",
pkt_len, rx_status);
diff --git a/drivers/net/ethernet/3com/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c
index da410f036869..b23253b9f742 100644
--- a/drivers/net/ethernet/3com/3c589_cs.c
+++ b/drivers/net/ethernet/3com/3c589_cs.c
@@ -819,7 +819,7 @@ static int el3_rx(struct net_device *dev)
short pkt_len = rx_status & 0x7ff;
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len+5);
+ skb = netdev_alloc_skb(dev, pkt_len + 5);
netdev_dbg(dev, " Receiving packet size %d status %4.4x.\n",
pkt_len, rx_status);
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index f9b74c0a8492..e463d1036829 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -1121,10 +1121,9 @@ static int __devinit vortex_probe1(struct device *gendev,
dev = alloc_etherdev(sizeof(*vp));
retval = -ENOMEM;
- if (!dev) {
- pr_err(PFX "unable to allocate etherdev, aborting\n");
+ if (!dev)
goto out;
- }
+
SET_NETDEV_DEV(dev, gendev);
vp = netdev_priv(dev);
@@ -2500,7 +2499,7 @@ static int vortex_rx(struct net_device *dev)
int pkt_len = rx_status & 0x1fff;
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len + 5);
+ skb = netdev_alloc_skb(dev, pkt_len + 5);
if (vortex_debug > 4)
pr_debug("Receiving packet size %d status %4.4x.\n",
pkt_len, rx_status);
@@ -2579,7 +2578,8 @@ boomerang_rx(struct net_device *dev)
/* Check if the packet is long enough to just accept without
copying to a properly sized skbuff. */
- if (pkt_len < rx_copybreak && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ if (pkt_len < rx_copybreak &&
+ (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
pci_dma_sync_single_for_cpu(VORTEX_PCI(vp), dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
/* 'skb_put()' points to the start of sk_buff data area. */
diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig
index a8bb30cf512d..bad4fa6815c5 100644
--- a/drivers/net/ethernet/3com/Kconfig
+++ b/drivers/net/ethernet/3com/Kconfig
@@ -97,7 +97,7 @@ config VORTEX
available from <http://www.tldp.org/docs.html#howto>. More
specific information is in
<file:Documentation/networking/vortex.txt> and in the comments at
- the beginning of <file:drivers/net/3c59x.c>.
+ the beginning of <file:drivers/net/ethernet/3com/3c59x.c>.
To compile this support as a module, choose M here.
diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index 6d6bc754b1a8..1234a14b2b73 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -966,18 +966,6 @@ typhoon_get_stats(struct net_device *dev)
return stats;
}
-static int
-typhoon_set_mac_address(struct net_device *dev, void *addr)
-{
- struct sockaddr *saddr = (struct sockaddr *) addr;
-
- if(netif_running(dev))
- return -EBUSY;
-
- memcpy(dev->dev_addr, saddr->sa_data, dev->addr_len);
- return 0;
-}
-
static void
typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
@@ -1607,7 +1595,7 @@ typhoon_alloc_rx_skb(struct typhoon *tp, u32 idx)
le32_to_cpu(indexes->rxBuffCleared))
return -ENOMEM;
- skb = dev_alloc_skb(PKT_BUF_SZ);
+ skb = netdev_alloc_skb(tp->dev, PKT_BUF_SZ);
if(!skb)
return -ENOMEM;
@@ -1618,7 +1606,6 @@ typhoon_alloc_rx_skb(struct typhoon *tp, u32 idx)
skb_reserve(skb, 2);
#endif
- skb->dev = tp->dev;
dma_addr = pci_map_single(tp->pdev, skb->data,
PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
@@ -1673,7 +1660,7 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile __le32 * read
pkt_len = le16_to_cpu(rx->frameLen);
if(pkt_len < rx_copybreak &&
- (new_skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ (new_skb = netdev_alloc_skb(tp->dev, pkt_len + 2)) != NULL) {
skb_reserve(new_skb, 2);
pci_dma_sync_single_for_cpu(tp->pdev, dma_addr,
PKT_BUF_SZ,
@@ -2267,7 +2254,7 @@ static const struct net_device_ops typhoon_netdev_ops = {
.ndo_tx_timeout = typhoon_tx_timeout,
.ndo_get_stats = typhoon_get_stats,
.ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = typhoon_set_mac_address,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
};
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index 0f92e3567f68..c30adcc9828a 100644
--- a/drivers/net/ethernet/8390/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -1,4 +1,4 @@
-/* drivers/net/ax88796.c
+/* drivers/net/ethernet/8390/ax88796.c
*
* Copyright 2005,2007 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c
index bba51cdc74a1..c5bd8eb7a9f5 100644
--- a/drivers/net/ethernet/8390/axnet_cs.c
+++ b/drivers/net/ethernet/8390/axnet_cs.c
@@ -192,7 +192,7 @@ static int get_prom(struct pcmcia_device *link)
unsigned int ioaddr = dev->base_addr;
int i, j;
- /* This is based on drivers/net/ne.c */
+ /* This is based on drivers/net/ethernet/8390/ne.c */
struct {
u_char value, offset;
} program_seq[] = {
@@ -1408,7 +1408,7 @@ static void ei_receive(struct net_device *dev)
{
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len+2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb == NULL)
{
if (ei_debug > 1)
diff --git a/drivers/net/ethernet/8390/lib8390.c b/drivers/net/ethernet/8390/lib8390.c
index 05ae21435bfd..e77f624e8194 100644
--- a/drivers/net/ethernet/8390/lib8390.c
+++ b/drivers/net/ethernet/8390/lib8390.c
@@ -717,7 +717,7 @@ static void ei_receive(struct net_device *dev)
} else if ((pkt_stat & 0x0F) == ENRSR_RXOK) {
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len+2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb == NULL) {
if (ei_debug > 1)
netdev_dbg(dev, "Couldn't allocate a sk_buff of size %d\n",
diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c
index 053b2551a72d..f2a4e5de18c4 100644
--- a/drivers/net/ethernet/8390/pcnet_cs.c
+++ b/drivers/net/ethernet/8390/pcnet_cs.c
@@ -326,7 +326,7 @@ static hw_info_t *get_prom(struct pcmcia_device *link)
u_char prom[32];
int i, j;
- /* This is lifted straight from drivers/net/ne.c */
+ /* This is lifted straight from drivers/net/ethernet/8390/ne.c */
struct {
u_char value, offset;
} program_seq[] = {
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index cb4f38a17f20..d896816512ca 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -686,10 +686,9 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
}
dev = alloc_etherdev(sizeof(*np));
- if (!dev) {
- printk(KERN_ERR DRV_NAME " %d: cannot alloc etherdev, aborting\n", card_idx);
+ if (!dev)
return -ENOMEM;
- }
+
SET_NETDEV_DEV(dev, &pdev->dev);
irq = pdev->irq;
@@ -1180,12 +1179,11 @@ static void init_ring(struct net_device *dev)
/* Fill in the Rx buffers. Handle allocation failure gracefully. */
for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);
+ struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz);
np->rx_info[i].skb = skb;
if (skb == NULL)
break;
np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
- skb->dev = dev; /* Mark as being used by this device. */
/* Grrr, we cannot offset to correctly align the IP header. */
np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
}
@@ -1473,7 +1471,7 @@ static int __netdev_rx(struct net_device *dev, int *quota)
/* Check if the packet is long enough to accept without copying
to a minimally-sized skbuff. */
if (pkt_len < rx_copybreak &&
- (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
skb_reserve(skb, 2); /* 16 byte align the IP header */
pci_dma_sync_single_for_cpu(np->pci_dev,
np->rx_info[entry].mapping,
@@ -1597,13 +1595,12 @@ static void refill_rx_ring(struct net_device *dev)
for (; np->cur_rx - np->dirty_rx > 0; np->dirty_rx++) {
entry = np->dirty_rx % RX_RING_SIZE;
if (np->rx_info[entry].skb == NULL) {
- skb = dev_alloc_skb(np->rx_buf_sz);
+ skb = netdev_alloc_skb(dev, np->rx_buf_sz);
np->rx_info[entry].skb = skb;
if (skb == NULL)
break; /* Better luck next round. */
np->rx_info[entry].mapping =
pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
- skb->dev = dev; /* Mark as being used by this device. */
np->rx_ring[entry].rxaddr =
cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
}
diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index d812a103e032..ab4daeccdf98 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -113,7 +113,7 @@ static void desc_list_free(void)
}
}
-static int desc_list_init(void)
+static int desc_list_init(struct net_device *dev)
{
int i;
struct sk_buff *new_skb;
@@ -187,7 +187,7 @@ static int desc_list_init(void)
struct dma_descriptor *b = &(r->desc_b);
/* allocate a new skb for next time receive */
- new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
+ new_skb = netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN);
if (!new_skb) {
pr_notice("init: low on mem - packet dropped\n");
goto init_error;
@@ -621,6 +621,7 @@ static int bfin_mac_set_mac_address(struct net_device *dev, void *p)
if (netif_running(dev))
return -EBUSY;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
setup_mac_addr(dev->dev_addr);
return 0;
}
@@ -1090,7 +1091,7 @@ static void bfin_mac_rx(struct net_device *dev)
/* allocate a new skb for next time receive */
skb = current_rx_ptr->skb;
- new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN);
+ new_skb = netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN);
if (!new_skb) {
netdev_notice(dev, "rx: low on mem - packet dropped\n");
dev->stats.rx_dropped++;
@@ -1397,7 +1398,7 @@ static int bfin_mac_open(struct net_device *dev)
}
/* initial rx and tx list */
- ret = desc_list_init();
+ ret = desc_list_init(dev);
if (ret)
return ret;
@@ -1467,10 +1468,8 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
int rc;
ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
- if (!ndev) {
- dev_err(&pdev->dev, "Cannot allocate net device!\n");
+ if (!ndev)
return -ENOMEM;
- }
SET_NETDEV_DEV(ndev, &pdev->dev);
platform_set_drvdata(pdev, ndev);
@@ -1496,12 +1495,14 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
* Grab the MAC from the board somehow
* this is done in the arch/blackfin/mach-bfxxx/boards/eth_mac.c
*/
- if (!is_valid_ether_addr(ndev->dev_addr))
- bfin_get_ether_addr(ndev->dev_addr);
-
- /* If still not valid, get a random one */
- if (!is_valid_ether_addr(ndev->dev_addr))
- random_ether_addr(ndev->dev_addr);
+ if (!is_valid_ether_addr(ndev->dev_addr)) {
+ if (bfin_get_ether_addr(ndev->dev_addr) ||
+ !is_valid_ether_addr(ndev->dev_addr)) {
+ /* Still not valid, get a random one */
+ netdev_warn(ndev, "Setting Ethernet MAC to a random one\n");
+ eth_hw_addr_random(ndev);
+ }
+ }
setup_mac_addr(ndev->dev_addr);
diff --git a/drivers/net/ethernet/adi/bfin_mac.h b/drivers/net/ethernet/adi/bfin_mac.h
index f8559ac9a403..960905c08223 100644
--- a/drivers/net/ethernet/adi/bfin_mac.h
+++ b/drivers/net/ethernet/adi/bfin_mac.h
@@ -101,6 +101,6 @@ struct bfin_mac_local {
#endif
};
-extern void bfin_get_ether_addr(char *addr);
+extern int bfin_get_ether_addr(char *addr);
#endif
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index c885aa905dec..348501178089 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -785,7 +785,6 @@ static int greth_rx(struct net_device *dev, int limit)
} else {
skb_reserve(skb, NET_IP_ALIGN);
- skb->dev = dev;
dma_sync_single_for_cpu(greth->dev,
dma_addr,
@@ -1018,7 +1017,7 @@ static int greth_set_mac_add(struct net_device *dev, void *p)
regs = (struct greth_regs *) greth->regs;
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
GRETH_REGSAVE(regs->esa_msb, dev->dev_addr[0] << 8 | dev->dev_addr[1]);
@@ -1422,7 +1421,7 @@ static int __devinit greth_of_probe(struct platform_device *ofdev)
SET_NETDEV_DEV(dev, greth->dev);
if (netif_msg_probe(greth))
- dev_dbg(greth->dev, "reseting controller.\n");
+ dev_dbg(greth->dev, "resetting controller.\n");
/* Reset the controller. */
GRETH_REGSAVE(regs->control, GRETH_RESET);
diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c
index f872748ab4e6..6c3b1c0adaa0 100644
--- a/drivers/net/ethernet/alteon/acenic.c
+++ b/drivers/net/ethernet/alteon/acenic.c
@@ -463,11 +463,8 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
static int boards_found;
dev = alloc_etherdev(sizeof(struct ace_private));
- if (dev == NULL) {
- printk(KERN_ERR "acenic: Unable to allocate "
- "net_device structure!\n");
+ if (dev == NULL)
return -ENOMEM;
- }
SET_NETDEV_DEV(dev, &pdev->dev);
diff --git a/drivers/net/ethernet/amd/7990.c b/drivers/net/ethernet/amd/7990.c
index 60b35fb5f524..1b046f58d58f 100644
--- a/drivers/net/ethernet/amd/7990.c
+++ b/drivers/net/ethernet/amd/7990.c
@@ -316,7 +316,7 @@ static int lance_rx (struct net_device *dev)
if (bits & LE_R1_EOP) dev->stats.rx_errors++;
} else {
int len = (rd->mblength & 0xfff) - 4;
- struct sk_buff *skb = dev_alloc_skb (len+2);
+ struct sk_buff *skb = netdev_alloc_skb(dev, len + 2);
if (!skb) {
printk ("%s: Memory squeeze, deferring packet.\n",
diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
index 238b537b68fe..8350f4b37a8a 100644
--- a/drivers/net/ethernet/amd/Kconfig
+++ b/drivers/net/ethernet/amd/Kconfig
@@ -113,7 +113,7 @@ config DEPCA
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto> as well as
- <file:drivers/net/depca.c>.
+ <file:drivers/net/ethernet/amd/depca.c>.
To compile this driver as a module, choose M here. The module
will be called depca.
diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c
index 825e5d4ef4c3..689dfcafc6d4 100644
--- a/drivers/net/ethernet/amd/a2065.c
+++ b/drivers/net/ethernet/amd/a2065.c
@@ -290,7 +290,7 @@ static int lance_rx(struct net_device *dev)
dev->stats.rx_errors++;
} else {
int len = (rd->mblength & 0xfff) - 4;
- struct sk_buff *skb = dev_alloc_skb(len + 2);
+ struct sk_buff *skb = netdev_alloc_skb(dev, len + 2);
if (!skb) {
netdev_warn(dev, "Memory squeeze, deferring packet\n");
diff --git a/drivers/net/ethernet/amd/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c
index 7d5ded80d2d7..cc7b9e46780c 100644
--- a/drivers/net/ethernet/amd/am79c961a.c
+++ b/drivers/net/ethernet/amd/am79c961a.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/net/am79c961.c
+ * linux/drivers/net/ethernet/amd/am79c961a.c
*
* by Russell King <rmk@arm.linux.org.uk> 1995-2001.
*
@@ -516,7 +516,7 @@ am79c961_rx(struct net_device *dev, struct dev_priv *priv)
}
len = am_readword(dev, hdraddr + 6);
- skb = dev_alloc_skb(len + 2);
+ skb = netdev_alloc_skb(dev, len + 2);
if (skb) {
skb_reserve(skb, 2);
diff --git a/drivers/net/ethernet/amd/am79c961a.h b/drivers/net/ethernet/amd/am79c961a.h
index fd634d32756b..9f384b79507b 100644
--- a/drivers/net/ethernet/amd/am79c961a.h
+++ b/drivers/net/ethernet/amd/am79c961a.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/net/arm/am79c961a.h
+ * linux/drivers/net/ethernet/amd/am79c961a.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
index 33e0a8c20f6b..9f62504d0086 100644
--- a/drivers/net/ethernet/amd/amd8111e.c
+++ b/drivers/net/ethernet/amd/amd8111e.c
@@ -336,7 +336,8 @@ static int amd8111e_init_ring(struct net_device *dev)
/* Allocating receive skbs */
for (i = 0; i < NUM_RX_BUFFERS; i++) {
- if (!(lp->rx_skbuff[i] = dev_alloc_skb(lp->rx_buff_len))) {
+ lp->rx_skbuff[i] = netdev_alloc_skb(dev, lp->rx_buff_len);
+ if (!lp->rx_skbuff[i]) {
/* Release previos allocated skbs */
for(--i; i >= 0 ;i--)
dev_kfree_skb(lp->rx_skbuff[i]);
@@ -768,7 +769,8 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
}
if(--rx_pkt_limit < 0)
goto rx_not_empty;
- if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){
+ new_skb = netdev_alloc_skb(dev, lp->rx_buff_len);
+ if (!new_skb) {
/* if allocation fail,
ignore that pkt and go to next one */
lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
@@ -1859,7 +1861,6 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(struct amd8111e_priv));
if (!dev) {
- printk(KERN_ERR "amd8111e: Etherdev alloc failed, exiting.\n");
err = -ENOMEM;
goto err_free_reg;
}
diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c
index eb18e1fe65c8..f4c228e4d76c 100644
--- a/drivers/net/ethernet/amd/ariadne.c
+++ b/drivers/net/ethernet/amd/ariadne.c
@@ -191,7 +191,7 @@ static int ariadne_rx(struct net_device *dev)
short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len + 2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb == NULL) {
netdev_warn(dev, "Memory squeeze, deferring packet\n");
for (i = 0; i < RX_RING_SIZE; i++)
diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c
index 15bfa28d6c53..70ed79c46245 100644
--- a/drivers/net/ethernet/amd/atarilance.c
+++ b/drivers/net/ethernet/amd/atarilance.c
@@ -997,7 +997,7 @@ static int lance_rx( struct net_device *dev )
dev->stats.rx_errors++;
}
else {
- skb = dev_alloc_skb( pkt_len+2 );
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb == NULL) {
DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n",
dev->name ));
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index 8b95dd314253..397596b078d9 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -725,7 +725,7 @@ static int au1000_rx(struct net_device *dev)
/* good frame */
frmlen = (status & RX_FRAME_LEN_MASK);
frmlen -= 4; /* Remove FCS */
- skb = dev_alloc_skb(frmlen + 2);
+ skb = netdev_alloc_skb(dev, frmlen + 2);
if (skb == NULL) {
netdev_err(dev, "Memory squeeze, dropping packet.\n");
dev->stats.rx_dropped++;
@@ -1077,7 +1077,6 @@ static int __devinit au1000_probe(struct platform_device *pdev)
dev = alloc_etherdev(sizeof(struct au1000_private));
if (!dev) {
- dev_err(&pdev->dev, "alloc_etherdev failed\n");
err = -ENOMEM;
goto err_alloc;
}
@@ -1130,9 +1129,6 @@ static int __devinit au1000_probe(struct platform_device *pdev)
au1000_setup_hw_rings(aup, aup->macdma);
- /* set a random MAC now in case platform_data doesn't provide one */
- random_ether_addr(dev->dev_addr);
-
writel(0, aup->enable);
aup->mac_enabled = 0;
@@ -1142,8 +1138,12 @@ static int __devinit au1000_probe(struct platform_device *pdev)
" PHY search on MAC0\n");
aup->phy1_search_mac0 = 1;
} else {
- if (is_valid_ether_addr(pd->mac))
+ if (is_valid_ether_addr(pd->mac)) {
memcpy(dev->dev_addr, pd->mac, 6);
+ } else {
+ /* Set a random MAC since no valid provided by platform_data. */
+ eth_hw_addr_random(dev);
+ }
aup->phy_static_config = pd->phy_static_config;
aup->phy_search_highest_addr = pd->phy_search_highest_addr;
diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c
index 73f8d4fa682d..7dc508e5c72e 100644
--- a/drivers/net/ethernet/amd/declance.c
+++ b/drivers/net/ethernet/amd/declance.c
@@ -605,7 +605,7 @@ static int lance_rx(struct net_device *dev)
dev->stats.rx_errors++;
} else {
len = (*rds_ptr(rd, mblength, lp->type) & 0xfff) - 4;
- skb = dev_alloc_skb(len + 2);
+ skb = netdev_alloc_skb(dev, len + 2);
if (skb == 0) {
printk("%s: Memory squeeze, deferring packet.\n",
@@ -1052,8 +1052,6 @@ static int __devinit dec_lance_probe(struct device *bdev, const int type)
dev = alloc_etherdev(sizeof(struct lance_private));
if (!dev) {
- printk(KERN_ERR "%s: Unable to allocate etherdev, aborting.\n",
- name);
ret = -ENOMEM;
goto err_out;
}
diff --git a/drivers/net/ethernet/amd/depca.c b/drivers/net/ethernet/amd/depca.c
index 681970c07f22..86dd95766a64 100644
--- a/drivers/net/ethernet/amd/depca.c
+++ b/drivers/net/ethernet/amd/depca.c
@@ -1042,7 +1042,7 @@ static int depca_rx(struct net_device *dev)
short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4;
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len + 2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb != NULL) {
unsigned char *buf;
skb_reserve(skb, 2); /* 16 byte align the IP header */
diff --git a/drivers/net/ethernet/amd/hplance.c b/drivers/net/ethernet/amd/hplance.c
index 86aa0d546a5b..4e2d68a4de8a 100644
--- a/drivers/net/ethernet/amd/hplance.c
+++ b/drivers/net/ethernet/amd/hplance.c
@@ -89,7 +89,6 @@ static int __devinit hplance_init_one(struct dio_dev *d,
{
struct net_device *dev;
int err = -ENOMEM;
- int i;
dev = alloc_etherdev(sizeof(struct hplance_private));
if (!dev)
@@ -107,13 +106,8 @@ static int __devinit hplance_init_one(struct dio_dev *d,
dio_set_drvdata(d, dev);
- printk(KERN_INFO "%s: %s; select code %d, addr %2.2x", dev->name, d->name, d->scode, dev->dev_addr[0]);
-
- for (i=1; i<6; i++) {
- printk(":%2.2x", dev->dev_addr[i]);
- }
-
- printk(", irq %d\n", d->ipl);
+ printk(KERN_INFO "%s: %s; select code %d, addr %pM, irq %d\n",
+ dev->name, d->name, d->scode, dev->dev_addr, d->ipl);
return 0;
diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c
index 6e6aa7213aab..013b65108536 100644
--- a/drivers/net/ethernet/amd/ni65.c
+++ b/drivers/net/ethernet/amd/ni65.c
@@ -621,10 +621,8 @@ static void *ni65_alloc_mem(struct net_device *dev,char *what,int size,int type)
}
else {
ret = ptr = kmalloc(T_BUF_SIZE,GFP_KERNEL | GFP_DMA);
- if(!ret) {
- printk(KERN_WARNING "%s: unable to allocate %s memory.\n",dev->name,what);
+ if(!ret)
return NULL;
- }
}
if( (u32) virt_to_phys(ptr+size) > 0x1000000) {
printk(KERN_WARNING "%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what);
@@ -1091,7 +1089,7 @@ static void ni65_recv_intr(struct net_device *dev,int csr0)
if (skb)
skb_reserve(skb,16);
#else
- struct sk_buff *skb = dev_alloc_skb(len+2);
+ struct sk_buff *skb = netdev_alloc_skb(dev, len + 2);
#endif
if(skb)
{
diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c
index 6be0dd67631a..ebdb9e238a8d 100644
--- a/drivers/net/ethernet/amd/nmclan_cs.c
+++ b/drivers/net/ethernet/amd/nmclan_cs.c
@@ -1104,7 +1104,7 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt)
pr_debug(" receiving packet size 0x%X rx_status"
" 0x%X.\n", pkt_len, rx_status);
- skb = dev_alloc_skb(pkt_len+2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb != NULL) {
skb_reserve(skb, 2);
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
index 20e6dab0186c..86b6d8e4e6cd 100644
--- a/drivers/net/ethernet/amd/pcnet32.c
+++ b/drivers/net/ethernet/amd/pcnet32.c
@@ -588,11 +588,11 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
/* now allocate any new buffers needed */
for (; new < size; new++) {
struct sk_buff *rx_skbuff;
- new_skb_list[new] = dev_alloc_skb(PKT_BUF_SKB);
+ new_skb_list[new] = netdev_alloc_skb(dev, PKT_BUF_SKB);
rx_skbuff = new_skb_list[new];
if (!rx_skbuff) {
/* keep the original lists and buffers */
- netif_err(lp, drv, dev, "%s dev_alloc_skb failed\n",
+ netif_err(lp, drv, dev, "%s netdev_alloc_skb failed\n",
__func__);
goto free_all_new;
}
@@ -909,7 +909,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
/* Initialize Transmit buffers. */
size = data_len + 15;
for (x = 0; x < numbuffs; x++) {
- skb = dev_alloc_skb(size);
+ skb = netdev_alloc_skb(dev, size);
if (!skb) {
netif_printk(lp, hw, KERN_DEBUG, dev,
"Cannot allocate skb at line: %d!\n",
@@ -1152,7 +1152,7 @@ static void pcnet32_rx_entry(struct net_device *dev,
if (pkt_len > rx_copybreak) {
struct sk_buff *newskb;
- newskb = dev_alloc_skb(PKT_BUF_SKB);
+ newskb = netdev_alloc_skb(dev, PKT_BUF_SKB);
if (newskb) {
skb_reserve(newskb, NET_IP_ALIGN);
skb = lp->rx_skbuff[entry];
@@ -1172,7 +1172,7 @@ static void pcnet32_rx_entry(struct net_device *dev,
} else
skb = NULL;
} else
- skb = dev_alloc_skb(pkt_len + NET_IP_ALIGN);
+ skb = netdev_alloc_skb(dev, pkt_len + NET_IP_ALIGN);
if (skb == NULL) {
netif_err(lp, drv, dev, "Memory squeeze, dropping packet\n");
@@ -1649,8 +1649,6 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
dev = alloc_etherdev(sizeof(*lp));
if (!dev) {
- if (pcnet32_debug & NETIF_MSG_PROBE)
- pr_err("Memory allocation failed\n");
ret = -ENOMEM;
goto err_release_region;
}
@@ -2273,11 +2271,11 @@ static int pcnet32_init_ring(struct net_device *dev)
for (i = 0; i < lp->rx_ring_size; i++) {
struct sk_buff *rx_skbuff = lp->rx_skbuff[i];
if (rx_skbuff == NULL) {
- lp->rx_skbuff[i] = dev_alloc_skb(PKT_BUF_SKB);
+ lp->rx_skbuff[i] = netdev_alloc_skb(dev, PKT_BUF_SKB);
rx_skbuff = lp->rx_skbuff[i];
if (!rx_skbuff) {
/* there is not much we can do at this point */
- netif_err(lp, drv, dev, "%s dev_alloc_skb failed\n",
+ netif_err(lp, drv, dev, "%s netdev_alloc_skb failed\n",
__func__);
return -1;
}
diff --git a/drivers/net/ethernet/amd/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c
index 080b71fcc683..74b3891b6483 100644
--- a/drivers/net/ethernet/amd/sun3lance.c
+++ b/drivers/net/ethernet/amd/sun3lance.c
@@ -810,7 +810,7 @@ static int lance_rx( struct net_device *dev )
dev->stats.rx_errors++;
}
else {
- skb = dev_alloc_skb( pkt_len+2 );
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb == NULL) {
DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n",
dev->name ));
diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c
index 7ea16d32a5f5..e3fe3504e198 100644
--- a/drivers/net/ethernet/amd/sunlance.c
+++ b/drivers/net/ethernet/amd/sunlance.c
@@ -534,7 +534,7 @@ static void lance_rx_dvma(struct net_device *dev)
if (bits & LE_R1_EOP) dev->stats.rx_errors++;
} else {
len = (rd->mblength & 0xfff) - 4;
- skb = dev_alloc_skb(len + 2);
+ skb = netdev_alloc_skb(dev, len + 2);
if (skb == NULL) {
printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
@@ -706,7 +706,7 @@ static void lance_rx_pio(struct net_device *dev)
if (bits & LE_R1_EOP) dev->stats.rx_errors++;
} else {
len = (sbus_readw(&rd->mblength) & 0xfff) - 4;
- skb = dev_alloc_skb(len + 2);
+ skb = netdev_alloc_skb(dev, len + 2);
if (skb == NULL) {
printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c
index d070b229dbf7..855bdafb1a87 100644
--- a/drivers/net/ethernet/apple/bmac.c
+++ b/drivers/net/ethernet/apple/bmac.c
@@ -607,8 +607,9 @@ bmac_init_tx_ring(struct bmac_data *bp)
}
static int
-bmac_init_rx_ring(struct bmac_data *bp)
+bmac_init_rx_ring(struct net_device *dev)
{
+ struct bmac_data *bp = netdev_priv(dev);
volatile struct dbdma_regs __iomem *rd = bp->rx_dma;
int i;
struct sk_buff *skb;
@@ -618,7 +619,7 @@ bmac_init_rx_ring(struct bmac_data *bp)
(N_RX_RING + 1) * sizeof(struct dbdma_cmd));
for (i = 0; i < N_RX_RING; i++) {
if ((skb = bp->rx_bufs[i]) == NULL) {
- bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
+ bp->rx_bufs[i] = skb = netdev_alloc_skb(dev, RX_BUFLEN + 2);
if (skb != NULL)
skb_reserve(skb, 2);
}
@@ -722,7 +723,7 @@ static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id)
++dev->stats.rx_dropped;
}
if ((skb = bp->rx_bufs[i]) == NULL) {
- bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
+ bp->rx_bufs[i] = skb = netdev_alloc_skb(dev, RX_BUFLEN + 2);
if (skb != NULL)
skb_reserve(bp->rx_bufs[i], 2);
}
@@ -1208,7 +1209,7 @@ static void bmac_reset_and_enable(struct net_device *dev)
spin_lock_irqsave(&bp->lock, flags);
bmac_enable_and_reset_chip(dev);
bmac_init_tx_ring(bp);
- bmac_init_rx_ring(bp);
+ bmac_init_rx_ring(dev);
bmac_init_chip(dev);
bmac_start_chip(dev);
bmwrite(dev, INTDISABLE, EnableNormal);
@@ -1218,7 +1219,7 @@ static void bmac_reset_and_enable(struct net_device *dev)
* It seems that the bmac can't receive until it's transmitted
* a packet. So we give it a dummy packet to transmit.
*/
- skb = dev_alloc_skb(ETHERMINPACKET);
+ skb = netdev_alloc_skb(dev, ETHERMINPACKET);
if (skb != NULL) {
data = skb_put(skb, ETHERMINPACKET);
memset(data, 0, ETHERMINPACKET);
@@ -1269,10 +1270,8 @@ static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_i
memcpy(addr, prop_addr, sizeof(addr));
dev = alloc_etherdev(PRIV_BYTES);
- if (!dev) {
- printk(KERN_ERR "BMAC: alloc_etherdev failed, out of memory\n");
+ if (!dev)
return -ENOMEM;
- }
bp = netdev_priv(dev);
SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
@@ -1660,10 +1659,8 @@ static int __init bmac_init(void)
{
if (bmac_emergency_rxbuf == NULL) {
bmac_emergency_rxbuf = kmalloc(RX_BUFLEN, GFP_KERNEL);
- if (bmac_emergency_rxbuf == NULL) {
- printk(KERN_ERR "BMAC: can't allocate emergency RX buffer\n");
+ if (bmac_emergency_rxbuf == NULL)
return -ENOMEM;
- }
}
return macio_register_driver(&bmac_driver);
diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c
index bec87bd9195c..e1df4b76c885 100644
--- a/drivers/net/ethernet/apple/mace.c
+++ b/drivers/net/ethernet/apple/mace.c
@@ -136,10 +136,8 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i
*/
if (dummy_buf == NULL) {
dummy_buf = kmalloc(RX_BUFLEN+2, GFP_KERNEL);
- if (dummy_buf == NULL) {
- printk(KERN_ERR "MACE: couldn't allocate dummy buffer\n");
+ if (dummy_buf == NULL)
return -ENOMEM;
- }
}
if (macio_request_resources(mdev, "mace")) {
@@ -149,7 +147,6 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i
dev = alloc_etherdev(PRIV_BYTES);
if (!dev) {
- printk(KERN_ERR "MACE: can't allocate ethernet device !\n");
rc = -ENOMEM;
goto err_release;
}
@@ -447,7 +444,7 @@ static int mace_open(struct net_device *dev)
memset((char *)mp->rx_cmds, 0, N_RX_RING * sizeof(struct dbdma_cmd));
cp = mp->rx_cmds;
for (i = 0; i < N_RX_RING - 1; ++i) {
- skb = dev_alloc_skb(RX_BUFLEN + 2);
+ skb = netdev_alloc_skb(dev, RX_BUFLEN + 2);
if (!skb) {
data = dummy_buf;
} else {
@@ -959,7 +956,7 @@ static irqreturn_t mace_rxdma_intr(int irq, void *dev_id)
cp = mp->rx_cmds + i;
skb = mp->rx_bufs[i];
if (!skb) {
- skb = dev_alloc_skb(RX_BUFLEN + 2);
+ skb = netdev_alloc_skb(dev, RX_BUFLEN + 2);
if (skb) {
skb_reserve(skb, 2);
mp->rx_bufs[i] = skb;
diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c
index 7cf81bbffe0e..ab7ff8645ab1 100644
--- a/drivers/net/ethernet/apple/macmace.c
+++ b/drivers/net/ethernet/apple/macmace.c
@@ -661,7 +661,7 @@ static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf)
} else {
unsigned int frame_length = mf->rcvcnt + ((frame_status & 0x0F) << 8 );
- skb = dev_alloc_skb(frame_length + 2);
+ skb = netdev_alloc_skb(dev, frame_length + 2);
if (!skb) {
dev->stats.rx_dropped++;
return;
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index 23f2ab0f2fa8..bd1667cbffa6 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -224,7 +224,7 @@ int atl1c_read_mac_addr(struct atl1c_hw *hw)
random_ether_addr(hw->perm_mac_addr);
memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
- return 0;
+ return err;
}
/*
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 1ff3c6df35a2..0f21a9b4cdd4 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -468,6 +468,7 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p)
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+ netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
atl1c_hw_set_mac_addr(&adapter->hw);
@@ -1765,7 +1766,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid
while (next_info->flags & ATL1C_BUFFER_FREE) {
rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use);
- skb = dev_alloc_skb(adapter->rx_buffer_len);
+ skb = netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len);
if (unlikely(!skb)) {
if (netif_msg_rx_err(adapter))
dev_warn(&pdev->dev, "alloc rx buffer failed\n");
@@ -2685,7 +2686,6 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
netdev = alloc_etherdev(sizeof(struct atl1c_adapter));
if (netdev == NULL) {
err = -ENOMEM;
- dev_err(&pdev->dev, "etherdev alloc failed\n");
goto err_alloc_etherdev;
}
@@ -2742,10 +2742,9 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
err = -EIO;
goto err_reset;
}
- if (atl1c_read_mac_addr(&adapter->hw) != 0) {
- err = -EIO;
- dev_err(&pdev->dev, "get mac address failed\n");
- goto err_eeprom;
+ if (atl1c_read_mac_addr(&adapter->hw)) {
+ /* got a random MAC address, set NET_ADDR_RANDOM to netdev */
+ netdev->addr_assign_type |= NET_ADDR_RANDOM;
}
memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
@@ -2770,7 +2769,6 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
err_reset:
err_register:
err_sw_init:
-err_eeprom:
iounmap(adapter->hw.hw_addr);
err_init_netdev:
err_ioremap:
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index c915c0873810..93ff2b231284 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -2300,7 +2300,6 @@ static int __devinit atl1e_probe(struct pci_dev *pdev,
netdev = alloc_etherdev(sizeof(struct atl1e_adapter));
if (netdev == NULL) {
err = -ENOMEM;
- dev_err(&pdev->dev, "etherdev alloc failed\n");
goto err_alloc_etherdev;
}
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index 9bd204976648..40ac41436549 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -534,14 +534,17 @@ static int atl1_get_permanent_address(struct atl1_hw *hw)
*/
static s32 atl1_read_mac_addr(struct atl1_hw *hw)
{
+ s32 ret = 0;
u16 i;
- if (atl1_get_permanent_address(hw))
+ if (atl1_get_permanent_address(hw)) {
random_ether_addr(hw->perm_mac_addr);
+ ret = 1;
+ }
for (i = 0; i < ETH_ALEN; i++)
hw->mac_addr[i] = hw->perm_mac_addr[i];
- return 0;
+ return ret;
}
/*
@@ -3007,7 +3010,10 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
}
/* copy the MAC address out of the EEPROM */
- atl1_read_mac_addr(&adapter->hw);
+ if (atl1_read_mac_addr(&adapter->hw)) {
+ /* mark random mac */
+ netdev->addr_assign_type |= NET_ADDR_RANDOM;
+ }
memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
if (!is_valid_ether_addr(netdev->dev_addr)) {
diff --git a/drivers/net/ethernet/atheros/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c
index 8ff7411094d5..3cd8837236dc 100644
--- a/drivers/net/ethernet/atheros/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
@@ -84,6 +84,7 @@ static int atlx_set_mac(struct net_device *netdev, void *p)
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+ netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
atlx_set_mac_addr(&adapter->hw);
return 0;
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index cab87456a34a..46b8b7d81633 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -2138,7 +2138,6 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
dev = alloc_etherdev(sizeof(*bp));
if (!dev) {
- dev_err(sdev->dev, "Etherdev alloc failed, aborting\n");
err = -ENOMEM;
goto out;
}
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 021fb818007a..8297e2868736 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -2625,10 +2625,8 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp)
u32 val;
good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL);
- if (good_mbuf == NULL) {
- pr_err("Failed to allocate memory in %s\n", __func__);
+ if (good_mbuf == NULL)
return -ENOMEM;
- }
REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE);
@@ -6248,7 +6246,16 @@ static int
bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
{
int cpus = num_online_cpus();
- int msix_vecs = min(cpus + 1, RX_MAX_RINGS);
+ int msix_vecs;
+
+ if (!bp->num_req_rx_rings)
+ msix_vecs = max(cpus + 1, bp->num_req_tx_rings);
+ else if (!bp->num_req_tx_rings)
+ msix_vecs = max(cpus, bp->num_req_rx_rings);
+ else
+ msix_vecs = max(bp->num_req_rx_rings, bp->num_req_tx_rings);
+
+ msix_vecs = min(msix_vecs, RX_MAX_RINGS);
bp->irq_tbl[0].handler = bnx2_interrupt;
strcpy(bp->irq_tbl[0].name, bp->dev->name);
@@ -6272,10 +6279,18 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
}
}
- bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
+ if (!bp->num_req_tx_rings)
+ bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
+ else
+ bp->num_tx_rings = min(bp->irq_nvecs, bp->num_req_tx_rings);
+
+ if (!bp->num_req_rx_rings)
+ bp->num_rx_rings = bp->irq_nvecs;
+ else
+ bp->num_rx_rings = min(bp->irq_nvecs, bp->num_req_rx_rings);
+
netif_set_real_num_tx_queues(bp->dev, bp->num_tx_rings);
- bp->num_rx_rings = bp->irq_nvecs;
return netif_set_real_num_rx_queues(bp->dev, bp->num_rx_rings);
}
@@ -6550,6 +6565,9 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END;
+ /* Sync BD data before updating TX mailbox */
+ wmb();
+
netdev_tx_sent_queue(txq, skb->len);
prod = NEXT_TX_BD(prod);
@@ -7164,7 +7182,7 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
}
static int
-bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
+bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx, bool reset_irq)
{
if (netif_running(bp->dev)) {
/* Reset will erase chipset stats; save them */
@@ -7172,7 +7190,12 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
bnx2_netif_stop(bp, true);
bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
- __bnx2_free_irq(bp);
+ if (reset_irq) {
+ bnx2_free_irq(bp);
+ bnx2_del_napi(bp);
+ } else {
+ __bnx2_free_irq(bp);
+ }
bnx2_free_skbs(bp);
bnx2_free_mem(bp);
}
@@ -7181,9 +7204,16 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
bp->tx_ring_size = tx;
if (netif_running(bp->dev)) {
- int rc;
+ int rc = 0;
+
+ if (reset_irq) {
+ rc = bnx2_setup_int_mode(bp, disable_msi);
+ bnx2_init_napi(bp);
+ }
+
+ if (!rc)
+ rc = bnx2_alloc_mem(bp);
- rc = bnx2_alloc_mem(bp);
if (!rc)
rc = bnx2_request_irq(bp);
@@ -7219,7 +7249,8 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
return -EINVAL;
}
- rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending);
+ rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending,
+ false);
return rc;
}
@@ -7607,6 +7638,54 @@ bnx2_set_features(struct net_device *dev, netdev_features_t features)
return 0;
}
+static void bnx2_get_channels(struct net_device *dev,
+ struct ethtool_channels *channels)
+{
+ struct bnx2 *bp = netdev_priv(dev);
+ u32 max_rx_rings = 1;
+ u32 max_tx_rings = 1;
+
+ if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) {
+ max_rx_rings = RX_MAX_RINGS;
+ max_tx_rings = TX_MAX_RINGS;
+ }
+
+ channels->max_rx = max_rx_rings;
+ channels->max_tx = max_tx_rings;
+ channels->max_other = 0;
+ channels->max_combined = 0;
+ channels->rx_count = bp->num_rx_rings;
+ channels->tx_count = bp->num_tx_rings;
+ channels->other_count = 0;
+ channels->combined_count = 0;
+}
+
+static int bnx2_set_channels(struct net_device *dev,
+ struct ethtool_channels *channels)
+{
+ struct bnx2 *bp = netdev_priv(dev);
+ u32 max_rx_rings = 1;
+ u32 max_tx_rings = 1;
+ int rc = 0;
+
+ if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !disable_msi) {
+ max_rx_rings = RX_MAX_RINGS;
+ max_tx_rings = TX_MAX_RINGS;
+ }
+ if (channels->rx_count > max_rx_rings ||
+ channels->tx_count > max_tx_rings)
+ return -EINVAL;
+
+ bp->num_req_rx_rings = channels->rx_count;
+ bp->num_req_tx_rings = channels->tx_count;
+
+ if (netif_running(dev))
+ rc = bnx2_change_ring_size(bp, bp->rx_ring_size,
+ bp->tx_ring_size, true);
+
+ return rc;
+}
+
static const struct ethtool_ops bnx2_ethtool_ops = {
.get_settings = bnx2_get_settings,
.set_settings = bnx2_set_settings,
@@ -7631,6 +7710,8 @@ static const struct ethtool_ops bnx2_ethtool_ops = {
.set_phys_id = bnx2_set_phys_id,
.get_ethtool_stats = bnx2_get_ethtool_stats,
.get_sset_count = bnx2_get_sset_count,
+ .get_channels = bnx2_get_channels,
+ .set_channels = bnx2_set_channels,
};
/* Called with rtnl_lock */
@@ -7692,7 +7773,7 @@ bnx2_change_mac_addr(struct net_device *dev, void *p)
struct bnx2 *bp = netdev_priv(dev);
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
if (netif_running(dev))
@@ -7712,7 +7793,8 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL;
dev->mtu = new_mtu;
- return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size);
+ return bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size,
+ false);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h
index 1db2d51ba3f1..dc06bda73be7 100644
--- a/drivers/net/ethernet/broadcom/bnx2.h
+++ b/drivers/net/ethernet/broadcom/bnx2.h
@@ -6933,6 +6933,9 @@ struct bnx2 {
u8 num_tx_rings;
u8 num_rx_rings;
+ int num_req_tx_rings;
+ int num_req_rx_rings;
+
u32 leds_save;
u32 idle_chk_status_idx;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 8c73d34b2ff1..c0cf313e6519 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1,6 +1,6 @@
/* bnx2x.h: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@
* (you will need to reboot afterwards) */
/* #define BNX2X_STOP_ON_ERROR */
-#define DRV_MODULE_VERSION "1.70.35-0"
-#define DRV_MODULE_RELDATE "2011/11/10"
+#define DRV_MODULE_VERSION "1.72.10-0"
+#define DRV_MODULE_RELDATE "2012/02/20"
#define BNX2X_BC_VER 0x040200
#if defined(CONFIG_DCB)
@@ -341,6 +341,7 @@ union db_prod {
#define SGE_PAGE_SIZE PAGE_SIZE
#define SGE_PAGE_SHIFT PAGE_SHIFT
#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN((typeof(PAGE_SIZE))(addr))
+#define SGE_PAGES (SGE_PAGE_SIZE * PAGES_PER_SGE)
/* SGE ring related macros */
#define NUM_RX_SGE_PAGES 2
@@ -445,6 +446,8 @@ struct bnx2x_agg_info {
u16 vlan_tag;
u16 len_on_bd;
u32 rxhash;
+ u16 gro_size;
+ u16 full_page;
};
#define Q_STATS_OFFSET32(stat_name) \
@@ -473,6 +476,11 @@ struct bnx2x_fp_txdata {
int txq_index;
};
+enum bnx2x_tpa_mode_t {
+ TPA_MODE_LRO,
+ TPA_MODE_GRO
+};
+
struct bnx2x_fastpath {
struct bnx2x *bp; /* parent */
@@ -489,6 +497,8 @@ struct bnx2x_fastpath {
dma_addr_t status_blk_mapping;
+ enum bnx2x_tpa_mode_t mode;
+
u8 max_cos; /* actual number of active tx coses */
struct bnx2x_fp_txdata txdata[BNX2X_MULTI_TX_COS];
@@ -540,6 +550,7 @@ struct bnx2x_fastpath {
struct ustorm_per_queue_stats old_uclient;
struct xstorm_per_queue_stats old_xclient;
struct bnx2x_eth_q_stats eth_q_stats;
+ struct bnx2x_eth_q_stats_old eth_q_stats_old;
/* The size is calculated using the following:
sizeof name field from netdev structure +
@@ -1046,7 +1057,6 @@ struct bnx2x_slowpath {
struct nig_stats nig_stats;
struct host_port_stats port_stats;
struct host_func_stats func_stats;
- struct host_func_stats func_stats_base;
u32 wb_comp;
u32 wb_data[4];
@@ -1088,7 +1098,8 @@ enum bnx2x_recovery_state {
BNX2X_RECOVERY_DONE,
BNX2X_RECOVERY_INIT,
BNX2X_RECOVERY_WAIT,
- BNX2X_RECOVERY_FAILED
+ BNX2X_RECOVERY_FAILED,
+ BNX2X_RECOVERY_NIC_LOADING
};
/*
@@ -1198,6 +1209,9 @@ struct bnx2x {
#define ETH_MIN_PACKET_SIZE 60
#define ETH_MAX_PACKET_SIZE 1500
#define ETH_MAX_JUMBO_PACKET_SIZE 9600
+/* TCP with Timestamp Option (32) + IPv6 (40) */
+#define ETH_MAX_TPA_HEADER_SIZE 72
+#define ETH_MIN_TPA_HEADER_SIZE 40
/* Max supported alignment is 256 (8 shift) */
#define BNX2X_RX_ALIGN_SHIFT min(8, L1_CACHE_SHIFT)
@@ -1268,6 +1282,7 @@ struct bnx2x {
#define NO_MCP_FLAG (1 << 9)
#define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG)
+#define GRO_ENABLE_FLAG (1 << 10)
#define MF_FUNC_DIS (1 << 11)
#define OWN_CNIC_IRQ (1 << 12)
#define NO_ISCSI_OOO_FLAG (1 << 13)
@@ -1316,6 +1331,8 @@ struct bnx2x {
u8 wol;
+ bool gro_check;
+
int rx_ring_size;
u16 tx_quick_cons_trip_int;
@@ -1461,6 +1478,10 @@ struct bnx2x {
u16 stats_counter;
struct bnx2x_eth_stats eth_stats;
+ struct bnx2x_eth_stats_old eth_stats_old;
+ struct bnx2x_net_stats_old net_stats_old;
+ struct bnx2x_fw_port_stats_old fw_stats_old;
+ bool stats_init;
struct z_stream_s *strm;
void *gunzip_buf;
@@ -2073,8 +2094,6 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define BNX2X_VPD_LEN 128
#define VENDOR_ID_LEN 4
-int bnx2x_close(struct net_device *dev);
-
/* Congestion management fairness mode */
#define CMNG_FNS_NONE 0
#define CMNG_FNS_MINMAX 1
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 7aee46983be4..f82dfff58243 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1,6 +1,6 @@
/* bnx2x_cmn.c: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,46 +32,6 @@
/**
- * bnx2x_bz_fp - zero content of the fastpath structure.
- *
- * @bp: driver handle
- * @index: fastpath index to be zeroed
- *
- * Makes sure the contents of the bp->fp[index].napi is kept
- * intact.
- */
-static inline void bnx2x_bz_fp(struct bnx2x *bp, int index)
-{
- struct bnx2x_fastpath *fp = &bp->fp[index];
- struct napi_struct orig_napi = fp->napi;
- /* bzero bnx2x_fastpath contents */
- memset(fp, 0, sizeof(*fp));
-
- /* Restore the NAPI object as it has been already initialized */
- fp->napi = orig_napi;
-
- fp->bp = bp;
- fp->index = index;
- if (IS_ETH_FP(fp))
- fp->max_cos = bp->max_cos;
- else
- /* Special queues support only one CoS */
- fp->max_cos = 1;
-
- /*
- * set the tpa flag for each queue. The tpa flag determines the queue
- * minimal size so it must be set prior to queue memory allocation
- */
- fp->disable_tpa = ((bp->flags & TPA_ENABLE_FLAG) == 0);
-
-#ifdef BCM_CNIC
- /* We don't want TPA on an FCoE L2 ring */
- if (IS_FCOE_FP(fp))
- fp->disable_tpa = 1;
-#endif
-}
-
-/**
* bnx2x_move_fp - move content of the fastpath structure.
*
* @bp: driver handle
@@ -249,13 +209,11 @@ static inline void bnx2x_update_last_max_sge(struct bnx2x_fastpath *fp,
fp->last_max_sge = idx;
}
-static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
- struct eth_fast_path_rx_cqe *fp_cqe)
+static inline void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
+ u16 sge_len,
+ struct eth_end_agg_rx_cqe *cqe)
{
struct bnx2x *bp = fp->bp;
- u16 sge_len = SGE_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) -
- le16_to_cpu(fp_cqe->len_on_bd)) >>
- SGE_PAGE_SHIFT;
u16 last_max, last_elem, first_elem;
u16 delta = 0;
u16 i;
@@ -266,15 +224,15 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
/* First mark all used pages */
for (i = 0; i < sge_len; i++)
BIT_VEC64_CLEAR_BIT(fp->sge_mask,
- RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[i])));
+ RX_SGE(le16_to_cpu(cqe->sgl_or_raw_data.sgl[i])));
DP(NETIF_MSG_RX_STATUS, "fp_cqe->sgl[%d] = %d\n",
- sge_len - 1, le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1]));
+ sge_len - 1, le16_to_cpu(cqe->sgl_or_raw_data.sgl[sge_len - 1]));
/* Here we assume that the last SGE index is the biggest */
prefetch((void *)(fp->sge_mask));
bnx2x_update_last_max_sge(fp,
- le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1]));
+ le16_to_cpu(cqe->sgl_or_raw_data.sgl[sge_len - 1]));
last_max = RX_SGE(fp->last_max_sge);
last_elem = last_max >> BIT_VEC64_ELEM_SHIFT;
@@ -368,6 +326,22 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
tpa_info->len_on_bd = le16_to_cpu(cqe->len_on_bd);
tpa_info->placement_offset = cqe->placement_offset;
tpa_info->rxhash = bnx2x_get_rxhash(bp, cqe);
+ if (fp->mode == TPA_MODE_GRO) {
+ u16 gro_size = le16_to_cpu(cqe->pkt_len_or_gro_seg_len);
+ tpa_info->full_page =
+ SGE_PAGE_SIZE * PAGES_PER_SGE / gro_size * gro_size;
+ /*
+ * FW 7.2.16 BUG workaround:
+ * if SGE size is (exactly) multiple gro_size
+ * fw will place one less frag on SGE.
+ * the calculation is done only for potentially
+ * dangerous MTUs.
+ */
+ if (unlikely(bp->gro_check))
+ if (!(SGE_PAGE_SIZE * PAGES_PER_SGE % gro_size))
+ tpa_info->full_page -= gro_size;
+ tpa_info->gro_size = gro_size;
+ }
#ifdef BNX2X_STOP_ON_ERROR
fp->tpa_queue_used |= (1 << queue);
@@ -424,25 +398,40 @@ static inline u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags,
}
static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
- u16 queue, struct sk_buff *skb,
+ struct bnx2x_agg_info *tpa_info,
+ u16 pages,
+ struct sk_buff *skb,
struct eth_end_agg_rx_cqe *cqe,
u16 cqe_idx)
{
struct sw_rx_page *rx_pg, old_rx_pg;
- u32 i, frag_len, frag_size, pages;
- int err;
- int j;
- struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
+ u32 i, frag_len, frag_size;
+ int err, j, frag_id = 0;
u16 len_on_bd = tpa_info->len_on_bd;
+ u16 full_page = 0, gro_size = 0;
frag_size = le16_to_cpu(cqe->pkt_len) - len_on_bd;
- pages = SGE_PAGE_ALIGN(frag_size) >> SGE_PAGE_SHIFT;
+
+ if (fp->mode == TPA_MODE_GRO) {
+ gro_size = tpa_info->gro_size;
+ full_page = tpa_info->full_page;
+ }
/* This is needed in order to enable forwarding support */
- if (frag_size)
+ if (frag_size) {
skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp,
tpa_info->parsing_flags, len_on_bd);
+ /* set for GRO */
+ if (fp->mode == TPA_MODE_GRO)
+ skb_shinfo(skb)->gso_type =
+ (GET_FLAG(tpa_info->parsing_flags,
+ PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) ==
+ PRS_FLAG_OVERETH_IPV6) ?
+ SKB_GSO_TCPV6 : SKB_GSO_TCPV4;
+ }
+
+
#ifdef BNX2X_STOP_ON_ERROR
if (pages > min_t(u32, 8, MAX_SKB_FRAGS)*SGE_PAGE_SIZE*PAGES_PER_SGE) {
BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n",
@@ -459,7 +448,12 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* FW gives the indices of the SGE as if the ring is an array
(meaning that "next" element will consume 2 indices) */
- frag_len = min(frag_size, (u32)(SGE_PAGE_SIZE*PAGES_PER_SGE));
+ if (fp->mode == TPA_MODE_GRO)
+ frag_len = min_t(u32, frag_size, (u32)full_page);
+ else /* LRO */
+ frag_len = min_t(u32, frag_size,
+ (u32)(SGE_PAGE_SIZE * PAGES_PER_SGE));
+
rx_pg = &fp->rx_page_ring[sge_idx];
old_rx_pg = *rx_pg;
@@ -475,9 +469,21 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
dma_unmap_page(&bp->pdev->dev,
dma_unmap_addr(&old_rx_pg, mapping),
SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE);
-
/* Add one frag and update the appropriate fields in the skb */
- skb_fill_page_desc(skb, j, old_rx_pg.page, 0, frag_len);
+ if (fp->mode == TPA_MODE_LRO)
+ skb_fill_page_desc(skb, j, old_rx_pg.page, 0, frag_len);
+ else { /* GRO */
+ int rem;
+ int offset = 0;
+ for (rem = frag_len; rem > 0; rem -= gro_size) {
+ int len = rem > gro_size ? gro_size : rem;
+ skb_fill_page_desc(skb, frag_id++,
+ old_rx_pg.page, offset, len);
+ if (offset)
+ get_page(old_rx_pg.page);
+ offset += len;
+ }
+ }
skb->data_len += frag_len;
skb->truesize += SGE_PAGE_SIZE * PAGES_PER_SGE;
@@ -489,18 +495,17 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
return 0;
}
-static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
- u16 queue, struct eth_end_agg_rx_cqe *cqe,
- u16 cqe_idx)
+static inline void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+ struct bnx2x_agg_info *tpa_info,
+ u16 pages,
+ struct eth_end_agg_rx_cqe *cqe,
+ u16 cqe_idx)
{
- struct bnx2x_agg_info *tpa_info = &fp->tpa_info[queue];
struct sw_rx_bd *rx_buf = &tpa_info->first_buf;
- u32 pad = tpa_info->placement_offset;
+ u8 pad = tpa_info->placement_offset;
u16 len = tpa_info->len_on_bd;
struct sk_buff *skb = NULL;
- u8 *data = rx_buf->data;
- /* alloc new skb */
- u8 *new_data;
+ u8 *new_data, *data = rx_buf->data;
u8 old_tpa_state = tpa_info->tpa_state;
tpa_info->tpa_state = BNX2X_TPA_STOP;
@@ -540,7 +545,8 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
skb->protocol = eth_type_trans(skb, bp->dev);
skb->ip_summed = CHECKSUM_UNNECESSARY;
- if (!bnx2x_fill_frag_skb(bp, fp, queue, skb, cqe, cqe_idx)) {
+ if (!bnx2x_fill_frag_skb(bp, fp, tpa_info, pages,
+ skb, cqe, cqe_idx)) {
if (tpa_info->parsing_flags & PARSING_FLAGS_VLAN)
__vlan_hwaccel_put_tag(skb, tpa_info->vlan_tag);
napi_gro_receive(&fp->napi, skb);
@@ -605,7 +611,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
struct eth_fast_path_rx_cqe *cqe_fp;
u8 cqe_fp_flags;
enum eth_rx_cqe_type cqe_fp_type;
- u16 len, pad;
+ u16 len, pad, queue;
u8 *data;
#ifdef BNX2X_STOP_ON_ERROR
@@ -626,17 +632,21 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
" queue %x vlan %x len %u\n", CQE_TYPE(cqe_fp_flags),
cqe_fp_flags, cqe_fp->status_flags,
le32_to_cpu(cqe_fp->rss_hash_result),
- le16_to_cpu(cqe_fp->vlan_tag), le16_to_cpu(cqe_fp->pkt_len));
+ le16_to_cpu(cqe_fp->vlan_tag),
+ le16_to_cpu(cqe_fp->pkt_len_or_gro_seg_len));
/* is this a slowpath msg? */
if (unlikely(CQE_TYPE_SLOW(cqe_fp_type))) {
bnx2x_sp_event(fp, cqe);
goto next_cqe;
}
+
rx_buf = &fp->rx_buf_ring[bd_cons];
data = rx_buf->data;
if (!CQE_TYPE_FAST(cqe_fp_type)) {
+ struct bnx2x_agg_info *tpa_info;
+ u16 frag_size, pages;
#ifdef BNX2X_STOP_ON_ERROR
/* sanity check */
if (fp->disable_tpa &&
@@ -656,28 +666,38 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
bnx2x_tpa_start(fp, queue,
bd_cons, bd_prod,
cqe_fp);
+
goto next_rx;
- } else {
- u16 queue =
- cqe->end_agg_cqe.queue_index;
- DP(NETIF_MSG_RX_STATUS,
- "calling tpa_stop on queue %d\n",
- queue);
- bnx2x_tpa_stop(bp, fp, queue,
- &cqe->end_agg_cqe,
- comp_ring_cons);
+ }
+ queue = cqe->end_agg_cqe.queue_index;
+ tpa_info = &fp->tpa_info[queue];
+ DP(NETIF_MSG_RX_STATUS,
+ "calling tpa_stop on queue %d\n",
+ queue);
+
+ frag_size = le16_to_cpu(cqe->end_agg_cqe.pkt_len) -
+ tpa_info->len_on_bd;
+
+ if (fp->mode == TPA_MODE_GRO)
+ pages = (frag_size + tpa_info->full_page - 1) /
+ tpa_info->full_page;
+ else
+ pages = SGE_PAGE_ALIGN(frag_size) >>
+ SGE_PAGE_SHIFT;
+
+ bnx2x_tpa_stop(bp, fp, tpa_info, pages,
+ &cqe->end_agg_cqe, comp_ring_cons);
#ifdef BNX2X_STOP_ON_ERROR
- if (bp->panic)
- return 0;
+ if (bp->panic)
+ return 0;
#endif
- bnx2x_update_sge_prod(fp, cqe_fp);
- goto next_cqe;
- }
+ bnx2x_update_sge_prod(fp, pages, &cqe->end_agg_cqe);
+ goto next_cqe;
}
/* non TPA */
- len = le16_to_cpu(cqe_fp->pkt_len);
+ len = le16_to_cpu(cqe_fp->pkt_len_or_gro_seg_len);
pad = cqe_fp->placement_offset;
dma_sync_single_for_cpu(&bp->pdev->dev,
dma_unmap_addr(rx_buf, mapping),
@@ -1766,12 +1786,27 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bnx2x_napi_enable(bp);
+ /* set pf load just before approaching the MCP */
+ bnx2x_set_pf_load(bp);
+
/* Send LOAD_REQUEST command to MCP
* Returns the type of LOAD command:
* if it is the first port to be initialized
* common blocks should be initialized, otherwise - not
*/
if (!BP_NOMCP(bp)) {
+ /* init fw_seq */
+ bp->fw_seq =
+ (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
+ DRV_MSG_SEQ_NUMBER_MASK);
+ BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
+
+ /* Get current FW pulse sequence */
+ bp->fw_drv_pulse_wr_seq =
+ (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb) &
+ DRV_PULSE_SEQ_MASK);
+ BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
+
load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
@@ -1782,6 +1817,29 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
rc = -EBUSY; /* other port in diagnostic mode */
LOAD_ERROR_EXIT(bp, load_error1);
}
+ if (load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP &&
+ load_code != FW_MSG_CODE_DRV_LOAD_COMMON) {
+ /* build FW version dword */
+ u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) +
+ (BCM_5710_FW_MINOR_VERSION << 8) +
+ (BCM_5710_FW_REVISION_VERSION << 16) +
+ (BCM_5710_FW_ENGINEERING_VERSION << 24);
+
+ /* read loaded FW from chip */
+ u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM);
+
+ DP(BNX2X_MSG_SP, "loaded fw %x, my fw %x",
+ loaded_fw, my_fw);
+
+ /* abort nic load if version mismatch */
+ if (my_fw != loaded_fw) {
+ BNX2X_ERR("bnx2x with FW %x already loaded, "
+ "which mismatches my %x FW. aborting",
+ loaded_fw, my_fw);
+ rc = -EBUSY;
+ LOAD_ERROR_EXIT(bp, load_error2);
+ }
+ }
} else {
int path = BP_PATH(bp);
@@ -1948,7 +2006,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if (bp->state == BNX2X_STATE_OPEN)
bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
#endif
- bnx2x_inc_load_cnt(bp);
/* Wait for all pending SP commands to complete */
if (!bnx2x_wait_sp_comp(bp, ~0x0UL)) {
@@ -1988,6 +2045,8 @@ load_error2:
bp->port.pmf = 0;
load_error1:
bnx2x_napi_disable(bp);
+ /* clear pf_load status, as it was already set */
+ bnx2x_clear_pf_load(bp);
load_error0:
bnx2x_free_mem(bp);
@@ -2045,6 +2104,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bnx2x_drv_pulse(bp);
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
+ bnx2x_save_statistics(bp);
/* Cleanup the chip if needed */
if (unload_mode != UNLOAD_RECOVERY)
@@ -2108,7 +2168,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
/* The last driver must disable a "close the gate" if there is no
* parity attention or "process kill" pending.
*/
- if (!bnx2x_dec_load_cnt(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
+ if (!bnx2x_clear_pf_load(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
bnx2x_disable_close_the_gate(bp);
return 0;
@@ -3007,6 +3067,7 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p)
return rc;
}
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
if (netif_running(dev))
@@ -3122,9 +3183,16 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
} else
#endif
if (!bp->rx_ring_size) {
+ u32 cfg = SHMEM_RD(bp,
+ dev_info.port_hw_config[BP_PORT(bp)].default_cfg);
rx_ring_size = MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp);
+ /* Dercease ring size for 1G functions */
+ if ((cfg & PORT_HW_CFG_NET_SERDES_IF_MASK) ==
+ PORT_HW_CFG_NET_SERDES_IF_SGMII)
+ rx_ring_size /= 10;
+
/* allocate at least number of buffers required by FW */
rx_ring_size = max_t(int, bp->disable_tpa ? MIN_RX_SIZE_NONTPA :
MIN_RX_SIZE_TPA, rx_ring_size);
@@ -3414,7 +3482,7 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
struct bnx2x *bp = netdev_priv(dev);
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
- pr_err("Handling parity error recovery. Try again later\n");
+ netdev_err(dev, "Handling parity error recovery. Try again later\n");
return -EAGAIN;
}
@@ -3428,17 +3496,21 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
*/
dev->mtu = new_mtu;
+ bp->gro_check = bnx2x_need_gro_check(new_mtu);
+
return bnx2x_reload_if_running(dev);
}
netdev_features_t bnx2x_fix_features(struct net_device *dev,
- netdev_features_t features)
+ netdev_features_t features)
{
struct bnx2x *bp = netdev_priv(dev);
/* TPA requires Rx CSUM offloading */
- if (!(features & NETIF_F_RXCSUM) || bp->disable_tpa)
+ if (!(features & NETIF_F_RXCSUM) || bp->disable_tpa) {
features &= ~NETIF_F_LRO;
+ features &= ~NETIF_F_GRO;
+ }
return features;
}
@@ -3454,6 +3526,11 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
else
flags &= ~TPA_ENABLE_FLAG;
+ if (features & NETIF_F_GRO)
+ flags |= GRO_ENABLE_FLAG;
+ else
+ flags &= ~GRO_ENABLE_FLAG;
+
if (features & NETIF_F_LOOPBACK) {
if (bp->link_params.loopback_mode != LOOPBACK_BMAC) {
bp->link_params.loopback_mode = LOOPBACK_BMAC;
@@ -3541,7 +3618,7 @@ int bnx2x_resume(struct pci_dev *pdev)
bp = netdev_priv(dev);
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
- pr_err("Handling parity error recovery. Try again later\n");
+ netdev_err(dev, "Handling parity error recovery. Try again later\n");
return -EAGAIN;
}
@@ -3557,8 +3634,6 @@ int bnx2x_resume(struct pci_dev *pdev)
bnx2x_set_power_state(bp, PCI_D0);
netif_device_attach(dev);
- /* Since the chip was reset, clear the FW sequence number */
- bp->fw_seq = 0;
rc = bnx2x_nic_load(bp, LOAD_OPEN);
rtnl_unlock();
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index bf27c54ff2e0..33aa7de24016 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -1,6 +1,6 @@
/* bnx2x_cmn.h: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -379,8 +379,8 @@ void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
unsigned long ramrod_flags);
/* Parity errors related */
-void bnx2x_inc_load_cnt(struct bnx2x *bp);
-u32 bnx2x_dec_load_cnt(struct bnx2x *bp);
+void bnx2x_set_pf_load(struct bnx2x *bp);
+bool bnx2x_clear_pf_load(struct bnx2x *bp);
bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print);
bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
void bnx2x_set_reset_in_progress(struct bnx2x *bp);
@@ -534,8 +534,9 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
*/
int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type);
#endif
+
netdev_features_t bnx2x_fix_features(struct net_device *dev,
- netdev_features_t features);
+ netdev_features_t features);
int bnx2x_set_features(struct net_device *dev, netdev_features_t features);
/**
@@ -614,8 +615,7 @@ static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func,
u32 igu_addr_ctl = IGU_REG_COMMAND_REG_CTRL;
u32 igu_addr_ack = IGU_REG_CSTORM_TYPE_0_SB_CLEANUP + (idu_sb_id/32)*4;
u32 sb_bit = 1 << (idu_sb_id%32);
- u32 func_encode = func |
- ((is_Pf == true ? 1 : 0) << IGU_FID_ENCODE_IS_PF_SHIFT);
+ u32 func_encode = func | (is_Pf ? 1 : 0) << IGU_FID_ENCODE_IS_PF_SHIFT;
u32 addr_encode = IGU_CMD_E2_PROD_UPD_BASE + idu_sb_id;
/* Not supported in BC mode */
@@ -984,10 +984,11 @@ static inline int bnx2x_func_start(struct bnx2x *bp)
/* Function parameters */
start_params->mf_mode = bp->mf_mode;
start_params->sd_vlan_tag = bp->mf_ov;
- if (CHIP_IS_E1x(bp))
- start_params->network_cos_mode = OVERRIDE_COS;
- else
+
+ if (CHIP_IS_E2(bp) || CHIP_IS_E3(bp))
start_params->network_cos_mode = STATIC_COS;
+ else /* CHIP_IS_E1X */
+ start_params->network_cos_mode = FW_WRR;
return bnx2x_func_state_change(bp, &func_params);
}
@@ -1491,6 +1492,105 @@ static inline u16 bnx2x_extract_max_cfg(struct bnx2x *bp, u32 mf_cfg)
return max_cfg;
}
+/* checks if HW supports GRO for given MTU */
+static inline bool bnx2x_mtu_allows_gro(int mtu)
+{
+ /* gro frags per page */
+ int fpp = SGE_PAGE_SIZE / (mtu - ETH_MAX_TPA_HEADER_SIZE);
+
+ /*
+ * 1. number of frags should not grow above MAX_SKB_FRAGS
+ * 2. frag must fit the page
+ */
+ return mtu <= SGE_PAGE_SIZE && (U_ETH_SGL_SIZE * fpp) <= MAX_SKB_FRAGS;
+}
+
+static inline bool bnx2x_need_gro_check(int mtu)
+{
+ return (SGE_PAGES / (mtu - ETH_MAX_TPA_HEADER_SIZE - 1)) !=
+ (SGE_PAGES / (mtu - ETH_MIN_TPA_HEADER_SIZE + 1));
+}
+
+/**
+ * bnx2x_bz_fp - zero content of the fastpath structure.
+ *
+ * @bp: driver handle
+ * @index: fastpath index to be zeroed
+ *
+ * Makes sure the contents of the bp->fp[index].napi is kept
+ * intact.
+ */
+static inline void bnx2x_bz_fp(struct bnx2x *bp, int index)
+{
+ struct bnx2x_fastpath *fp = &bp->fp[index];
+ struct napi_struct orig_napi = fp->napi;
+ /* bzero bnx2x_fastpath contents */
+ if (bp->stats_init)
+ memset(fp, 0, sizeof(*fp));
+ else {
+ /* Keep Queue statistics */
+ struct bnx2x_eth_q_stats *tmp_eth_q_stats;
+ struct bnx2x_eth_q_stats_old *tmp_eth_q_stats_old;
+
+ tmp_eth_q_stats = kzalloc(sizeof(struct bnx2x_eth_q_stats),
+ GFP_KERNEL);
+ if (tmp_eth_q_stats)
+ memcpy(tmp_eth_q_stats, &fp->eth_q_stats,
+ sizeof(struct bnx2x_eth_q_stats));
+
+ tmp_eth_q_stats_old =
+ kzalloc(sizeof(struct bnx2x_eth_q_stats_old),
+ GFP_KERNEL);
+ if (tmp_eth_q_stats_old)
+ memcpy(tmp_eth_q_stats_old, &fp->eth_q_stats_old,
+ sizeof(struct bnx2x_eth_q_stats_old));
+
+ memset(fp, 0, sizeof(*fp));
+
+ if (tmp_eth_q_stats) {
+ memcpy(&fp->eth_q_stats, tmp_eth_q_stats,
+ sizeof(struct bnx2x_eth_q_stats));
+ kfree(tmp_eth_q_stats);
+ }
+
+ if (tmp_eth_q_stats_old) {
+ memcpy(&fp->eth_q_stats_old, tmp_eth_q_stats_old,
+ sizeof(struct bnx2x_eth_q_stats_old));
+ kfree(tmp_eth_q_stats_old);
+ }
+
+ }
+
+ /* Restore the NAPI object as it has been already initialized */
+ fp->napi = orig_napi;
+
+ fp->bp = bp;
+ fp->index = index;
+ if (IS_ETH_FP(fp))
+ fp->max_cos = bp->max_cos;
+ else
+ /* Special queues support only one CoS */
+ fp->max_cos = 1;
+
+ /*
+ * set the tpa flag for each queue. The tpa flag determines the queue
+ * minimal size so it must be set prior to queue memory allocation
+ */
+ fp->disable_tpa = !(bp->flags & TPA_ENABLE_FLAG ||
+ (bp->flags & GRO_ENABLE_FLAG &&
+ bnx2x_mtu_allows_gro(bp->dev->mtu)));
+ if (bp->flags & TPA_ENABLE_FLAG)
+ fp->mode = TPA_MODE_LRO;
+ 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
+}
+
/**
* bnx2x_get_iscsi_info - update iSCSI params according to licensing info.
*
@@ -1539,7 +1639,7 @@ static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set)
{
if (SHMEM2_HAS(bp, drv_flags)) {
u32 drv_flags;
- bnx2x_acquire_hw_lock(bp, HW_LOCK_DRV_FLAGS);
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_DRV_FLAGS);
drv_flags = SHMEM2_RD(bp, drv_flags);
if (set)
@@ -1549,7 +1649,7 @@ static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set)
SHMEM2_WR(bp, drv_flags, drv_flags);
DP(NETIF_MSG_HW, "drv_flags 0x%08x\n", drv_flags);
- bnx2x_release_hw_lock(bp, HW_LOCK_DRV_FLAGS);
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_DRV_FLAGS);
}
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
index 5051cf3deb20..9a9bd3ab4793 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
@@ -1,6 +1,6 @@
/* bnx2x_dcb.c: Broadcom Everest network driver.
*
- * Copyright 2009-2011 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h
index 2ab9254e2d5e..06c7a0435948 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h
@@ -1,6 +1,6 @@
/* bnx2x_dcb.h: Broadcom Everest network driver.
*
- * Copyright 2009-2011 Broadcom Corporation
+ * Copyright 2009-2012 Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h
index b983825d0ee9..3e4cff9b1ebe 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h
@@ -1,6 +1,6 @@
/* bnx2x_dump.h: Broadcom Everest network driver.
*
- * Copyright (c) 2011 Broadcom Corporation
+ * Copyright (c) 2012 Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 31a8b38ab15e..9c24d536edef 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -1,6 +1,6 @@
/* bnx2x_ethtool.c: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -175,7 +175,11 @@ static const struct {
{ STATS_OFFSET32(total_tpa_aggregated_frames_hi),
8, STATS_FLAGS_FUNC, "tpa_aggregated_frames"},
{ STATS_OFFSET32(total_tpa_bytes_hi),
- 8, STATS_FLAGS_FUNC, "tpa_bytes"}
+ 8, STATS_FLAGS_FUNC, "tpa_bytes"},
+ { STATS_OFFSET32(recoverable_error),
+ 4, STATS_FLAGS_FUNC, "recoverable_errors" },
+ { STATS_OFFSET32(unrecoverable_error),
+ 4, STATS_FLAGS_FUNC, "unrecoverable_errors" },
};
#define BNX2X_NUM_STATS ARRAY_SIZE(bnx2x_stats_arr)
@@ -242,6 +246,34 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
else
cmd->autoneg = AUTONEG_DISABLE;
+ /* Publish LP advertised speeds and FC */
+ if (bp->link_vars.link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
+ u32 status = bp->link_vars.link_status;
+
+ cmd->lp_advertising |= ADVERTISED_Autoneg;
+ if (status & LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE)
+ cmd->lp_advertising |= ADVERTISED_Pause;
+ if (status & LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
+ cmd->lp_advertising |= ADVERTISED_Asym_Pause;
+
+ if (status & LINK_STATUS_LINK_PARTNER_10THD_CAPABLE)
+ cmd->lp_advertising |= ADVERTISED_10baseT_Half;
+ if (status & LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE)
+ cmd->lp_advertising |= ADVERTISED_10baseT_Full;
+ if (status & LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE)
+ cmd->lp_advertising |= ADVERTISED_100baseT_Half;
+ if (status & LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE)
+ cmd->lp_advertising |= ADVERTISED_100baseT_Full;
+ if (status & LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE)
+ cmd->lp_advertising |= ADVERTISED_1000baseT_Half;
+ if (status & LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE)
+ cmd->lp_advertising |= ADVERTISED_1000baseT_Full;
+ if (status & LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE)
+ cmd->lp_advertising |= ADVERTISED_2500baseX_Full;
+ if (status & LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE)
+ cmd->lp_advertising |= ADVERTISED_10000baseT_Full;
+ }
+
cmd->maxtxpkt = 0;
cmd->maxrxpkt = 0;
@@ -774,14 +806,8 @@ static void bnx2x_get_drvinfo(struct net_device *dev,
strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
phy_fw_ver[0] = '\0';
- if (bp->port.pmf) {
- bnx2x_acquire_phy_lock(bp);
- bnx2x_get_ext_phy_fw_version(&bp->link_params,
- (bp->state != BNX2X_STATE_CLOSED),
- phy_fw_ver, PHY_FW_VER_LEN);
- bnx2x_release_phy_lock(bp);
- }
-
+ bnx2x_get_ext_phy_fw_version(&bp->link_params,
+ phy_fw_ver, PHY_FW_VER_LEN);
strlcpy(info->fw_version, bp->fw_ver, sizeof(info->fw_version));
snprintf(info->fw_version + strlen(bp->fw_ver), 32 - strlen(bp->fw_ver),
"bc %d.%d.%d%s%s",
@@ -882,11 +908,27 @@ static int bnx2x_get_eeprom_len(struct net_device *dev)
return bp->common.flash_size;
}
+/* Per pf misc lock must be aquired before the per port mcp lock. Otherwise, had
+ * we done things the other way around, if two pfs from the same port would
+ * attempt to access nvram at the same time, we could run into a scenario such
+ * as:
+ * pf A takes the port lock.
+ * pf B succeeds in taking the same lock since they are from the same port.
+ * pf A takes the per pf misc lock. Performs eeprom access.
+ * pf A finishes. Unlocks the per pf misc lock.
+ * Pf B takes the lock and proceeds to perform it's own access.
+ * pf A unlocks the per port lock, while pf B is still working (!).
+ * mcp takes the per port lock and corrupts pf B's access (and/or has it's own
+ * acess corrupted by pf B).*
+ */
static int bnx2x_acquire_nvram_lock(struct bnx2x *bp)
{
int port = BP_PORT(bp);
int count, i;
- u32 val = 0;
+ u32 val;
+
+ /* acquire HW lock: protect against other PFs in PF Direct Assignment */
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_NVRAM);
/* adjust timeout for emulation/FPGA */
count = BNX2X_NVRAM_TIMEOUT_COUNT;
@@ -917,7 +959,7 @@ static int bnx2x_release_nvram_lock(struct bnx2x *bp)
{
int port = BP_PORT(bp);
int count, i;
- u32 val = 0;
+ u32 val;
/* adjust timeout for emulation/FPGA */
count = BNX2X_NVRAM_TIMEOUT_COUNT;
@@ -941,6 +983,8 @@ static int bnx2x_release_nvram_lock(struct bnx2x *bp)
return -EBUSY;
}
+ /* release HW lock: protect against other PFs in PF Direct Assignment */
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_NVRAM);
return 0;
}
@@ -1370,7 +1414,8 @@ static int bnx2x_set_ringparam(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev);
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
- pr_err("Handling parity error recovery. Try again later\n");
+ netdev_err(dev, "Handling parity error recovery. "
+ "Try again later\n");
return -EAGAIN;
}
@@ -1392,12 +1437,19 @@ static void bnx2x_get_pauseparam(struct net_device *dev,
{
struct bnx2x *bp = netdev_priv(dev);
int cfg_idx = bnx2x_get_link_cfg_idx(bp);
+ int cfg_reg;
+
epause->autoneg = (bp->link_params.req_flow_ctrl[cfg_idx] ==
BNX2X_FLOW_CTRL_AUTO);
- epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) ==
+ if (!epause->autoneg)
+ cfg_reg = bp->link_vars.flow_ctrl;
+ else
+ cfg_reg = bp->link_params.req_fc_auto_adv;
+
+ epause->rx_pause = ((cfg_reg & BNX2X_FLOW_CTRL_RX) ==
BNX2X_FLOW_CTRL_RX);
- epause->tx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX) ==
+ epause->tx_pause = ((cfg_reg & BNX2X_FLOW_CTRL_TX) ==
BNX2X_FLOW_CTRL_TX);
DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
@@ -1879,7 +1931,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
if (!CQE_TYPE_FAST(cqe_fp_type) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
goto test_loopback_rx_exit;
- len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
+ len = le16_to_cpu(cqe->fast_path_cqe.pkt_len_or_gro_seg_len);
if (len != pkt_size)
goto test_loopback_rx_exit;
@@ -1958,14 +2010,22 @@ static int bnx2x_test_nvram(struct bnx2x *bp)
{ 0x708, 0x70 }, /* manuf_key_info */
{ 0, 0 }
};
- __be32 buf[0x350 / 4];
- u8 *data = (u8 *)buf;
+ __be32 *buf;
+ u8 *data;
int i, rc;
u32 magic, crc;
if (BP_NOMCP(bp))
return 0;
+ buf = kmalloc(0x350, GFP_KERNEL);
+ if (!buf) {
+ DP(NETIF_MSG_PROBE, "kmalloc failed\n");
+ rc = -ENOMEM;
+ goto test_nvram_exit;
+ }
+ data = (u8 *)buf;
+
rc = bnx2x_nvram_read(bp, 0, data, 4);
if (rc) {
DP(NETIF_MSG_PROBE, "magic value read (rc %d)\n", rc);
@@ -1999,6 +2059,7 @@ static int bnx2x_test_nvram(struct bnx2x *bp)
}
test_nvram_exit:
+ kfree(buf);
return rc;
}
@@ -2024,7 +2085,8 @@ static void bnx2x_self_test(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev);
u8 is_serdes;
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
- pr_err("Handling parity error recovery. Try again later\n");
+ netdev_err(bp->dev, "Handling parity error recovery. "
+ "Try again later\n");
etest->flags |= ETH_TEST_FL_FAILED;
return;
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
index 998652a1b858..e5c5982ae06d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
@@ -1,6 +1,6 @@
/* bnx2x_fw_defs.h: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h
index f4a07fbaed05..4bed52ba300d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_file_hdr.h
@@ -1,6 +1,6 @@
/* bnx2x_fw_file_hdr.h: FW binary file header structure.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
index 3e30c8642c26..a1413ad7757d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
@@ -1,6 +1,6 @@
/* bnx2x_hsi.h: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -34,9 +34,10 @@ struct license_key {
};
-#define PORT_0 0
-#define PORT_1 1
-#define PORT_MAX 2
+#define PORT_0 0
+#define PORT_1 1
+#define PORT_MAX 2
+#define NVM_PATH_MAX 2
/****************************************************************************
* Shared HW configuration *
@@ -618,12 +619,6 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */
#define PORT_HW_CFG_ENABLE_CMS_DISABLED 0x00000000
#define PORT_HW_CFG_ENABLE_CMS_ENABLED 0x00200000
- /* Enable RJ45 magjack pair swapping on 10GBase-T PHY, 84833 only */
- #define PORT_HW_CFG_RJ45_PR_SWP_MASK 0x00400000
- #define PORT_HW_CFG_RJ45_PR_SWP_SHIFT 22
- #define PORT_HW_CFG_RJ45_PR_SWP_DISABLED 0x00000000
- #define PORT_HW_CFG_RJ45_PR_SWP_ENABLED 0x00400000
-
/* Determine the Serdes electrical interface */
#define PORT_HW_CFG_NET_SERDES_IF_MASK 0x0F000000
#define PORT_HW_CFG_NET_SERDES_IF_SHIFT 24
@@ -898,11 +893,6 @@ struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */
#define PORT_FEAT_CFG_DCBX_DISABLED 0x00000000
#define PORT_FEAT_CFG_DCBX_ENABLED 0x00000100
- #define PORT_FEAT_CFG_AUTOGREEN_MASK 0x00000200
- #define PORT_FEAT_CFG_AUTOGREEN_SHIFT 9
- #define PORT_FEAT_CFG_AUTOGREEN_DISABLED 0x00000000
- #define PORT_FEAT_CFG_AUTOGREEN_ENABLED 0x00000200
-
#define PORT_FEATURE_EN_SIZE_MASK 0x0f000000
#define PORT_FEATURE_EN_SIZE_SHIFT 24
#define PORT_FEATURE_WOL_ENABLED 0x01000000
@@ -1139,9 +1129,6 @@ struct shm_dev_info { /* size */
#define FW_ACK_NUM_OF_POLL (FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS)
-/* LED Blink rate that will achieve ~15.9Hz */
-#define LED_BLINK_RATE_VAL 480
-
/****************************************************************************
* Driver <-> FW Mailbox *
****************************************************************************/
@@ -1407,7 +1394,7 @@ struct port_mf_cfg {
#define PORT_MF_CFG_E1HOV_TAG_SHIFT 0
#define PORT_MF_CFG_E1HOV_TAG_DEFAULT PORT_MF_CFG_E1HOV_TAG_MASK
- u32 reserved[3];
+ u32 reserved[1];
};
@@ -1493,7 +1480,8 @@ struct func_ext_cfg {
struct mf_cfg {
struct shared_mf_cfg shared_mf_config; /* 0x4 */
- struct port_mf_cfg port_mf_config[PORT_MAX]; /* 0x10 * 2 = 0x20 */
+ /* 0x8*2*2=0x20 */
+ struct port_mf_cfg port_mf_config[NVM_PATH_MAX][PORT_MAX];
/* for all chips, there are 8 mf functions */
struct func_mf_cfg func_mf_config[E1H_FUNC_MAX]; /* 0x18 * 8 = 0xc0 */
/*
@@ -2002,6 +1990,7 @@ struct shmem2_region {
#define DRV_INFO_CONTROL_VER_SHIFT 0
#define DRV_INFO_CONTROL_OP_CODE_MASK 0x0000ff00
#define DRV_INFO_CONTROL_OP_CODE_SHIFT 8
+ u32 ibft_host_addr; /* initialized by option ROM */
};
@@ -2700,8 +2689,8 @@ union drv_info_to_mcp {
struct iscsi_stats_info iscsi_stat;
};
#define BCM_5710_FW_MAJOR_VERSION 7
-#define BCM_5710_FW_MINOR_VERSION 0
-#define BCM_5710_FW_REVISION_VERSION 29
+#define BCM_5710_FW_MINOR_VERSION 2
+#define BCM_5710_FW_REVISION_VERSION 16
#define BCM_5710_FW_ENGINEERING_VERSION 0
#define BCM_5710_FW_COMPILE_FLAGS 1
@@ -3308,8 +3297,10 @@ struct client_init_rx_data {
#define CLIENT_INIT_RX_DATA_TPA_EN_IPV4_SHIFT 0
#define CLIENT_INIT_RX_DATA_TPA_EN_IPV6 (0x1<<1)
#define CLIENT_INIT_RX_DATA_TPA_EN_IPV6_SHIFT 1
-#define CLIENT_INIT_RX_DATA_RESERVED5 (0x3F<<2)
-#define CLIENT_INIT_RX_DATA_RESERVED5_SHIFT 2
+#define CLIENT_INIT_RX_DATA_TPA_MODE (0x1<<2)
+#define CLIENT_INIT_RX_DATA_TPA_MODE_SHIFT 2
+#define CLIENT_INIT_RX_DATA_RESERVED5 (0x1F<<3)
+#define CLIENT_INIT_RX_DATA_RESERVED5_SHIFT 3
u8 vmqueue_mode_en_flg;
u8 extra_data_over_sgl_en_flg;
u8 cache_line_alignment_log_size;
@@ -3324,7 +3315,7 @@ struct client_init_rx_data {
u8 outer_vlan_removal_enable_flg;
u8 status_block_id;
u8 rx_sb_index_number;
- u8 reserved0;
+ u8 dont_verify_rings_pause_thr_flg;
u8 max_tpa_queues;
u8 silent_vlan_removal_flg;
__le16 max_bytes_on_bd;
@@ -3657,7 +3648,7 @@ struct eth_fast_path_rx_cqe {
u8 placement_offset;
__le32 rss_hash_result;
__le16 vlan_tag;
- __le16 pkt_len;
+ __le16 pkt_len_or_gro_seg_len;
__le16 len_on_bd;
struct parsing_flags pars_flags;
union eth_sgl_or_raw_data sgl_or_raw_data;
@@ -4215,6 +4206,15 @@ enum set_mac_action_type {
/*
+ * Ethernet TPA Modes
+ */
+enum tpa_mode {
+ TPA_LRO,
+ TPA_GRO,
+ MAX_TPA_MODE};
+
+
+/*
* tpa update ramrod data
*/
struct tpa_update_ramrod_data {
@@ -4224,7 +4224,8 @@ struct tpa_update_ramrod_data {
u8 max_tpa_queues;
u8 max_sges_for_packet;
u8 complete_on_both_clients;
- __le16 reserved1;
+ u8 dont_verify_rings_pause_thr_flg;
+ u8 tpa_mode;
__le16 sge_buff_size;
__le16 max_agg_size;
__le32 sge_page_base_lo;
@@ -4447,13 +4448,13 @@ enum common_spqe_cmd_id {
RAMROD_CMD_ID_COMMON_UNUSED,
RAMROD_CMD_ID_COMMON_FUNCTION_START,
RAMROD_CMD_ID_COMMON_FUNCTION_STOP,
+ RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE,
RAMROD_CMD_ID_COMMON_CFC_DEL,
RAMROD_CMD_ID_COMMON_CFC_DEL_WB,
RAMROD_CMD_ID_COMMON_STAT_QUERY,
RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
RAMROD_CMD_ID_COMMON_START_TRAFFIC,
RAMROD_CMD_ID_COMMON_RESERVED1,
- RAMROD_CMD_ID_COMMON_RESERVED2,
MAX_COMMON_SPQE_CMD_ID
};
@@ -4733,8 +4734,8 @@ enum event_ring_opcode {
EVENT_RING_OPCODE_MALICIOUS_VF,
EVENT_RING_OPCODE_FORWARD_SETUP,
EVENT_RING_OPCODE_RSS_UPDATE_RULES,
+ EVENT_RING_OPCODE_FUNCTION_UPDATE,
EVENT_RING_OPCODE_RESERVED1,
- EVENT_RING_OPCODE_RESERVED2,
EVENT_RING_OPCODE_SET_MAC,
EVENT_RING_OPCODE_CLASSIFICATION_RULES,
EVENT_RING_OPCODE_FILTERS_RULES,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
index 4d748e77d1ac..29f5c3cca31a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
@@ -1,7 +1,7 @@
/* bnx2x_init.h: Broadcom Everest network driver.
* Structures and macroes needed during the initialization.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
index 7ec1724753ad..fe66d902dc62 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
@@ -2,7 +2,7 @@
* Static functions needed during the initialization.
* This file is "included" in bnx2x_main.c.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -69,12 +69,12 @@ static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len,
{
if (bp->dmae_ready)
bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
- else if (wb)
- /*
- * Wide bus registers with no dmae need to be written
- * using indirect write.
- */
+
+ /* in E1 chips BIOS initiated ZLR may interrupt widebus writes */
+ else if (wb && CHIP_IS_E1(bp))
bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
+
+ /* in later chips PXP root complex handles BIOS ZLR w/o interrupting */
else
bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len);
}
@@ -99,8 +99,14 @@ static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
{
if (bp->dmae_ready)
bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
- else
+
+ /* in E1 chips BIOS initiated ZLR may interrupt widebus writes */
+ else if (CHIP_IS_E1(bp))
bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
+
+ /* in later chips PXP root complex handles BIOS ZLR w/o interrupting */
+ else
+ bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len);
}
static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr,
@@ -177,8 +183,14 @@ static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr,
{
if (bp->dmae_ready)
VIRT_WR_DMAE_LEN(bp, data, addr, len, 0);
- else
+
+ /* in E1 chips BIOS initiated ZLR may interrupt widebus writes */
+ else if (CHIP_IS_E1(bp))
bnx2x_init_ind_wr(bp, addr, data, len);
+
+ /* in later chips PXP root complex handles BIOS ZLR w/o interrupting */
+ else
+ bnx2x_init_str_wr(bp, addr, data, len);
}
static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo,
@@ -840,25 +852,15 @@ static void bnx2x_qm_init_cid_count(struct bnx2x *bp, int qm_cid_count,
}
}
-static void bnx2x_qm_set_ptr_table(struct bnx2x *bp, int qm_cid_count)
+static void bnx2x_qm_set_ptr_table(struct bnx2x *bp, int qm_cid_count,
+ u32 base_reg, u32 reg)
{
int i;
- u32 wb_data[2];
-
- wb_data[0] = wb_data[1] = 0;
-
+ u32 wb_data[2] = {0, 0};
for (i = 0; i < 4 * QM_QUEUES_PER_FUNC; i++) {
- REG_WR(bp, QM_REG_BASEADDR + i*4,
+ REG_WR(bp, base_reg + i*4,
qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC));
- bnx2x_init_ind_wr(bp, QM_REG_PTRTBL + i*8,
- wb_data, 2);
-
- if (CHIP_IS_E1H(bp)) {
- REG_WR(bp, QM_REG_BASEADDR_EXT_A + i*4,
- qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC));
- bnx2x_init_ind_wr(bp, QM_REG_PTRTBL_EXT_A + i*8,
- wb_data, 2);
- }
+ bnx2x_init_wr_wb(bp, reg + i*8, wb_data, 2);
}
}
@@ -873,7 +875,12 @@ static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
case INITOP_INIT:
/* set in the init-value array */
case INITOP_SET:
- bnx2x_qm_set_ptr_table(bp, qm_cid_count);
+ bnx2x_qm_set_ptr_table(bp, qm_cid_count,
+ QM_REG_BASEADDR, QM_REG_PTRTBL);
+ if (CHIP_IS_E1H(bp))
+ bnx2x_qm_set_ptr_table(bp, qm_cid_count,
+ QM_REG_BASEADDR_EXT_A,
+ QM_REG_PTRTBL_EXT_A);
break;
case INITOP_CLEAR:
break;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 2091e5dbbcdd..beb4cdbdb6e1 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -1,4 +1,4 @@
-/* Copyright 2008-2011 Broadcom Corporation
+/* Copyright 2008-2012 Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -1612,6 +1612,9 @@ static void bnx2x_umac_enable(struct link_params *params,
if (!(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
val |= UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE;
+ if (vars->duplex == DUPLEX_HALF)
+ val |= UMAC_COMMAND_CONFIG_REG_HD_ENA;
+
REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
udelay(50);
@@ -3635,45 +3638,50 @@ static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
}
-static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
- struct link_params *params,
- struct link_vars *vars)
+static void bnx2x_ext_phy_update_adv_fc(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
{
- struct bnx2x *bp = params->bp;
u16 ld_pause; /* local */
u16 lp_pause; /* link partner */
u16 pause_result;
- u8 ret = 0;
- /* read twice */
+ struct bnx2x *bp = params->bp;
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
+ bnx2x_cl22_read(bp, phy, 0x4, &ld_pause);
+ bnx2x_cl22_read(bp, phy, 0x5, &lp_pause);
+ } else {
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_ADV_PAUSE, &ld_pause);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
+ }
+ pause_result = (ld_pause &
+ MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
+ pause_result |= (lp_pause &
+ MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
+ DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n", pause_result);
+ bnx2x_pause_resolve(vars, pause_result);
+}
+static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars)
+{
+ u8 ret = 0;
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-
- if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+ if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO) {
+ /* Update the advertised flow-controled of LD/LP in AN */
+ if (phy->req_line_speed == SPEED_AUTO_NEG)
+ bnx2x_ext_phy_update_adv_fc(phy, params, vars);
+ /* But set the flow-control result as the requested one */
vars->flow_ctrl = phy->req_flow_ctrl;
- else if (phy->req_line_speed != SPEED_AUTO_NEG)
+ } else if (phy->req_line_speed != SPEED_AUTO_NEG)
vars->flow_ctrl = params->req_fc_auto_adv;
else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
ret = 1;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
- bnx2x_cl22_read(bp, phy,
- 0x4, &ld_pause);
- bnx2x_cl22_read(bp, phy,
- 0x5, &lp_pause);
- } else {
- bnx2x_cl45_read(bp, phy,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV_PAUSE, &ld_pause);
- bnx2x_cl45_read(bp, phy,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
- }
- pause_result = (ld_pause &
- MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
- pause_result |= (lp_pause &
- MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
- DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
- pause_result);
- bnx2x_pause_resolve(vars, pause_result);
+ bnx2x_ext_phy_update_adv_fc(phy, params, vars);
}
return ret;
}
@@ -3785,7 +3793,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
/* Enable Autoneg */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
- MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1000);
+ MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
}
@@ -5216,22 +5224,69 @@ static int bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
return 0;
}
+static void bnx2x_update_adv_fc(struct bnx2x_phy *phy,
+ struct link_params *params,
+ struct link_vars *vars,
+ u32 gp_status)
+{
+ u16 ld_pause; /* local driver */
+ u16 lp_pause; /* link partner */
+ u16 pause_result;
+ struct bnx2x *bp = params->bp;
+ if ((gp_status &
+ (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
+ MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
+ (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
+ MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
+
+ CL22_RD_OVER_CL45(bp, phy,
+ MDIO_REG_BANK_CL73_IEEEB1,
+ MDIO_CL73_IEEEB1_AN_ADV1,
+ &ld_pause);
+ CL22_RD_OVER_CL45(bp, phy,
+ MDIO_REG_BANK_CL73_IEEEB1,
+ MDIO_CL73_IEEEB1_AN_LP_ADV1,
+ &lp_pause);
+ pause_result = (ld_pause &
+ MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK) >> 8;
+ pause_result |= (lp_pause &
+ MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK) >> 10;
+ DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n", pause_result);
+ } else {
+ CL22_RD_OVER_CL45(bp, phy,
+ MDIO_REG_BANK_COMBO_IEEE0,
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
+ &ld_pause);
+ CL22_RD_OVER_CL45(bp, phy,
+ MDIO_REG_BANK_COMBO_IEEE0,
+ MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
+ &lp_pause);
+ pause_result = (ld_pause &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
+ pause_result |= (lp_pause &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
+ DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n", pause_result);
+ }
+ bnx2x_pause_resolve(vars, pause_result);
+
+}
+
static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars,
u32 gp_status)
{
struct bnx2x *bp = params->bp;
- u16 ld_pause; /* local driver */
- u16 lp_pause; /* link partner */
- u16 pause_result;
-
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
/* resolve from gp_status in case of AN complete and not sgmii */
- if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
+ if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO) {
+ /* Update the advertised flow-controled of LD/LP in AN */
+ if (phy->req_line_speed == SPEED_AUTO_NEG)
+ bnx2x_update_adv_fc(phy, params, vars, gp_status);
+ /* But set the flow-control result as the requested one */
vars->flow_ctrl = phy->req_flow_ctrl;
- else if (phy->req_line_speed != SPEED_AUTO_NEG)
+ } else if (phy->req_line_speed != SPEED_AUTO_NEG)
vars->flow_ctrl = params->req_fc_auto_adv;
else if ((gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
(!(vars->phy_flags & PHY_SGMII_FLAG))) {
@@ -5239,45 +5294,7 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
vars->flow_ctrl = params->req_fc_auto_adv;
return;
}
- if ((gp_status &
- (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
- MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
- (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
- MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
-
- CL22_RD_OVER_CL45(bp, phy,
- MDIO_REG_BANK_CL73_IEEEB1,
- MDIO_CL73_IEEEB1_AN_ADV1,
- &ld_pause);
- CL22_RD_OVER_CL45(bp, phy,
- MDIO_REG_BANK_CL73_IEEEB1,
- MDIO_CL73_IEEEB1_AN_LP_ADV1,
- &lp_pause);
- pause_result = (ld_pause &
- MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK)
- >> 8;
- pause_result |= (lp_pause &
- MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK)
- >> 10;
- DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n",
- pause_result);
- } else {
- CL22_RD_OVER_CL45(bp, phy,
- MDIO_REG_BANK_COMBO_IEEE0,
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
- &ld_pause);
- CL22_RD_OVER_CL45(bp, phy,
- MDIO_REG_BANK_COMBO_IEEE0,
- MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
- &lp_pause);
- pause_result = (ld_pause &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
- pause_result |= (lp_pause &
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
- DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n",
- pause_result);
- }
- bnx2x_pause_resolve(vars, pause_result);
+ bnx2x_update_adv_fc(phy, params, vars, gp_status);
}
DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
}
@@ -5496,6 +5513,33 @@ static int bnx2x_link_settings_status(struct bnx2x_phy *phy,
}
}
+ /* Read LP advertised speeds*/
+ if (SINGLE_MEDIA_DIRECT(params) &&
+ (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)) {
+ u16 val;
+
+ CL22_RD_OVER_CL45(bp, phy, MDIO_REG_BANK_CL73_IEEEB1,
+ MDIO_CL73_IEEEB1_AN_LP_ADV2, &val);
+
+ if (val & MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX)
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
+ if (val & (MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 |
+ MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
+
+ CL22_RD_OVER_CL45(bp, phy, MDIO_REG_BANK_OVER_1G,
+ MDIO_OVER_1G_LP_UP1, &val);
+
+ if (val & MDIO_OVER_1G_UP1_2_5G)
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE;
+ if (val & (MDIO_OVER_1G_UP1_10G | MDIO_OVER_1G_UP1_10GH))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
+ }
+
DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x link_status 0x%x\n",
vars->duplex, vars->flow_ctrl, vars->link_status);
return rc;
@@ -5553,6 +5597,34 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
}
}
+ if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) &&
+ SINGLE_MEDIA_DIRECT(params)) {
+ u16 val;
+
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_LP_AUTO_NEG2, &val);
+
+ if (val & MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX)
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
+ if (val & (MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 |
+ MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
+
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_DIGITAL3_LP_UP1, &val);
+
+ if (val & MDIO_OVER_1G_UP1_2_5G)
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE;
+ if (val & (MDIO_OVER_1G_UP1_10G | MDIO_OVER_1G_UP1_10GH))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
+
+ }
+
+
if (lane < 2) {
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_GP2_STATUS_GP_2_2, &gp_speed);
@@ -5970,8 +6042,8 @@ static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
return 0;
}
-int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
- u8 *version, u16 len)
+int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 *version,
+ u16 len)
{
struct bnx2x *bp;
u32 spirom_ver = 0;
@@ -6418,7 +6490,9 @@ static int bnx2x_update_link_down(struct link_params *params,
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_PARALLEL_DETECTION_FLAG_MASK |
+ LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE |
+ LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE);
vars->line_speed = 0;
bnx2x_update_mng(params, vars->link_status);
@@ -7367,6 +7441,19 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
bnx2x_8073_resolve_fc(phy, params, vars);
vars->duplex = DUPLEX_FULL;
}
+
+ if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_LP_AUTO_NEG2, &val1);
+
+ if (val1 & (1<<5))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
+ if (val1 & (1<<7))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
+ }
+
return link_up;
}
@@ -9405,13 +9492,8 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
{
struct bnx2x *bp = params->bp;
u16 autoneg_val, an_1000_val, an_10_100_val, an_10g_val;
- u16 tmp_req_line_speed;
- tmp_req_line_speed = phy->req_line_speed;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
- if (phy->req_line_speed == SPEED_10000)
- phy->req_line_speed = SPEED_AUTO_NEG;
- } else {
+ if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
/* Save spirom version */
bnx2x_save_848xx_spirom_version(phy, bp, params->port);
}
@@ -9555,8 +9637,6 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
1);
- phy->req_line_speed = tmp_req_line_speed;
-
return 0;
}
@@ -9948,6 +10028,42 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "BCM84823: link speed is %d\n",
vars->line_speed);
bnx2x_ext_phy_resolve_fc(phy, params, vars);
+
+ /* Read LP advertised speeds */
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_CL37_FC_LP, &val);
+ if (val & (1<<5))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_10THD_CAPABLE;
+ if (val & (1<<6))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE;
+ if (val & (1<<7))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE;
+ if (val & (1<<8))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE;
+ if (val & (1<<9))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_100T4_CAPABLE;
+
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_1000T_STATUS, &val);
+
+ if (val & (1<<10))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE;
+ if (val & (1<<11))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
+
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_MASTER_STATUS, &val);
+
+ if (val & (1<<11))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
}
return link_up;
@@ -10571,6 +10687,35 @@ static u8 bnx2x_54618se_read_status(struct bnx2x_phy *phy,
}
bnx2x_ext_phy_resolve_fc(phy, params, vars);
+
+ if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
+ /* report LP advertised speeds */
+ bnx2x_cl22_read(bp, phy, 0x5, &val);
+
+ if (val & (1<<5))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_10THD_CAPABLE;
+ if (val & (1<<6))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE;
+ if (val & (1<<7))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE;
+ if (val & (1<<8))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE;
+ if (val & (1<<9))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_100T4_CAPABLE;
+
+ bnx2x_cl22_read(bp, phy, 0xa, &val);
+ if (val & (1<<10))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE;
+ if (val & (1<<11))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE;
+ }
}
return link_up;
}
@@ -10699,6 +10844,11 @@ static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
val2, (val2 & (1<<14)));
bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
bnx2x_ext_phy_resolve_fc(phy, params, vars);
+
+ /* read LP advertised speeds */
+ if (val2 & (1<<11))
+ vars->link_status |=
+ LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE;
}
return link_up;
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
index e02a68a7fb85..7ba557a610da 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
@@ -1,4 +1,4 @@
-/* Copyright 2008-2011 Broadcom Corporation
+/* Copyright 2008-2012 Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -337,8 +337,8 @@ int bnx2x_phy_write(struct link_params *params, u8 phy_addr,
void bnx2x_link_status_update(struct link_params *input,
struct link_vars *output);
/* returns string representing the fw_version of the external phy */
-int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
- u8 *version, u16 len);
+int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 *version,
+ u16 len);
/* Set/Unset the led
Basically, the CLC takes care of the led for the link, but in case one needs
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 254521319150..b4afef60a25b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -1,6 +1,6 @@
/* bnx2x_main.c: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -464,7 +464,9 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp,
while ((*wb_comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) {
DP(BNX2X_MSG_OFF, "wb_comp 0x%08x\n", *wb_comp);
- if (!cnt) {
+ if (!cnt ||
+ (bp->recovery_state != BNX2X_RECOVERY_DONE &&
+ bp->recovery_state != BNX2X_RECOVERY_NIC_LOADING)) {
BNX2X_ERR("DMAE timeout!\n");
rc = DMAE_TIMEOUT;
goto unlock;
@@ -494,9 +496,13 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
if (!bp->dmae_ready) {
u32 *data = bnx2x_sp(bp, wb_data[0]);
- DP(BNX2X_MSG_OFF, "DMAE is not ready (dst_addr %08x len32 %d)"
- " using indirect\n", dst_addr, len32);
- bnx2x_init_ind_wr(bp, dst_addr, data, len32);
+ DP(BNX2X_MSG_OFF,
+ "DMAE is not ready (dst_addr %08x len32 %d) using indirect\n",
+ dst_addr, len32);
+ if (CHIP_IS_E1(bp))
+ bnx2x_init_ind_wr(bp, dst_addr, data, len32);
+ else
+ bnx2x_init_str_wr(bp, dst_addr, data, len32);
return;
}
@@ -524,10 +530,16 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
u32 *data = bnx2x_sp(bp, wb_data[0]);
int i;
- DP(BNX2X_MSG_OFF, "DMAE is not ready (src_addr %08x len32 %d)"
- " using indirect\n", src_addr, len32);
- for (i = 0; i < len32; i++)
- data[i] = bnx2x_reg_rd_ind(bp, src_addr + i*4);
+ if (CHIP_IS_E1(bp)) {
+ DP(BNX2X_MSG_OFF,
+ "DMAE is not ready (src_addr %08x len32 %d) using indirect\n",
+ src_addr, len32);
+ for (i = 0; i < len32; i++)
+ data[i] = bnx2x_reg_rd_ind(bp, src_addr + i*4);
+ } else
+ for (i = 0; i < len32; i++)
+ data[i] = REG_RD(bp, src_addr + i*4);
+
return;
}
@@ -768,6 +780,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
#endif
bp->stats_state = STATS_STATE_DISABLED;
+ bp->eth_stats.unrecoverable_error++;
DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
BNX2X_ERR("begin crash dump -----------------\n");
@@ -1003,8 +1016,8 @@ void bnx2x_panic_dump(struct bnx2x *bp)
* initialization.
*/
#define FLR_WAIT_USEC 10000 /* 10 miliseconds */
-#define FLR_WAIT_INTERAVAL 50 /* usec */
-#define FLR_POLL_CNT (FLR_WAIT_USEC/FLR_WAIT_INTERAVAL) /* 200 */
+#define FLR_WAIT_INTERVAL 50 /* usec */
+#define FLR_POLL_CNT (FLR_WAIT_USEC/FLR_WAIT_INTERVAL) /* 200 */
struct pbf_pN_buf_regs {
int pN;
@@ -1037,7 +1050,7 @@ static void bnx2x_pbf_pN_buf_flushed(struct bnx2x *bp,
while ((crd != init_crd) && ((u32)SUB_S32(crd_freed, crd_freed_start) <
(init_crd - crd_start))) {
if (cur_cnt--) {
- udelay(FLR_WAIT_INTERAVAL);
+ udelay(FLR_WAIT_INTERVAL);
crd = REG_RD(bp, regs->crd);
crd_freed = REG_RD(bp, regs->crd_freed);
} else {
@@ -1051,7 +1064,7 @@ static void bnx2x_pbf_pN_buf_flushed(struct bnx2x *bp,
}
}
DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF tx buffer[%d]\n",
- poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN);
+ poll_count-cur_cnt, FLR_WAIT_INTERVAL, regs->pN);
}
static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp,
@@ -1069,7 +1082,7 @@ static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp,
while (occup && ((u32)SUB_S32(freed, freed_start) < to_free)) {
if (cur_cnt--) {
- udelay(FLR_WAIT_INTERAVAL);
+ udelay(FLR_WAIT_INTERVAL);
occup = REG_RD(bp, regs->lines_occup);
freed = REG_RD(bp, regs->lines_freed);
} else {
@@ -1083,7 +1096,7 @@ static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp,
}
}
DP(BNX2X_MSG_SP, "Waited %d*%d usec for PBF cmd queue[%d]\n",
- poll_count-cur_cnt, FLR_WAIT_INTERAVAL, regs->pN);
+ poll_count-cur_cnt, FLR_WAIT_INTERVAL, regs->pN);
}
static inline u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg,
@@ -1093,7 +1106,7 @@ static inline u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg,
u32 val;
while ((val = REG_RD(bp, reg)) != expected && cur_cnt--)
- udelay(FLR_WAIT_INTERAVAL);
+ udelay(FLR_WAIT_INTERVAL);
return val;
}
@@ -1206,7 +1219,7 @@ static inline int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func,
int ret = 0;
if (REG_RD(bp, comp_addr)) {
- BNX2X_ERR("Cleanup complete is not 0\n");
+ BNX2X_ERR("Cleanup complete was not 0 before sending\n");
return 1;
}
@@ -1215,7 +1228,7 @@ static inline int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func,
op_gen.command |= OP_GEN_AGG_VECT(clnup_func);
op_gen.command |= 1 << SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT;
- DP(BNX2X_MSG_SP, "FW Final cleanup\n");
+ DP(BNX2X_MSG_SP, "sending FW Final cleanup\n");
REG_WR(bp, XSDM_REG_OPERATION_GEN, op_gen.command);
if (bnx2x_flr_clnup_reg_poll(bp, comp_addr, 1, poll_cnt) != 1) {
@@ -1330,6 +1343,7 @@ static int bnx2x_pf_flr_clnup(struct bnx2x *bp)
REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
/* Poll HW usage counters */
+ DP(BNX2X_MSG_SP, "Polling usage counters\n");
if (bnx2x_poll_hw_usage_counters(bp, poll_cnt))
return -EBUSY;
@@ -2688,6 +2702,8 @@ static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
if (!fp->disable_tpa) {
__set_bit(BNX2X_Q_FLG_TPA, &flags);
__set_bit(BNX2X_Q_FLG_TPA_IPV6, &flags);
+ if (fp->mode == TPA_MODE_GRO)
+ __set_bit(BNX2X_Q_FLG_TPA_GRO, &flags);
}
if (leading) {
@@ -3709,11 +3725,11 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
*/
void bnx2x_set_reset_global(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-
+ u32 val;
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
+ val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val | BNX2X_GLOBAL_RESET_BIT);
- barrier();
- mmiowb();
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
}
/*
@@ -3723,11 +3739,11 @@ void bnx2x_set_reset_global(struct bnx2x *bp)
*/
static inline void bnx2x_clear_reset_global(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
-
+ u32 val;
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
+ val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~BNX2X_GLOBAL_RESET_BIT));
- barrier();
- mmiowb();
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
}
/*
@@ -3750,15 +3766,17 @@ static inline bool bnx2x_reset_is_global(struct bnx2x *bp)
*/
static inline void bnx2x_set_reset_done(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 val;
u32 bit = BP_PATH(bp) ?
BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
+ val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
/* Clear the bit */
val &= ~bit;
REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
- barrier();
- mmiowb();
+
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
}
/*
@@ -3768,15 +3786,16 @@ static inline void bnx2x_set_reset_done(struct bnx2x *bp)
*/
void bnx2x_set_reset_in_progress(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 val;
u32 bit = BP_PATH(bp) ?
BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT;
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
+ val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
/* Set the bit */
val |= bit;
REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
- barrier();
- mmiowb();
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
}
/*
@@ -3794,25 +3813,28 @@ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine)
}
/*
- * Increment the load counter for the current engine.
+ * set pf load for the current pf.
*
* should be run under rtnl lock
*/
-void bnx2x_inc_load_cnt(struct bnx2x *bp)
+void bnx2x_set_pf_load(struct bnx2x *bp)
{
- u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 val1, val;
u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
BNX2X_PATH0_LOAD_CNT_MASK;
u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT :
BNX2X_PATH0_LOAD_CNT_SHIFT;
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
+ val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+
DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
/* get the current counter value */
val1 = (val & mask) >> shift;
- /* increment... */
- val1++;
+ /* set bit of that PF */
+ val1 |= (1 << bp->pf_num);
/* clear the old value */
val &= ~mask;
@@ -3821,34 +3843,35 @@ void bnx2x_inc_load_cnt(struct bnx2x *bp)
val |= ((val1 << shift) & mask);
REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
- barrier();
- mmiowb();
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
}
/**
- * bnx2x_dec_load_cnt - decrement the load counter
+ * bnx2x_clear_pf_load - clear pf load mark
*
* @bp: driver handle
*
* Should be run under rtnl lock.
* Decrements the load counter for the current engine. Returns
- * the new counter value.
+ * whether other functions are still loaded
*/
-u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
+bool bnx2x_clear_pf_load(struct bnx2x *bp)
{
- u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 val1, val;
u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
BNX2X_PATH0_LOAD_CNT_MASK;
u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT :
BNX2X_PATH0_LOAD_CNT_SHIFT;
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
+ val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val);
/* get the current counter value */
val1 = (val & mask) >> shift;
- /* decrement... */
- val1--;
+ /* clear bit of that PF */
+ val1 &= ~(1 << bp->pf_num);
/* clear the old value */
val &= ~mask;
@@ -3857,18 +3880,16 @@ u32 bnx2x_dec_load_cnt(struct bnx2x *bp)
val |= ((val1 << shift) & mask);
REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val);
- barrier();
- mmiowb();
-
- return val1;
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
+ return val1 != 0;
}
/*
- * Read the load counter for the current engine.
+ * Read the load status for the current engine.
*
* should be run under rtnl lock
*/
-static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine)
+static inline bool bnx2x_get_load_status(struct bnx2x *bp, int engine)
{
u32 mask = (engine ? BNX2X_PATH1_LOAD_CNT_MASK :
BNX2X_PATH0_LOAD_CNT_MASK);
@@ -3880,23 +3901,23 @@ static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine)
val = (val & mask) >> shift;
- DP(NETIF_MSG_HW, "load_cnt for engine %d = %d\n", engine, val);
+ DP(NETIF_MSG_HW, "load mask for engine %d = 0x%x\n", engine, val);
- return val;
+ return val != 0;
}
/*
- * Reset the load counter for the current engine.
- *
- * should be run under rtnl lock
+ * Reset the load status for the current engine.
*/
-static inline void bnx2x_clear_load_cnt(struct bnx2x *bp)
+static inline void bnx2x_clear_load_status(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
+ u32 val;
u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
- BNX2X_PATH0_LOAD_CNT_MASK);
-
+ BNX2X_PATH0_LOAD_CNT_MASK);
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
+ val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~mask));
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
}
static inline void _print_next_block(int idx, const char *blk)
@@ -5410,6 +5431,7 @@ static void bnx2x_init_eth_fp(struct bnx2x *bp, int fp_idx)
/* init shortcut */
fp->ustorm_rx_prods_offset = bnx2x_rx_ustorm_prods_offset(fp);
+
/* Setup SB indicies */
fp->rx_cons_sb = BNX2X_RX_SB_INDEX;
@@ -6674,13 +6696,16 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
u16 cdu_ilt_start;
u32 addr, val;
u32 main_mem_base, main_mem_size, main_mem_prty_clr;
- int i, main_mem_width;
+ int i, main_mem_width, rc;
DP(BNX2X_MSG_MCP, "starting func init func %d\n", func);
/* FLR cleanup - hmmm */
- if (!CHIP_IS_E1x(bp))
- bnx2x_pf_flr_clnup(bp);
+ if (!CHIP_IS_E1x(bp)) {
+ rc = bnx2x_pf_flr_clnup(bp);
+ if (rc)
+ return rc;
+ }
/* set MSI reconfigure capability */
if (bp->common.int_block == INT_BLOCK_HC) {
@@ -7089,6 +7114,11 @@ 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;
@@ -8445,13 +8475,38 @@ int bnx2x_leader_reset(struct bnx2x *bp)
{
int rc = 0;
bool global = bnx2x_reset_is_global(bp);
+ u32 load_code;
+
+ /* if not going to reset MCP - load "fake" driver to reset HW while
+ * driver is owner of the HW
+ */
+ if (!global && !BP_NOMCP(bp)) {
+ load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
+ if (!load_code) {
+ BNX2X_ERR("MCP response failure, aborting\n");
+ rc = -EAGAIN;
+ goto exit_leader_reset;
+ }
+ if ((load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) &&
+ (load_code != FW_MSG_CODE_DRV_LOAD_COMMON)) {
+ BNX2X_ERR("MCP unexpected resp, aborting\n");
+ rc = -EAGAIN;
+ goto exit_leader_reset2;
+ }
+ load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0);
+ if (!load_code) {
+ BNX2X_ERR("MCP response failure, aborting\n");
+ rc = -EAGAIN;
+ goto exit_leader_reset2;
+ }
+ }
/* Try to recover after the failure */
if (bnx2x_process_kill(bp, global)) {
netdev_err(bp->dev, "Something bad had happen on engine %d! "
"Aii!\n", BP_PATH(bp));
rc = -EAGAIN;
- goto exit_leader_reset;
+ goto exit_leader_reset2;
}
/*
@@ -8462,6 +8517,12 @@ int bnx2x_leader_reset(struct bnx2x *bp)
if (global)
bnx2x_clear_reset_global(bp);
+exit_leader_reset2:
+ /* unload "fake driver" if it was loaded */
+ if (!global && !BP_NOMCP(bp)) {
+ bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+ }
exit_leader_reset:
bp->is_leader = 0;
bnx2x_release_leader_lock(bp);
@@ -8498,13 +8559,16 @@ static inline void bnx2x_recovery_failed(struct bnx2x *bp)
static void bnx2x_parity_recover(struct bnx2x *bp)
{
bool global = false;
+ u32 error_recovered, error_unrecovered;
+ bool is_parity;
DP(NETIF_MSG_HW, "Handling parity\n");
while (1) {
switch (bp->recovery_state) {
case BNX2X_RECOVERY_INIT:
DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_INIT\n");
- bnx2x_chk_parity_attn(bp, &global, false);
+ is_parity = bnx2x_chk_parity_attn(bp, &global, false);
+ WARN_ON(!is_parity);
/* Try to get a LEADER_LOCK HW lock */
if (bnx2x_trylock_leader_lock(bp)) {
@@ -8528,15 +8592,6 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
bp->recovery_state = BNX2X_RECOVERY_WAIT;
- /*
- * Reset MCP command sequence number and MCP mail box
- * sequence as we are going to reset the MCP.
- */
- if (global) {
- bp->fw_seq = 0;
- bp->fw_drv_pulse_wr_seq = 0;
- }
-
/* Ensure "is_leader", MCP command sequence and
* "recovery_state" update values are seen on other
* CPUs.
@@ -8548,10 +8603,10 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
DP(NETIF_MSG_HW, "State is BNX2X_RECOVERY_WAIT\n");
if (bp->is_leader) {
int other_engine = BP_PATH(bp) ? 0 : 1;
- u32 other_load_counter =
- bnx2x_get_load_cnt(bp, other_engine);
- u32 load_counter =
- bnx2x_get_load_cnt(bp, BP_PATH(bp));
+ bool other_load_status =
+ bnx2x_get_load_status(bp, other_engine);
+ bool load_status =
+ bnx2x_get_load_status(bp, BP_PATH(bp));
global = bnx2x_reset_is_global(bp);
/*
@@ -8562,8 +8617,8 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
* the the gates will remain closed for that
* engine.
*/
- if (load_counter ||
- (global && other_load_counter)) {
+ if (load_status ||
+ (global && other_load_status)) {
/* Wait until all other functions get
* down.
*/
@@ -8620,13 +8675,34 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
return;
}
- if (bnx2x_nic_load(bp, LOAD_NORMAL))
- bnx2x_recovery_failed(bp);
- else {
+ error_recovered =
+ bp->eth_stats.recoverable_error;
+ error_unrecovered =
+ bp->eth_stats.unrecoverable_error;
+ bp->recovery_state =
+ BNX2X_RECOVERY_NIC_LOADING;
+ if (bnx2x_nic_load(bp, LOAD_NORMAL)) {
+ error_unrecovered++;
+ netdev_err(bp->dev,
+ "Recovery failed. "
+ "Power cycle "
+ "needed\n");
+ /* Disconnect this device */
+ netif_device_detach(bp->dev);
+ /* Shut down the power */
+ bnx2x_set_power_state(
+ bp, PCI_D3hot);
+ smp_mb();
+ } else {
bp->recovery_state =
BNX2X_RECOVERY_DONE;
+ error_recovered++;
smp_mb();
}
+ bp->eth_stats.recoverable_error =
+ error_recovered;
+ bp->eth_stats.unrecoverable_error =
+ error_unrecovered;
return;
}
@@ -8637,6 +8713,8 @@ static void bnx2x_parity_recover(struct bnx2x *bp)
}
}
+static int bnx2x_close(struct net_device *dev);
+
/* bnx2x_nic_unload() flushes the bnx2x_wq, thus reset task is
* scheduled on a general queue in order to prevent a dead lock.
*/
@@ -8782,11 +8860,13 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
{
u32 val;
- /* Check if there is any driver already loaded */
- val = REG_RD(bp, MISC_REG_UNPREPARED);
- if (val == 0x1) {
+ /* possibly another driver is trying to reset the chip */
+ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
+
+ /* check if doorbell queue is reset */
+ if (REG_RD(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET)
+ & MISC_REGISTERS_RESET_REG_1_RST_DORQ) {
- bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
/*
* Check if it is the UNDI driver
* UNDI driver initializes CID offset for normal bell to 0x7
@@ -8874,14 +8954,11 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
/* restore our func and fw_seq */
bp->pf_num = orig_pf_num;
- bp->fw_seq =
- (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
- DRV_MSG_SEQ_NUMBER_MASK);
}
-
- /* now it's safe to release the lock */
- bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
}
+
+ /* now it's safe to release the lock */
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
}
static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
@@ -9212,6 +9289,11 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
SPEED_AUTO_NEG;
bp->port.advertising[idx] |=
bp->port.supported[idx];
+ if (bp->link_params.phy[EXT_PHY1].type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+ bp->port.advertising[idx] |=
+ (SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full);
} else {
/* force 10G, no AN */
bp->link_params.req_line_speed[idx] =
@@ -9592,7 +9674,7 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
if (BP_NOMCP(bp)) {
BNX2X_ERROR("warning: random MAC workaround active\n");
- random_ether_addr(bp->dev->dev_addr);
+ 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);
@@ -9902,16 +9984,6 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
bnx2x_get_cnic_info(bp);
- /* Get current FW pulse sequence */
- if (!BP_NOMCP(bp)) {
- int mb_idx = BP_FW_MB_IDX(bp);
-
- bp->fw_drv_pulse_wr_seq =
- (SHMEM_RD(bp, func_mb[mb_idx].drv_pulse_mb) &
- DRV_PULSE_SEQ_MASK);
- BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
- }
-
return rc;
}
@@ -10080,14 +10152,6 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
if (!BP_NOMCP(bp))
bnx2x_undi_unload(bp);
- /* init fw_seq after undi_unload! */
- if (!BP_NOMCP(bp)) {
- bp->fw_seq =
- (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
- DRV_MSG_SEQ_NUMBER_MASK);
- BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
- }
-
if (CHIP_REV_IS_FPGA(bp))
dev_err(&bp->pdev->dev, "FPGA detected\n");
@@ -10105,10 +10169,10 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
/* Set TPA flags */
if (bp->disable_tpa) {
- bp->flags &= ~TPA_ENABLE_FLAG;
+ bp->flags &= ~(TPA_ENABLE_FLAG | GRO_ENABLE_FLAG);
bp->dev->features &= ~NETIF_F_LRO;
} else {
- bp->flags |= TPA_ENABLE_FLAG;
+ bp->flags |= (TPA_ENABLE_FLAG | GRO_ENABLE_FLAG);
bp->dev->features |= NETIF_F_LRO;
}
@@ -10150,6 +10214,8 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
if (CHIP_IS_E3B0(bp))
bp->max_cos = BNX2X_MULTI_TX_COS_E3B0;
+ bp->gro_check = bnx2x_need_gro_check(bp->dev->mtu);
+
return rc;
}
@@ -10168,14 +10234,16 @@ static int bnx2x_open(struct net_device *dev)
struct bnx2x *bp = netdev_priv(dev);
bool global = false;
int other_engine = BP_PATH(bp) ? 0 : 1;
- u32 other_load_counter, load_counter;
+ bool other_load_status, load_status;
+
+ bp->stats_init = true;
netif_carrier_off(dev);
bnx2x_set_power_state(bp, PCI_D0);
- other_load_counter = bnx2x_get_load_cnt(bp, other_engine);
- load_counter = bnx2x_get_load_cnt(bp, BP_PATH(bp));
+ other_load_status = bnx2x_get_load_status(bp, other_engine);
+ load_status = bnx2x_get_load_status(bp, BP_PATH(bp));
/*
* If parity had happen during the unload, then attentions
@@ -10201,8 +10269,8 @@ static int bnx2x_open(struct net_device *dev)
* global blocks only the first in the chip should try
* to recover.
*/
- if ((!load_counter &&
- (!global || !other_load_counter)) &&
+ if ((!load_status &&
+ (!global || !other_load_status)) &&
bnx2x_trylock_leader_lock(bp) &&
!bnx2x_leader_reset(bp)) {
netdev_info(bp->dev, "Recovered in open\n");
@@ -10226,7 +10294,7 @@ static int bnx2x_open(struct net_device *dev)
}
/* called with rtnl_lock */
-int bnx2x_close(struct net_device *dev)
+static int bnx2x_close(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -10521,6 +10589,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
{
struct bnx2x *bp;
int rc;
+ u32 pci_cfg_dword;
bool chip_is_e1x = (board_type == BCM57710 ||
board_type == BCM57711 ||
board_type == BCM57711E);
@@ -10531,7 +10600,6 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
bp->dev = dev;
bp->pdev = pdev;
bp->flags = 0;
- bp->pf_num = PCI_FUNC(pdev->devfn);
rc = pci_enable_device(pdev);
if (rc) {
@@ -10598,6 +10666,21 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
goto err_out_release;
}
+ /* In E1/E1H use pci device function given by kernel.
+ * In E2/E3 read physical function from ME register since these chips
+ * support Physical Device Assignment where kernel BDF maybe arbitrary
+ * (depending on hypervisor).
+ */
+ if (chip_is_e1x)
+ bp->pf_num = PCI_FUNC(pdev->devfn);
+ else {/* chip is E2/3*/
+ pci_read_config_dword(bp->pdev,
+ PCICFG_ME_REGISTER, &pci_cfg_dword);
+ bp->pf_num = (u8)((pci_cfg_dword & ME_REG_ABS_PF_NUM) >>
+ ME_REG_ABS_PF_NUM_SHIFT);
+ }
+ DP(BNX2X_MSG_SP, "me reg PF num: %d\n", bp->pf_num);
+
bnx2x_set_power_state(bp, PCI_D0);
/* clean indirect addresses */
@@ -10627,7 +10710,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
/* Reset the load counter */
- bnx2x_clear_load_cnt(bp);
+ bnx2x_clear_load_status(bp);
dev->watchdog_timeo = TX_TIMEOUT;
@@ -10637,8 +10720,9 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
dev->priv_flags |= IFF_UNICAST_FLT;
dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
- NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_LRO |
- NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_HW_VLAN_TX;
+ NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
+ NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO |
+ NETIF_F_RXHASH | NETIF_F_HW_VLAN_TX;
dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;
@@ -10814,10 +10898,8 @@ static inline void be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
do { \
u32 len = be32_to_cpu(fw_hdr->arr.len); \
bp->arr = kmalloc(len, GFP_KERNEL); \
- if (!bp->arr) { \
- pr_err("Failed to allocate %d bytes for "#arr"\n", len); \
+ if (!bp->arr) \
goto lbl; \
- } \
func(bp->firmware->data + be32_to_cpu(fw_hdr->arr.offset), \
(u8 *)bp->arr, len); \
} while (0)
@@ -11055,10 +11137,8 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
/* dev zeroed in init_etherdev */
dev = alloc_etherdev_mqs(sizeof(*bp), tx_count, rx_count);
- if (!dev) {
- dev_err(&pdev->dev, "Cannot allocate net device\n");
+ if (!dev)
return -ENOMEM;
- }
bp = netdev_priv(dev);
@@ -11264,29 +11344,11 @@ static void bnx2x_eeh_recover(struct bnx2x *bp)
mutex_init(&bp->port.phy_mutex);
- bp->common.shmem_base = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
- bp->link_params.shmem_base = bp->common.shmem_base;
- BNX2X_DEV_INFO("shmem offset is 0x%x\n", bp->common.shmem_base);
-
- if (!bp->common.shmem_base ||
- (bp->common.shmem_base < 0xA0000) ||
- (bp->common.shmem_base >= 0xC0000)) {
- BNX2X_DEV_INFO("MCP not active\n");
- bp->flags |= NO_MCP_FLAG;
- return;
- }
val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]);
if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
!= (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB))
BNX2X_ERR("BAD MCP validity signature\n");
-
- if (!BP_NOMCP(bp)) {
- bp->fw_seq =
- (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
- DRV_MSG_SEQ_NUMBER_MASK);
- BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
- }
}
/**
@@ -11542,6 +11604,13 @@ static int bnx2x_cnic_sp_queue(struct net_device *dev,
return -EIO;
#endif
+ if ((bp->recovery_state != BNX2X_RECOVERY_DONE) &&
+ (bp->recovery_state != BNX2X_RECOVERY_NIC_LOADING)) {
+ netdev_err(dev, "Handling parity error recovery. Try again "
+ "later\n");
+ return -EAGAIN;
+ }
+
spin_lock_bh(&bp->spq_lock);
for (i = 0; i < count; i++) {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index dddbcf6e154e..fd7fb4581849 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
@@ -1,6 +1,6 @@
/* bnx2x_reg.h: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -4812,6 +4812,7 @@
The fields are: [4:0] - tail pointer; 10:5] - Link List size; 15:11] -
header pointer. */
#define UCM_REG_XX_TABLE 0xe0300
+#define UMAC_COMMAND_CONFIG_REG_HD_ENA (0x1<<10)
#define UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE (0x1<<28)
#define UMAC_COMMAND_CONFIG_REG_LOOP_ENA (0x1<<15)
#define UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK (0x1<<24)
@@ -5731,6 +5732,7 @@
#define MISC_REGISTERS_GPIO_PORT_SHIFT 4
#define MISC_REGISTERS_GPIO_SET_POS 8
#define MISC_REGISTERS_RESET_REG_1_CLEAR 0x588
+#define MISC_REGISTERS_RESET_REG_1_RST_DORQ (0x1<<19)
#define MISC_REGISTERS_RESET_REG_1_RST_HC (0x1<<29)
#define MISC_REGISTERS_RESET_REG_1_RST_NIG (0x1<<7)
#define MISC_REGISTERS_RESET_REG_1_RST_PXP (0x1<<26)
@@ -5783,15 +5785,17 @@
#define MISC_REGISTERS_SPIO_OUTPUT_HIGH 1
#define MISC_REGISTERS_SPIO_OUTPUT_LOW 0
#define MISC_REGISTERS_SPIO_SET_POS 8
-#define HW_LOCK_DRV_FLAGS 10
#define HW_LOCK_MAX_RESOURCE_VALUE 31
+#define HW_LOCK_RESOURCE_DRV_FLAGS 10
#define HW_LOCK_RESOURCE_GPIO 1
#define HW_LOCK_RESOURCE_MDIO 0
+#define HW_LOCK_RESOURCE_NVRAM 12
#define HW_LOCK_RESOURCE_PORT0_ATT_MASK 3
#define HW_LOCK_RESOURCE_RECOVERY_LEADER_0 8
#define HW_LOCK_RESOURCE_RECOVERY_LEADER_1 9
-#define HW_LOCK_RESOURCE_SPIO 2
+#define HW_LOCK_RESOURCE_RECOVERY_REG 11
#define HW_LOCK_RESOURCE_RESET 5
+#define HW_LOCK_RESOURCE_SPIO 2
#define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT (0x1<<4)
#define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR (0x1<<5)
#define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR (0x1<<18)
@@ -6023,7 +6027,8 @@
#define PCICFG_MSI_CONTROL_64_BIT_ADDR_CAP (0x1<<23)
#define PCICFG_MSI_CONTROL_MSI_PVMASK_CAPABLE (0x1<<24)
#define PCICFG_GRC_ADDRESS 0x78
-#define PCICFG_GRC_DATA 0x80
+#define PCICFG_GRC_DATA 0x80
+#define PCICFG_ME_REGISTER 0x98
#define PCICFG_MSIX_CAP_ID_OFFSET 0xa0
#define PCICFG_MSIX_CONTROL_TABLE_SIZE (0x7ff<<16)
#define PCICFG_MSIX_CONTROL_RESERVED (0x7<<27)
@@ -6401,6 +6406,7 @@
#define MDIO_CL73_IEEEB1_AN_LP_ADV1_ASYMMETRIC 0x0800
#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_BOTH 0x0C00
#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK 0x0C00
+#define MDIO_CL73_IEEEB1_AN_LP_ADV2 0x04
#define MDIO_REG_BANK_RX0 0x80b0
#define MDIO_RX0_RX_STATUS 0x10
@@ -6794,14 +6800,16 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_AN_REG_ADV_PAUSE_MASK 0x0C00
#define MDIO_AN_REG_ADV 0x0011
#define MDIO_AN_REG_ADV2 0x0012
-#define MDIO_AN_REG_LP_AUTO_NEG 0x0013
+#define MDIO_AN_REG_LP_AUTO_NEG 0x0013
+#define MDIO_AN_REG_LP_AUTO_NEG2 0x0014
#define MDIO_AN_REG_MASTER_STATUS 0x0021
/*bcm*/
#define MDIO_AN_REG_LINK_STATUS 0x8304
#define MDIO_AN_REG_CL37_CL73 0x8370
#define MDIO_AN_REG_CL37_AN 0xffe0
#define MDIO_AN_REG_CL37_FC_LD 0xffe4
-#define MDIO_AN_REG_CL37_FC_LP 0xffe5
+#define MDIO_AN_REG_CL37_FC_LP 0xffe5
+#define MDIO_AN_REG_1000T_STATUS 0xffea
#define MDIO_AN_REG_8073_2_5G 0x8329
#define MDIO_AN_REG_8073_BAM 0x8350
@@ -6966,6 +6974,7 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_WC_REG_SERDESDIGITAL_MISC1 0x8308
#define MDIO_WC_REG_SERDESDIGITAL_MISC2 0x8309
#define MDIO_WC_REG_DIGITAL3_UP1 0x8329
+#define MDIO_WC_REG_DIGITAL3_LP_UP1 0x832c
#define MDIO_WC_REG_DIGITAL4_MISC3 0x833c
#define MDIO_WC_REG_DIGITAL5_MISC6 0x8345
#define MDIO_WC_REG_DIGITAL5_MISC7 0x8349
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index cb6339c35571..adfae6bb430b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -1,6 +1,6 @@
/* bnx2x_sp.c: Broadcom Everest network driver.
*
- * Copyright 2011 Broadcom Corporation
+ * Copyright (c) 2011-2012 Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -1836,6 +1836,7 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
rc = exeq->remove(bp, exeq->owner, exeq_pos);
if (rc) {
BNX2X_ERR("Failed to remove command\n");
+ spin_unlock_bh(&exeq->lock);
return rc;
}
list_del(&exeq_pos->link);
@@ -4430,9 +4431,10 @@ static void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o,
struct client_init_rx_data *rx_data,
unsigned long *flags)
{
- /* Rx data */
rx_data->tpa_en = test_bit(BNX2X_Q_FLG_TPA, flags) *
CLIENT_INIT_RX_DATA_TPA_EN_IPV4;
+ rx_data->tpa_en |= test_bit(BNX2X_Q_FLG_TPA_GRO, flags) *
+ CLIENT_INIT_RX_DATA_TPA_MODE;
rx_data->vmqueue_mode_en_flg = 0;
rx_data->cache_line_alignment_log_size =
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index 66da39f0c84a..685d42e1b2fc 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -1,6 +1,6 @@
/* bnx2x_sp.h: Broadcom Everest network driver.
*
- * Copyright 2011 Broadcom Corporation
+ * Copyright (c) 2011-2012 Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -774,6 +774,7 @@ enum bnx2x_queue_cmd {
enum {
BNX2X_Q_FLG_TPA,
BNX2X_Q_FLG_TPA_IPV6,
+ BNX2X_Q_FLG_TPA_GRO,
BNX2X_Q_FLG_STATS,
BNX2X_Q_FLG_ZERO_STATS,
BNX2X_Q_FLG_ACTIVE,
@@ -803,10 +804,10 @@ enum bnx2x_q_type {
};
#define BNX2X_PRIMARY_CID_INDEX 0
-#define BNX2X_MULTI_TX_COS_E1X 1
+#define BNX2X_MULTI_TX_COS_E1X 3 /* QM only */
#define BNX2X_MULTI_TX_COS_E2_E3A0 2
#define BNX2X_MULTI_TX_COS_E3B0 3
-#define BNX2X_MULTI_TX_COS BNX2X_MULTI_TX_COS_E3B0
+#define BNX2X_MULTI_TX_COS 3 /* Maximum possible */
struct bnx2x_queue_init_params {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
index 1adef266fcd5..14c961beaadb 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
@@ -1,6 +1,6 @@
/* bnx2x_stats.c: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -161,7 +161,7 @@ static void bnx2x_stats_pmf_update(struct bnx2x *bp)
u32 *stats_comp = bnx2x_sp(bp, stats_comp);
/* sanity */
- if (!IS_MF(bp) || !bp->port.pmf || !bp->port.port_stx) {
+ if (!bp->port.pmf || !bp->port.port_stx) {
BNX2X_ERR("BUG!\n");
return;
}
@@ -638,31 +638,30 @@ static void bnx2x_mstat_stats_update(struct bnx2x *bp)
tx_stat_dot3statsinternalmactransmiterrors);
ADD_STAT64(stats_tx.tx_gtufl, tx_stat_mac_ufl);
- ADD_64(estats->etherstatspkts1024octetsto1522octets_hi,
- new->stats_tx.tx_gt1518_hi,
- estats->etherstatspkts1024octetsto1522octets_lo,
- new->stats_tx.tx_gt1518_lo);
+ estats->etherstatspkts1024octetsto1522octets_hi =
+ pstats->mac_stx[1].tx_stat_etherstatspkts1024octetsto1522octets_hi;
+ estats->etherstatspkts1024octetsto1522octets_lo =
+ pstats->mac_stx[1].tx_stat_etherstatspkts1024octetsto1522octets_lo;
- ADD_64(estats->etherstatspktsover1522octets_hi,
- new->stats_tx.tx_gt2047_hi,
- estats->etherstatspktsover1522octets_lo,
- new->stats_tx.tx_gt2047_lo);
+ estats->etherstatspktsover1522octets_hi =
+ pstats->mac_stx[1].tx_stat_mac_2047_hi;
+ estats->etherstatspktsover1522octets_lo =
+ pstats->mac_stx[1].tx_stat_mac_2047_lo;
ADD_64(estats->etherstatspktsover1522octets_hi,
- new->stats_tx.tx_gt4095_hi,
+ pstats->mac_stx[1].tx_stat_mac_4095_hi,
estats->etherstatspktsover1522octets_lo,
- new->stats_tx.tx_gt4095_lo);
+ pstats->mac_stx[1].tx_stat_mac_4095_lo);
ADD_64(estats->etherstatspktsover1522octets_hi,
- new->stats_tx.tx_gt9216_hi,
+ pstats->mac_stx[1].tx_stat_mac_9216_hi,
estats->etherstatspktsover1522octets_lo,
- new->stats_tx.tx_gt9216_lo);
-
+ pstats->mac_stx[1].tx_stat_mac_9216_lo);
ADD_64(estats->etherstatspktsover1522octets_hi,
- new->stats_tx.tx_gt16383_hi,
+ pstats->mac_stx[1].tx_stat_mac_16383_hi,
estats->etherstatspktsover1522octets_lo,
- new->stats_tx.tx_gt16383_lo);
+ pstats->mac_stx[1].tx_stat_mac_16383_lo);
estats->pause_frames_received_hi =
pstats->mac_stx[1].rx_stat_mac_xpf_hi;
@@ -817,6 +816,7 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
&bp->fw_stats_data->pf.tstorm_pf_statistics;
struct host_func_stats *fstats = bnx2x_sp(bp, func_stats);
struct bnx2x_eth_stats *estats = &bp->eth_stats;
+ struct bnx2x_eth_stats_old *estats_old = &bp->eth_stats_old;
struct stats_counter *counters = &bp->fw_stats_data->storm_counters;
int i;
u16 cur_stats_counter;
@@ -857,21 +857,8 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
return -EAGAIN;
}
- memcpy(&(fstats->total_bytes_received_hi),
- &(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi),
- sizeof(struct host_func_stats) - 2*sizeof(u32));
estats->error_bytes_received_hi = 0;
estats->error_bytes_received_lo = 0;
- estats->etherstatsoverrsizepkts_hi = 0;
- estats->etherstatsoverrsizepkts_lo = 0;
- estats->no_buff_discard_hi = 0;
- estats->no_buff_discard_lo = 0;
- estats->total_tpa_aggregations_hi = 0;
- estats->total_tpa_aggregations_lo = 0;
- estats->total_tpa_aggregated_frames_hi = 0;
- estats->total_tpa_aggregated_frames_lo = 0;
- estats->total_tpa_bytes_hi = 0;
- estats->total_tpa_bytes_lo = 0;
for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
@@ -888,6 +875,8 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
xstorm_queue_statistics;
struct xstorm_per_queue_stats *old_xclient = &fp->old_xclient;
struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
+ struct bnx2x_eth_q_stats_old *qstats_old = &fp->eth_q_stats_old;
+
u32 diff;
DP(BNX2X_MSG_STATS, "queue[%d]: ucast_sent 0x%x, "
@@ -897,20 +886,12 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
DP(BNX2X_MSG_STATS, "---------------\n");
- qstats->total_broadcast_bytes_received_hi =
- le32_to_cpu(tclient->rcv_bcast_bytes.hi);
- qstats->total_broadcast_bytes_received_lo =
- le32_to_cpu(tclient->rcv_bcast_bytes.lo);
-
- qstats->total_multicast_bytes_received_hi =
- le32_to_cpu(tclient->rcv_mcast_bytes.hi);
- qstats->total_multicast_bytes_received_lo =
- le32_to_cpu(tclient->rcv_mcast_bytes.lo);
-
- qstats->total_unicast_bytes_received_hi =
- le32_to_cpu(tclient->rcv_ucast_bytes.hi);
- qstats->total_unicast_bytes_received_lo =
- le32_to_cpu(tclient->rcv_ucast_bytes.lo);
+ UPDATE_QSTAT(tclient->rcv_bcast_bytes,
+ total_broadcast_bytes_received);
+ UPDATE_QSTAT(tclient->rcv_mcast_bytes,
+ total_multicast_bytes_received);
+ UPDATE_QSTAT(tclient->rcv_ucast_bytes,
+ total_unicast_bytes_received);
/*
* sum to total_bytes_received all
@@ -943,9 +924,9 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
total_multicast_packets_received);
UPDATE_EXTEND_TSTAT(rcv_bcast_pkts,
total_broadcast_packets_received);
- UPDATE_EXTEND_TSTAT(pkts_too_big_discard,
- etherstatsoverrsizepkts);
- UPDATE_EXTEND_TSTAT(no_buff_discard, no_buff_discard);
+ UPDATE_EXTEND_E_TSTAT(pkts_too_big_discard,
+ etherstatsoverrsizepkts);
+ UPDATE_EXTEND_E_TSTAT(no_buff_discard, no_buff_discard);
SUB_EXTEND_USTAT(ucast_no_buff_pkts,
total_unicast_packets_received);
@@ -953,24 +934,17 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
total_multicast_packets_received);
SUB_EXTEND_USTAT(bcast_no_buff_pkts,
total_broadcast_packets_received);
- UPDATE_EXTEND_USTAT(ucast_no_buff_pkts, no_buff_discard);
- UPDATE_EXTEND_USTAT(mcast_no_buff_pkts, no_buff_discard);
- UPDATE_EXTEND_USTAT(bcast_no_buff_pkts, no_buff_discard);
-
- qstats->total_broadcast_bytes_transmitted_hi =
- le32_to_cpu(xclient->bcast_bytes_sent.hi);
- qstats->total_broadcast_bytes_transmitted_lo =
- le32_to_cpu(xclient->bcast_bytes_sent.lo);
-
- qstats->total_multicast_bytes_transmitted_hi =
- le32_to_cpu(xclient->mcast_bytes_sent.hi);
- qstats->total_multicast_bytes_transmitted_lo =
- le32_to_cpu(xclient->mcast_bytes_sent.lo);
-
- qstats->total_unicast_bytes_transmitted_hi =
- le32_to_cpu(xclient->ucast_bytes_sent.hi);
- qstats->total_unicast_bytes_transmitted_lo =
- le32_to_cpu(xclient->ucast_bytes_sent.lo);
+ UPDATE_EXTEND_E_USTAT(ucast_no_buff_pkts, no_buff_discard);
+ UPDATE_EXTEND_E_USTAT(mcast_no_buff_pkts, no_buff_discard);
+ UPDATE_EXTEND_E_USTAT(bcast_no_buff_pkts, no_buff_discard);
+
+ UPDATE_QSTAT(xclient->bcast_bytes_sent,
+ total_broadcast_bytes_transmitted);
+ UPDATE_QSTAT(xclient->mcast_bytes_sent,
+ total_multicast_bytes_transmitted);
+ UPDATE_QSTAT(xclient->ucast_bytes_sent,
+ total_unicast_bytes_transmitted);
+
/*
* sum to total_bytes_transmitted all
* unicast/multicast/broadcast
@@ -1006,110 +980,54 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
total_transmitted_dropped_packets_error);
/* TPA aggregations completed */
- UPDATE_EXTEND_USTAT(coalesced_events, total_tpa_aggregations);
+ UPDATE_EXTEND_E_USTAT(coalesced_events, total_tpa_aggregations);
/* Number of network frames aggregated by TPA */
- UPDATE_EXTEND_USTAT(coalesced_pkts,
- total_tpa_aggregated_frames);
+ UPDATE_EXTEND_E_USTAT(coalesced_pkts,
+ total_tpa_aggregated_frames);
/* Total number of bytes in completed TPA aggregations */
- qstats->total_tpa_bytes_lo =
- le32_to_cpu(uclient->coalesced_bytes.lo);
- qstats->total_tpa_bytes_hi =
- le32_to_cpu(uclient->coalesced_bytes.hi);
-
- /* TPA stats per-function */
- ADD_64(estats->total_tpa_aggregations_hi,
- qstats->total_tpa_aggregations_hi,
- estats->total_tpa_aggregations_lo,
- qstats->total_tpa_aggregations_lo);
- ADD_64(estats->total_tpa_aggregated_frames_hi,
- qstats->total_tpa_aggregated_frames_hi,
- estats->total_tpa_aggregated_frames_lo,
- qstats->total_tpa_aggregated_frames_lo);
- ADD_64(estats->total_tpa_bytes_hi,
- qstats->total_tpa_bytes_hi,
- estats->total_tpa_bytes_lo,
- qstats->total_tpa_bytes_lo);
-
- ADD_64(fstats->total_bytes_received_hi,
- qstats->total_bytes_received_hi,
- fstats->total_bytes_received_lo,
- qstats->total_bytes_received_lo);
- ADD_64(fstats->total_bytes_transmitted_hi,
- qstats->total_bytes_transmitted_hi,
- fstats->total_bytes_transmitted_lo,
- qstats->total_bytes_transmitted_lo);
- ADD_64(fstats->total_unicast_packets_received_hi,
- qstats->total_unicast_packets_received_hi,
- fstats->total_unicast_packets_received_lo,
- qstats->total_unicast_packets_received_lo);
- ADD_64(fstats->total_multicast_packets_received_hi,
- qstats->total_multicast_packets_received_hi,
- fstats->total_multicast_packets_received_lo,
- qstats->total_multicast_packets_received_lo);
- ADD_64(fstats->total_broadcast_packets_received_hi,
- qstats->total_broadcast_packets_received_hi,
- fstats->total_broadcast_packets_received_lo,
- qstats->total_broadcast_packets_received_lo);
- ADD_64(fstats->total_unicast_packets_transmitted_hi,
- qstats->total_unicast_packets_transmitted_hi,
- fstats->total_unicast_packets_transmitted_lo,
- qstats->total_unicast_packets_transmitted_lo);
- ADD_64(fstats->total_multicast_packets_transmitted_hi,
- qstats->total_multicast_packets_transmitted_hi,
- fstats->total_multicast_packets_transmitted_lo,
- qstats->total_multicast_packets_transmitted_lo);
- ADD_64(fstats->total_broadcast_packets_transmitted_hi,
- qstats->total_broadcast_packets_transmitted_hi,
- fstats->total_broadcast_packets_transmitted_lo,
- qstats->total_broadcast_packets_transmitted_lo);
- ADD_64(fstats->valid_bytes_received_hi,
- qstats->valid_bytes_received_hi,
- fstats->valid_bytes_received_lo,
- qstats->valid_bytes_received_lo);
-
- ADD_64(estats->etherstatsoverrsizepkts_hi,
- qstats->etherstatsoverrsizepkts_hi,
- estats->etherstatsoverrsizepkts_lo,
- qstats->etherstatsoverrsizepkts_lo);
- ADD_64(estats->no_buff_discard_hi, qstats->no_buff_discard_hi,
- estats->no_buff_discard_lo, qstats->no_buff_discard_lo);
+ UPDATE_QSTAT(uclient->coalesced_bytes, total_tpa_bytes);
+
+ UPDATE_ESTAT_QSTAT_64(total_tpa_bytes);
+
+ UPDATE_FSTAT_QSTAT(total_bytes_received);
+ UPDATE_FSTAT_QSTAT(total_bytes_transmitted);
+ UPDATE_FSTAT_QSTAT(total_unicast_packets_received);
+ UPDATE_FSTAT_QSTAT(total_multicast_packets_received);
+ UPDATE_FSTAT_QSTAT(total_broadcast_packets_received);
+ UPDATE_FSTAT_QSTAT(total_unicast_packets_transmitted);
+ UPDATE_FSTAT_QSTAT(total_multicast_packets_transmitted);
+ UPDATE_FSTAT_QSTAT(total_broadcast_packets_transmitted);
+ UPDATE_FSTAT_QSTAT(valid_bytes_received);
}
- ADD_64(fstats->total_bytes_received_hi,
+ ADD_64(estats->total_bytes_received_hi,
estats->rx_stat_ifhcinbadoctets_hi,
- fstats->total_bytes_received_lo,
+ estats->total_bytes_received_lo,
estats->rx_stat_ifhcinbadoctets_lo);
- ADD_64(fstats->total_bytes_received_hi,
+ ADD_64(estats->total_bytes_received_hi,
le32_to_cpu(tfunc->rcv_error_bytes.hi),
- fstats->total_bytes_received_lo,
+ estats->total_bytes_received_lo,
le32_to_cpu(tfunc->rcv_error_bytes.lo));
- memcpy(estats, &(fstats->total_bytes_received_hi),
- sizeof(struct host_func_stats) - 2*sizeof(u32));
-
ADD_64(estats->error_bytes_received_hi,
le32_to_cpu(tfunc->rcv_error_bytes.hi),
estats->error_bytes_received_lo,
le32_to_cpu(tfunc->rcv_error_bytes.lo));
- ADD_64(estats->etherstatsoverrsizepkts_hi,
- estats->rx_stat_dot3statsframestoolong_hi,
- estats->etherstatsoverrsizepkts_lo,
- estats->rx_stat_dot3statsframestoolong_lo);
+ UPDATE_ESTAT(etherstatsoverrsizepkts, rx_stat_dot3statsframestoolong);
+
ADD_64(estats->error_bytes_received_hi,
estats->rx_stat_ifhcinbadoctets_hi,
estats->error_bytes_received_lo,
estats->rx_stat_ifhcinbadoctets_lo);
if (bp->port.pmf) {
- estats->mac_filter_discard =
- le32_to_cpu(tport->mac_filter_discard);
- estats->mf_tag_discard =
- le32_to_cpu(tport->mf_tag_discard);
- estats->brb_truncate_discard =
- le32_to_cpu(tport->brb_truncate_discard);
- estats->mac_discard = le32_to_cpu(tport->mac_discard);
+ struct bnx2x_fw_port_stats_old *fwstats = &bp->fw_stats_old;
+ UPDATE_FW_STAT(mac_filter_discard);
+ UPDATE_FW_STAT(mf_tag_discard);
+ UPDATE_FW_STAT(brb_truncate_discard);
+ UPDATE_FW_STAT(mac_discard);
}
fstats->host_func_stats_start = ++fstats->host_func_stats_end;
@@ -1143,7 +1061,7 @@ static void bnx2x_net_stats_update(struct bnx2x *bp)
tmp = estats->mac_discard;
for_each_rx_queue(bp, i)
tmp += le32_to_cpu(bp->fp[i].old_tclient.checksum_discard);
- nstats->rx_dropped = tmp;
+ nstats->rx_dropped = tmp + bp->net_stats_old.rx_dropped;
nstats->tx_dropped = 0;
@@ -1191,17 +1109,15 @@ static void bnx2x_drv_stats_update(struct bnx2x *bp)
struct bnx2x_eth_stats *estats = &bp->eth_stats;
int i;
- estats->driver_xoff = 0;
- estats->rx_err_discard_pkt = 0;
- estats->rx_skb_alloc_failed = 0;
- estats->hw_csum_err = 0;
for_each_queue(bp, i) {
struct bnx2x_eth_q_stats *qstats = &bp->fp[i].eth_q_stats;
+ struct bnx2x_eth_q_stats_old *qstats_old =
+ &bp->fp[i].eth_q_stats_old;
- estats->driver_xoff += qstats->driver_xoff;
- estats->rx_err_discard_pkt += qstats->rx_err_discard_pkt;
- estats->rx_skb_alloc_failed += qstats->rx_skb_alloc_failed;
- estats->hw_csum_err += qstats->hw_csum_err;
+ UPDATE_ESTAT_QSTAT(driver_xoff);
+ UPDATE_ESTAT_QSTAT(rx_err_discard_pkt);
+ UPDATE_ESTAT_QSTAT(rx_skb_alloc_failed);
+ UPDATE_ESTAT_QSTAT(hw_csum_err);
}
}
@@ -1446,33 +1362,6 @@ static void bnx2x_port_stats_base_init(struct bnx2x *bp)
bnx2x_stats_comp(bp);
}
-static void bnx2x_func_stats_base_init(struct bnx2x *bp)
-{
- int vn, vn_max = IS_MF(bp) ? BP_MAX_VN_NUM(bp) : E1VN_MAX;
- u32 func_stx;
-
- /* sanity */
- if (!bp->port.pmf || !bp->func_stx) {
- BNX2X_ERR("BUG!\n");
- return;
- }
-
- /* save our func_stx */
- func_stx = bp->func_stx;
-
- for (vn = VN_0; vn < vn_max; vn++) {
- int mb_idx = BP_FW_MB_IDX_VN(bp, vn);
-
- bp->func_stx = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_param);
- bnx2x_func_stats_init(bp);
- bnx2x_hw_stats_post(bp);
- bnx2x_stats_comp(bp);
- }
-
- /* restore our func_stx */
- bp->func_stx = func_stx;
-}
-
static void bnx2x_func_stats_base_update(struct bnx2x *bp)
{
struct dmae_command *dmae = &bp->stats_dmae;
@@ -1491,8 +1380,8 @@ static void bnx2x_func_stats_base_update(struct bnx2x *bp)
true, DMAE_COMP_PCI);
dmae->src_addr_lo = bp->func_stx >> 2;
dmae->src_addr_hi = 0;
- dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats_base));
- dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats_base));
+ dmae->dst_addr_lo = U64_LO(bnx2x_sp_mapping(bp, func_stats));
+ dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, func_stats));
dmae->len = sizeof(struct host_func_stats) >> 2;
dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp));
dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp));
@@ -1653,6 +1542,10 @@ void bnx2x_stats_init(struct bnx2x *bp)
DP(BNX2X_MSG_STATS, "port_stx 0x%x func_stx 0x%x\n",
bp->port.port_stx, bp->func_stx);
+ /* pmf should retrieve port statistics from SP on a non-init*/
+ if (!bp->stats_init && bp->port.pmf && bp->port.port_stx)
+ bnx2x_stats_handle(bp, STATS_EVENT_PMF);
+
port = BP_PORT(bp);
/* port stats */
memset(&(bp->port.old_nig_stats), 0, sizeof(struct nig_stats));
@@ -1674,24 +1567,83 @@ void bnx2x_stats_init(struct bnx2x *bp)
memset(&fp->old_tclient, 0, sizeof(fp->old_tclient));
memset(&fp->old_uclient, 0, sizeof(fp->old_uclient));
memset(&fp->old_xclient, 0, sizeof(fp->old_xclient));
- memset(&fp->eth_q_stats, 0, sizeof(fp->eth_q_stats));
+ if (bp->stats_init) {
+ memset(&fp->eth_q_stats, 0, sizeof(fp->eth_q_stats));
+ memset(&fp->eth_q_stats_old, 0,
+ sizeof(fp->eth_q_stats_old));
+ }
}
/* Prepare statistics ramrod data */
bnx2x_prep_fw_stats_req(bp);
memset(&bp->dev->stats, 0, sizeof(bp->dev->stats));
- memset(&bp->eth_stats, 0, sizeof(bp->eth_stats));
+ if (bp->stats_init) {
+ memset(&bp->net_stats_old, 0, sizeof(bp->net_stats_old));
+ memset(&bp->fw_stats_old, 0, sizeof(bp->fw_stats_old));
+ memset(&bp->eth_stats_old, 0, sizeof(bp->eth_stats_old));
+ memset(&bp->eth_stats, 0, sizeof(bp->eth_stats));
- bp->stats_state = STATS_STATE_DISABLED;
+ /* Clean SP from previous statistics */
+ if (bp->func_stx) {
+ memset(bnx2x_sp(bp, func_stats), 0,
+ sizeof(struct host_func_stats));
+ bnx2x_func_stats_init(bp);
+ bnx2x_hw_stats_post(bp);
+ bnx2x_stats_comp(bp);
+ }
+ }
- if (bp->port.pmf) {
- if (bp->port.port_stx)
- bnx2x_port_stats_base_init(bp);
+ bp->stats_state = STATS_STATE_DISABLED;
- if (bp->func_stx)
- bnx2x_func_stats_base_init(bp);
+ if (bp->port.pmf && bp->port.port_stx)
+ bnx2x_port_stats_base_init(bp);
- } else if (bp->func_stx)
+ /* On a non-init, retrieve previous statistics from SP */
+ if (!bp->stats_init && bp->func_stx)
bnx2x_func_stats_base_update(bp);
+
+ /* mark the end of statistics initializiation */
+ bp->stats_init = false;
+}
+
+void bnx2x_save_statistics(struct bnx2x *bp)
+{
+ int i;
+ struct net_device_stats *nstats = &bp->dev->stats;
+
+ /* save queue statistics */
+ for_each_eth_queue(bp, i) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
+ struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
+ struct bnx2x_eth_q_stats_old *qstats_old = &fp->eth_q_stats_old;
+
+ UPDATE_QSTAT_OLD(total_unicast_bytes_received_hi);
+ UPDATE_QSTAT_OLD(total_unicast_bytes_received_lo);
+ UPDATE_QSTAT_OLD(total_broadcast_bytes_received_hi);
+ UPDATE_QSTAT_OLD(total_broadcast_bytes_received_lo);
+ UPDATE_QSTAT_OLD(total_multicast_bytes_received_hi);
+ UPDATE_QSTAT_OLD(total_multicast_bytes_received_lo);
+ UPDATE_QSTAT_OLD(total_unicast_bytes_transmitted_hi);
+ UPDATE_QSTAT_OLD(total_unicast_bytes_transmitted_lo);
+ UPDATE_QSTAT_OLD(total_broadcast_bytes_transmitted_hi);
+ UPDATE_QSTAT_OLD(total_broadcast_bytes_transmitted_lo);
+ UPDATE_QSTAT_OLD(total_multicast_bytes_transmitted_hi);
+ UPDATE_QSTAT_OLD(total_multicast_bytes_transmitted_lo);
+ UPDATE_QSTAT_OLD(total_tpa_bytes_hi);
+ UPDATE_QSTAT_OLD(total_tpa_bytes_lo);
+ }
+
+ /* save net_device_stats statistics */
+ bp->net_stats_old.rx_dropped = nstats->rx_dropped;
+
+ /* store port firmware statistics */
+ if (bp->port.pmf && IS_MF(bp)) {
+ struct bnx2x_eth_stats *estats = &bp->eth_stats;
+ struct bnx2x_fw_port_stats_old *fwstats = &bp->fw_stats_old;
+ UPDATE_FW_STAT_OLD(mac_filter_discard);
+ UPDATE_FW_STAT_OLD(mf_tag_discard);
+ UPDATE_FW_STAT_OLD(brb_truncate_discard);
+ UPDATE_FW_STAT_OLD(mac_discard);
+ }
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
index 683deb053109..39ffd6dcdf1a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
@@ -1,6 +1,6 @@
/* bnx2x_stats.h: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2011 Broadcom Corporation
+ * Copyright (c) 2007-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -199,6 +199,10 @@ struct bnx2x_eth_stats {
u32 pfc_frames_received_lo;
u32 pfc_frames_sent_hi;
u32 pfc_frames_sent_lo;
+
+ /* Recovery */
+ u32 recoverable_error;
+ u32 unrecoverable_error;
};
@@ -260,6 +264,69 @@ struct bnx2x_eth_q_stats {
u32 total_tpa_bytes_lo;
};
+struct bnx2x_eth_stats_old {
+ u32 rx_stat_dot3statsframestoolong_hi;
+ u32 rx_stat_dot3statsframestoolong_lo;
+};
+
+struct bnx2x_eth_q_stats_old {
+ /* Fields to perserve over fw reset*/
+ u32 total_unicast_bytes_received_hi;
+ u32 total_unicast_bytes_received_lo;
+ u32 total_broadcast_bytes_received_hi;
+ u32 total_broadcast_bytes_received_lo;
+ u32 total_multicast_bytes_received_hi;
+ u32 total_multicast_bytes_received_lo;
+ u32 total_unicast_bytes_transmitted_hi;
+ u32 total_unicast_bytes_transmitted_lo;
+ u32 total_broadcast_bytes_transmitted_hi;
+ u32 total_broadcast_bytes_transmitted_lo;
+ u32 total_multicast_bytes_transmitted_hi;
+ u32 total_multicast_bytes_transmitted_lo;
+ u32 total_tpa_bytes_hi;
+ u32 total_tpa_bytes_lo;
+
+ /* Fields to perserve last of */
+ u32 total_bytes_received_hi;
+ u32 total_bytes_received_lo;
+ u32 total_bytes_transmitted_hi;
+ u32 total_bytes_transmitted_lo;
+ u32 total_unicast_packets_received_hi;
+ u32 total_unicast_packets_received_lo;
+ u32 total_multicast_packets_received_hi;
+ u32 total_multicast_packets_received_lo;
+ u32 total_broadcast_packets_received_hi;
+ u32 total_broadcast_packets_received_lo;
+ u32 total_unicast_packets_transmitted_hi;
+ u32 total_unicast_packets_transmitted_lo;
+ u32 total_multicast_packets_transmitted_hi;
+ u32 total_multicast_packets_transmitted_lo;
+ u32 total_broadcast_packets_transmitted_hi;
+ u32 total_broadcast_packets_transmitted_lo;
+ u32 valid_bytes_received_hi;
+ u32 valid_bytes_received_lo;
+
+ u32 total_tpa_bytes_hi_old;
+ u32 total_tpa_bytes_lo_old;
+
+ u32 driver_xoff_old;
+ u32 rx_err_discard_pkt_old;
+ u32 rx_skb_alloc_failed_old;
+ u32 hw_csum_err_old;
+};
+
+struct bnx2x_net_stats_old {
+ u32 rx_dropped;
+};
+
+struct bnx2x_fw_port_stats_old {
+ u32 mac_filter_discard;
+ u32 mf_tag_discard;
+ u32 brb_truncate_discard;
+ u32 mac_discard;
+};
+
+
/****************************************************************************
* Macros
****************************************************************************/
@@ -344,11 +411,28 @@ struct bnx2x_eth_q_stats {
ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
} while (0)
+#define UPDATE_EXTEND_E_TSTAT(s, t) \
+ do { \
+ UPDATE_EXTEND_TSTAT(s, t); \
+ ADD_EXTEND_64(estats->t##_hi, estats->t##_lo, diff); \
+ } while (0)
+
#define UPDATE_EXTEND_USTAT(s, t) \
do { \
diff = le32_to_cpu(uclient->s) - le32_to_cpu(old_uclient->s); \
old_uclient->s = uclient->s; \
- ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
+ } while (0)
+
+#define UPDATE_EXTEND_E_USTAT(s, t) \
+ do { \
+ UPDATE_EXTEND_USTAT(s, t); \
+ ADD_EXTEND_64(estats->t##_hi, estats->t##_lo, diff); \
+ } while (0)
+
+#define UPDATE_EXTEND_E_USTAT(s, t) \
+ do { \
+ UPDATE_EXTEND_USTAT(s, t); \
+ ADD_EXTEND_64(estats->t##_hi, estats->t##_lo, diff); \
} while (0)
#define UPDATE_EXTEND_XSTAT(s, t) \
@@ -358,6 +442,66 @@ struct bnx2x_eth_q_stats {
ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \
} while (0)
+#define UPDATE_QSTAT(s, t) \
+ do { \
+ qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi); \
+ qstats->t##_lo = qstats_old->t##_lo + le32_to_cpu(s.lo); \
+ } while (0)
+
+#define UPDATE_QSTAT_OLD(f) \
+ do { \
+ qstats_old->f = qstats->f; \
+ } while (0)
+
+#define UPDATE_ESTAT_QSTAT_64(s) \
+ do { \
+ ADD_64(estats->s##_hi, qstats->s##_hi, \
+ estats->s##_lo, qstats->s##_lo); \
+ SUB_64(estats->s##_hi, qstats_old->s##_hi_old, \
+ estats->s##_lo, qstats_old->s##_lo_old); \
+ qstats_old->s##_hi_old = qstats->s##_hi; \
+ qstats_old->s##_lo_old = qstats->s##_lo; \
+ } while (0)
+
+#define UPDATE_ESTAT_QSTAT(s) \
+ do { \
+ estats->s += qstats->s; \
+ estats->s -= qstats_old->s##_old; \
+ qstats_old->s##_old = qstats->s; \
+ } while (0)
+
+#define UPDATE_FSTAT_QSTAT(s) \
+ do { \
+ ADD_64(fstats->s##_hi, qstats->s##_hi, \
+ fstats->s##_lo, qstats->s##_lo); \
+ SUB_64(fstats->s##_hi, qstats_old->s##_hi, \
+ fstats->s##_lo, qstats_old->s##_lo); \
+ estats->s##_hi = fstats->s##_hi; \
+ estats->s##_lo = fstats->s##_lo; \
+ qstats_old->s##_hi = qstats->s##_hi; \
+ qstats_old->s##_lo = qstats->s##_lo; \
+ } while (0)
+
+#define UPDATE_FW_STAT(s) \
+ do { \
+ estats->s = le32_to_cpu(tport->s) + fwstats->s; \
+ } while (0)
+
+#define UPDATE_FW_STAT_OLD(f) \
+ do { \
+ fwstats->f = estats->f; \
+ } while (0)
+
+#define UPDATE_ESTAT(s, t) \
+ do { \
+ SUB_64(estats->s##_hi, estats_old->t##_hi, \
+ estats->s##_lo, estats_old->t##_lo); \
+ ADD_64(estats->s##_hi, estats->t##_hi, \
+ estats->s##_lo, estats->t##_lo); \
+ estats_old->t##_hi = estats->t##_hi; \
+ estats_old->t##_lo = estats->t##_lo; \
+ } while (0)
+
/* minuend -= subtrahend */
#define SUB_64(m_hi, s_hi, m_lo, s_lo) \
do { \
@@ -384,4 +528,10 @@ void bnx2x_stats_init(struct bnx2x *bp);
void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
+/**
+ * bnx2x_save_statistics - save statistics when unloading.
+ *
+ * @bp: driver handle
+ */
+void bnx2x_save_statistics(struct bnx2x *bp);
#endif /* BNX2X_STATS_H */
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index 818a573669e6..7b65716b8734 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -1,6 +1,6 @@
/* cnic.c: Broadcom CNIC core network driver.
*
- * Copyright (c) 2006-2011 Broadcom Corporation
+ * Copyright (c) 2006-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -380,6 +380,8 @@ static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type,
if (cnic_in_use(csk) &&
test_bit(SK_F_CONNECT_START, &csk->flags)) {
+ csk->vlan_id = path_resp->vlan_id;
+
memcpy(csk->ha, path_resp->mac_addr, 6);
if (test_bit(SK_F_IPV6, &csk->flags))
memcpy(&csk->src_ip[0], &path_resp->src.v6_addr,
@@ -2521,12 +2523,35 @@ static void cnic_bnx2x_kwqe_err(struct cnic_dev *dev, struct kwqe *kwqe)
u32 cid;
u32 opcode = KWQE_OPCODE(kwqe->kwqe_op_flag);
u32 layer_code = kwqe->kwqe_op_flag & KWQE_LAYER_MASK;
+ u32 kcqe_op;
int ulp_type;
cid = kwqe->kwqe_info0;
memset(&kcqe, 0, sizeof(kcqe));
- if (layer_code == KWQE_FLAGS_LAYER_MASK_L5_ISCSI) {
+ if (layer_code == KWQE_FLAGS_LAYER_MASK_L5_FCOE) {
+ u32 l5_cid = 0;
+
+ ulp_type = CNIC_ULP_FCOE;
+ if (opcode == FCOE_KWQE_OPCODE_DISABLE_CONN) {
+ struct fcoe_kwqe_conn_enable_disable *req;
+
+ req = (struct fcoe_kwqe_conn_enable_disable *) kwqe;
+ kcqe_op = FCOE_KCQE_OPCODE_DISABLE_CONN;
+ cid = req->context_id;
+ l5_cid = req->conn_id;
+ } else if (opcode == FCOE_KWQE_OPCODE_DESTROY) {
+ kcqe_op = FCOE_KCQE_OPCODE_DESTROY_FUNC;
+ } else {
+ return;
+ }
+ kcqe.kcqe_op_flag = kcqe_op << KCQE_FLAGS_OPCODE_SHIFT;
+ kcqe.kcqe_op_flag |= KCQE_FLAGS_LAYER_MASK_L5_FCOE;
+ kcqe.kcqe_info1 = FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR;
+ kcqe.kcqe_info2 = cid;
+ kcqe.kcqe_info0 = l5_cid;
+
+ } else if (layer_code == KWQE_FLAGS_LAYER_MASK_L5_ISCSI) {
ulp_type = CNIC_ULP_ISCSI;
if (opcode == ISCSI_KWQE_OPCODE_UPDATE_CONN)
cid = kwqe->kwqe_info1;
@@ -2539,7 +2564,6 @@ static void cnic_bnx2x_kwqe_err(struct cnic_dev *dev, struct kwqe *kwqe)
} else if (layer_code == KWQE_FLAGS_LAYER_MASK_L4) {
struct l4_kcq *l4kcqe = (struct l4_kcq *) &kcqe;
- u32 kcqe_op;
ulp_type = CNIC_ULP_L4;
if (opcode == L4_KWQE_OPCODE_VALUE_CONNECT1)
@@ -2686,9 +2710,17 @@ static int cnic_submit_bnx2x_fcoe_kwqes(struct cnic_dev *dev,
opcode);
break;
}
- if (ret < 0)
+ if (ret < 0) {
netdev_err(dev->netdev, "KWQE(0x%x) failed\n",
opcode);
+
+ /* Possibly bnx2x parity error, send completion
+ * to ulp drivers with error code to speed up
+ * cleanup and reset recovery.
+ */
+ if (ret == -EIO || ret == -EAGAIN)
+ cnic_bnx2x_kwqe_err(dev, kwqe);
+ }
i += work;
}
return 0;
@@ -3901,6 +3933,8 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe)
case L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE:
if (l4kcqe->status == 0)
set_bit(SK_F_OFFLD_COMPLETE, &csk->flags);
+ else if (l4kcqe->status == L4_KCQE_COMPLETION_STATUS_NIC_ERROR)
+ set_bit(SK_F_HW_ERR, &csk->flags);
smp_mb__before_clear_bit();
clear_bit(SK_F_OFFLD_SCHED, &csk->flags);
diff --git a/drivers/net/ethernet/broadcom/cnic_defs.h b/drivers/net/ethernet/broadcom/cnic_defs.h
index 86936f6b6dbc..06ca00266d70 100644
--- a/drivers/net/ethernet/broadcom/cnic_defs.h
+++ b/drivers/net/ethernet/broadcom/cnic_defs.h
@@ -1,7 +1,7 @@
/* cnic.c: Broadcom CNIC core network driver.
*
- * Copyright (c) 2006-2009 Broadcom Corporation
+ * Copyright (c) 2006-2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -69,6 +69,7 @@
#define FCOE_KCQE_COMPLETION_STATUS_ERROR (0x1)
#define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE (0x3)
+#define FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR (0x5)
/* KCQ (kernel completion queue) response op codes */
#define L4_KCQE_OPCODE_VALUE_CLOSE_COMP (53)
@@ -1392,9 +1393,9 @@ struct xstorm_fcoe_extra_ag_context_section {
#define __XSTORM_FCOE_EXTRA_AG_CONTEXT_SECTION_RESERVED_DA_EXPIRATION_FLAG_SHIFT 7
#endif
u32 snd_nxt;
- u32 tx_wnd;
- u32 __reserved55;
- u32 local_adv_wnd;
+ u32 __xfrqe_bd_addr_lo;
+ u32 __xfrqe_bd_addr_hi;
+ u32 __xfrqe_data1;
#if defined(__BIG_ENDIAN)
u8 __agg_val8_th;
u8 __tx_dest;
@@ -1480,13 +1481,13 @@ struct xstorm_fcoe_extra_ag_context_section {
#endif
u32 __tcp_agg_vars6;
#if defined(__BIG_ENDIAN)
- u16 __agg_misc6;
+ u16 __xfrqe_mng;
u16 __tcp_agg_vars7;
#elif defined(__LITTLE_ENDIAN)
u16 __tcp_agg_vars7;
- u16 __agg_misc6;
+ u16 __xfrqe_mng;
#endif
- u32 __agg_val10;
+ u32 __xfrqe_data0;
u32 __agg_val10_th;
#if defined(__BIG_ENDIAN)
u16 __reserved3;
@@ -1706,11 +1707,11 @@ struct xstorm_fcoe_ag_context {
#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3 (0xFF<<24)
#define XSTORM_FCOE_AG_CONTEXT_AGG_MISC3_SHIFT 24
#if defined(__BIG_ENDIAN)
- u16 agg_misc0;
+ u16 __cache_wqe_db;
u16 sq_prod;
#elif defined(__LITTLE_ENDIAN)
u16 sq_prod;
- u16 agg_misc0;
+ u16 __cache_wqe_db;
#endif
#if defined(__BIG_ENDIAN)
u8 agg_val3;
@@ -3016,8 +3017,8 @@ struct fcoe_tce_tx_wr_rx_rd_const {
#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV1_SHIFT 5
#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT (0x1<<6)
#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_SEQ_INIT_SHIFT 6
-#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2 (0x1<<7)
-#define FCOE_TCE_TX_WR_RX_RD_CONST_RSRV2_SHIFT 7
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_COMP_TRNS (0x1<<7)
+#define FCOE_TCE_TX_WR_RX_RD_CONST_TX_COMP_TRNS_SHIFT 7
__le16 rsrv3;
__le32 verify_tx_seq;
};
@@ -4298,7 +4299,7 @@ struct xstorm_eth_context_section {
#endif
#if defined(__BIG_ENDIAN)
u16 reserved_vlan_type;
- u16 params;
+ u16 vlan_params;
#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
#define XSTORM_ETH_CONTEXT_SECTION_CFI (0x1<<12)
@@ -4306,7 +4307,7 @@ struct xstorm_eth_context_section {
#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY (0x7<<13)
#define XSTORM_ETH_CONTEXT_SECTION_PRIORITY_SHIFT 13
#elif defined(__LITTLE_ENDIAN)
- u16 params;
+ u16 vlan_params;
#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID (0xFFF<<0)
#define XSTORM_ETH_CONTEXT_SECTION_VLAN_ID_SHIFT 0
#define XSTORM_ETH_CONTEXT_SECTION_CFI (0x1<<12)
diff --git a/drivers/net/ethernet/broadcom/cnic_if.h b/drivers/net/ethernet/broadcom/cnic_if.h
index 1517763d4e55..60deb84d36bd 100644
--- a/drivers/net/ethernet/broadcom/cnic_if.h
+++ b/drivers/net/ethernet/broadcom/cnic_if.h
@@ -12,8 +12,8 @@
#ifndef CNIC_IF_H
#define CNIC_IF_H
-#define CNIC_MODULE_VERSION "2.5.8"
-#define CNIC_MODULE_RELDATE "Jan 3, 2012"
+#define CNIC_MODULE_VERSION "2.5.9"
+#define CNIC_MODULE_RELDATE "Feb 8, 2012"
#define CNIC_ULP_RDMA 0
#define CNIC_ULP_ISCSI 1
diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c
index 084904ceaa30..49e7a258da8a 100644
--- a/drivers/net/ethernet/broadcom/sb1250-mac.c
+++ b/drivers/net/ethernet/broadcom/sb1250-mac.c
@@ -2623,8 +2623,6 @@ static int __devinit sbmac_probe(struct platform_device *pldev)
*/
dev = alloc_etherdev(sizeof(struct sbmac_softc));
if (!dev) {
- printk(KERN_ERR "%s: unable to allocate etherdev\n",
- dev_name(&pldev->dev));
err = -ENOMEM;
goto out_unmap;
}
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index a1f2e0fed78b..97dcccdb9eb2 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -4,7 +4,7 @@
* Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
* Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
* Copyright (C) 2004 Sun Microsystems Inc.
- * Copyright (C) 2005-2011 Broadcom Corporation.
+ * Copyright (C) 2005-2012 Broadcom Corporation.
*
* Firmware is:
* Derived from proprietary unpublished source code,
@@ -204,6 +204,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
#define TG3_RAW_IP_ALIGN 2
#define TG3_FW_UPDATE_TIMEOUT_SEC 5
+#define TG3_FW_UPDATE_FREQ_SEC (TG3_FW_UPDATE_TIMEOUT_SEC / 2)
#define FIRMWARE_TG3 "tigon/tg3.bin"
#define FIRMWARE_TG3TSO "tigon/tg3_tso.bin"
@@ -1453,33 +1454,23 @@ static void tg3_wait_for_event_ack(struct tg3 *tp)
}
/* tp->lock is held. */
-static void tg3_ump_link_report(struct tg3 *tp)
+static void tg3_phy_gather_ump_data(struct tg3 *tp, u32 *data)
{
- u32 reg;
- u32 val;
-
- if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF))
- return;
-
- tg3_wait_for_event_ack(tp);
-
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);
-
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);
+ u32 reg, val;
val = 0;
if (!tg3_readphy(tp, MII_BMCR, &reg))
val = reg << 16;
if (!tg3_readphy(tp, MII_BMSR, &reg))
val |= (reg & 0xffff);
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val);
+ *data++ = val;
val = 0;
if (!tg3_readphy(tp, MII_ADVERTISE, &reg))
val = reg << 16;
if (!tg3_readphy(tp, MII_LPA, &reg))
val |= (reg & 0xffff);
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val);
+ *data++ = val;
val = 0;
if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) {
@@ -1488,13 +1479,33 @@ static void tg3_ump_link_report(struct tg3 *tp)
if (!tg3_readphy(tp, MII_STAT1000, &reg))
val |= (reg & 0xffff);
}
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val);
+ *data++ = val;
if (!tg3_readphy(tp, MII_PHYADDR, &reg))
val = reg << 16;
else
val = 0;
- tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
+ *data++ = val;
+}
+
+/* tp->lock is held. */
+static void tg3_ump_link_report(struct tg3 *tp)
+{
+ u32 data[4];
+
+ if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF))
+ return;
+
+ tg3_phy_gather_ump_data(tp, data);
+
+ tg3_wait_for_event_ack(tp);
+
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x0, data[0]);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x4, data[1]);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0x8, data[2]);
+ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 0xc, data[3]);
tg3_generate_fw_event(tp);
}
@@ -1809,13 +1820,13 @@ static void tg3_adjust_link(struct net_device *dev)
(6 << TX_LENGTHS_IPG_SHIFT) |
(32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
- if ((phydev->link && tp->link_config.active_speed == SPEED_INVALID) ||
- (!phydev->link && tp->link_config.active_speed != SPEED_INVALID) ||
+ if (phydev->link != tp->old_link ||
phydev->speed != tp->link_config.active_speed ||
phydev->duplex != tp->link_config.active_duplex ||
oldflowctrl != tp->link_config.active_flowctrl)
linkmesg = 1;
+ tp->old_link = phydev->link;
tp->link_config.active_speed = phydev->speed;
tp->link_config.active_duplex = phydev->duplex;
@@ -1884,10 +1895,10 @@ static void tg3_phy_start(struct tg3 *tp)
if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER;
- phydev->speed = tp->link_config.orig_speed;
- phydev->duplex = tp->link_config.orig_duplex;
- phydev->autoneg = tp->link_config.orig_autoneg;
- phydev->advertising = tp->link_config.orig_advertising;
+ phydev->speed = tp->link_config.speed;
+ phydev->duplex = tp->link_config.duplex;
+ phydev->autoneg = tp->link_config.autoneg;
+ phydev->advertising = tp->link_config.advertising;
}
phy_start(phydev);
@@ -2709,9 +2720,6 @@ static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
return 0;
}
-static int tg3_setup_phy(struct tg3 *, int);
-static int tg3_halt_cpu(struct tg3 *, u32);
-
static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
{
u32 val;
@@ -2978,6 +2986,259 @@ static int tg3_nvram_read_be32(struct tg3 *tp, u32 offset, __be32 *val)
return res;
}
+static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp,
+ u32 offset, u32 len, u8 *buf)
+{
+ int i, j, rc = 0;
+ u32 val;
+
+ for (i = 0; i < len; i += 4) {
+ u32 addr;
+ __be32 data;
+
+ addr = offset + i;
+
+ memcpy(&data, buf + i, 4);
+
+ /*
+ * The SEEPROM interface expects the data to always be opposite
+ * the native endian format. We accomplish this by reversing
+ * all the operations that would have been performed on the
+ * data from a call to tg3_nvram_read_be32().
+ */
+ tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data)));
+
+ val = tr32(GRC_EEPROM_ADDR);
+ tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE);
+
+ val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK |
+ EEPROM_ADDR_READ);
+ tw32(GRC_EEPROM_ADDR, val |
+ (0 << EEPROM_ADDR_DEVID_SHIFT) |
+ (addr & EEPROM_ADDR_ADDR_MASK) |
+ EEPROM_ADDR_START |
+ EEPROM_ADDR_WRITE);
+
+ for (j = 0; j < 1000; j++) {
+ val = tr32(GRC_EEPROM_ADDR);
+
+ if (val & EEPROM_ADDR_COMPLETE)
+ break;
+ msleep(1);
+ }
+ if (!(val & EEPROM_ADDR_COMPLETE)) {
+ rc = -EBUSY;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+/* offset and length are dword aligned */
+static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len,
+ u8 *buf)
+{
+ int ret = 0;
+ u32 pagesize = tp->nvram_pagesize;
+ u32 pagemask = pagesize - 1;
+ u32 nvram_cmd;
+ u8 *tmp;
+
+ tmp = kmalloc(pagesize, GFP_KERNEL);
+ if (tmp == NULL)
+ return -ENOMEM;
+
+ while (len) {
+ int j;
+ u32 phy_addr, page_off, size;
+
+ phy_addr = offset & ~pagemask;
+
+ for (j = 0; j < pagesize; j += 4) {
+ ret = tg3_nvram_read_be32(tp, phy_addr + j,
+ (__be32 *) (tmp + j));
+ if (ret)
+ break;
+ }
+ if (ret)
+ break;
+
+ page_off = offset & pagemask;
+ size = pagesize;
+ if (len < size)
+ size = len;
+
+ len -= size;
+
+ memcpy(tmp + page_off, buf, size);
+
+ offset = offset + (pagesize - page_off);
+
+ tg3_enable_nvram_access(tp);
+
+ /*
+ * Before we can erase the flash page, we need
+ * to issue a special "write enable" command.
+ */
+ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
+
+ if (tg3_nvram_exec_cmd(tp, nvram_cmd))
+ break;
+
+ /* Erase the target page */
+ tw32(NVRAM_ADDR, phy_addr);
+
+ nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR |
+ NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE;
+
+ if (tg3_nvram_exec_cmd(tp, nvram_cmd))
+ break;
+
+ /* Issue another write enable to start the write. */
+ nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
+
+ if (tg3_nvram_exec_cmd(tp, nvram_cmd))
+ break;
+
+ for (j = 0; j < pagesize; j += 4) {
+ __be32 data;
+
+ data = *((__be32 *) (tmp + j));
+
+ tw32(NVRAM_WRDATA, be32_to_cpu(data));
+
+ tw32(NVRAM_ADDR, phy_addr + j);
+
+ nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE |
+ NVRAM_CMD_WR;
+
+ if (j == 0)
+ nvram_cmd |= NVRAM_CMD_FIRST;
+ else if (j == (pagesize - 4))
+ nvram_cmd |= NVRAM_CMD_LAST;
+
+ ret = tg3_nvram_exec_cmd(tp, nvram_cmd);
+ if (ret)
+ break;
+ }
+ if (ret)
+ break;
+ }
+
+ nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE;
+ tg3_nvram_exec_cmd(tp, nvram_cmd);
+
+ kfree(tmp);
+
+ return ret;
+}
+
+/* offset and length are dword aligned */
+static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
+ u8 *buf)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < len; i += 4, offset += 4) {
+ u32 page_off, phy_addr, nvram_cmd;
+ __be32 data;
+
+ memcpy(&data, buf + i, 4);
+ tw32(NVRAM_WRDATA, be32_to_cpu(data));
+
+ page_off = offset % tp->nvram_pagesize;
+
+ phy_addr = tg3_nvram_phys_addr(tp, offset);
+
+ nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR;
+
+ if (page_off == 0 || i == 0)
+ nvram_cmd |= NVRAM_CMD_FIRST;
+ if (page_off == (tp->nvram_pagesize - 4))
+ nvram_cmd |= NVRAM_CMD_LAST;
+
+ if (i == (len - 4))
+ nvram_cmd |= NVRAM_CMD_LAST;
+
+ if ((nvram_cmd & NVRAM_CMD_FIRST) ||
+ !tg3_flag(tp, FLASH) ||
+ !tg3_flag(tp, 57765_PLUS))
+ tw32(NVRAM_ADDR, phy_addr);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
+ !tg3_flag(tp, 5755_PLUS) &&
+ (tp->nvram_jedecnum == JEDEC_ST) &&
+ (nvram_cmd & NVRAM_CMD_FIRST)) {
+ u32 cmd;
+
+ cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
+ ret = tg3_nvram_exec_cmd(tp, cmd);
+ if (ret)
+ break;
+ }
+ if (!tg3_flag(tp, FLASH)) {
+ /* We always do complete word writes to eeprom. */
+ nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST);
+ }
+
+ ret = tg3_nvram_exec_cmd(tp, nvram_cmd);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
+/* offset and length are dword aligned */
+static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
+{
+ int ret;
+
+ if (tg3_flag(tp, EEPROM_WRITE_PROT)) {
+ tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
+ ~GRC_LCLCTRL_GPIO_OUTPUT1);
+ udelay(40);
+ }
+
+ if (!tg3_flag(tp, NVRAM)) {
+ ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf);
+ } else {
+ u32 grc_mode;
+
+ ret = tg3_nvram_lock(tp);
+ if (ret)
+ return ret;
+
+ tg3_enable_nvram_access(tp);
+ if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM))
+ tw32(NVRAM_WRITE1, 0x406);
+
+ grc_mode = tr32(GRC_MODE);
+ tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE);
+
+ if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) {
+ ret = tg3_nvram_write_block_buffered(tp, offset, len,
+ buf);
+ } else {
+ ret = tg3_nvram_write_block_unbuffered(tp, offset, len,
+ buf);
+ }
+
+ grc_mode = tr32(GRC_MODE);
+ tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE);
+
+ tg3_disable_nvram_access(tp);
+ tg3_nvram_unlock(tp);
+ }
+
+ if (tg3_flag(tp, EEPROM_WRITE_PROT)) {
+ tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+ udelay(40);
+ }
+
+ return ret;
+}
+
#define RX_CPU_SCRATCH_BASE 0x30000
#define RX_CPU_SCRATCH_SIZE 0x04000
#define TX_CPU_SCRATCH_BASE 0x34000
@@ -3264,6 +3525,8 @@ static int tg3_power_up(struct tg3 *tp)
return err;
}
+static int tg3_setup_phy(struct tg3 *, int);
+
static int tg3_power_down_prepare(struct tg3 *tp)
{
u32 misc_host_ctrl;
@@ -3302,10 +3565,10 @@ static int tg3_power_down_prepare(struct tg3 *tp)
tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
- tp->link_config.orig_speed = phydev->speed;
- tp->link_config.orig_duplex = phydev->duplex;
- tp->link_config.orig_autoneg = phydev->autoneg;
- tp->link_config.orig_advertising = phydev->advertising;
+ tp->link_config.speed = phydev->speed;
+ tp->link_config.duplex = phydev->duplex;
+ tp->link_config.autoneg = phydev->autoneg;
+ tp->link_config.advertising = phydev->advertising;
advertising = ADVERTISED_TP |
ADVERTISED_Pause |
@@ -3338,19 +3601,11 @@ static int tg3_power_down_prepare(struct tg3 *tp)
} else {
do_low_power = true;
- if (!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
+ if (!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER))
tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
- tp->link_config.orig_speed = tp->link_config.speed;
- tp->link_config.orig_duplex = tp->link_config.duplex;
- tp->link_config.orig_autoneg = tp->link_config.autoneg;
- }
- if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) {
- tp->link_config.speed = SPEED_10;
- tp->link_config.duplex = DUPLEX_HALF;
- tp->link_config.autoneg = AUTONEG_ENABLE;
+ if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
tg3_setup_phy(tp, 0);
- }
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
@@ -3559,8 +3814,8 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8
DUPLEX_HALF;
break;
}
- *speed = SPEED_INVALID;
- *duplex = DUPLEX_INVALID;
+ *speed = SPEED_UNKNOWN;
+ *duplex = DUPLEX_UNKNOWN;
break;
}
}
@@ -3640,51 +3895,33 @@ done:
static void tg3_phy_copper_begin(struct tg3 *tp)
{
- u32 new_adv;
- int i;
+ if (tp->link_config.autoneg == AUTONEG_ENABLE ||
+ (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
+ u32 adv, fc;
- if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
- new_adv = ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full;
- if (tg3_flag(tp, WOL_SPEED_100MB))
- new_adv |= ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full;
-
- tg3_phy_autoneg_cfg(tp, new_adv,
- FLOW_CTRL_TX | FLOW_CTRL_RX);
- } else if (tp->link_config.speed == SPEED_INVALID) {
- if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
- tp->link_config.advertising &=
- ~(ADVERTISED_1000baseT_Half |
- ADVERTISED_1000baseT_Full);
+ if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
+ adv = ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full;
+ if (tg3_flag(tp, WOL_SPEED_100MB))
+ adv |= ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full;
- tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
- tp->link_config.flowctrl);
- } else {
- /* Asking for a specific link mode. */
- if (tp->link_config.speed == SPEED_1000) {
- if (tp->link_config.duplex == DUPLEX_FULL)
- new_adv = ADVERTISED_1000baseT_Full;
- else
- new_adv = ADVERTISED_1000baseT_Half;
- } else if (tp->link_config.speed == SPEED_100) {
- if (tp->link_config.duplex == DUPLEX_FULL)
- new_adv = ADVERTISED_100baseT_Full;
- else
- new_adv = ADVERTISED_100baseT_Half;
+ fc = FLOW_CTRL_TX | FLOW_CTRL_RX;
} else {
- if (tp->link_config.duplex == DUPLEX_FULL)
- new_adv = ADVERTISED_10baseT_Full;
- else
- new_adv = ADVERTISED_10baseT_Half;
+ adv = tp->link_config.advertising;
+ if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+ adv &= ~(ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full);
+
+ fc = tp->link_config.flowctrl;
}
- tg3_phy_autoneg_cfg(tp, new_adv,
- tp->link_config.flowctrl);
- }
+ tg3_phy_autoneg_cfg(tp, adv, fc);
- if (tp->link_config.autoneg == AUTONEG_DISABLE &&
- tp->link_config.speed != SPEED_INVALID) {
+ tg3_writephy(tp, MII_BMCR,
+ BMCR_ANENABLE | BMCR_ANRESTART);
+ } else {
+ int i;
u32 bmcr, orig_bmcr;
tp->link_config.active_speed = tp->link_config.speed;
@@ -3726,9 +3963,6 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
tg3_writephy(tp, MII_BMCR, bmcr);
udelay(40);
}
- } else {
- tg3_writephy(tp, MII_BMCR,
- BMCR_ANENABLE | BMCR_ANRESTART);
}
}
@@ -3778,7 +4012,16 @@ static bool tg3_phy_copper_an_config_ok(struct tg3 *tp, u32 *lcladv)
if (tg3_readphy(tp, MII_CTRL1000, &tg3_ctrl))
return false;
- tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
+ if (tgtadv &&
+ (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)) {
+ tgtadv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
+ tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL |
+ CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER);
+ } else {
+ tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
+ }
+
if (tg3_ctrl != tgtadv)
return false;
}
@@ -3909,8 +4152,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
}
current_link_up = 0;
- current_speed = SPEED_INVALID;
- current_duplex = DUPLEX_INVALID;
+ current_speed = SPEED_UNKNOWN;
+ current_duplex = DUPLEX_UNKNOWN;
tp->phy_flags &= ~TG3_PHYFLG_MDIX_STATE;
tp->link_config.rmt_adv = 0;
@@ -4806,8 +5049,8 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
LED_CTRL_LNKLED_OVERRIDE |
LED_CTRL_1000MBPS_ON));
} else {
- tp->link_config.active_speed = SPEED_INVALID;
- tp->link_config.active_duplex = DUPLEX_INVALID;
+ tp->link_config.active_speed = SPEED_UNKNOWN;
+ tp->link_config.active_duplex = DUPLEX_UNKNOWN;
tw32(MAC_LED_CTRL, (tp->led_ctrl |
LED_CTRL_LNKLED_OVERRIDE |
LED_CTRL_TRAFFIC_OVERRIDE));
@@ -4855,8 +5098,8 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
tg3_phy_reset(tp);
current_link_up = 0;
- current_speed = SPEED_INVALID;
- current_duplex = DUPLEX_INVALID;
+ current_speed = SPEED_UNKNOWN;
+ current_duplex = DUPLEX_UNKNOWN;
tp->link_config.rmt_adv = 0;
err |= tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -5921,6 +6164,7 @@ static inline void tg3_reset_task_cancel(struct tg3 *tp)
{
cancel_work_sync(&tp->reset_task);
tg3_flag_clear(tp, RESET_TASK_PENDING);
+ tg3_flag_clear(tp, TX_RECOVERY_PENDING);
}
static int tg3_poll_msix(struct napi_struct *napi, int budget)
@@ -6292,33 +6536,6 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id)
return IRQ_RETVAL(0);
}
-static int tg3_init_hw(struct tg3 *, int);
-static int tg3_halt(struct tg3 *, int, int);
-
-/* Restart hardware after configuration changes, self-test, etc.
- * Invoked with tp->lock held.
- */
-static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
- __releases(tp->lock)
- __acquires(tp->lock)
-{
- int err;
-
- err = tg3_init_hw(tp, reset_phy);
- if (err) {
- netdev_err(tp->dev,
- "Failed to re-initialize device, aborting\n");
- tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
- tg3_full_unlock(tp);
- del_timer_sync(&tp->timer);
- tp->irq_sync = 0;
- tg3_napi_enable(tp);
- dev_close(tp->dev);
- tg3_full_lock(tp, 0);
- }
- return err;
-}
-
#ifdef CONFIG_NET_POLL_CONTROLLER
static void tg3_poll_controller(struct net_device *dev)
{
@@ -6330,50 +6547,6 @@ static void tg3_poll_controller(struct net_device *dev)
}
#endif
-static void tg3_reset_task(struct work_struct *work)
-{
- struct tg3 *tp = container_of(work, struct tg3, reset_task);
- int err;
-
- tg3_full_lock(tp, 0);
-
- if (!netif_running(tp->dev)) {
- tg3_flag_clear(tp, RESET_TASK_PENDING);
- tg3_full_unlock(tp);
- return;
- }
-
- tg3_full_unlock(tp);
-
- tg3_phy_stop(tp);
-
- tg3_netif_stop(tp);
-
- tg3_full_lock(tp, 1);
-
- if (tg3_flag(tp, TX_RECOVERY_PENDING)) {
- tp->write32_tx_mbox = tg3_write32_tx_mbox;
- tp->write32_rx_mbox = tg3_write_flush_reg32;
- tg3_flag_set(tp, MBOX_WRITE_REORDER);
- tg3_flag_clear(tp, TX_RECOVERY_PENDING);
- }
-
- tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
- err = tg3_init_hw(tp, 1);
- if (err)
- goto out;
-
- tg3_netif_start(tp);
-
-out:
- tg3_full_unlock(tp);
-
- if (!err)
- tg3_phy_start(tp);
-
- tg3_flag_clear(tp, RESET_TASK_PENDING);
-}
-
static void tg3_tx_timeout(struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
@@ -6745,7 +6918,6 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
((skb_shinfo(skb)->nr_frags == 0) ? TXD_FLAG_END : 0),
mss, vlan)) {
would_hit_hwbug = 1;
- /* Now loop through additional data fragments, and queue them. */
} else if (skb_shinfo(skb)->nr_frags > 0) {
u32 tmp_mss = mss;
@@ -6754,6 +6926,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
!tg3_flag(tp, HW_TSO_3))
tmp_mss = 0;
+ /* Now loop through additional data
+ * fragments, and queue them.
+ */
last = skb_shinfo(skb)->nr_frags - 1;
for (i = 0; i <= last; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -6993,66 +7168,6 @@ static int tg3_set_features(struct net_device *dev, netdev_features_t features)
return 0;
}
-static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
- int new_mtu)
-{
- dev->mtu = new_mtu;
-
- if (new_mtu > ETH_DATA_LEN) {
- if (tg3_flag(tp, 5780_CLASS)) {
- netdev_update_features(dev);
- tg3_flag_clear(tp, TSO_CAPABLE);
- } else {
- tg3_flag_set(tp, JUMBO_RING_ENABLE);
- }
- } else {
- if (tg3_flag(tp, 5780_CLASS)) {
- tg3_flag_set(tp, TSO_CAPABLE);
- netdev_update_features(dev);
- }
- tg3_flag_clear(tp, JUMBO_RING_ENABLE);
- }
-}
-
-static int tg3_change_mtu(struct net_device *dev, int new_mtu)
-{
- struct tg3 *tp = netdev_priv(dev);
- int err;
-
- if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
- return -EINVAL;
-
- if (!netif_running(dev)) {
- /* We'll just catch it later when the
- * device is up'd.
- */
- tg3_set_mtu(dev, tp, new_mtu);
- return 0;
- }
-
- tg3_phy_stop(tp);
-
- tg3_netif_stop(tp);
-
- tg3_full_lock(tp, 1);
-
- tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-
- tg3_set_mtu(dev, tp, new_mtu);
-
- err = tg3_restart_hw(tp, 0);
-
- if (!err)
- tg3_netif_start(tp);
-
- tg3_full_unlock(tp);
-
- if (!err)
- tg3_phy_start(tp);
-
- return err;
-}
-
static void tg3_rx_prodring_free(struct tg3 *tp,
struct tg3_rx_prodring_set *tpr)
{
@@ -7930,7 +8045,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
int err = 0, skip_mac_1 = 0;
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
@@ -7978,7 +8093,6 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
nic_addr);
}
-static void __tg3_set_rx_mode(struct net_device *);
static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
{
int i;
@@ -8215,6 +8329,93 @@ static void tg3_setup_rxbd_thresholds(struct tg3 *tp)
tw32(JMB_REPLENISH_LWM, bdcache_maxcnt);
}
+static inline u32 calc_crc(unsigned char *buf, int len)
+{
+ u32 reg;
+ u32 tmp;
+ int j, k;
+
+ reg = 0xffffffff;
+
+ for (j = 0; j < len; j++) {
+ reg ^= buf[j];
+
+ for (k = 0; k < 8; k++) {
+ tmp = reg & 0x01;
+
+ reg >>= 1;
+
+ if (tmp)
+ reg ^= 0xedb88320;
+ }
+ }
+
+ return ~reg;
+}
+
+static void tg3_set_multi(struct tg3 *tp, unsigned int accept_all)
+{
+ /* accept or reject all multicast frames */
+ tw32(MAC_HASH_REG_0, accept_all ? 0xffffffff : 0);
+ tw32(MAC_HASH_REG_1, accept_all ? 0xffffffff : 0);
+ tw32(MAC_HASH_REG_2, accept_all ? 0xffffffff : 0);
+ tw32(MAC_HASH_REG_3, accept_all ? 0xffffffff : 0);
+}
+
+static void __tg3_set_rx_mode(struct net_device *dev)
+{
+ struct tg3 *tp = netdev_priv(dev);
+ u32 rx_mode;
+
+ rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
+ RX_MODE_KEEP_VLAN_TAG);
+
+#if !defined(CONFIG_VLAN_8021Q) && !defined(CONFIG_VLAN_8021Q_MODULE)
+ /* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG
+ * flag clear.
+ */
+ if (!tg3_flag(tp, ENABLE_ASF))
+ rx_mode |= RX_MODE_KEEP_VLAN_TAG;
+#endif
+
+ if (dev->flags & IFF_PROMISC) {
+ /* Promiscuous mode. */
+ rx_mode |= RX_MODE_PROMISC;
+ } else if (dev->flags & IFF_ALLMULTI) {
+ /* Accept all multicast. */
+ tg3_set_multi(tp, 1);
+ } else if (netdev_mc_empty(dev)) {
+ /* Reject all multicast. */
+ tg3_set_multi(tp, 0);
+ } else {
+ /* Accept one or more multicast(s). */
+ struct netdev_hw_addr *ha;
+ u32 mc_filter[4] = { 0, };
+ u32 regidx;
+ u32 bit;
+ u32 crc;
+
+ netdev_for_each_mc_addr(ha, dev) {
+ crc = calc_crc(ha->addr, ETH_ALEN);
+ bit = ~crc & 0x7f;
+ regidx = (bit & 0x60) >> 5;
+ bit &= 0x1f;
+ mc_filter[regidx] |= (1 << bit);
+ }
+
+ tw32(MAC_HASH_REG_0, mc_filter[0]);
+ tw32(MAC_HASH_REG_1, mc_filter[1]);
+ tw32(MAC_HASH_REG_2, mc_filter[2]);
+ tw32(MAC_HASH_REG_3, mc_filter[3]);
+ }
+
+ if (rx_mode != tp->rx_mode) {
+ tp->rx_mode = rx_mode;
+ tw32_f(MAC_RX_MODE, rx_mode);
+ udelay(10);
+ }
+}
+
static void tg3_rss_init_dflt_indir_tbl(struct tg3 *tp)
{
int i;
@@ -8690,9 +8891,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
if (tg3_flag(tp, PCI_EXPRESS))
rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766)
- rdmac_mode |= RDMAC_MODE_JMB_2K_MMRR;
-
if (tg3_flag(tp, HW_TSO_1) ||
tg3_flag(tp, HW_TSO_2) ||
tg3_flag(tp, HW_TSO_3))
@@ -9039,12 +9237,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
}
if (!tg3_flag(tp, USE_PHYLIB)) {
- if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
+ if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)
tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER;
- tp->link_config.speed = tp->link_config.orig_speed;
- tp->link_config.duplex = tp->link_config.orig_duplex;
- tp->link_config.autoneg = tp->link_config.orig_autoneg;
- }
err = tg3_setup_phy(tp, 0);
if (err)
@@ -9347,6 +9541,108 @@ restart_timer:
add_timer(&tp->timer);
}
+static void __devinit tg3_timer_init(struct tg3 *tp)
+{
+ if (tg3_flag(tp, TAGGED_STATUS) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
+ !tg3_flag(tp, 57765_CLASS))
+ tp->timer_offset = HZ;
+ else
+ tp->timer_offset = HZ / 10;
+
+ BUG_ON(tp->timer_offset > HZ);
+
+ tp->timer_multiplier = (HZ / tp->timer_offset);
+ tp->asf_multiplier = (HZ / tp->timer_offset) *
+ TG3_FW_UPDATE_FREQ_SEC;
+
+ init_timer(&tp->timer);
+ tp->timer.data = (unsigned long) tp;
+ tp->timer.function = tg3_timer;
+}
+
+static void tg3_timer_start(struct tg3 *tp)
+{
+ tp->asf_counter = tp->asf_multiplier;
+ tp->timer_counter = tp->timer_multiplier;
+
+ tp->timer.expires = jiffies + tp->timer_offset;
+ add_timer(&tp->timer);
+}
+
+static void tg3_timer_stop(struct tg3 *tp)
+{
+ del_timer_sync(&tp->timer);
+}
+
+/* Restart hardware after configuration changes, self-test, etc.
+ * Invoked with tp->lock held.
+ */
+static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
+ __releases(tp->lock)
+ __acquires(tp->lock)
+{
+ int err;
+
+ err = tg3_init_hw(tp, reset_phy);
+ if (err) {
+ netdev_err(tp->dev,
+ "Failed to re-initialize device, aborting\n");
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
+ tg3_full_unlock(tp);
+ tg3_timer_stop(tp);
+ tp->irq_sync = 0;
+ tg3_napi_enable(tp);
+ dev_close(tp->dev);
+ tg3_full_lock(tp, 0);
+ }
+ return err;
+}
+
+static void tg3_reset_task(struct work_struct *work)
+{
+ struct tg3 *tp = container_of(work, struct tg3, reset_task);
+ int err;
+
+ tg3_full_lock(tp, 0);
+
+ if (!netif_running(tp->dev)) {
+ tg3_flag_clear(tp, RESET_TASK_PENDING);
+ tg3_full_unlock(tp);
+ return;
+ }
+
+ tg3_full_unlock(tp);
+
+ tg3_phy_stop(tp);
+
+ tg3_netif_stop(tp);
+
+ tg3_full_lock(tp, 1);
+
+ if (tg3_flag(tp, TX_RECOVERY_PENDING)) {
+ tp->write32_tx_mbox = tg3_write32_tx_mbox;
+ tp->write32_rx_mbox = tg3_write_flush_reg32;
+ tg3_flag_set(tp, MBOX_WRITE_REORDER);
+ tg3_flag_clear(tp, TX_RECOVERY_PENDING);
+ }
+
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
+ err = tg3_init_hw(tp, 1);
+ if (err)
+ goto out;
+
+ tg3_netif_start(tp);
+
+out:
+ tg3_full_unlock(tp);
+
+ if (!err)
+ tg3_phy_start(tp);
+
+ tg3_flag_clear(tp, RESET_TASK_PENDING);
+}
+
static int tg3_request_irq(struct tg3 *tp, int irq_num)
{
irq_handler_t fn;
@@ -9401,7 +9697,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
}
err = request_irq(tnapi->irq_vec, tg3_test_isr,
- IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi);
+ IRQF_SHARED, dev->name, tnapi);
if (err)
return err;
@@ -9712,24 +10008,6 @@ static int tg3_open(struct net_device *dev)
if (err) {
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
- } else {
- if (tg3_flag(tp, TAGGED_STATUS) &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
- !tg3_flag(tp, 57765_CLASS))
- tp->timer_offset = HZ;
- else
- tp->timer_offset = HZ / 10;
-
- BUG_ON(tp->timer_offset > HZ);
- tp->timer_counter = tp->timer_multiplier =
- (HZ / tp->timer_offset);
- tp->asf_counter = tp->asf_multiplier =
- ((HZ / tp->timer_offset) * 2);
-
- init_timer(&tp->timer);
- tp->timer.expires = jiffies + tp->timer_offset;
- tp->timer.data = (unsigned long) tp;
- tp->timer.function = tg3_timer;
}
tg3_full_unlock(tp);
@@ -9761,7 +10039,7 @@ static int tg3_open(struct net_device *dev)
tg3_full_lock(tp, 0);
- add_timer(&tp->timer);
+ tg3_timer_start(tp);
tg3_flag_set(tp, INIT_COMPLETE);
tg3_enable_ints(tp);
@@ -9806,7 +10084,7 @@ static int tg3_close(struct net_device *dev)
netif_tx_stop_all_queues(dev);
- del_timer_sync(&tp->timer);
+ tg3_timer_stop(tp);
tg3_phy_stop(tp);
@@ -9883,9 +10161,6 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp,
struct tg3_ethtool_stats *old_estats = &tp->estats_prev;
struct tg3_hw_stats *hw_stats = tp->hw_stats;
- if (!hw_stats)
- return old_estats;
-
ESTAT_ADD(rx_octets);
ESTAT_ADD(rx_fragments);
ESTAT_ADD(rx_ucast_packets);
@@ -10030,105 +10305,6 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
return stats;
}
-static inline u32 calc_crc(unsigned char *buf, int len)
-{
- u32 reg;
- u32 tmp;
- int j, k;
-
- reg = 0xffffffff;
-
- for (j = 0; j < len; j++) {
- reg ^= buf[j];
-
- for (k = 0; k < 8; k++) {
- tmp = reg & 0x01;
-
- reg >>= 1;
-
- if (tmp)
- reg ^= 0xedb88320;
- }
- }
-
- return ~reg;
-}
-
-static void tg3_set_multi(struct tg3 *tp, unsigned int accept_all)
-{
- /* accept or reject all multicast frames */
- tw32(MAC_HASH_REG_0, accept_all ? 0xffffffff : 0);
- tw32(MAC_HASH_REG_1, accept_all ? 0xffffffff : 0);
- tw32(MAC_HASH_REG_2, accept_all ? 0xffffffff : 0);
- tw32(MAC_HASH_REG_3, accept_all ? 0xffffffff : 0);
-}
-
-static void __tg3_set_rx_mode(struct net_device *dev)
-{
- struct tg3 *tp = netdev_priv(dev);
- u32 rx_mode;
-
- rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
- RX_MODE_KEEP_VLAN_TAG);
-
-#if !defined(CONFIG_VLAN_8021Q) && !defined(CONFIG_VLAN_8021Q_MODULE)
- /* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG
- * flag clear.
- */
- if (!tg3_flag(tp, ENABLE_ASF))
- rx_mode |= RX_MODE_KEEP_VLAN_TAG;
-#endif
-
- if (dev->flags & IFF_PROMISC) {
- /* Promiscuous mode. */
- rx_mode |= RX_MODE_PROMISC;
- } else if (dev->flags & IFF_ALLMULTI) {
- /* Accept all multicast. */
- tg3_set_multi(tp, 1);
- } else if (netdev_mc_empty(dev)) {
- /* Reject all multicast. */
- tg3_set_multi(tp, 0);
- } else {
- /* Accept one or more multicast(s). */
- struct netdev_hw_addr *ha;
- u32 mc_filter[4] = { 0, };
- u32 regidx;
- u32 bit;
- u32 crc;
-
- netdev_for_each_mc_addr(ha, dev) {
- crc = calc_crc(ha->addr, ETH_ALEN);
- bit = ~crc & 0x7f;
- regidx = (bit & 0x60) >> 5;
- bit &= 0x1f;
- mc_filter[regidx] |= (1 << bit);
- }
-
- tw32(MAC_HASH_REG_0, mc_filter[0]);
- tw32(MAC_HASH_REG_1, mc_filter[1]);
- tw32(MAC_HASH_REG_2, mc_filter[2]);
- tw32(MAC_HASH_REG_3, mc_filter[3]);
- }
-
- if (rx_mode != tp->rx_mode) {
- tp->rx_mode = rx_mode;
- tw32_f(MAC_RX_MODE, rx_mode);
- udelay(10);
- }
-}
-
-static void tg3_set_rx_mode(struct net_device *dev)
-{
- struct tg3 *tp = netdev_priv(dev);
-
- if (!netif_running(dev))
- return;
-
- tg3_full_lock(tp, 0);
- __tg3_set_rx_mode(dev);
- tg3_full_unlock(tp);
-}
-
static int tg3_get_regs_len(struct net_device *dev)
{
return TG3_REG_BLK_SIZE;
@@ -10223,8 +10399,6 @@ static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
return 0;
}
-static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf);
-
static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
{
struct tg3 *tp = netdev_priv(dev);
@@ -10338,8 +10512,8 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->eth_tp_mdix = ETH_TP_MDI;
}
} else {
- ethtool_cmd_speed_set(cmd, SPEED_INVALID);
- cmd->duplex = DUPLEX_INVALID;
+ ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
+ cmd->duplex = DUPLEX_UNKNOWN;
cmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
}
cmd->phy_address = tp->phy_addr;
@@ -10421,18 +10595,14 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (cmd->autoneg == AUTONEG_ENABLE) {
tp->link_config.advertising = (cmd->advertising |
ADVERTISED_Autoneg);
- tp->link_config.speed = SPEED_INVALID;
- tp->link_config.duplex = DUPLEX_INVALID;
+ tp->link_config.speed = SPEED_UNKNOWN;
+ tp->link_config.duplex = DUPLEX_UNKNOWN;
} else {
tp->link_config.advertising = 0;
tp->link_config.speed = speed;
tp->link_config.duplex = cmd->duplex;
}
- tp->link_config.orig_speed = tp->link_config.speed;
- tp->link_config.orig_duplex = tp->link_config.duplex;
- tp->link_config.orig_autoneg = tp->link_config.autoneg;
-
if (netif_running(dev))
tg3_setup_phy(tp, 1);
@@ -10679,10 +10849,10 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
if (!epause->autoneg)
tg3_setup_flow_control(tp, 0, 0);
} else {
- tp->link_config.orig_advertising &=
+ tp->link_config.advertising &=
~(ADVERTISED_Pause |
ADVERTISED_Asym_Pause);
- tp->link_config.orig_advertising |= newadv;
+ tp->link_config.advertising |= newadv;
}
} else {
int irq_sync = 0;
@@ -10859,7 +11029,10 @@ static void tg3_get_ethtool_stats(struct net_device *dev,
{
struct tg3 *tp = netdev_priv(dev);
- tg3_get_estats(tp, (struct tg3_ethtool_stats *)tmp_stats);
+ if (tp->hw_stats)
+ tg3_get_estats(tp, (struct tg3_ethtool_stats *)tmp_stats);
+ else
+ memset(tmp_stats, 0, sizeof(struct tg3_ethtool_stats));
}
static __be32 *tg3_vpd_readblock(struct tg3 *tp, u32 *vpdlen)
@@ -12040,6 +12213,96 @@ static const struct ethtool_ops tg3_ethtool_ops = {
.set_rxfh_indir = tg3_set_rxfh_indir,
};
+static void tg3_set_rx_mode(struct net_device *dev)
+{
+ struct tg3 *tp = netdev_priv(dev);
+
+ if (!netif_running(dev))
+ return;
+
+ tg3_full_lock(tp, 0);
+ __tg3_set_rx_mode(dev);
+ tg3_full_unlock(tp);
+}
+
+static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
+ int new_mtu)
+{
+ dev->mtu = new_mtu;
+
+ if (new_mtu > ETH_DATA_LEN) {
+ if (tg3_flag(tp, 5780_CLASS)) {
+ netdev_update_features(dev);
+ tg3_flag_clear(tp, TSO_CAPABLE);
+ } else {
+ tg3_flag_set(tp, JUMBO_RING_ENABLE);
+ }
+ } else {
+ if (tg3_flag(tp, 5780_CLASS)) {
+ tg3_flag_set(tp, TSO_CAPABLE);
+ netdev_update_features(dev);
+ }
+ tg3_flag_clear(tp, JUMBO_RING_ENABLE);
+ }
+}
+
+static int tg3_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct tg3 *tp = netdev_priv(dev);
+ int err;
+
+ if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
+ return -EINVAL;
+
+ if (!netif_running(dev)) {
+ /* We'll just catch it later when the
+ * device is up'd.
+ */
+ tg3_set_mtu(dev, tp, new_mtu);
+ return 0;
+ }
+
+ tg3_phy_stop(tp);
+
+ tg3_netif_stop(tp);
+
+ tg3_full_lock(tp, 1);
+
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
+
+ tg3_set_mtu(dev, tp, new_mtu);
+
+ err = tg3_restart_hw(tp, 0);
+
+ if (!err)
+ tg3_netif_start(tp);
+
+ tg3_full_unlock(tp);
+
+ if (!err)
+ tg3_phy_start(tp);
+
+ return err;
+}
+
+static const struct net_device_ops tg3_netdev_ops = {
+ .ndo_open = tg3_open,
+ .ndo_stop = tg3_close,
+ .ndo_start_xmit = tg3_start_xmit,
+ .ndo_get_stats64 = tg3_get_stats64,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_rx_mode = tg3_set_rx_mode,
+ .ndo_set_mac_address = tg3_set_mac_addr,
+ .ndo_do_ioctl = tg3_ioctl,
+ .ndo_tx_timeout = tg3_tx_timeout,
+ .ndo_change_mtu = tg3_change_mtu,
+ .ndo_fix_features = tg3_fix_features,
+ .ndo_set_features = tg3_set_features,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = tg3_poll_controller,
+#endif
+};
+
static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
{
u32 cursize, val, magic;
@@ -12731,254 +12994,6 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
}
}
-static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp,
- u32 offset, u32 len, u8 *buf)
-{
- int i, j, rc = 0;
- u32 val;
-
- for (i = 0; i < len; i += 4) {
- u32 addr;
- __be32 data;
-
- addr = offset + i;
-
- memcpy(&data, buf + i, 4);
-
- /*
- * The SEEPROM interface expects the data to always be opposite
- * the native endian format. We accomplish this by reversing
- * all the operations that would have been performed on the
- * data from a call to tg3_nvram_read_be32().
- */
- tw32(GRC_EEPROM_DATA, swab32(be32_to_cpu(data)));
-
- val = tr32(GRC_EEPROM_ADDR);
- tw32(GRC_EEPROM_ADDR, val | EEPROM_ADDR_COMPLETE);
-
- val &= ~(EEPROM_ADDR_ADDR_MASK | EEPROM_ADDR_DEVID_MASK |
- EEPROM_ADDR_READ);
- tw32(GRC_EEPROM_ADDR, val |
- (0 << EEPROM_ADDR_DEVID_SHIFT) |
- (addr & EEPROM_ADDR_ADDR_MASK) |
- EEPROM_ADDR_START |
- EEPROM_ADDR_WRITE);
-
- for (j = 0; j < 1000; j++) {
- val = tr32(GRC_EEPROM_ADDR);
-
- if (val & EEPROM_ADDR_COMPLETE)
- break;
- msleep(1);
- }
- if (!(val & EEPROM_ADDR_COMPLETE)) {
- rc = -EBUSY;
- break;
- }
- }
-
- return rc;
-}
-
-/* offset and length are dword aligned */
-static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len,
- u8 *buf)
-{
- int ret = 0;
- u32 pagesize = tp->nvram_pagesize;
- u32 pagemask = pagesize - 1;
- u32 nvram_cmd;
- u8 *tmp;
-
- tmp = kmalloc(pagesize, GFP_KERNEL);
- if (tmp == NULL)
- return -ENOMEM;
-
- while (len) {
- int j;
- u32 phy_addr, page_off, size;
-
- phy_addr = offset & ~pagemask;
-
- for (j = 0; j < pagesize; j += 4) {
- ret = tg3_nvram_read_be32(tp, phy_addr + j,
- (__be32 *) (tmp + j));
- if (ret)
- break;
- }
- if (ret)
- break;
-
- page_off = offset & pagemask;
- size = pagesize;
- if (len < size)
- size = len;
-
- len -= size;
-
- memcpy(tmp + page_off, buf, size);
-
- offset = offset + (pagesize - page_off);
-
- tg3_enable_nvram_access(tp);
-
- /*
- * Before we can erase the flash page, we need
- * to issue a special "write enable" command.
- */
- nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
-
- if (tg3_nvram_exec_cmd(tp, nvram_cmd))
- break;
-
- /* Erase the target page */
- tw32(NVRAM_ADDR, phy_addr);
-
- nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR |
- NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_ERASE;
-
- if (tg3_nvram_exec_cmd(tp, nvram_cmd))
- break;
-
- /* Issue another write enable to start the write. */
- nvram_cmd = NVRAM_CMD_WREN | NVRAM_CMD_GO | NVRAM_CMD_DONE;
-
- if (tg3_nvram_exec_cmd(tp, nvram_cmd))
- break;
-
- for (j = 0; j < pagesize; j += 4) {
- __be32 data;
-
- data = *((__be32 *) (tmp + j));
-
- tw32(NVRAM_WRDATA, be32_to_cpu(data));
-
- tw32(NVRAM_ADDR, phy_addr + j);
-
- nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE |
- NVRAM_CMD_WR;
-
- if (j == 0)
- nvram_cmd |= NVRAM_CMD_FIRST;
- else if (j == (pagesize - 4))
- nvram_cmd |= NVRAM_CMD_LAST;
-
- if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd)))
- break;
- }
- if (ret)
- break;
- }
-
- nvram_cmd = NVRAM_CMD_WRDI | NVRAM_CMD_GO | NVRAM_CMD_DONE;
- tg3_nvram_exec_cmd(tp, nvram_cmd);
-
- kfree(tmp);
-
- return ret;
-}
-
-/* offset and length are dword aligned */
-static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
- u8 *buf)
-{
- int i, ret = 0;
-
- for (i = 0; i < len; i += 4, offset += 4) {
- u32 page_off, phy_addr, nvram_cmd;
- __be32 data;
-
- memcpy(&data, buf + i, 4);
- tw32(NVRAM_WRDATA, be32_to_cpu(data));
-
- page_off = offset % tp->nvram_pagesize;
-
- phy_addr = tg3_nvram_phys_addr(tp, offset);
-
- tw32(NVRAM_ADDR, phy_addr);
-
- nvram_cmd = NVRAM_CMD_GO | NVRAM_CMD_DONE | NVRAM_CMD_WR;
-
- if (page_off == 0 || i == 0)
- nvram_cmd |= NVRAM_CMD_FIRST;
- if (page_off == (tp->nvram_pagesize - 4))
- nvram_cmd |= NVRAM_CMD_LAST;
-
- if (i == (len - 4))
- nvram_cmd |= NVRAM_CMD_LAST;
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
- !tg3_flag(tp, 5755_PLUS) &&
- (tp->nvram_jedecnum == JEDEC_ST) &&
- (nvram_cmd & NVRAM_CMD_FIRST)) {
-
- if ((ret = tg3_nvram_exec_cmd(tp,
- NVRAM_CMD_WREN | NVRAM_CMD_GO |
- NVRAM_CMD_DONE)))
-
- break;
- }
- if (!tg3_flag(tp, FLASH)) {
- /* We always do complete word writes to eeprom. */
- nvram_cmd |= (NVRAM_CMD_FIRST | NVRAM_CMD_LAST);
- }
-
- if ((ret = tg3_nvram_exec_cmd(tp, nvram_cmd)))
- break;
- }
- return ret;
-}
-
-/* offset and length are dword aligned */
-static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
-{
- int ret;
-
- if (tg3_flag(tp, EEPROM_WRITE_PROT)) {
- tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
- ~GRC_LCLCTRL_GPIO_OUTPUT1);
- udelay(40);
- }
-
- if (!tg3_flag(tp, NVRAM)) {
- ret = tg3_nvram_write_block_using_eeprom(tp, offset, len, buf);
- } else {
- u32 grc_mode;
-
- ret = tg3_nvram_lock(tp);
- if (ret)
- return ret;
-
- tg3_enable_nvram_access(tp);
- if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM))
- tw32(NVRAM_WRITE1, 0x406);
-
- grc_mode = tr32(GRC_MODE);
- tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE);
-
- if (tg3_flag(tp, NVRAM_BUFFERED) || !tg3_flag(tp, FLASH)) {
- ret = tg3_nvram_write_block_buffered(tp, offset, len,
- buf);
- } else {
- ret = tg3_nvram_write_block_unbuffered(tp, offset, len,
- buf);
- }
-
- grc_mode = tr32(GRC_MODE);
- tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE);
-
- tg3_disable_nvram_access(tp);
- tg3_nvram_unlock(tp);
- }
-
- if (tg3_flag(tp, EEPROM_WRITE_PROT)) {
- tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
- udelay(40);
- }
-
- return ret;
-}
-
struct subsys_tbl_ent {
u16 subsys_vendor, subsys_devid;
u32 phy_id;
@@ -13329,14 +13344,13 @@ static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
adv |= ADVERTISED_FIBRE;
tp->link_config.advertising = adv;
- tp->link_config.speed = SPEED_INVALID;
- tp->link_config.duplex = DUPLEX_INVALID;
+ tp->link_config.speed = SPEED_UNKNOWN;
+ tp->link_config.duplex = DUPLEX_UNKNOWN;
tp->link_config.autoneg = AUTONEG_ENABLE;
- tp->link_config.active_speed = SPEED_INVALID;
- tp->link_config.active_duplex = DUPLEX_INVALID;
- tp->link_config.orig_speed = SPEED_INVALID;
- tp->link_config.orig_duplex = DUPLEX_INVALID;
- tp->link_config.orig_autoneg = AUTONEG_INVALID;
+ tp->link_config.active_speed = SPEED_UNKNOWN;
+ tp->link_config.active_duplex = DUPLEX_UNKNOWN;
+
+ tp->old_link = -1;
}
static int __devinit tg3_phy_probe(struct tg3 *tp)
@@ -13833,8 +13847,6 @@ done:
tp->fw_ver[TG3_VER_SIZE - 1] = 0;
}
-static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
-
static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp)
{
if (tg3_flag(tp, LRG_PROD_RING_CAP))
@@ -13852,49 +13864,50 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = {
{ },
};
-static int __devinit tg3_get_invariants(struct tg3 *tp)
+static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
{
- u32 misc_ctrl_reg;
- u32 pci_state_reg, grc_misc_cfg;
- u32 val;
- u16 pci_cmd;
- int err;
+ struct pci_dev *peer;
+ unsigned int func, devnr = tp->pdev->devfn & ~7;
- /* Force memory write invalidate off. If we leave it on,
- * then on 5700_BX chips we have to enable a workaround.
- * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
- * to match the cacheline size. The Broadcom driver have this
- * workaround but turns MWI off all the times so never uses
- * it. This seems to suggest that the workaround is insufficient.
+ for (func = 0; func < 8; func++) {
+ peer = pci_get_slot(tp->pdev->bus, devnr | func);
+ if (peer && peer != tp->pdev)
+ break;
+ pci_dev_put(peer);
+ }
+ /* 5704 can be configured in single-port mode, set peer to
+ * tp->pdev in that case.
*/
- pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
- pci_cmd &= ~PCI_COMMAND_INVALIDATE;
- pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+ if (!peer) {
+ peer = tp->pdev;
+ return peer;
+ }
- /* Important! -- Make sure register accesses are byteswapped
- * correctly. Also, for those chips that require it, make
- * sure that indirect register accesses are enabled before
- * the first operation.
+ /*
+ * We don't need to keep the refcount elevated; there's no way
+ * to remove one half of this device without removing the other
*/
- pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
- &misc_ctrl_reg);
- tp->misc_host_ctrl |= (misc_ctrl_reg &
- MISC_HOST_CTRL_CHIPREV);
- pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
- tp->misc_host_ctrl);
+ pci_dev_put(peer);
- tp->pci_chip_rev_id = (misc_ctrl_reg >>
- MISC_HOST_CTRL_CHIPREV_SHIFT);
+ return peer;
+}
+
+static void __devinit 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) {
- u32 prod_id_asic_rev;
+ u32 reg;
+
+ /* All devices that use the alternate
+ * ASIC REV location have a CPMU.
+ */
+ tg3_flag_set(tp, CPMU_PRESENT);
if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720)
- pci_read_config_dword(tp->pdev,
- TG3PCI_GEN2_PRODID_ASICREV,
- &prod_id_asic_rev);
+ reg = TG3PCI_GEN2_PRODID_ASICREV;
else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 ||
@@ -13905,14 +13918,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57766 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57782 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57786)
- pci_read_config_dword(tp->pdev,
- TG3PCI_GEN15_PRODID_ASICREV,
- &prod_id_asic_rev);
+ reg = TG3PCI_GEN15_PRODID_ASICREV;
else
- pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
- &prod_id_asic_rev);
+ reg = TG3PCI_PRODID_ASICREV;
- tp->pci_chip_rev_id = prod_id_asic_rev;
+ pci_read_config_dword(tp->pdev, reg, &tp->pci_chip_rev_id);
}
/* Wrong chip ID in 5752 A0. This code can be removed later
@@ -13921,6 +13931,77 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
tp->pci_chip_rev_id = CHIPREV_ID_5752_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)
+ tg3_flag_set(tp, 5717_PLUS);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766)
+ tg3_flag_set(tp, 57765_CLASS);
+
+ if (tg3_flag(tp, 57765_CLASS) || tg3_flag(tp, 5717_PLUS))
+ tg3_flag_set(tp, 57765_PLUS);
+
+ /* Intentionally exclude ASIC_REV_5906 */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+ tg3_flag(tp, 57765_PLUS))
+ tg3_flag_set(tp, 5755_PLUS);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)
+ tg3_flag_set(tp, 5780_CLASS);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
+ tg3_flag(tp, 5755_PLUS) ||
+ tg3_flag(tp, 5780_CLASS))
+ tg3_flag_set(tp, 5750_PLUS);
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+ tg3_flag(tp, 5750_PLUS))
+ tg3_flag_set(tp, 5705_PLUS);
+}
+
+static int __devinit tg3_get_invariants(struct tg3 *tp)
+{
+ u32 misc_ctrl_reg;
+ u32 pci_state_reg, grc_misc_cfg;
+ u32 val;
+ u16 pci_cmd;
+ int err;
+
+ /* Force memory write invalidate off. If we leave it on,
+ * then on 5700_BX chips we have to enable a workaround.
+ * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
+ * to match the cacheline size. The Broadcom driver have this
+ * workaround but turns MWI off all the times so never uses
+ * it. This seems to suggest that the workaround is insufficient.
+ */
+ pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
+ pci_cmd &= ~PCI_COMMAND_INVALIDATE;
+ pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+
+ /* Important! -- Make sure register accesses are byteswapped
+ * correctly. Also, for those chips that require it, make
+ * sure that indirect register accesses are enabled before
+ * the first operation.
+ */
+ pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ &misc_ctrl_reg);
+ tp->misc_host_ctrl |= (misc_ctrl_reg &
+ MISC_HOST_CTRL_CHIPREV);
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+
+ tg3_detect_asic_rev(tp, misc_ctrl_reg);
+
/* If we have 5702/03 A1 or A2 on certain ICH chipsets,
* we need to disable memory and use config. cycles
* only to access all registers. The 5702/03 chips
@@ -14017,9 +14098,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
* Any tg3 device found behind the bridge will also need the 40-bit
* DMA workaround.
*/
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
- tg3_flag_set(tp, 5780_CLASS);
+ if (tg3_flag(tp, 5780_CLASS)) {
tg3_flag_set(tp, 40BIT_DMA_BUG);
tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI);
} else {
@@ -14045,39 +14124,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)
tp->pdev_peer = tg3_find_peer(tp);
- 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)
- tg3_flag_set(tp, 5717_PLUS);
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766)
- tg3_flag_set(tp, 57765_CLASS);
-
- if (tg3_flag(tp, 57765_CLASS) || tg3_flag(tp, 5717_PLUS))
- tg3_flag_set(tp, 57765_PLUS);
-
- /* Intentionally exclude ASIC_REV_5906 */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
- tg3_flag(tp, 57765_PLUS))
- tg3_flag_set(tp, 5755_PLUS);
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
- tg3_flag(tp, 5755_PLUS) ||
- tg3_flag(tp, 5780_CLASS))
- tg3_flag_set(tp, 5750_PLUS);
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
- tg3_flag(tp, 5750_PLUS))
- tg3_flag_set(tp, 5705_PLUS);
-
/* Determine TSO capabilities */
if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0)
; /* Do nothing. HW bug. */
@@ -14149,8 +14195,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
tp->dma_limit = TG3_TX_BD_DMA_MAX_4K;
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766)
- tp->dma_limit = TG3_TX_BD_DMA_MAX_2K;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
@@ -14409,13 +14453,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tg3_ape_lock_init(tp);
}
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
- tg3_flag(tp, 57765_PLUS))
- tg3_flag_set(tp, CPMU_PRESENT);
-
/* Set up tp->grc_local_ctrl before calling
* tg3_pwrsrc_switch_to_vmain(). GPIO1 driven high
* will bring 5700's external PHY out of reset.
@@ -15350,34 +15387,6 @@ static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
return str;
}
-static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
-{
- struct pci_dev *peer;
- unsigned int func, devnr = tp->pdev->devfn & ~7;
-
- for (func = 0; func < 8; func++) {
- peer = pci_get_slot(tp->pdev->bus, devnr | func);
- if (peer && peer != tp->pdev)
- break;
- pci_dev_put(peer);
- }
- /* 5704 can be configured in single-port mode, set peer to
- * tp->pdev in that case.
- */
- if (!peer) {
- peer = tp->pdev;
- return peer;
- }
-
- /*
- * We don't need to keep the refcount elevated; there's no way
- * to remove one half of this device without removing the other
- */
- pci_dev_put(peer);
-
- return peer;
-}
-
static void __devinit tg3_init_coal(struct tg3 *tp)
{
struct ethtool_coalesce *ec = &tp->coal;
@@ -15409,24 +15418,6 @@ static void __devinit tg3_init_coal(struct tg3 *tp)
}
}
-static const struct net_device_ops tg3_netdev_ops = {
- .ndo_open = tg3_open,
- .ndo_stop = tg3_close,
- .ndo_start_xmit = tg3_start_xmit,
- .ndo_get_stats64 = tg3_get_stats64,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_rx_mode = tg3_set_rx_mode,
- .ndo_set_mac_address = tg3_set_mac_addr,
- .ndo_do_ioctl = tg3_ioctl,
- .ndo_tx_timeout = tg3_tx_timeout,
- .ndo_change_mtu = tg3_change_mtu,
- .ndo_fix_features = tg3_fix_features,
- .ndo_set_features = tg3_set_features,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = tg3_poll_controller,
-#endif
-};
-
static int __devinit tg3_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -15471,7 +15462,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS);
if (!dev) {
- dev_err(&pdev->dev, "Etherdev alloc failed, aborting\n");
err = -ENOMEM;
goto err_out_power_down;
}
@@ -15728,6 +15718,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tg3_frob_aux_power(tp, false);
}
+ tg3_timer_init(tp);
+
err = register_netdev(dev);
if (err) {
dev_err(&pdev->dev, "Cannot register net device, aborting\n");
@@ -15853,7 +15845,7 @@ static int tg3_suspend(struct device *device)
tg3_phy_stop(tp);
tg3_netif_stop(tp);
- del_timer_sync(&tp->timer);
+ tg3_timer_stop(tp);
tg3_full_lock(tp, 1);
tg3_disable_ints(tp);
@@ -15877,8 +15869,7 @@ static int tg3_suspend(struct device *device)
if (err2)
goto out;
- tp->timer.expires = jiffies + tp->timer_offset;
- add_timer(&tp->timer);
+ tg3_timer_start(tp);
netif_device_attach(dev);
tg3_netif_start(tp);
@@ -15912,8 +15903,7 @@ static int tg3_resume(struct device *device)
if (err)
goto out;
- tp->timer.expires = jiffies + tp->timer_offset;
- add_timer(&tp->timer);
+ tg3_timer_start(tp);
tg3_netif_start(tp);
@@ -15961,11 +15951,10 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
tg3_netif_stop(tp);
- del_timer_sync(&tp->timer);
+ tg3_timer_stop(tp);
/* Want to make sure that the reset task doesn't run */
tg3_reset_task_cancel(tp);
- tg3_flag_clear(tp, TX_RECOVERY_PENDING);
netif_device_detach(netdev);
@@ -16058,8 +16047,7 @@ static void tg3_io_resume(struct pci_dev *pdev)
netif_device_attach(netdev);
- tp->timer.expires = jiffies + tp->timer_offset;
- add_timer(&tp->timer);
+ tg3_timer_start(tp);
tg3_netif_start(tp);
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index aea8f72c24fa..66bcfca55261 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -4,7 +4,7 @@
* Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
* Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com)
* Copyright (C) 2004 Sun Microsystems Inc.
- * Copyright (C) 2007-2011 Broadcom Corporation.
+ * Copyright (C) 2007-2012 Broadcom Corporation.
*/
#ifndef _T3_H
@@ -2702,19 +2702,8 @@ struct tg3_link_config {
u8 active_flowctrl;
u8 active_duplex;
-#define SPEED_INVALID 0xffff
-#define DUPLEX_INVALID 0xff
-#define AUTONEG_INVALID 0xff
u16 active_speed;
u32 rmt_adv;
-
- /* When we go in and out of low power mode we need
- * to swap with this state.
- */
- u16 orig_speed;
- u8 orig_duplex;
- u8 orig_autoneg;
- u32 orig_advertising;
};
struct tg3_bufmgr_config {
@@ -3075,6 +3064,7 @@ struct tg3 {
struct mii_bus *mdio_bus;
int mdio_irq[PHY_MAX_ADDR];
+ int old_link;
u8 phy_addr;
diff --git a/drivers/net/ethernet/brocade/bna/bfa_cee.c b/drivers/net/ethernet/brocade/bna/bfa_cee.c
index 29f284f79e02..689e5e19cc0b 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_cee.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_cee.c
@@ -203,7 +203,7 @@ bfa_nw_cee_get_attr(struct bfa_cee *cee, struct bfa_cee_attr *attr,
if (!bfa_nw_ioc_is_operational(cee->ioc))
return BFA_STATUS_IOC_FAILURE;
- if (cee->get_attr_pending == true)
+ if (cee->get_attr_pending)
return BFA_STATUS_DEVBUSY;
cee->get_attr_pending = true;
@@ -272,7 +272,7 @@ bfa_cee_notify(void *arg, enum bfa_ioc_event event)
switch (event) {
case BFA_IOC_E_DISABLED:
case BFA_IOC_E_FAILED:
- if (cee->get_attr_pending == true) {
+ if (cee->get_attr_pending) {
cee->get_attr_status = BFA_STATUS_FAILED;
cee->get_attr_pending = false;
if (cee->cbfn.get_attr_cbfn) {
@@ -281,7 +281,7 @@ bfa_cee_notify(void *arg, enum bfa_ioc_event event)
BFA_STATUS_FAILED);
}
}
- if (cee->get_stats_pending == true) {
+ if (cee->get_stats_pending) {
cee->get_stats_status = BFA_STATUS_FAILED;
cee->get_stats_pending = false;
if (cee->cbfn.get_stats_cbfn) {
@@ -290,7 +290,7 @@ bfa_cee_notify(void *arg, enum bfa_ioc_event event)
BFA_STATUS_FAILED);
}
}
- if (cee->reset_stats_pending == true) {
+ if (cee->reset_stats_pending) {
cee->reset_stats_status = BFA_STATUS_FAILED;
cee->reset_stats_pending = false;
if (cee->cbfn.reset_stats_cbfn) {
diff --git a/drivers/net/ethernet/brocade/bna/bfa_defs.h b/drivers/net/ethernet/brocade/bna/bfa_defs.h
index 871c6309334c..48f877337390 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_defs.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_defs.h
@@ -297,6 +297,7 @@ enum bfa_mode {
#define BFA_FLASH_PART_ENTRY_SIZE 32 /* partition entry size */
#define BFA_FLASH_PART_MAX 32 /* maximal # of partitions */
#define BFA_TOTAL_FLASH_SIZE 0x400000
+#define BFA_FLASH_PART_FWIMG 2
#define BFA_FLASH_PART_MFG 7
/*
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index abfad275b5f3..77977d735dd7 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -692,7 +692,7 @@ static void
bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf)
{
/* Call only the first time sm enters fwmismatch state. */
- if (iocpf->fw_mismatch_notified == false)
+ if (!iocpf->fw_mismatch_notified)
bfa_ioc_pf_fwmismatch(iocpf->ioc);
iocpf->fw_mismatch_notified = true;
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index be7d91e4b785..ff78f770dec9 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -3284,7 +3284,6 @@ bnad_pci_probe(struct pci_dev *pdev,
*/
netdev = alloc_etherdev(sizeof(struct bnad));
if (!netdev) {
- dev_err(&pdev->dev, "netdev allocation failed\n");
err = -ENOMEM;
return err;
}
diff --git a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
index 592ad3929f53..c9fdceb135f3 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
@@ -62,8 +62,6 @@ bnad_debugfs_open_fwtrc(struct inode *inode, struct file *file)
if (!fw_debug->debug_buffer) {
kfree(fw_debug);
fw_debug = NULL;
- pr_warn("bna %s: Failed to allocate fwtrc buffer\n",
- pci_name(bnad->pcidev));
return -ENOMEM;
}
@@ -105,8 +103,6 @@ bnad_debugfs_open_fwsave(struct inode *inode, struct file *file)
if (!fw_debug->debug_buffer) {
kfree(fw_debug);
fw_debug = NULL;
- pr_warn("bna %s: Failed to allocate fwsave buffer\n",
- pci_name(bnad->pcidev));
return -ENOMEM;
}
@@ -208,8 +204,6 @@ bnad_debugfs_open_drvinfo(struct inode *inode, struct file *file)
if (!drv_info->debug_buffer) {
kfree(drv_info);
drv_info = NULL;
- pr_warn("bna %s: Failed to allocate drv info buffer\n",
- pci_name(bnad->pcidev));
return -ENOMEM;
}
@@ -348,11 +342,8 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf,
/* Allocate memory to store the user space buf */
kern_buf = kzalloc(nbytes, GFP_KERNEL);
- if (!kern_buf) {
- pr_warn("bna %s: Failed to allocate user buffer\n",
- pci_name(bnad->pcidev));
+ if (!kern_buf)
return -ENOMEM;
- }
if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) {
kfree(kern_buf);
@@ -373,11 +364,8 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf,
bnad->reglen = 0;
bnad->regdata = kzalloc(len << 2, GFP_KERNEL);
- if (!bnad->regdata) {
- pr_warn("bna %s: Failed to allocate regrd buffer\n",
- pci_name(bnad->pcidev));
+ if (!bnad->regdata)
return -ENOMEM;
- }
bnad->reglen = len << 2;
rb = bfa_ioc_bar0(ioc);
@@ -421,11 +409,8 @@ bnad_debugfs_write_regwr(struct file *file, const char __user *buf,
/* Allocate memory to store the user space buf */
kern_buf = kzalloc(nbytes, GFP_KERNEL);
- if (!kern_buf) {
- pr_warn("bna %s: Failed to allocate user buffer\n",
- pci_name(bnad->pcidev));
+ if (!kern_buf)
return -ENOMEM;
- }
if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) {
kfree(kern_buf);
diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
index 803ea32aa99d..ab753d7334a6 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
@@ -1070,6 +1070,47 @@ done:
return ret;
}
+static int
+bnad_flash_device(struct net_device *netdev, struct ethtool_flash *eflash)
+{
+ struct bnad *bnad = netdev_priv(netdev);
+ struct bnad_iocmd_comp fcomp;
+ const struct firmware *fw;
+ int ret = 0;
+
+ ret = request_firmware(&fw, eflash->data, &bnad->pcidev->dev);
+ if (ret) {
+ pr_err("BNA: Can't locate firmware %s\n", eflash->data);
+ goto out;
+ }
+
+ fcomp.bnad = bnad;
+ fcomp.comp_status = 0;
+
+ init_completion(&fcomp.comp);
+ spin_lock_irq(&bnad->bna_lock);
+ ret = bfa_nw_flash_update_part(&bnad->bna.flash, BFA_FLASH_PART_FWIMG,
+ bnad->id, (u8 *)fw->data, fw->size, 0,
+ bnad_cb_completion, &fcomp);
+ if (ret != BFA_STATUS_OK) {
+ pr_warn("BNA: Flash update failed with err: %d\n", ret);
+ ret = -EIO;
+ spin_unlock_irq(&bnad->bna_lock);
+ goto out;
+ }
+
+ spin_unlock_irq(&bnad->bna_lock);
+ wait_for_completion(&fcomp.comp);
+ if (fcomp.comp_status != BFA_STATUS_OK) {
+ ret = -EIO;
+ pr_warn("BNA: Firmware image update to flash failed with: %d\n",
+ fcomp.comp_status);
+ }
+out:
+ release_firmware(fw);
+ return ret;
+}
+
static const struct ethtool_ops bnad_ethtool_ops = {
.get_settings = bnad_get_settings,
.set_settings = bnad_set_settings,
@@ -1088,6 +1129,7 @@ static const struct ethtool_ops bnad_ethtool_ops = {
.get_eeprom_len = bnad_get_eeprom_len,
.get_eeprom = bnad_get_eeprom,
.set_eeprom = bnad_set_eeprom,
+ .flash_device = bnad_flash_device,
};
void
diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
index 1a5b6efa0120..906117016fc4 100644
--- a/drivers/net/ethernet/cadence/at91_ether.c
+++ b/drivers/net/ethernet/cadence/at91_ether.c
@@ -886,7 +886,7 @@ static void at91ether_rx(struct net_device *dev)
while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
p_recv = dlist->recv_buf[lp->rxBuffIndex];
pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */
- skb = dev_alloc_skb(pktlen + 2);
+ skb = netdev_alloc_skb(dev, pktlen + 2);
if (skb != NULL) {
skb_reserve(skb, 2);
memcpy(skb_put(skb, pktlen), p_recv, pktlen);
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 23200680d4c1..c4834c23be35 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -87,7 +87,7 @@ static void __init macb_get_hwaddr(struct macb *bp)
memcpy(bp->dev->dev_addr, addr, sizeof(addr));
} else {
netdev_info(bp->dev, "invalid hw address, using random\n");
- random_ether_addr(bp->dev->dev_addr);
+ eth_hw_addr_random(bp->dev);
}
}
@@ -397,7 +397,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
netdev_dbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
first_frag, last_frag, len);
- skb = dev_alloc_skb(len + RX_OFFSET);
+ skb = netdev_alloc_skb(bp->dev, len + RX_OFFSET);
if (!skb) {
bp->stats.rx_dropped++;
for (frag = first_frag; ; frag = NEXT_RX(frag)) {
@@ -1308,10 +1308,8 @@ static int __init macb_probe(struct platform_device *pdev)
err = -ENOMEM;
dev = alloc_etherdev(sizeof(*bp));
- if (!dev) {
- dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n");
+ if (!dev)
goto err_out;
- }
SET_NETDEV_DEV(dev, &pdev->dev);
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 1fce186a9031..11f667f6131a 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1012,7 +1012,7 @@ static int xgmac_open(struct net_device *dev)
* address using the following linux command:
* ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx */
if (!is_valid_ether_addr(dev->dev_addr)) {
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
netdev_dbg(priv->dev, "generated random MAC address %pM\n",
dev->dev_addr);
}
@@ -1482,6 +1482,7 @@ static int xgmac_set_mac_address(struct net_device *dev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
xgmac_set_mac_addr(ioaddr, dev->dev_addr, 0);
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 857cc254cab8..63bfdd10bd6d 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -2499,7 +2499,7 @@ static int cxgb_set_mac_addr(struct net_device *dev, void *p)
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
t3_mac_set_address(&pi->mac, LAN_MAC_IDX, dev->dev_addr);
diff --git a/drivers/net/ethernet/chelsio/cxgb3/version.h b/drivers/net/ethernet/chelsio/cxgb3/version.h
index 8bda06e366c8..165bfb91487a 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/version.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/version.h
@@ -35,10 +35,10 @@
#define DRV_DESC "Chelsio T3 Network Driver"
#define DRV_NAME "cxgb3"
/* Driver version */
-#define DRV_VERSION "1.1.4-ko"
+#define DRV_VERSION "1.1.5-ko"
/* Firmware version */
#define FW_VERSION_MAJOR 7
-#define FW_VERSION_MINOR 10
+#define FW_VERSION_MINOR 12
#define FW_VERSION_MICRO 0
#endif /* __CHELSIO_VERSION_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index e83d12c7bf20..1d889427073f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2809,7 +2809,7 @@ static int cxgb_set_mac_addr(struct net_device *dev, void *p)
struct port_info *pi = netdev_priv(dev);
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
ret = t4_change_mac(pi->adapter, pi->adapter->fn, pi->viid,
pi->xact_addr_filt, addr->sa_data, true, true);
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index e53365a71484..3f580c0c28a6 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -1130,7 +1130,7 @@ static int cxgb4vf_set_mac_addr(struct net_device *dev, void *_addr)
struct port_info *pi = netdev_priv(dev);
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
ret = t4vf_change_mac(pi->adapter, pi->viid, pi->xact_addr_filt,
addr->sa_data, true);
@@ -2596,8 +2596,6 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
netdev = alloc_etherdev_mq(sizeof(struct port_info),
MAX_PORT_QSETS);
if (netdev == NULL) {
- dev_err(&pdev->dev, "cannot allocate netdev for"
- " port %d\n", port_id);
t4vf_free_vi(adapter, viid);
err = -ENOMEM;
goto err_free_dev;
diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c
index f328da24c8fa..d5ff93653e4c 100644
--- a/drivers/net/ethernet/cirrus/cs89x0.c
+++ b/drivers/net/ethernet/cirrus/cs89x0.c
@@ -911,7 +911,7 @@ dma_rx(struct net_device *dev)
}
/* Malloc up new buffer. */
- skb = dev_alloc_skb(length + 2);
+ skb = netdev_alloc_skb(dev, length + 2);
if (skb == NULL) {
if (net_debug) /* I don't think we want to do this to a stressed system */
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
@@ -1616,7 +1616,7 @@ net_rx(struct net_device *dev)
}
/* Malloc up new buffer. */
- skb = dev_alloc_skb(length + 2);
+ skb = netdev_alloc_skb(dev, length + 2);
if (skb == NULL) {
#if 0 /* Again, this seems a cruel thing to do */
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c
index 4317af8d2f0a..78c55213eaf7 100644
--- a/drivers/net/ethernet/cirrus/ep93xx_eth.c
+++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c
@@ -282,7 +282,7 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget)
if (rstat0 & RSTAT0_CRCI)
length -= 4;
- skb = dev_alloc_skb(length + 2);
+ skb = netdev_alloc_skb(dev, length + 2);
if (likely(skb != NULL)) {
struct ep93xx_rdesc *rxd = &ep->descs->rdesc[entry];
skb_reserve(skb, 2);
@@ -859,7 +859,7 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
ep->mdc_divisor = 40; /* Max HCLK 100 MHz, min MDIO clk 2.5 MHz. */
if (is_zero_ether_addr(dev->dev_addr))
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
err = register_netdev(dev);
if (err) {
diff --git a/drivers/net/ethernet/cirrus/mac89x0.c b/drivers/net/ethernet/cirrus/mac89x0.c
index 83781f316d1f..419825ceab3b 100644
--- a/drivers/net/ethernet/cirrus/mac89x0.c
+++ b/drivers/net/ethernet/cirrus/mac89x0.c
@@ -592,10 +592,14 @@ static void set_multicast_list(struct net_device *dev)
static int set_mac_address(struct net_device *dev, void *addr)
{
int i;
- printk("%s: Setting MAC address to ", dev->name);
- for (i = 0; i < 6; i++)
- printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);
- printk(".\n");
+ struct sockaddr *saddr = addr;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+ printk("%s: Setting MAC address to %pM\n", dev->name, dev->dev_addr);
+
/* set the Ethernet address */
for (i=0; i < ETH_ALEN/2; i++)
writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index ee93a2087fe6..99998c606d3e 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -32,13 +32,13 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION "2.1.1.31"
+#define DRV_VERSION "2.1.1.38"
#define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
#define ENIC_WQ_MAX 1
-#define ENIC_RQ_MAX 1
+#define ENIC_RQ_MAX 8
#define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX)
#define ENIC_INTR_MAX (ENIC_CQ_MAX + 2)
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index ab3f67f980d8..e27ec1d3778d 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -865,6 +865,7 @@ static int enic_set_mac_addr(struct net_device *netdev, char *addr)
}
memcpy(netdev->dev_addr, addr, netdev->addr_len);
+ netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
return 0;
}
@@ -1069,8 +1070,17 @@ static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
return err;
if (is_valid_ether_addr(mac)) {
- memcpy(pp->vf_mac, mac, ETH_ALEN);
- return 0;
+ if (vf == PORT_SELF_VF) {
+ memcpy(pp->vf_mac, mac, ETH_ALEN);
+ return 0;
+ } else {
+ /*
+ * For sriov vf's set the mac in hw
+ */
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic,
+ vnic_dev_set_mac_addr, mac);
+ return enic_dev_status_to_errno(err);
+ }
} else
return -EINVAL;
}
@@ -1114,12 +1124,23 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
}
- /* Special case handling: mac came from IFLA_VF_MAC */
- if (!is_zero_ether_addr(prev_pp.vf_mac))
- memcpy(pp->mac_addr, prev_pp.vf_mac, ETH_ALEN);
+ if (vf == PORT_SELF_VF) {
+ /* Special case handling: mac came from IFLA_VF_MAC */
+ if (!is_zero_ether_addr(prev_pp.vf_mac))
+ memcpy(pp->mac_addr, prev_pp.vf_mac, ETH_ALEN);
- if (vf == PORT_SELF_VF && is_zero_ether_addr(netdev->dev_addr))
- random_ether_addr(netdev->dev_addr);
+ if (is_zero_ether_addr(netdev->dev_addr))
+ eth_hw_addr_random(netdev);
+ } else {
+ /* SR-IOV VF: get mac from adapter */
+ ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic,
+ vnic_dev_get_mac_addr, pp->mac_addr);
+ if (err) {
+ netdev_err(netdev, "Error getting mac for vf %d\n", vf);
+ memcpy(pp, &prev_pp, sizeof(*pp));
+ return enic_dev_status_to_errno(err);
+ }
+ }
err = enic_process_set_pp_request(enic, vf, &prev_pp, &restore_pp);
if (err) {
@@ -1147,7 +1168,8 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
}
}
- memset(pp->vf_mac, 0, ETH_ALEN);
+ if (vf == PORT_SELF_VF)
+ memset(pp->vf_mac, 0, ETH_ALEN);
return err;
}
@@ -2280,10 +2302,8 @@ static int __devinit enic_probe(struct pci_dev *pdev,
*/
netdev = alloc_etherdev(sizeof(struct enic));
- if (!netdev) {
- pr_err("Etherdev alloc failed, aborting\n");
+ if (!netdev)
return -ENOMEM;
- }
pci_set_drvdata(pdev, netdev);
@@ -2388,7 +2408,6 @@ static int __devinit enic_probe(struct pci_dev *pdev,
/* Allocate structure for port profiles */
enic->pp = kcalloc(num_pps, sizeof(*enic->pp), GFP_KERNEL);
if (!enic->pp) {
- pr_err("port profile alloc failed, aborting\n");
err = -ENOMEM;
goto err_out_disable_sriov_pp;
}
@@ -2433,7 +2452,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
* called later by an upper layer.
*/
- if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) {
+ if (!enic_is_dynamic(enic)) {
err = vnic_dev_init(enic->vdev, 0);
if (err) {
dev_err(dev, "vNIC dev init failed, aborting\n");
@@ -2466,11 +2485,6 @@ static int __devinit enic_probe(struct pci_dev *pdev,
enic->port_mtu = enic->config.mtu;
(void)enic_change_mtu(netdev, enic->port_mtu);
-#ifdef CONFIG_PCI_IOV
- if (enic_is_sriov_vf(enic) && is_zero_ether_addr(enic->mac_addr))
- random_ether_addr(enic->mac_addr);
-#endif
-
err = enic_set_mac_addr(netdev, enic->mac_addr);
if (err) {
dev_err(dev, "Invalid MAC address, aborting\n");
diff --git a/drivers/net/ethernet/cisco/enic/enic_pp.c b/drivers/net/ethernet/cisco/enic/enic_pp.c
index c347b6236f8f..dafea1ecb7b1 100644
--- a/drivers/net/ethernet/cisco/enic/enic_pp.c
+++ b/drivers/net/ethernet/cisco/enic/enic_pp.c
@@ -207,7 +207,7 @@ static int enic_pp_disassociate(struct enic *enic, int vf,
if (!is_zero_ether_addr(pp->mac_addr))
ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_del_addr,
pp->mac_addr);
- else if (!is_zero_ether_addr(netdev->dev_addr))
+ else if (vf == PORT_SELF_VF && !is_zero_ether_addr(netdev->dev_addr))
ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_del_addr,
netdev->dev_addr);
@@ -294,7 +294,7 @@ static int enic_pp_associate(struct enic *enic, int vf,
if (!is_zero_ether_addr(pp->mac_addr))
ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_add_addr,
pp->mac_addr);
- else if (!is_zero_ether_addr(netdev->dev_addr))
+ else if (vf == PORT_SELF_VF && !is_zero_ether_addr(netdev->dev_addr))
ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnic_dev_add_addr,
netdev->dev_addr);
diff --git a/drivers/net/ethernet/cisco/enic/enic_res.c b/drivers/net/ethernet/cisco/enic/enic_res.c
index 4a35367de790..31d658880c3c 100644
--- a/drivers/net/ethernet/cisco/enic/enic_res.c
+++ b/drivers/net/ethernet/cisco/enic/enic_res.c
@@ -44,7 +44,7 @@ int enic_get_vnic_config(struct enic *enic)
struct vnic_enet_config *c = &enic->config;
int err;
- err = vnic_dev_mac_addr(enic->vdev, enic->mac_addr);
+ err = vnic_dev_get_mac_addr(enic->vdev, enic->mac_addr);
if (err) {
dev_err(enic_get_dev(enic),
"Error getting MAC addr, %d\n", err);
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c
index 31e7f9bc2067..605b22283be1 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c
@@ -439,11 +439,12 @@ int vnic_dev_fw_info(struct vnic_dev *vdev,
a1 = sizeof(struct vnic_devcmd_fw_info);
/* only get fw_info once and cache it */
- err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, &a0, &a1, wait);
- if (err == ERR_ECMDUNKNOWN) {
+ if (vnic_dev_capable(vdev, CMD_MCPU_FW_INFO))
+ err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO,
+ &a0, &a1, wait);
+ else
err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO_OLD,
&a0, &a1, wait);
- }
}
*fw_info = vdev->fw_info;
@@ -504,13 +505,11 @@ int vnic_dev_enable_wait(struct vnic_dev *vdev)
{
u64 a0 = 0, a1 = 0;
int wait = 1000;
- int err;
- err = vnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait);
- if (err == ERR_ECMDUNKNOWN)
+ if (vnic_dev_capable(vdev, CMD_ENABLE_WAIT))
+ return vnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait);
+ else
return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
-
- return err;
}
int vnic_dev_disable(struct vnic_dev *vdev)
@@ -574,16 +573,15 @@ int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg)
int wait = 1000;
int err;
- err = vnic_dev_cmd(vdev, CMD_HANG_RESET, &a0, &a1, wait);
- if (err == ERR_ECMDUNKNOWN) {
+ if (vnic_dev_capable(vdev, CMD_HANG_RESET)) {
+ return vnic_dev_cmd(vdev, CMD_HANG_RESET,
+ &a0, &a1, wait);
+ } else {
err = vnic_dev_soft_reset(vdev, arg);
if (err)
return err;
-
return vnic_dev_init(vdev, 0);
}
-
- return err;
}
int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done)
@@ -594,11 +592,13 @@ int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done)
*done = 0;
- err = vnic_dev_cmd(vdev, CMD_HANG_RESET_STATUS, &a0, &a1, wait);
- if (err) {
- if (err == ERR_ECMDUNKNOWN)
- return vnic_dev_soft_reset_done(vdev, done);
- return err;
+ if (vnic_dev_capable(vdev, CMD_HANG_RESET_STATUS)) {
+ err = vnic_dev_cmd(vdev, CMD_HANG_RESET_STATUS,
+ &a0, &a1, wait);
+ if (err)
+ return err;
+ } else {
+ return vnic_dev_soft_reset_done(vdev, done);
}
*done = (a0 == 0);
@@ -613,7 +613,7 @@ int vnic_dev_hang_notify(struct vnic_dev *vdev)
return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait);
}
-int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
+int vnic_dev_get_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
{
u64 a0, a1;
int wait = 1000;
@@ -622,7 +622,7 @@ int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
for (i = 0; i < ETH_ALEN; i++)
mac_addr[i] = 0;
- err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
+ err = vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait);
if (err)
return err;
@@ -691,13 +691,12 @@ int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
{
u64 a0 = ig_vlan_rewrite_mode, a1 = 0;
int wait = 1000;
- int err;
- err = vnic_dev_cmd(vdev, CMD_IG_VLAN_REWRITE_MODE, &a0, &a1, wait);
- if (err == ERR_ECMDUNKNOWN)
+ if (vnic_dev_capable(vdev, CMD_IG_VLAN_REWRITE_MODE))
+ return vnic_dev_cmd(vdev, CMD_IG_VLAN_REWRITE_MODE,
+ &a0, &a1, wait);
+ else
return 0;
-
- return err;
}
static int vnic_dev_notify_setcmd(struct vnic_dev *vdev,
@@ -804,7 +803,7 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg)
/* Emulate these for old CMD_INIT_v1 which
* didn't pass a0 so no CMD_INITF_*.
*/
- vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
+ vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait);
vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
}
}
@@ -835,7 +834,10 @@ int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev)
memset(vdev->args, 0, sizeof(vdev->args));
- err = _vnic_dev_cmd(vdev, CMD_INTR_COAL_CONVERT, wait);
+ if (vnic_dev_capable(vdev, CMD_INTR_COAL_CONVERT))
+ err = _vnic_dev_cmd(vdev, CMD_INTR_COAL_CONVERT, wait);
+ else
+ err = ERR_ECMDUNKNOWN;
/* Use defaults when firmware doesn't support the devcmd at all or
* supports it for only specific hardware
@@ -848,9 +850,11 @@ int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev)
return 0;
}
- vdev->intr_coal_timer_info.mul = (u32) vdev->args[0];
- vdev->intr_coal_timer_info.div = (u32) vdev->args[1];
- vdev->intr_coal_timer_info.max_usec = (u32) vdev->args[2];
+ if (!err) {
+ vdev->intr_coal_timer_info.mul = (u32) vdev->args[0];
+ vdev->intr_coal_timer_info.div = (u32) vdev->args[1];
+ vdev->intr_coal_timer_info.max_usec = (u32) vdev->args[2];
+ }
return err;
}
@@ -1019,3 +1023,15 @@ int vnic_dev_deinit_done(struct vnic_dev *vdev, int *status)
{
return vnic_dev_cmd_status(vdev, CMD_DEINIT, status);
}
+
+int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
+{
+ u64 a0, a1;
+ int wait = 1000;
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ ((u8 *)&a0)[i] = mac_addr[i];
+
+ return vnic_dev_cmd(vdev, CMD_SET_MAC_ADDR, &a0, &a1, wait);
+}
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.h b/drivers/net/ethernet/cisco/enic/vnic_dev.h
index 6a138b625d13..f3d9b79ba77e 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.h
@@ -97,7 +97,7 @@ int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
int broadcast, int promisc, int allmulti);
int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr);
int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr);
-int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
+int vnic_dev_get_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr);
int vnic_dev_notify_unset(struct vnic_dev *vdev);
int vnic_dev_link_status(struct vnic_dev *vdev);
@@ -131,5 +131,6 @@ int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len);
int vnic_dev_enable2(struct vnic_dev *vdev, int active);
int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status);
int vnic_dev_deinit_done(struct vnic_dev *vdev, int *status);
+int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
#endif /* _VNIC_DEV_H_ */
diff --git a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
index 8025e8808d61..23d555255cf8 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
@@ -131,7 +131,7 @@ enum vnic_devcmd_cmd {
CMD_HANG_NOTIFY = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 8),
/* MAC address in (u48)a0 */
- CMD_MAC_ADDR = _CMDC(_CMD_DIR_READ,
+ CMD_GET_MAC_ADDR = _CMDC(_CMD_DIR_READ,
_CMD_VTYPE_ENET | _CMD_VTYPE_FC, 9),
/* add addr from (u48)a0 */
@@ -337,6 +337,15 @@ enum vnic_devcmd_cmd {
* (u32)a2 = maximum timer value in usec
*/
CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50),
+
+ /*
+ * cmd_set_mac_addr
+ * set mac address
+ * in:
+ * (u48)a0 = mac addr
+ *
+ */
+ CMD_SET_MAC_ADDR = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 55),
};
/* CMD_ENABLE2 flags */
diff --git a/drivers/net/ethernet/cisco/enic/vnic_rq.c b/drivers/net/ethernet/cisco/enic/vnic_rq.c
index 34105e0951a5..7e1488fc8ab2 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_rq.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_rq.c
@@ -38,10 +38,8 @@ static int vnic_rq_alloc_bufs(struct vnic_rq *rq)
for (i = 0; i < blks; i++) {
rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ(count), GFP_ATOMIC);
- if (!rq->bufs[i]) {
- pr_err("Failed to alloc rq_bufs\n");
+ if (!rq->bufs[i])
return -ENOMEM;
- }
}
for (i = 0; i < blks; i++) {
diff --git a/drivers/net/ethernet/cisco/enic/vnic_wq.c b/drivers/net/ethernet/cisco/enic/vnic_wq.c
index df61bd932ea6..5e0d7a2be9bc 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_wq.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_wq.c
@@ -38,10 +38,8 @@ static int vnic_wq_alloc_bufs(struct vnic_wq *wq)
for (i = 0; i < blks; i++) {
wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ(count), GFP_ATOMIC);
- if (!wq->bufs[i]) {
- pr_err("Failed to alloc wq_bufs\n");
+ if (!wq->bufs[i])
return -ENOMEM;
- }
}
for (i = 0; i < blks; i++) {
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index f801754c71a7..36499d5edd95 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -1028,7 +1028,7 @@ dm9000_rx(struct net_device *dev)
/* Move data from DM9000 */
if (GoodPacket &&
- ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
+ ((skb = netdev_alloc_skb(dev, RxLen + 4)) != NULL)) {
skb_reserve(skb, 2);
rdptr = (u8 *) skb_put(skb, RxLen - 4);
@@ -1373,10 +1373,8 @@ dm9000_probe(struct platform_device *pdev)
/* Init network device */
ndev = alloc_etherdev(sizeof(struct board_info));
- if (!ndev) {
- dev_err(&pdev->dev, "could not allocate device.\n");
+ if (!ndev)
return -ENOMEM;
- }
SET_NETDEV_DEV(ndev, &pdev->dev);
@@ -1587,7 +1585,7 @@ dm9000_probe(struct platform_device *pdev)
dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please "
"set using ifconfig\n", ndev->name);
- random_ether_addr(ndev->dev_addr);
+ eth_hw_addr_random(ndev);
mac_src = "random";
}
diff --git a/drivers/net/ethernet/dec/ewrk3.c b/drivers/net/ethernet/dec/ewrk3.c
index f9df5e4d0341..1879f84a25a3 100644
--- a/drivers/net/ethernet/dec/ewrk3.c
+++ b/drivers/net/ethernet/dec/ewrk3.c
@@ -986,8 +986,10 @@ static int ewrk3_rx(struct net_device *dev)
dev->stats.rx_fifo_errors++;
} else {
struct sk_buff *skb;
+ skb = netdev_alloc_skb(dev,
+ pkt_len + 2);
- if ((skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ if (skb != NULL) {
unsigned char *p;
skb_reserve(skb, 2); /* Align to 16 bytes */
p = skb_put(skb, pkt_len);
diff --git a/drivers/net/ethernet/dec/tulip/21142.c b/drivers/net/ethernet/dec/tulip/21142.c
index 25b8deedbef8..369858272650 100644
--- a/drivers/net/ethernet/dec/tulip/21142.c
+++ b/drivers/net/ethernet/dec/tulip/21142.c
@@ -1,5 +1,5 @@
/*
- drivers/net/tulip/21142.c
+ drivers/net/ethernet/dec/tulip/21142.c
Copyright 2000,2001 The Linux Kernel Team
Written/copyright 1994-2001 by Donald Becker.
diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
index 1eb46a0bb488..68f1c39184df 100644
--- a/drivers/net/ethernet/dec/tulip/de2104x.c
+++ b/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -439,7 +439,7 @@ static void de_rx (struct de_private *de)
rx_tail, status, len, copying_skb);
buflen = copying_skb ? (len + RX_OFFSET) : de->rx_buf_sz;
- copy_skb = dev_alloc_skb (buflen);
+ copy_skb = netdev_alloc_skb(de->dev, buflen);
if (unlikely(!copy_skb)) {
de->net_stats.rx_dropped++;
drop = 1;
@@ -1283,12 +1283,10 @@ static int de_refill_rx (struct de_private *de)
for (i = 0; i < DE_RX_RING_SIZE; i++) {
struct sk_buff *skb;
- skb = dev_alloc_skb(de->rx_buf_sz);
+ skb = netdev_alloc_skb(de->dev, de->rx_buf_sz);
if (!skb)
goto err_out;
- skb->dev = de->dev;
-
de->rx_skb[i].mapping = pci_map_single(de->pdev,
skb->data, de->rx_buf_sz, PCI_DMA_FROMDEVICE);
de->rx_skb[i].skb = skb;
diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c
index 4d71f5ae20c8..18b106cc6d2b 100644
--- a/drivers/net/ethernet/dec/tulip/de4x5.c
+++ b/drivers/net/ethernet/dec/tulip/de4x5.c
@@ -3598,7 +3598,7 @@ de4x5_alloc_rx_buff(struct net_device *dev, int index, int len)
struct sk_buff *ret;
u_long i=0, tmp;
- p = dev_alloc_skb(IEEE802_3_SZ + DE4X5_ALIGN + 2);
+ p = netdev_alloc_skb(dev, IEEE802_3_SZ + DE4X5_ALIGN + 2);
if (!p) return NULL;
tmp = virt_to_bus(p->data);
@@ -3618,7 +3618,7 @@ de4x5_alloc_rx_buff(struct net_device *dev, int index, int len)
#else
if (lp->state != OPEN) return (struct sk_buff *)1; /* Fake out the open */
- p = dev_alloc_skb(len + 2);
+ p = netdev_alloc_skb(dev, len + 2);
if (!p) return NULL;
skb_reserve(p, 2); /* Align */
@@ -5234,11 +5234,7 @@ de4x5_dbg_open(struct net_device *dev)
if (de4x5_debug & DEBUG_OPEN) {
printk("%s: de4x5 opening with irq %d\n",dev->name,dev->irq);
- printk("\tphysical address: ");
- for (i=0;i<6;i++) {
- printk("%2.2x:",(short)dev->dev_addr[i]);
- }
- printk("\n");
+ printk("\tphysical address: %pM\n", dev->dev_addr);
printk("Descriptor head addresses:\n");
printk("\t0x%8.8lx 0x%8.8lx\n",(u_long)lp->rx_ring,(u_long)lp->tx_ring);
printk("Descriptor addresses:\nRX: ");
diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c
index 51f7542eb451..1eccf4945485 100644
--- a/drivers/net/ethernet/dec/tulip/dmfe.c
+++ b/drivers/net/ethernet/dec/tulip/dmfe.c
@@ -325,8 +325,8 @@ static irqreturn_t dmfe_interrupt(int , void *);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void poll_dmfe (struct net_device *dev);
#endif
-static void dmfe_descriptor_init(struct dmfe_board_info *, unsigned long);
-static void allocate_rx_buffer(struct dmfe_board_info *);
+static void dmfe_descriptor_init(struct net_device *, unsigned long);
+static void allocate_rx_buffer(struct net_device *);
static void update_cr6(u32, unsigned long);
static void send_filter_frame(struct DEVICE *);
static void dm9132_id_table(struct DEVICE *);
@@ -649,7 +649,7 @@ static void dmfe_init_dm910x(struct DEVICE *dev)
db->op_mode = db->media_mode; /* Force Mode */
/* Initialize Transmit/Receive decriptor and CR3/4 */
- dmfe_descriptor_init(db, ioaddr);
+ dmfe_descriptor_init(dev, ioaddr);
/* Init CR6 to program DM910x operation */
update_cr6(db->cr6_data, ioaddr);
@@ -828,7 +828,7 @@ static irqreturn_t dmfe_interrupt(int irq, void *dev_id)
/* reallocate rx descriptor buffer */
if (db->rx_avail_cnt<RX_DESC_CNT)
- allocate_rx_buffer(db);
+ allocate_rx_buffer(dev);
/* Free the transmitted descriptor */
if ( db->cr5_data & 0x01)
@@ -1008,7 +1008,7 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db)
/* Good packet, send to upper layer */
/* Shorst packet used new SKB */
if ((rxlen < RX_COPY_SIZE) &&
- ((newskb = dev_alloc_skb(rxlen + 2))
+ ((newskb = netdev_alloc_skb(dev, rxlen + 2))
!= NULL)) {
skb = newskb;
@@ -1364,8 +1364,9 @@ static void dmfe_reuse_skb(struct dmfe_board_info *db, struct sk_buff * skb)
* Using Chain structure, and allocate Tx/Rx buffer
*/
-static void dmfe_descriptor_init(struct dmfe_board_info *db, unsigned long ioaddr)
+static void dmfe_descriptor_init(struct net_device *dev, unsigned long ioaddr)
{
+ struct dmfe_board_info *db = netdev_priv(dev);
struct tx_desc *tmp_tx;
struct rx_desc *tmp_rx;
unsigned char *tmp_buf;
@@ -1421,7 +1422,7 @@ static void dmfe_descriptor_init(struct dmfe_board_info *db, unsigned long ioadd
tmp_rx->next_rx_desc = db->first_rx_desc;
/* pre-allocate Rx buffer */
- allocate_rx_buffer(db);
+ allocate_rx_buffer(dev);
}
@@ -1551,15 +1552,16 @@ static void send_filter_frame(struct DEVICE *dev)
* As possible as allocate maxiumn Rx buffer
*/
-static void allocate_rx_buffer(struct dmfe_board_info *db)
+static void allocate_rx_buffer(struct net_device *dev)
{
+ struct dmfe_board_info *db = netdev_priv(dev);
struct rx_desc *rxptr;
struct sk_buff *skb;
rxptr = db->rx_insert_ptr;
while(db->rx_avail_cnt < RX_DESC_CNT) {
- if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL )
+ if ( ( skb = netdev_alloc_skb(dev, RX_ALLOC_SIZE) ) == NULL )
break;
rxptr->rx_skb_ptr = skb; /* FIXME (?) */
rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data,
diff --git a/drivers/net/ethernet/dec/tulip/eeprom.c b/drivers/net/ethernet/dec/tulip/eeprom.c
index 14d5b611783d..ed7d1dcd9566 100644
--- a/drivers/net/ethernet/dec/tulip/eeprom.c
+++ b/drivers/net/ethernet/dec/tulip/eeprom.c
@@ -1,5 +1,5 @@
/*
- drivers/net/tulip/eeprom.c
+ drivers/net/ethernet/dec/tulip/eeprom.c
Copyright 2000,2001 The Linux Kernel Team
Written/copyright 1994-2001 by Donald Becker.
diff --git a/drivers/net/ethernet/dec/tulip/interrupt.c b/drivers/net/ethernet/dec/tulip/interrupt.c
index 4fb8c8c0a420..28a5e425fecf 100644
--- a/drivers/net/ethernet/dec/tulip/interrupt.c
+++ b/drivers/net/ethernet/dec/tulip/interrupt.c
@@ -1,5 +1,5 @@
/*
- drivers/net/tulip/interrupt.c
+ drivers/net/ethernet/dec/tulip/interrupt.c
Copyright 2000,2001 The Linux Kernel Team
Written/copyright 1994-2001 by Donald Becker.
@@ -69,7 +69,8 @@ int tulip_refill_rx(struct net_device *dev)
struct sk_buff *skb;
dma_addr_t mapping;
- skb = tp->rx_buffers[entry].skb = dev_alloc_skb(PKT_BUF_SZ);
+ skb = tp->rx_buffers[entry].skb =
+ netdev_alloc_skb(dev, PKT_BUF_SZ);
if (skb == NULL)
break;
@@ -77,7 +78,6 @@ int tulip_refill_rx(struct net_device *dev)
PCI_DMA_FROMDEVICE);
tp->rx_buffers[entry].mapping = mapping;
- skb->dev = dev; /* Mark as being used by this device. */
tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping);
refilled++;
}
@@ -202,7 +202,7 @@ int tulip_poll(struct napi_struct *napi, int budget)
/* Check if the packet is long enough to accept without copying
to a minimally-sized skbuff. */
if (pkt_len < tulip_rx_copybreak &&
- (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
skb_reserve(skb, 2); /* 16 byte align the IP header */
pci_dma_sync_single_for_cpu(tp->pdev,
tp->rx_buffers[entry].mapping,
@@ -428,7 +428,7 @@ static int tulip_rx(struct net_device *dev)
/* Check if the packet is long enough to accept without copying
to a minimally-sized skbuff. */
if (pkt_len < tulip_rx_copybreak &&
- (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
skb_reserve(skb, 2); /* 16 byte align the IP header */
pci_dma_sync_single_for_cpu(tp->pdev,
tp->rx_buffers[entry].mapping,
diff --git a/drivers/net/ethernet/dec/tulip/media.c b/drivers/net/ethernet/dec/tulip/media.c
index beeb17b52ad4..ae937c6749e7 100644
--- a/drivers/net/ethernet/dec/tulip/media.c
+++ b/drivers/net/ethernet/dec/tulip/media.c
@@ -1,5 +1,5 @@
/*
- drivers/net/tulip/media.c
+ drivers/net/ethernet/dec/tulip/media.c
Copyright 2000,2001 The Linux Kernel Team
Written/copyright 1994-2001 by Donald Becker.
diff --git a/drivers/net/ethernet/dec/tulip/pnic.c b/drivers/net/ethernet/dec/tulip/pnic.c
index 9c16e4ad02a6..5364563c4378 100644
--- a/drivers/net/ethernet/dec/tulip/pnic.c
+++ b/drivers/net/ethernet/dec/tulip/pnic.c
@@ -1,5 +1,5 @@
/*
- drivers/net/tulip/pnic.c
+ drivers/net/ethernet/dec/tulip/pnic.c
Copyright 2000,2001 The Linux Kernel Team
Written/copyright 1994-2001 by Donald Becker.
diff --git a/drivers/net/ethernet/dec/tulip/pnic2.c b/drivers/net/ethernet/dec/tulip/pnic2.c
index 04a7e477eaff..5895fc43f6e0 100644
--- a/drivers/net/ethernet/dec/tulip/pnic2.c
+++ b/drivers/net/ethernet/dec/tulip/pnic2.c
@@ -1,5 +1,5 @@
/*
- drivers/net/tulip/pnic2.c
+ drivers/net/ethernet/dec/tulip/pnic2.c
Copyright 2000,2001 The Linux Kernel Team
Written/copyright 1994-2001 by Donald Becker.
diff --git a/drivers/net/ethernet/dec/tulip/timer.c b/drivers/net/ethernet/dec/tulip/timer.c
index 19078d28ffb9..768379b8aee9 100644
--- a/drivers/net/ethernet/dec/tulip/timer.c
+++ b/drivers/net/ethernet/dec/tulip/timer.c
@@ -1,5 +1,5 @@
/*
- drivers/net/tulip/timer.c
+ drivers/net/ethernet/dec/tulip/timer.c
Copyright 2000,2001 The Linux Kernel Team
Written/copyright 1994-2001 by Donald Becker.
diff --git a/drivers/net/ethernet/dec/tulip/tulip.h b/drivers/net/ethernet/dec/tulip/tulip.h
index fb3887c18dc6..38431a155f09 100644
--- a/drivers/net/ethernet/dec/tulip/tulip.h
+++ b/drivers/net/ethernet/dec/tulip/tulip.h
@@ -1,5 +1,5 @@
/*
- drivers/net/tulip/tulip.h
+ drivers/net/ethernet/dec/tulip/tulip.h
Copyright 2000,2001 The Linux Kernel Team
Written/copyright 1994-2001 by Donald Becker.
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index 4eb0d76145c2..fea3641d9398 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -636,16 +636,15 @@ static void tulip_init_ring(struct net_device *dev)
dma_addr_t mapping;
/* Note the receive buffer must be longword aligned.
- dev_alloc_skb() provides 16 byte alignment. But do *not*
+ netdev_alloc_skb() provides 16 byte alignment. But do *not*
use skb_reserve() to align the IP header! */
- struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
+ struct sk_buff *skb = netdev_alloc_skb(dev, PKT_BUF_SZ);
tp->rx_buffers[i].skb = skb;
if (skb == NULL)
break;
mapping = pci_map_single(tp->pdev, skb->data,
PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
tp->rx_buffers[i].mapping = mapping;
- skb->dev = dev; /* Mark as being used by this device. */
tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */
tp->rx_ring[i].buffer1 = cpu_to_le32(mapping);
}
@@ -1424,10 +1423,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
/* alloc_etherdev ensures aligned and zeroed private structures */
dev = alloc_etherdev (sizeof (*tp));
- if (!dev) {
- pr_err("ether device alloc failed, aborting\n");
+ if (!dev)
return -ENOMEM;
- }
SET_NETDEV_DEV(dev, &pdev->dev);
if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) {
diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c
index 48b0b6566eef..fc4001f6a5e4 100644
--- a/drivers/net/ethernet/dec/tulip/uli526x.c
+++ b/drivers/net/ethernet/dec/tulip/uli526x.c
@@ -232,8 +232,8 @@ static irqreturn_t uli526x_interrupt(int, void *);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void uli526x_poll(struct net_device *dev);
#endif
-static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
-static void allocate_rx_buffer(struct uli526x_board_info *);
+static void uli526x_descriptor_init(struct net_device *, unsigned long);
+static void allocate_rx_buffer(struct net_device *);
static void update_cr6(u32, unsigned long);
static void send_filter_frame(struct net_device *, int);
static u16 phy_read(unsigned long, u8, u8, u32);
@@ -549,7 +549,7 @@ static void uli526x_init(struct net_device *dev)
db->op_mode = db->media_mode; /* Force Mode */
/* Initialize Transmit/Receive decriptor and CR3/4 */
- uli526x_descriptor_init(db, ioaddr);
+ uli526x_descriptor_init(dev, ioaddr);
/* Init CR6 to program M526X operation */
update_cr6(db->cr6_data, ioaddr);
@@ -711,7 +711,7 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id)
/* reallocate rx descriptor buffer */
if (db->rx_avail_cnt<RX_DESC_CNT)
- allocate_rx_buffer(db);
+ allocate_rx_buffer(dev);
/* Free the transmitted descriptor */
if ( db->cr5_data & 0x01)
@@ -844,7 +844,7 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
/* Good packet, send to upper layer */
/* Shorst packet used new SKB */
if ((rxlen < RX_COPY_SIZE) &&
- (((new_skb = dev_alloc_skb(rxlen + 2)) != NULL))) {
+ (((new_skb = netdev_alloc_skb(dev, rxlen + 2)) != NULL))) {
skb = new_skb;
/* size less than COPY_SIZE, allocate a rxlen SKB */
skb_reserve(skb, 2); /* 16byte align */
@@ -1289,8 +1289,9 @@ static void uli526x_reuse_skb(struct uli526x_board_info *db, struct sk_buff * sk
* Using Chain structure, and allocate Tx/Rx buffer
*/
-static void uli526x_descriptor_init(struct uli526x_board_info *db, unsigned long ioaddr)
+static void uli526x_descriptor_init(struct net_device *dev, unsigned long ioaddr)
{
+ struct uli526x_board_info *db = netdev_priv(dev);
struct tx_desc *tmp_tx;
struct rx_desc *tmp_rx;
unsigned char *tmp_buf;
@@ -1343,7 +1344,7 @@ static void uli526x_descriptor_init(struct uli526x_board_info *db, unsigned long
tmp_rx->next_rx_desc = db->first_rx_desc;
/* pre-allocate Rx buffer */
- allocate_rx_buffer(db);
+ allocate_rx_buffer(dev);
}
@@ -1433,15 +1434,17 @@ static void send_filter_frame(struct net_device *dev, int mc_cnt)
* As possible as allocate maxiumn Rx buffer
*/
-static void allocate_rx_buffer(struct uli526x_board_info *db)
+static void allocate_rx_buffer(struct net_device *dev)
{
+ struct uli526x_board_info *db = netdev_priv(dev);
struct rx_desc *rxptr;
struct sk_buff *skb;
rxptr = db->rx_insert_ptr;
while(db->rx_avail_cnt < RX_DESC_CNT) {
- if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL )
+ skb = netdev_alloc_skb(dev, RX_ALLOC_SIZE);
+ if (skb == NULL)
break;
rxptr->rx_skb_ptr = skb; /* FIXME (?) */
rxptr->rdes2 = cpu_to_le32(pci_map_single(db->pdev,
diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c
index 52da7b2fe3b6..2ac6fff0363a 100644
--- a/drivers/net/ethernet/dec/tulip/winbond-840.c
+++ b/drivers/net/ethernet/dec/tulip/winbond-840.c
@@ -815,7 +815,7 @@ static void init_rxtx_rings(struct net_device *dev)
/* Fill in the Rx buffers. Handle allocation failure gracefully. */
for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);
+ struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz);
np->rx_skbuff[i] = skb;
if (skb == NULL)
break;
@@ -1231,7 +1231,7 @@ static int netdev_rx(struct net_device *dev)
/* Check if the packet is long enough to accept without copying
to a minimally-sized skbuff. */
if (pkt_len < rx_copybreak &&
- (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
skb_reserve(skb, 2); /* 16 byte align the IP header */
pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry],
np->rx_skbuff[entry]->len,
@@ -1270,7 +1270,7 @@ static int netdev_rx(struct net_device *dev)
struct sk_buff *skb;
entry = np->dirty_rx % RX_RING_SIZE;
if (np->rx_skbuff[entry] == NULL) {
- skb = dev_alloc_skb(np->rx_buf_sz);
+ skb = netdev_alloc_skb(dev, np->rx_buf_sz);
np->rx_skbuff[entry] = skb;
if (skb == NULL)
break; /* Better luck next round. */
diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c
index 988b8eb24d37..fdb329fe6e8e 100644
--- a/drivers/net/ethernet/dec/tulip/xircom_cb.c
+++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c
@@ -222,10 +222,9 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
is available.
*/
dev = alloc_etherdev(sizeof(struct xircom_private));
- if (!dev) {
- pr_err("%s: failed to allocate etherdev\n", __func__);
+ if (!dev)
goto device_fail;
- }
+
private = netdev_priv(dev);
/* Allocate the send/receive buffers */
@@ -1085,7 +1084,7 @@ investigate_read_descriptor(struct net_device *dev, struct xircom_private *card,
pkt_len = 1518;
}
- skb = dev_alloc_skb(pkt_len + 2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb == NULL) {
dev->stats.rx_dropped++;
goto out;
diff --git a/drivers/net/ethernet/dlink/de600.c b/drivers/net/ethernet/dlink/de600.c
index c24fab1e9cbe..682750c052c8 100644
--- a/drivers/net/ethernet/dlink/de600.c
+++ b/drivers/net/ethernet/dlink/de600.c
@@ -335,7 +335,7 @@ static void de600_rx_intr(struct net_device *dev)
return;
}
- skb = dev_alloc_skb(size+2);
+ skb = netdev_alloc_skb(dev, size + 2);
if (skb == NULL) {
printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size);
return;
diff --git a/drivers/net/ethernet/dlink/de620.c b/drivers/net/ethernet/dlink/de620.c
index 3b934ab784d3..afc5aaac6b60 100644
--- a/drivers/net/ethernet/dlink/de620.c
+++ b/drivers/net/ethernet/dlink/de620.c
@@ -650,7 +650,7 @@ static int de620_rx_intr(struct net_device *dev)
printk(KERN_WARNING "%s: Illegal packet size: %d!\n", dev->name, size);
}
else { /* Good packet? */
- skb = dev_alloc_skb(size+2);
+ skb = netdev_alloc_skb(dev, size + 2);
if (skb == NULL) { /* Yeah, but no place to put it... */
printk(KERN_WARNING "%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size);
dev->stats.rx_dropped++;
diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c
index 28a3a9b50b8b..d783f4f96ec0 100644
--- a/drivers/net/ethernet/dlink/sundance.c
+++ b/drivers/net/ethernet/dlink/sundance.c
@@ -1020,11 +1020,11 @@ static void init_ring(struct net_device *dev)
/* Fill in the Rx buffers. Handle allocation failure gracefully. */
for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + 2);
+ struct sk_buff *skb =
+ netdev_alloc_skb(dev, np->rx_buf_sz + 2);
np->rx_skbuff[i] = skb;
if (skb == NULL)
break;
- skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* 16 byte align the IP header. */
np->rx_ring[i].frag[0].addr = cpu_to_le32(
dma_map_single(&np->pci_dev->dev, skb->data,
@@ -1358,7 +1358,7 @@ static void rx_poll(unsigned long data)
/* Check if the packet is long enough to accept without copying
to a minimally-sized skbuff. */
if (pkt_len < rx_copybreak &&
- (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
skb_reserve(skb, 2); /* 16 byte align the IP header */
dma_sync_single_for_cpu(&np->pci_dev->dev,
le32_to_cpu(desc->frag[0].addr),
@@ -1411,11 +1411,10 @@ static void refill_rx (struct net_device *dev)
struct sk_buff *skb;
entry = np->dirty_rx % RX_RING_SIZE;
if (np->rx_skbuff[entry] == NULL) {
- skb = dev_alloc_skb(np->rx_buf_sz + 2);
+ skb = netdev_alloc_skb(dev, np->rx_buf_sz + 2);
np->rx_skbuff[entry] = skb;
if (skb == NULL)
break; /* Better luck next round. */
- skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
np->rx_ring[entry].frag[0].addr = cpu_to_le32(
dma_map_single(&np->pci_dev->dev, skb->data,
@@ -1602,7 +1601,7 @@ static int sundance_set_mac_addr(struct net_device *dev, void *data)
const struct sockaddr *addr = data;
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
__set_mac_addr(dev);
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index 925c9bafc9b9..b276469f74e9 100644
--- a/drivers/net/ethernet/dnet.c
+++ b/drivers/net/ethernet/dnet.c
@@ -421,7 +421,7 @@ static int dnet_poll(struct napi_struct *napi, int budget)
printk(KERN_ERR "%s packet receive error %x\n",
__func__, cmd_word);
- skb = dev_alloc_skb(pkt_len + 5);
+ skb = netdev_alloc_skb(dev, pkt_len + 5);
if (skb != NULL) {
/* Align IP on 16 byte boundaries */
skb_reserve(skb, 2);
@@ -854,10 +854,8 @@ static int __devinit dnet_probe(struct platform_device *pdev)
err = -ENOMEM;
dev = alloc_etherdev(sizeof(*bp));
- if (!dev) {
- dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n");
+ if (!dev)
goto err_out_release_mem;
- }
/* TODO: Actually, we have some interesting features... */
dev->features |= 0;
@@ -897,7 +895,7 @@ static int __devinit dnet_probe(struct platform_device *pdev)
if (!is_valid_ether_addr(dev->dev_addr)) {
/* choose a random ethernet address */
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
__dnet_set_hwaddr(bp);
}
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index cbdec2536da6..c357172d0543 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -33,7 +33,7 @@
#include "be_hw.h"
-#define DRV_VER "4.0.100u"
+#define DRV_VER "4.2.116u"
#define DRV_NAME "be2net"
#define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC"
#define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC"
@@ -74,11 +74,14 @@ static inline char *nic_name(struct pci_dev *pdev)
/* Number of bytes of an RX frame that are copied to skb->data */
#define BE_HDR_LEN ((u16) 64)
+/* allocate extra space to allow tunneling decapsulation without head reallocation */
+#define BE_RX_SKB_ALLOC_SIZE (BE_HDR_LEN + 64)
+
#define BE_MAX_JUMBO_FRAME_SIZE 9018
#define BE_MIN_MTU 256
#define BE_NUM_VLANS_SUPPORTED 64
-#define BE_MAX_EQD 96
+#define BE_MAX_EQD 96u
#define BE_MAX_TX_FRAG_COUNT 30
#define EVNT_Q_LEN 1024
@@ -89,12 +92,16 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MCC_Q_LEN 128 /* total size not to exceed 8 pages */
#define MCC_CQ_LEN 256
-#define MAX_RSS_QS 4 /* BE limit is 4 queues/port */
+#define BE3_MAX_RSS_QS 8
+#define BE2_MAX_RSS_QS 4
+#define MAX_RSS_QS BE3_MAX_RSS_QS
#define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */
+
#define MAX_TX_QS 8
-#define BE_MAX_MSIX_VECTORS (MAX_RX_QS + 1)/* RX + TX */
+#define MAX_MSIX_VECTORS MAX_RSS_QS
+#define BE_TX_BUDGET 256
#define BE_NAPI_WEIGHT 64
-#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
+#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
#define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST)
#define FW_VER_LEN 32
@@ -162,13 +169,16 @@ struct be_eq_obj {
/* Adaptive interrupt coalescing (AIC) info */
bool enable_aic;
- u16 min_eqd; /* in usecs */
- u16 max_eqd; /* in usecs */
- u16 cur_eqd; /* in usecs */
- u8 eq_idx;
+ u32 min_eqd; /* in usecs */
+ u32 max_eqd; /* in usecs */
+ u32 eqd; /* configured val when aic is off */
+ u32 cur_eqd; /* in usecs */
+ u8 idx; /* array index */
+ u16 tx_budget;
struct napi_struct napi;
-};
+ struct be_adapter *adapter;
+} ____cacheline_aligned_in_smp;
struct be_mcc_obj {
struct be_queue_info q;
@@ -194,7 +204,7 @@ struct be_tx_obj {
/* Remember the skbs that were transmitted */
struct sk_buff *sent_skb_list[TX_Q_LEN];
struct be_tx_stats stats;
-};
+} ____cacheline_aligned_in_smp;
/* Struct to remember the pages posted for rx frags */
struct be_rx_page_info {
@@ -212,8 +222,6 @@ struct be_rx_stats {
u32 rx_drops_no_skbs; /* skb allocation errors */
u32 rx_drops_no_frags; /* HW has no fetched frags */
u32 rx_post_fail; /* page post alloc failures */
- u32 rx_polls; /* NAPI calls */
- u32 rx_events;
u32 rx_compl;
u32 rx_mcast_pkts;
u32 rx_compl_err; /* completions with err set */
@@ -246,23 +254,19 @@ struct be_rx_obj {
struct be_queue_info cq;
struct be_rx_compl_info rxcp;
struct be_rx_page_info page_info_tbl[RX_Q_LEN];
- struct be_eq_obj rx_eq;
struct be_rx_stats stats;
u8 rss_id;
bool rx_post_starved; /* Zero rx frags have been posted to BE */
- u32 cache_line_barrier[16];
-};
+} ____cacheline_aligned_in_smp;
struct be_drv_stats {
u32 be_on_die_temperature;
- u32 tx_events;
u32 eth_red_drops;
u32 rx_drops_no_pbuf;
u32 rx_drops_no_txpb;
u32 rx_drops_no_erx_descr;
u32 rx_drops_no_tpre_descr;
u32 rx_drops_too_many_frags;
- u32 rx_drops_invalid_ring;
u32 forwarded_packets;
u32 rx_drops_mtu;
u32 rx_crc_errors;
@@ -273,7 +277,7 @@ struct be_drv_stats {
u32 rx_in_range_errors;
u32 rx_out_range_errors;
u32 rx_frame_too_long;
- u32 rx_address_match_errors;
+ u32 rx_address_mismatch_drops;
u32 rx_dropped_too_small;
u32 rx_dropped_too_short;
u32 rx_dropped_header_too_small;
@@ -300,6 +304,7 @@ struct be_vf_cfg {
};
#define BE_FLAGS_LINK_STATUS_INIT 1
+#define BE_FLAGS_WORKER_SCHEDULED (1 << 3)
struct be_adapter {
struct pci_dev *pdev;
@@ -318,20 +323,19 @@ struct be_adapter {
spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */
spinlock_t mcc_cq_lock;
- struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS];
u32 num_msix_vec;
+ u32 num_evt_qs;
+ struct be_eq_obj eq_obj[MAX_MSIX_VECTORS];
+ struct msix_entry msix_entries[MAX_MSIX_VECTORS];
bool isr_registered;
/* TX Rings */
- struct be_eq_obj tx_eq;
+ u32 num_tx_qs;
struct be_tx_obj tx_obj[MAX_TX_QS];
- u8 num_tx_qs;
-
- u32 cache_line_break[8];
/* Rx rings */
- struct be_rx_obj rx_obj[MAX_RX_QS];
u32 num_rx_qs;
+ struct be_rx_obj rx_obj[MAX_RX_QS];
u32 big_page_size; /* Compounded page size shared by rx wrbs */
u8 eq_next_idx;
@@ -402,24 +406,34 @@ struct be_adapter {
extern const struct ethtool_ops be_ethtool_ops;
#define msix_enabled(adapter) (adapter->num_msix_vec > 0)
-#define tx_stats(txo) (&txo->stats)
-#define rx_stats(rxo) (&rxo->stats)
+#define num_irqs(adapter) (msix_enabled(adapter) ? \
+ adapter->num_msix_vec : 1)
+#define tx_stats(txo) (&(txo)->stats)
+#define rx_stats(rxo) (&(rxo)->stats)
-#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops)
+/* The default RXQ is the last RXQ */
+#define default_rxo(adpt) (&adpt->rx_obj[adpt->num_rx_qs - 1])
#define for_all_rx_queues(adapter, rxo, i) \
for (i = 0, rxo = &adapter->rx_obj[i]; i < adapter->num_rx_qs; \
i++, rxo++)
-/* Just skip the first default non-rss queue */
+/* Skip the default non-rss queue (last one)*/
#define for_all_rss_queues(adapter, rxo, i) \
- for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\
+ for (i = 0, rxo = &adapter->rx_obj[i]; i < (adapter->num_rx_qs - 1);\
i++, rxo++)
#define for_all_tx_queues(adapter, txo, i) \
for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs; \
i++, txo++)
+#define for_all_evt_queues(adapter, eqo, i) \
+ for (i = 0, eqo = &adapter->eq_obj[i]; i < adapter->num_evt_qs; \
+ i++, eqo++)
+
+#define is_mcc_eqo(eqo) (eqo->idx == 0)
+#define mcc_eqo(adapter) (&adapter->eq_obj[0])
+
#define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 0fcb45624796..398fb5ca0fe2 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -235,10 +235,10 @@ void be_async_mcc_disable(struct be_adapter *adapter)
adapter->mcc_obj.rearm_cq = false;
}
-int be_process_mcc(struct be_adapter *adapter, int *status)
+int be_process_mcc(struct be_adapter *adapter)
{
struct be_mcc_compl *compl;
- int num = 0;
+ int num = 0, status = 0;
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
spin_lock_bh(&adapter->mcc_cq_lock);
@@ -252,32 +252,32 @@ int be_process_mcc(struct be_adapter *adapter, int *status)
be_async_grp5_evt_process(adapter,
compl->flags, compl);
} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
- *status = be_mcc_compl_process(adapter, compl);
+ status = be_mcc_compl_process(adapter, compl);
atomic_dec(&mcc_obj->q.used);
}
be_mcc_compl_use(compl);
num++;
}
+ if (num)
+ be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
+
spin_unlock_bh(&adapter->mcc_cq_lock);
- return num;
+ return status;
}
/* Wait till no more pending mcc requests are present */
static int be_mcc_wait_compl(struct be_adapter *adapter)
{
#define mcc_timeout 120000 /* 12s timeout */
- int i, num, status = 0;
+ int i, status = 0;
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
for (i = 0; i < mcc_timeout; i++) {
if (be_error(adapter))
return -EIO;
- num = be_process_mcc(adapter, &status);
- if (num)
- be_cq_notify(adapter, mcc_obj->cq.id,
- mcc_obj->rearm_cq, num);
+ status = be_process_mcc(adapter);
if (atomic_read(&mcc_obj->q.used) == 0)
break;
@@ -726,9 +726,8 @@ err:
}
/* Uses Mbox */
-int be_cmd_cq_create(struct be_adapter *adapter,
- struct be_queue_info *cq, struct be_queue_info *eq,
- bool sol_evts, bool no_delay, int coalesce_wm)
+int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
+ struct be_queue_info *eq, bool no_delay, int coalesce_wm)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_cq_create *req;
@@ -759,7 +758,6 @@ int be_cmd_cq_create(struct be_adapter *adapter,
ctxt, 1);
AMAP_SET_BITS(struct amap_cq_context_lancer, eqid,
ctxt, eq->id);
- AMAP_SET_BITS(struct amap_cq_context_lancer, armed, ctxt, 1);
} else {
AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt,
coalesce_wm);
@@ -768,11 +766,8 @@ int be_cmd_cq_create(struct be_adapter *adapter,
AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt,
__ilog2_u32(cq->len/256));
AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1);
- AMAP_SET_BITS(struct amap_cq_context_be, solevent,
- ctxt, sol_evts);
AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1);
AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id);
- AMAP_SET_BITS(struct amap_cq_context_be, armed, ctxt, 1);
}
be_dws_cpu_to_le(ctxt, sizeof(req->context));
@@ -973,7 +968,7 @@ err:
/* Uses MCC */
int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
- u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id)
+ u32 if_id, u32 rss, u8 *rss_id)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_eth_rx_create *req;
@@ -997,7 +992,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
req->num_pages = 2;
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
req->interface_id = cpu_to_le32(if_id);
- req->max_frame_size = cpu_to_le16(max_frame_size);
+ req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE);
req->rss_queue = cpu_to_le32(rss);
status = be_mcc_notify_wait(adapter);
@@ -1257,11 +1252,13 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
}
req = embedded_payload(wrb);
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL);
+
if (adapter->generation == BE_GEN3 || lancer_chip(adapter))
req->hdr.version = 1;
- be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL);
+ req->hdr.domain = dom;
status = be_mcc_notify_wait(adapter);
if (!status) {
@@ -1697,7 +1694,8 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)
OPCODE_ETH_RSS_CONFIG, sizeof(*req), wrb, NULL);
req->if_id = cpu_to_le32(adapter->if_handle);
- req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4);
+ req->enable_rss = cpu_to_le16(RSS_ENABLE_TCP_IPV4 | RSS_ENABLE_IPV4 |
+ RSS_ENABLE_TCP_IPV6 | RSS_ENABLE_IPV6);
req->cpu_table_size_log2 = cpu_to_le16(fls(table_size) - 1);
memcpy(req->cpu_table, rsstable, table_size);
memcpy(req->hash, myhash, sizeof(myhash));
@@ -2298,52 +2296,81 @@ err:
/* Uses synchronous MCCQ */
int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain,
- u32 *pmac_id)
+ bool *pmac_id_active, u32 *pmac_id, u8 *mac)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_mac_list *req;
int status;
int mac_count;
+ struct be_dma_mem get_mac_list_cmd;
+ int i;
+
+ memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem));
+ get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list);
+ get_mac_list_cmd.va = pci_alloc_consistent(adapter->pdev,
+ get_mac_list_cmd.size,
+ &get_mac_list_cmd.dma);
+
+ if (!get_mac_list_cmd.va) {
+ dev_err(&adapter->pdev->dev,
+ "Memory allocation failure during GET_MAC_LIST\n");
+ return -ENOMEM;
+ }
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
if (!wrb) {
status = -EBUSY;
- goto err;
+ goto out;
}
- req = embedded_payload(wrb);
+
+ req = get_mac_list_cmd.va;
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_GET_MAC_LIST, sizeof(*req),
- wrb, NULL);
+ wrb, &get_mac_list_cmd);
req->hdr.domain = domain;
+ req->mac_type = MAC_ADDRESS_TYPE_NETWORK;
+ req->perm_override = 1;
status = be_mcc_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_get_mac_list *resp =
- embedded_payload(wrb);
- int i;
- u8 *ctxt = &resp->context[0][0];
- status = -EIO;
- mac_count = resp->mac_count;
- be_dws_le_to_cpu(&resp->context, sizeof(resp->context));
+ get_mac_list_cmd.va;
+ mac_count = resp->true_mac_count + resp->pseudo_mac_count;
+ /* Mac list returned could contain one or more active mac_ids
+ * or one or more pseudo permanant mac addresses. If an active
+ * mac_id is present, return first active mac_id found
+ */
for (i = 0; i < mac_count; i++) {
- if (!AMAP_GET_BITS(struct amap_get_mac_list_context,
- act, ctxt)) {
- *pmac_id = AMAP_GET_BITS
- (struct amap_get_mac_list_context,
- macid, ctxt);
- status = 0;
- break;
+ struct get_list_macaddr *mac_entry;
+ u16 mac_addr_size;
+ u32 mac_id;
+
+ mac_entry = &resp->macaddr_list[i];
+ mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size);
+ /* mac_id is a 32 bit value and mac_addr size
+ * is 6 bytes
+ */
+ if (mac_addr_size == sizeof(u32)) {
+ *pmac_id_active = true;
+ mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id;
+ *pmac_id = le32_to_cpu(mac_id);
+ goto out;
}
- ctxt += sizeof(struct amap_get_mac_list_context) / 8;
}
+ /* If no active mac_id found, return first pseudo mac addr */
+ *pmac_id_active = false;
+ memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr,
+ ETH_ALEN);
}
-err:
+out:
spin_unlock_bh(&adapter->mcc_lock);
+ pci_free_consistent(adapter->pdev, get_mac_list_cmd.size,
+ get_mac_list_cmd.va, get_mac_list_cmd.dma);
return status;
}
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index dca89249088f..687c42071411 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -592,8 +592,8 @@ struct be_port_rxf_stats_v0 {
u32 rx_in_range_errors; /* dword 10*/
u32 rx_out_range_errors; /* dword 11*/
u32 rx_frame_too_long; /* dword 12*/
- u32 rx_address_match_errors; /* dword 13*/
- u32 rx_vlan_mismatch; /* dword 14*/
+ u32 rx_address_mismatch_drops; /* dword 13*/
+ u32 rx_vlan_mismatch_drops; /* dword 14*/
u32 rx_dropped_too_small; /* dword 15*/
u32 rx_dropped_too_short; /* dword 16*/
u32 rx_dropped_header_too_small; /* dword 17*/
@@ -799,8 +799,8 @@ struct lancer_pport_stats {
u32 rx_control_frames_unknown_opcode_hi;
u32 rx_in_range_errors;
u32 rx_out_of_range_errors;
- u32 rx_address_match_errors;
- u32 rx_vlan_mismatch_errors;
+ u32 rx_address_mismatch_drops;
+ u32 rx_vlan_mismatch_drops;
u32 rx_dropped_too_small;
u32 rx_dropped_too_short;
u32 rx_dropped_header_too_small;
@@ -1346,22 +1346,36 @@ struct be_cmd_resp_set_func_cap {
/******************** GET/SET_MACLIST **************************/
#define BE_MAX_MAC 64
-struct amap_get_mac_list_context {
- u8 macid[31];
- u8 act;
-} __packed;
-
struct be_cmd_req_get_mac_list {
struct be_cmd_req_hdr hdr;
- u32 rsvd;
+ u8 mac_type;
+ u8 perm_override;
+ u16 iface_id;
+ u32 mac_id;
+ u32 rsvd[3];
+} __packed;
+
+struct get_list_macaddr {
+ u16 mac_addr_size;
+ union {
+ u8 macaddr[6];
+ struct {
+ u8 rsvd[2];
+ u32 mac_id;
+ } __packed s_mac_id;
+ } __packed mac_addr_id;
} __packed;
struct be_cmd_resp_get_mac_list {
struct be_cmd_resp_hdr hdr;
- u8 mac_count;
- u8 rsvd1;
- u16 rsvd2;
- u8 context[sizeof(struct amap_get_mac_list_context) / 8][BE_MAX_MAC];
+ struct get_list_macaddr fd_macaddr; /* Factory default mac */
+ struct get_list_macaddr macid_macaddr; /* soft mac */
+ u8 true_mac_count;
+ u8 pseudo_mac_count;
+ u8 mac_list_size;
+ u8 rsvd;
+ /* perm override mac */
+ struct get_list_macaddr macaddr_list[BE_MAX_MAC];
} __packed;
struct be_cmd_req_set_mac_list {
@@ -1384,7 +1398,7 @@ struct be_port_rxf_stats_v1 {
u32 rx_in_range_errors;
u32 rx_out_range_errors;
u32 rx_frame_too_long;
- u32 rx_address_match_errors;
+ u32 rx_address_mismatch_drops;
u32 rx_dropped_too_small;
u32 rx_dropped_too_short;
u32 rx_dropped_header_too_small;
@@ -1492,8 +1506,7 @@ extern int be_cmd_eq_create(struct be_adapter *adapter,
struct be_queue_info *eq, int eq_delay);
extern int be_cmd_cq_create(struct be_adapter *adapter,
struct be_queue_info *cq, struct be_queue_info *eq,
- bool sol_evts, bool no_delay,
- int num_cqe_dma_coalesce);
+ bool no_delay, int num_cqe_dma_coalesce);
extern int be_cmd_mccq_create(struct be_adapter *adapter,
struct be_queue_info *mccq,
struct be_queue_info *cq);
@@ -1502,8 +1515,7 @@ extern int be_cmd_txq_create(struct be_adapter *adapter,
struct be_queue_info *cq);
extern int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_queue_info *rxq, u16 cq_id,
- u16 frag_size, u16 max_frame_size, u32 if_id,
- u32 rss, u8 *rss_id);
+ u16 frag_size, u32 if_id, u32 rss, u8 *rss_id);
extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
int type);
extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
@@ -1532,7 +1544,7 @@ extern int be_cmd_query_fw_cfg(struct be_adapter *adapter,
extern int be_cmd_reset_function(struct be_adapter *adapter);
extern int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
u16 table_size);
-extern int be_process_mcc(struct be_adapter *adapter, int *status);
+extern int be_process_mcc(struct be_adapter *adapter);
extern int be_cmd_set_beacon_state(struct be_adapter *adapter,
u8 port_num, u8 beacon, u8 status, u8 state);
extern int be_cmd_get_beacon_state(struct be_adapter *adapter,
@@ -1575,7 +1587,7 @@ extern int be_cmd_req_native_mode(struct be_adapter *adapter);
extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain,
- u32 *pmac_id);
+ bool *pmac_id_active, u32 *pmac_id, u8 *mac);
extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
u8 mac_count, u32 domain);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 802e5ddef8a8..30ce17806916 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -37,20 +37,46 @@ enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT};
FIELDINFO(struct be_drv_stats, field)
static const struct be_ethtool_stat et_stats[] = {
- {DRVSTAT_INFO(tx_events)},
{DRVSTAT_INFO(rx_crc_errors)},
{DRVSTAT_INFO(rx_alignment_symbol_errors)},
{DRVSTAT_INFO(rx_pause_frames)},
{DRVSTAT_INFO(rx_control_frames)},
+ /* Received packets dropped when the Ethernet length field
+ * is not equal to the actual Ethernet data length.
+ */
{DRVSTAT_INFO(rx_in_range_errors)},
+ /* Received packets dropped when their length field is >= 1501 bytes
+ * and <= 1535 bytes.
+ */
{DRVSTAT_INFO(rx_out_range_errors)},
+ /* Received packets dropped when they are longer than 9216 bytes */
{DRVSTAT_INFO(rx_frame_too_long)},
- {DRVSTAT_INFO(rx_address_match_errors)},
+ /* Received packets dropped when they don't pass the unicast or
+ * multicast address filtering.
+ */
+ {DRVSTAT_INFO(rx_address_mismatch_drops)},
+ /* Received packets dropped when IP packet length field is less than
+ * the IP header length field.
+ */
{DRVSTAT_INFO(rx_dropped_too_small)},
+ /* Received packets dropped when IP length field is greater than
+ * the actual packet length.
+ */
{DRVSTAT_INFO(rx_dropped_too_short)},
+ /* Received packets dropped when the IP header length field is less
+ * than 5.
+ */
{DRVSTAT_INFO(rx_dropped_header_too_small)},
+ /* Received packets dropped when the TCP header length field is less
+ * than 5 or the TCP header length + IP header length is more
+ * than IP packet length.
+ */
{DRVSTAT_INFO(rx_dropped_tcp_length)},
{DRVSTAT_INFO(rx_dropped_runt)},
+ /* Number of received packets dropped when a fifo for descriptors going
+ * into the packet demux block overflows. In normal operation, this
+ * fifo must never overflow.
+ */
{DRVSTAT_INFO(rxpp_fifo_overflow_drop)},
{DRVSTAT_INFO(rx_input_fifo_overflow_drop)},
{DRVSTAT_INFO(rx_ip_checksum_errs)},
@@ -59,16 +85,35 @@ static const struct be_ethtool_stat et_stats[] = {
{DRVSTAT_INFO(tx_pauseframes)},
{DRVSTAT_INFO(tx_controlframes)},
{DRVSTAT_INFO(rx_priority_pause_frames)},
+ /* Received packets dropped when an internal fifo going into
+ * main packet buffer tank (PMEM) overflows.
+ */
{DRVSTAT_INFO(pmem_fifo_overflow_drop)},
{DRVSTAT_INFO(jabber_events)},
+ /* Received packets dropped due to lack of available HW packet buffers
+ * used to temporarily hold the received packets.
+ */
{DRVSTAT_INFO(rx_drops_no_pbuf)},
- {DRVSTAT_INFO(rx_drops_no_txpb)},
+ /* Received packets dropped due to input receive buffer
+ * descriptor fifo overflowing.
+ */
{DRVSTAT_INFO(rx_drops_no_erx_descr)},
+ /* Packets dropped because the internal FIFO to the offloaded TCP
+ * receive processing block is full. This could happen only for
+ * offloaded iSCSI or FCoE trarffic.
+ */
{DRVSTAT_INFO(rx_drops_no_tpre_descr)},
+ /* Received packets dropped when they need more than 8
+ * receive buffers. This cannot happen as the driver configures
+ * 2048 byte receive buffers.
+ */
{DRVSTAT_INFO(rx_drops_too_many_frags)},
- {DRVSTAT_INFO(rx_drops_invalid_ring)},
{DRVSTAT_INFO(forwarded_packets)},
+ /* Received packets dropped when the frame length
+ * is more than 9018 bytes
+ */
{DRVSTAT_INFO(rx_drops_mtu)},
+ /* Number of packets dropped due to random early drop function */
{DRVSTAT_INFO(eth_red_drops)},
{DRVSTAT_INFO(be_on_die_temperature)}
};
@@ -80,12 +125,17 @@ static const struct be_ethtool_stat et_stats[] = {
static const struct be_ethtool_stat et_rx_stats[] = {
{DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */
{DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */
- {DRVSTAT_RX_INFO(rx_polls)},
- {DRVSTAT_RX_INFO(rx_events)},
{DRVSTAT_RX_INFO(rx_compl)},
{DRVSTAT_RX_INFO(rx_mcast_pkts)},
+ /* Number of page allocation failures while posting receive buffers
+ * to HW.
+ */
{DRVSTAT_RX_INFO(rx_post_fail)},
+ /* Recevied packets dropped due to skb allocation failure */
{DRVSTAT_RX_INFO(rx_drops_no_skbs)},
+ /* Received packets dropped due to lack of available fetched buffers
+ * posted by the driver.
+ */
{DRVSTAT_RX_INFO(rx_drops_no_frags)}
};
#define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats))
@@ -97,9 +147,13 @@ static const struct be_ethtool_stat et_tx_stats[] = {
{DRVSTAT_TX_INFO(tx_compl)}, /* If moving this member see above note */
{DRVSTAT_TX_INFO(tx_bytes)},
{DRVSTAT_TX_INFO(tx_pkts)},
+ /* Number of skbs queued for trasmission by the driver */
{DRVSTAT_TX_INFO(tx_reqs)},
+ /* Number of TX work request blocks DMAed to HW */
{DRVSTAT_TX_INFO(tx_wrbs)},
- {DRVSTAT_TX_INFO(tx_compl)},
+ /* Number of times the TX queue was stopped due to lack
+ * of spaces in the TXQ.
+ */
{DRVSTAT_TX_INFO(tx_stops)}
};
#define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats))
@@ -232,86 +286,42 @@ be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
}
}
-static int
-be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
+static int be_get_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *et)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq;
- struct be_eq_obj *tx_eq = &adapter->tx_eq;
+ struct be_eq_obj *eqo = &adapter->eq_obj[0];
+
- coalesce->rx_coalesce_usecs = rx_eq->cur_eqd;
- coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd;
- coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd;
+ et->rx_coalesce_usecs = eqo->cur_eqd;
+ et->rx_coalesce_usecs_high = eqo->max_eqd;
+ et->rx_coalesce_usecs_low = eqo->min_eqd;
- coalesce->tx_coalesce_usecs = tx_eq->cur_eqd;
- coalesce->tx_coalesce_usecs_high = tx_eq->max_eqd;
- coalesce->tx_coalesce_usecs_low = tx_eq->min_eqd;
+ et->tx_coalesce_usecs = eqo->cur_eqd;
+ et->tx_coalesce_usecs_high = eqo->max_eqd;
+ et->tx_coalesce_usecs_low = eqo->min_eqd;
- coalesce->use_adaptive_rx_coalesce = rx_eq->enable_aic;
- coalesce->use_adaptive_tx_coalesce = tx_eq->enable_aic;
+ et->use_adaptive_rx_coalesce = eqo->enable_aic;
+ et->use_adaptive_tx_coalesce = eqo->enable_aic;
return 0;
}
-/*
- * This routine is used to set interrup coalescing delay
+/* TX attributes are ignored. Only RX attributes are considered
+ * eqd cmd is issued in the worker thread.
*/
-static int
-be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
+static int be_set_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *et)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_rx_obj *rxo;
- struct be_eq_obj *rx_eq;
- struct be_eq_obj *tx_eq = &adapter->tx_eq;
- u32 rx_max, rx_min, rx_cur;
- int status = 0, i;
- u32 tx_cur;
-
- if (coalesce->use_adaptive_tx_coalesce == 1)
- return -EINVAL;
-
- for_all_rx_queues(adapter, rxo, i) {
- rx_eq = &rxo->rx_eq;
-
- if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce)
- rx_eq->cur_eqd = 0;
- rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
-
- rx_max = coalesce->rx_coalesce_usecs_high;
- rx_min = coalesce->rx_coalesce_usecs_low;
- rx_cur = coalesce->rx_coalesce_usecs;
-
- if (rx_eq->enable_aic) {
- if (rx_max > BE_MAX_EQD)
- rx_max = BE_MAX_EQD;
- if (rx_min > rx_max)
- rx_min = rx_max;
- rx_eq->max_eqd = rx_max;
- rx_eq->min_eqd = rx_min;
- if (rx_eq->cur_eqd > rx_max)
- rx_eq->cur_eqd = rx_max;
- if (rx_eq->cur_eqd < rx_min)
- rx_eq->cur_eqd = rx_min;
- } else {
- if (rx_cur > BE_MAX_EQD)
- rx_cur = BE_MAX_EQD;
- if (rx_eq->cur_eqd != rx_cur) {
- status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
- rx_cur);
- if (!status)
- rx_eq->cur_eqd = rx_cur;
- }
- }
- }
-
- tx_cur = coalesce->tx_coalesce_usecs;
-
- if (tx_cur > BE_MAX_EQD)
- tx_cur = BE_MAX_EQD;
- if (tx_eq->cur_eqd != tx_cur) {
- status = be_cmd_modify_eqd(adapter, tx_eq->q.id, tx_cur);
- if (!status)
- tx_eq->cur_eqd = tx_cur;
+ struct be_eq_obj *eqo;
+ int i;
+
+ for_all_evt_queues(adapter, eqo, i) {
+ eqo->enable_aic = et->use_adaptive_rx_coalesce;
+ eqo->max_eqd = min(et->rx_coalesce_usecs_high, BE_MAX_EQD);
+ eqo->min_eqd = min(et->rx_coalesce_usecs_low, eqo->max_eqd);
+ eqo->eqd = et->rx_coalesce_usecs;
}
return 0;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index e703d64434f8..e3822788f532 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -127,9 +127,11 @@ static inline bool be_is_mc(struct be_adapter *adapter) {
static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q)
{
struct be_dma_mem *mem = &q->dma_mem;
- if (mem->va)
+ if (mem->va) {
dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
mem->dma);
+ mem->va = NULL;
+ }
}
static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
@@ -144,7 +146,7 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma,
GFP_KERNEL);
if (!mem->va)
- return -1;
+ return -ENOMEM;
memset(mem->va, 0, mem->size);
return 0;
}
@@ -286,7 +288,9 @@ static void populate_be2_stats(struct be_adapter *adapter)
drvs->rx_input_fifo_overflow_drop = port_stats->rx_input_fifo_overflow;
drvs->rx_dropped_header_too_small =
port_stats->rx_dropped_header_too_small;
- drvs->rx_address_match_errors = port_stats->rx_address_match_errors;
+ drvs->rx_address_mismatch_drops =
+ port_stats->rx_address_mismatch_drops +
+ port_stats->rx_vlan_mismatch_drops;
drvs->rx_alignment_symbol_errors =
port_stats->rx_alignment_symbol_errors;
@@ -298,9 +302,7 @@ static void populate_be2_stats(struct be_adapter *adapter)
else
drvs->jabber_events = rxf_stats->port0_jabber_events;
drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf;
- drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb;
drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr;
- drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring;
drvs->forwarded_packets = rxf_stats->forwarded_packets;
drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu;
drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr;
@@ -337,7 +339,7 @@ static void populate_be3_stats(struct be_adapter *adapter)
port_stats->rx_dropped_header_too_small;
drvs->rx_input_fifo_overflow_drop =
port_stats->rx_input_fifo_overflow_drop;
- drvs->rx_address_match_errors = port_stats->rx_address_match_errors;
+ drvs->rx_address_mismatch_drops = port_stats->rx_address_mismatch_drops;
drvs->rx_alignment_symbol_errors =
port_stats->rx_alignment_symbol_errors;
drvs->rxpp_fifo_overflow_drop = port_stats->rxpp_fifo_overflow_drop;
@@ -345,9 +347,7 @@ static void populate_be3_stats(struct be_adapter *adapter)
drvs->tx_controlframes = port_stats->tx_controlframes;
drvs->jabber_events = port_stats->jabber_events;
drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf;
- drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb;
drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr;
- drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring;
drvs->forwarded_packets = rxf_stats->forwarded_packets;
drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu;
drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr;
@@ -380,13 +380,14 @@ static void populate_lancer_stats(struct be_adapter *adapter)
drvs->rx_dropped_header_too_small =
pport_stats->rx_dropped_header_too_small;
drvs->rx_input_fifo_overflow_drop = pport_stats->rx_fifo_overflow;
- drvs->rx_address_match_errors = pport_stats->rx_address_match_errors;
+ drvs->rx_address_mismatch_drops =
+ pport_stats->rx_address_mismatch_drops +
+ pport_stats->rx_vlan_mismatch_drops;
drvs->rx_alignment_symbol_errors = pport_stats->rx_symbol_errors_lo;
drvs->rxpp_fifo_overflow_drop = pport_stats->rx_fifo_overflow;
drvs->tx_pauseframes = pport_stats->tx_pause_frames_lo;
drvs->tx_controlframes = pport_stats->tx_control_frames_lo;
drvs->jabber_events = pport_stats->rx_jabbers;
- drvs->rx_drops_invalid_ring = pport_stats->rx_drops_invalid_queue;
drvs->forwarded_packets = pport_stats->num_forwards_lo;
drvs->rx_drops_mtu = pport_stats->rx_drops_mtu_lo;
drvs->rx_drops_too_many_frags =
@@ -997,18 +998,24 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
return status;
}
-static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo)
+static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo)
{
- struct be_eq_obj *rx_eq = &rxo->rx_eq;
- struct be_rx_stats *stats = rx_stats(rxo);
+ struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]);
ulong now = jiffies;
ulong delta = now - stats->rx_jiffies;
u64 pkts;
unsigned int start, eqd;
- if (!rx_eq->enable_aic)
+ if (!eqo->enable_aic) {
+ eqd = eqo->eqd;
+ goto modify_eqd;
+ }
+
+ if (eqo->idx >= adapter->num_rx_qs)
return;
+ stats = rx_stats(&adapter->rx_obj[eqo->idx]);
+
/* Wrapped around */
if (time_before(now, stats->rx_jiffies)) {
stats->rx_jiffies = now;
@@ -1027,17 +1034,16 @@ static void be_rx_eqd_update(struct be_adapter *adapter, struct be_rx_obj *rxo)
stats->rx_pps = (unsigned long)(pkts - stats->rx_pkts_prev) / (delta / HZ);
stats->rx_pkts_prev = pkts;
stats->rx_jiffies = now;
- eqd = stats->rx_pps / 110000;
- eqd = eqd << 3;
- if (eqd > rx_eq->max_eqd)
- eqd = rx_eq->max_eqd;
- if (eqd < rx_eq->min_eqd)
- eqd = rx_eq->min_eqd;
+ eqd = (stats->rx_pps / 110000) << 3;
+ eqd = min(eqd, eqo->max_eqd);
+ eqd = max(eqd, eqo->min_eqd);
if (eqd < 10)
eqd = 0;
- if (eqd != rx_eq->cur_eqd) {
- be_cmd_modify_eqd(adapter, rx_eq->q.id, eqd);
- rx_eq->cur_eqd = eqd;
+
+modify_eqd:
+ if (eqd != eqo->cur_eqd) {
+ be_cmd_modify_eqd(adapter, eqo->q.id, eqd);
+ eqo->cur_eqd = eqd;
}
}
@@ -1065,11 +1071,10 @@ static inline bool csum_passed(struct be_rx_compl_info *rxcp)
(rxcp->ip_csum || rxcp->ipv6);
}
-static struct be_rx_page_info *
-get_rx_page_info(struct be_adapter *adapter,
- struct be_rx_obj *rxo,
- u16 frag_idx)
+static struct be_rx_page_info *get_rx_page_info(struct be_rx_obj *rxo,
+ u16 frag_idx)
{
+ struct be_adapter *adapter = rxo->adapter;
struct be_rx_page_info *rx_page_info;
struct be_queue_info *rxq = &rxo->q;
@@ -1088,16 +1093,15 @@ get_rx_page_info(struct be_adapter *adapter,
}
/* Throwaway the data in the Rx completion */
-static void be_rx_compl_discard(struct be_adapter *adapter,
- struct be_rx_obj *rxo,
- struct be_rx_compl_info *rxcp)
+static void be_rx_compl_discard(struct be_rx_obj *rxo,
+ struct be_rx_compl_info *rxcp)
{
struct be_queue_info *rxq = &rxo->q;
struct be_rx_page_info *page_info;
u16 i, num_rcvd = rxcp->num_rcvd;
for (i = 0; i < num_rcvd; i++) {
- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
+ page_info = get_rx_page_info(rxo, rxcp->rxq_idx);
put_page(page_info->page);
memset(page_info, 0, sizeof(*page_info));
index_inc(&rxcp->rxq_idx, rxq->len);
@@ -1108,8 +1112,8 @@ static void be_rx_compl_discard(struct be_adapter *adapter,
* skb_fill_rx_data forms a complete skb for an ether frame
* indicated by rxcp.
*/
-static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
- struct sk_buff *skb, struct be_rx_compl_info *rxcp)
+static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb,
+ struct be_rx_compl_info *rxcp)
{
struct be_queue_info *rxq = &rxo->q;
struct be_rx_page_info *page_info;
@@ -1117,7 +1121,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
u16 hdr_len, curr_frag_len, remaining;
u8 *start;
- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
+ page_info = get_rx_page_info(rxo, rxcp->rxq_idx);
start = page_address(page_info->page) + page_info->page_offset;
prefetch(start);
@@ -1154,7 +1158,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
index_inc(&rxcp->rxq_idx, rxq->len);
remaining = rxcp->pkt_size - curr_frag_len;
for (i = 1, j = 0; i < rxcp->num_rcvd; i++) {
- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
+ page_info = get_rx_page_info(rxo, rxcp->rxq_idx);
curr_frag_len = min(remaining, rx_frag_size);
/* Coalesce all frags from the same physical page in one slot */
@@ -1182,21 +1186,21 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
}
/* Process the RX completion indicated by rxcp when GRO is disabled */
-static void be_rx_compl_process(struct be_adapter *adapter,
- struct be_rx_obj *rxo,
- struct be_rx_compl_info *rxcp)
+static void be_rx_compl_process(struct be_rx_obj *rxo,
+ struct be_rx_compl_info *rxcp)
{
+ struct be_adapter *adapter = rxo->adapter;
struct net_device *netdev = adapter->netdev;
struct sk_buff *skb;
- skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN);
+ skb = netdev_alloc_skb_ip_align(netdev, BE_RX_SKB_ALLOC_SIZE);
if (unlikely(!skb)) {
rx_stats(rxo)->rx_drops_no_skbs++;
- be_rx_compl_discard(adapter, rxo, rxcp);
+ be_rx_compl_discard(rxo, rxcp);
return;
}
- skb_fill_rx_data(adapter, rxo, skb, rxcp);
+ skb_fill_rx_data(rxo, skb, rxcp);
if (likely((netdev->features & NETIF_F_RXCSUM) && csum_passed(rxcp)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1204,7 +1208,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, netdev);
- if (adapter->netdev->features & NETIF_F_RXHASH)
+ if (netdev->features & NETIF_F_RXHASH)
skb->rxhash = rxcp->rss_hash;
@@ -1215,26 +1219,25 @@ static void be_rx_compl_process(struct be_adapter *adapter,
}
/* Process the RX completion indicated by rxcp when GRO is enabled */
-static void be_rx_compl_process_gro(struct be_adapter *adapter,
- struct be_rx_obj *rxo,
- struct be_rx_compl_info *rxcp)
+void be_rx_compl_process_gro(struct be_rx_obj *rxo, struct napi_struct *napi,
+ struct be_rx_compl_info *rxcp)
{
+ struct be_adapter *adapter = rxo->adapter;
struct be_rx_page_info *page_info;
struct sk_buff *skb = NULL;
struct be_queue_info *rxq = &rxo->q;
- struct be_eq_obj *eq_obj = &rxo->rx_eq;
u16 remaining, curr_frag_len;
u16 i, j;
- skb = napi_get_frags(&eq_obj->napi);
+ skb = napi_get_frags(napi);
if (!skb) {
- be_rx_compl_discard(adapter, rxo, rxcp);
+ be_rx_compl_discard(rxo, rxcp);
return;
}
remaining = rxcp->pkt_size;
for (i = 0, j = -1; i < rxcp->num_rcvd; i++) {
- page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
+ page_info = get_rx_page_info(rxo, rxcp->rxq_idx);
curr_frag_len = min(remaining, rx_frag_size);
@@ -1267,12 +1270,11 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
if (rxcp->vlanf)
__vlan_hwaccel_put_tag(skb, rxcp->vlan_tag);
- napi_gro_frags(&eq_obj->napi);
+ napi_gro_frags(napi);
}
-static void be_parse_rx_compl_v1(struct be_adapter *adapter,
- struct be_eth_rx_compl *compl,
- struct be_rx_compl_info *rxcp)
+static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl,
+ struct be_rx_compl_info *rxcp)
{
rxcp->pkt_size =
AMAP_GET_BITS(struct amap_eth_rx_compl_v1, pktsize, compl);
@@ -1303,9 +1305,8 @@ static void be_parse_rx_compl_v1(struct be_adapter *adapter,
rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, port, compl);
}
-static void be_parse_rx_compl_v0(struct be_adapter *adapter,
- struct be_eth_rx_compl *compl,
- struct be_rx_compl_info *rxcp)
+static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl,
+ struct be_rx_compl_info *rxcp)
{
rxcp->pkt_size =
AMAP_GET_BITS(struct amap_eth_rx_compl_v0, pktsize, compl);
@@ -1351,9 +1352,9 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
be_dws_le_to_cpu(compl, sizeof(*compl));
if (adapter->be3_native)
- be_parse_rx_compl_v1(adapter, compl, rxcp);
+ be_parse_rx_compl_v1(compl, rxcp);
else
- be_parse_rx_compl_v0(adapter, compl, rxcp);
+ be_parse_rx_compl_v0(compl, rxcp);
if (rxcp->vlanf) {
/* vlanf could be wrongly set in some cards.
@@ -1392,7 +1393,6 @@ static inline struct page *be_alloc_pages(u32 size, gfp_t gfp)
static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
{
struct be_adapter *adapter = rxo->adapter;
- struct be_rx_page_info *page_info_tbl = rxo->page_info_tbl;
struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL;
struct be_queue_info *rxq = &rxo->q;
struct page *pagep = NULL;
@@ -1434,7 +1434,7 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
prev_page_info = page_info;
queue_head_inc(rxq);
- page_info = &page_info_tbl[rxq->head];
+ page_info = &rxo->page_info_tbl[rxq->head];
}
if (pagep)
prev_page_info->last_page_user = true;
@@ -1496,62 +1496,51 @@ static u16 be_tx_compl_process(struct be_adapter *adapter,
return num_wrbs;
}
-static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj)
+/* Return the number of events in the event queue */
+static inline int events_get(struct be_eq_obj *eqo)
{
- struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q);
+ struct be_eq_entry *eqe;
+ int num = 0;
- if (!eqe->evt)
- return NULL;
+ do {
+ eqe = queue_tail_node(&eqo->q);
+ if (eqe->evt == 0)
+ break;
- rmb();
- eqe->evt = le32_to_cpu(eqe->evt);
- queue_tail_inc(&eq_obj->q);
- return eqe;
+ rmb();
+ eqe->evt = 0;
+ num++;
+ queue_tail_inc(&eqo->q);
+ } while (true);
+
+ return num;
}
-static int event_handle(struct be_adapter *adapter,
- struct be_eq_obj *eq_obj,
- bool rearm)
+static int event_handle(struct be_eq_obj *eqo)
{
- struct be_eq_entry *eqe;
- u16 num = 0;
-
- while ((eqe = event_get(eq_obj)) != NULL) {
- eqe->evt = 0;
- num++;
- }
+ bool rearm = false;
+ int num = events_get(eqo);
- /* Deal with any spurious interrupts that come
- * without events
- */
+ /* Deal with any spurious interrupts that come without events */
if (!num)
rearm = true;
- be_eq_notify(adapter, eq_obj->q.id, rearm, true, num);
+ be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num);
if (num)
- napi_schedule(&eq_obj->napi);
+ napi_schedule(&eqo->napi);
return num;
}
-/* Just read and notify events without processing them.
- * Used at the time of destroying event queues */
-static void be_eq_clean(struct be_adapter *adapter,
- struct be_eq_obj *eq_obj)
+/* Leaves the EQ is disarmed state */
+static void be_eq_clean(struct be_eq_obj *eqo)
{
- struct be_eq_entry *eqe;
- u16 num = 0;
-
- while ((eqe = event_get(eq_obj)) != NULL) {
- eqe->evt = 0;
- num++;
- }
+ int num = events_get(eqo);
- if (num)
- be_eq_notify(adapter, eq_obj->q.id, false, true, num);
+ be_eq_notify(eqo->adapter, eqo->q.id, false, true, num);
}
-static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo)
+static void be_rx_cq_clean(struct be_rx_obj *rxo)
{
struct be_rx_page_info *page_info;
struct be_queue_info *rxq = &rxo->q;
@@ -1561,14 +1550,14 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo)
/* First cleanup pending rx completions */
while ((rxcp = be_rx_compl_get(rxo)) != NULL) {
- be_rx_compl_discard(adapter, rxo, rxcp);
- be_cq_notify(adapter, rx_cq->id, false, 1);
+ be_rx_compl_discard(rxo, rxcp);
+ be_cq_notify(rxo->adapter, rx_cq->id, false, 1);
}
/* Then free posted rx buffer 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(adapter, rxo, tail);
+ page_info = get_rx_page_info(rxo, tail);
put_page(page_info->page);
memset(page_info, 0, sizeof(*page_info));
}
@@ -1576,54 +1565,106 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo)
rxq->tail = rxq->head = 0;
}
-static void be_tx_compl_clean(struct be_adapter *adapter,
- struct be_tx_obj *txo)
+static void be_tx_compl_clean(struct be_adapter *adapter)
{
- struct be_queue_info *tx_cq = &txo->cq;
- struct be_queue_info *txq = &txo->q;
+ struct be_tx_obj *txo;
+ struct be_queue_info *txq;
struct be_eth_tx_compl *txcp;
u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0;
- struct sk_buff **sent_skbs = txo->sent_skb_list;
struct sk_buff *sent_skb;
bool dummy_wrb;
+ int i, pending_txqs;
/* Wait for a max of 200ms for all the tx-completions to arrive. */
do {
- while ((txcp = be_tx_compl_get(tx_cq))) {
- end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
- wrb_index, txcp);
- num_wrbs += be_tx_compl_process(adapter, txo, end_idx);
- cmpl++;
- }
- if (cmpl) {
- be_cq_notify(adapter, tx_cq->id, false, cmpl);
- atomic_sub(num_wrbs, &txq->used);
- cmpl = 0;
- num_wrbs = 0;
+ pending_txqs = adapter->num_tx_qs;
+
+ for_all_tx_queues(adapter, txo, i) {
+ txq = &txo->q;
+ while ((txcp = be_tx_compl_get(&txo->cq))) {
+ end_idx =
+ AMAP_GET_BITS(struct amap_eth_tx_compl,
+ wrb_index, txcp);
+ num_wrbs += be_tx_compl_process(adapter, txo,
+ end_idx);
+ cmpl++;
+ }
+ if (cmpl) {
+ be_cq_notify(adapter, txo->cq.id, false, cmpl);
+ atomic_sub(num_wrbs, &txq->used);
+ cmpl = 0;
+ num_wrbs = 0;
+ }
+ if (atomic_read(&txq->used) == 0)
+ pending_txqs--;
}
- if (atomic_read(&txq->used) == 0 || ++timeo > 200)
+ if (pending_txqs == 0 || ++timeo > 200)
break;
mdelay(1);
} while (true);
- if (atomic_read(&txq->used))
- dev_err(&adapter->pdev->dev, "%d pending tx-completions\n",
- atomic_read(&txq->used));
+ for_all_tx_queues(adapter, txo, i) {
+ txq = &txo->q;
+ if (atomic_read(&txq->used))
+ dev_err(&adapter->pdev->dev, "%d pending tx-compls\n",
+ atomic_read(&txq->used));
+
+ /* free posted tx for which compls will never arrive */
+ while (atomic_read(&txq->used)) {
+ sent_skb = txo->sent_skb_list[txq->tail];
+ end_idx = txq->tail;
+ num_wrbs = wrb_cnt_for_skb(adapter, sent_skb,
+ &dummy_wrb);
+ index_adv(&end_idx, num_wrbs - 1, txq->len);
+ num_wrbs = be_tx_compl_process(adapter, txo, end_idx);
+ atomic_sub(num_wrbs, &txq->used);
+ }
+ }
+}
- /* free posted tx for which compls will never arrive */
- while (atomic_read(&txq->used)) {
- sent_skb = sent_skbs[txq->tail];
- end_idx = txq->tail;
- index_adv(&end_idx,
- wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1,
- txq->len);
- num_wrbs = be_tx_compl_process(adapter, txo, end_idx);
- atomic_sub(num_wrbs, &txq->used);
+static void be_evt_queues_destroy(struct be_adapter *adapter)
+{
+ struct be_eq_obj *eqo;
+ int i;
+
+ for_all_evt_queues(adapter, eqo, i) {
+ be_eq_clean(eqo);
+ if (eqo->q.created)
+ be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ);
+ be_queue_free(adapter, &eqo->q);
}
}
+static int be_evt_queues_create(struct be_adapter *adapter)
+{
+ struct be_queue_info *eq;
+ struct be_eq_obj *eqo;
+ int i, rc;
+
+ adapter->num_evt_qs = num_irqs(adapter);
+
+ for_all_evt_queues(adapter, eqo, i) {
+ eqo->adapter = adapter;
+ eqo->tx_budget = BE_TX_BUDGET;
+ eqo->idx = i;
+ eqo->max_eqd = BE_MAX_EQD;
+ eqo->enable_aic = true;
+
+ eq = &eqo->q;
+ rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN,
+ sizeof(struct be_eq_entry));
+ if (rc)
+ return rc;
+
+ rc = be_cmd_eq_create(adapter, eq, eqo->cur_eqd);
+ if (rc)
+ return rc;
+ }
+ return 0;
+}
+
static void be_mcc_queues_destroy(struct be_adapter *adapter)
{
struct be_queue_info *q;
@@ -1644,22 +1685,19 @@ static int be_mcc_queues_create(struct be_adapter *adapter)
{
struct be_queue_info *q, *cq;
- /* Alloc MCC compl queue */
cq = &adapter->mcc_obj.cq;
if (be_queue_alloc(adapter, cq, MCC_CQ_LEN,
sizeof(struct be_mcc_compl)))
goto err;
- /* Ask BE to create MCC compl queue; share TX's eq */
- if (be_cmd_cq_create(adapter, cq, &adapter->tx_eq.q, false, true, 0))
+ /* Use the default EQ for MCC completions */
+ if (be_cmd_cq_create(adapter, cq, &mcc_eqo(adapter)->q, true, 0))
goto mcc_cq_free;
- /* Alloc MCC queue */
q = &adapter->mcc_obj.q;
if (be_queue_alloc(adapter, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb)))
goto mcc_cq_destroy;
- /* Ask BE to create MCC queue */
if (be_cmd_mccq_create(adapter, q, cq))
goto mcc_q_free;
@@ -1692,14 +1730,6 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
be_cmd_q_destroy(adapter, q, QTYPE_CQ);
be_queue_free(adapter, q);
}
-
- /* Clear any residual events */
- be_eq_clean(adapter, &adapter->tx_eq);
-
- q = &adapter->tx_eq.q;
- if (q->created)
- be_cmd_q_destroy(adapter, q, QTYPE_EQ);
- be_queue_free(adapter, q);
}
static int be_num_txqs_want(struct be_adapter *adapter)
@@ -1712,10 +1742,10 @@ static int be_num_txqs_want(struct be_adapter *adapter)
return MAX_TX_QS;
}
-/* One TX event queue is shared by all TX compl qs */
-static int be_tx_queues_create(struct be_adapter *adapter)
+static int be_tx_cqs_create(struct be_adapter *adapter)
{
- struct be_queue_info *eq, *q, *cq;
+ struct be_queue_info *cq, *eq;
+ int status;
struct be_tx_obj *txo;
u8 i;
@@ -1727,192 +1757,109 @@ static int be_tx_queues_create(struct be_adapter *adapter)
rtnl_unlock();
}
- adapter->tx_eq.max_eqd = 0;
- adapter->tx_eq.min_eqd = 0;
- adapter->tx_eq.cur_eqd = 96;
- adapter->tx_eq.enable_aic = false;
+ for_all_tx_queues(adapter, txo, i) {
+ cq = &txo->cq;
+ status = be_queue_alloc(adapter, cq, TX_CQ_LEN,
+ sizeof(struct be_eth_tx_compl));
+ if (status)
+ return status;
- eq = &adapter->tx_eq.q;
- if (be_queue_alloc(adapter, eq, EVNT_Q_LEN,
- sizeof(struct be_eq_entry)))
- return -1;
+ /* If num_evt_qs is less than num_tx_qs, then more than
+ * one txq share an eq
+ */
+ eq = &adapter->eq_obj[i % adapter->num_evt_qs].q;
+ status = be_cmd_cq_create(adapter, cq, eq, false, 3);
+ if (status)
+ return status;
+ }
+ return 0;
+}
- if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd))
- goto err;
- adapter->tx_eq.eq_idx = adapter->eq_next_idx++;
+static int be_tx_qs_create(struct be_adapter *adapter)
+{
+ struct be_tx_obj *txo;
+ int i, status;
for_all_tx_queues(adapter, txo, i) {
- cq = &txo->cq;
- if (be_queue_alloc(adapter, cq, TX_CQ_LEN,
- sizeof(struct be_eth_tx_compl)))
- goto err;
-
- if (be_cmd_cq_create(adapter, cq, eq, false, false, 3))
- goto err;
+ status = be_queue_alloc(adapter, &txo->q, TX_Q_LEN,
+ sizeof(struct be_eth_wrb));
+ if (status)
+ return status;
- q = &txo->q;
- if (be_queue_alloc(adapter, q, TX_Q_LEN,
- sizeof(struct be_eth_wrb)))
- goto err;
+ status = be_cmd_txq_create(adapter, &txo->q, &txo->cq);
+ if (status)
+ return status;
}
- return 0;
-err:
- be_tx_queues_destroy(adapter);
- return -1;
+ return 0;
}
-static void be_rx_queues_destroy(struct be_adapter *adapter)
+static void be_rx_cqs_destroy(struct be_adapter *adapter)
{
struct be_queue_info *q;
struct be_rx_obj *rxo;
int i;
for_all_rx_queues(adapter, rxo, i) {
- be_queue_free(adapter, &rxo->q);
-
q = &rxo->cq;
if (q->created)
be_cmd_q_destroy(adapter, q, QTYPE_CQ);
be_queue_free(adapter, q);
-
- q = &rxo->rx_eq.q;
- if (q->created)
- be_cmd_q_destroy(adapter, q, QTYPE_EQ);
- be_queue_free(adapter, q);
- }
-}
-
-static u32 be_num_rxqs_want(struct be_adapter *adapter)
-{
- if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
- !sriov_enabled(adapter) && be_physfn(adapter)) {
- return 1 + MAX_RSS_QS; /* one default non-RSS queue */
- } else {
- dev_warn(&adapter->pdev->dev,
- "No support for multiple RX queues\n");
- return 1;
}
}
-static int be_rx_queues_create(struct be_adapter *adapter)
+static int be_rx_cqs_create(struct be_adapter *adapter)
{
- struct be_queue_info *eq, *q, *cq;
+ struct be_queue_info *eq, *cq;
struct be_rx_obj *rxo;
int rc, i;
- adapter->num_rx_qs = min(be_num_rxqs_want(adapter),
- msix_enabled(adapter) ?
- adapter->num_msix_vec - 1 : 1);
- if (adapter->num_rx_qs != MAX_RX_QS)
- dev_warn(&adapter->pdev->dev,
- "Can create only %d RX queues", adapter->num_rx_qs);
+ /* We'll create as many RSS rings as there are irqs.
+ * But when there's only one irq there's no use creating RSS rings
+ */
+ adapter->num_rx_qs = (num_irqs(adapter) > 1) ?
+ num_irqs(adapter) + 1 : 1;
adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
for_all_rx_queues(adapter, rxo, i) {
rxo->adapter = adapter;
- rxo->rx_eq.max_eqd = BE_MAX_EQD;
- rxo->rx_eq.enable_aic = true;
-
- /* EQ */
- eq = &rxo->rx_eq.q;
- rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN,
- sizeof(struct be_eq_entry));
- if (rc)
- goto err;
-
- rc = be_cmd_eq_create(adapter, eq, rxo->rx_eq.cur_eqd);
- if (rc)
- goto err;
-
- rxo->rx_eq.eq_idx = adapter->eq_next_idx++;
-
- /* CQ */
cq = &rxo->cq;
rc = be_queue_alloc(adapter, cq, RX_CQ_LEN,
sizeof(struct be_eth_rx_compl));
if (rc)
- goto err;
-
- rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
- if (rc)
- goto err;
+ return rc;
- /* Rx Q - will be created in be_open() */
- q = &rxo->q;
- rc = be_queue_alloc(adapter, q, RX_Q_LEN,
- sizeof(struct be_eth_rx_d));
+ eq = &adapter->eq_obj[i % adapter->num_evt_qs].q;
+ rc = be_cmd_cq_create(adapter, cq, eq, false, 3);
if (rc)
- goto err;
-
+ return rc;
}
- return 0;
-err:
- be_rx_queues_destroy(adapter);
- return -1;
-}
+ if (adapter->num_rx_qs != MAX_RX_QS)
+ dev_info(&adapter->pdev->dev,
+ "Created only %d receive queues", adapter->num_rx_qs);
-static bool event_peek(struct be_eq_obj *eq_obj)
-{
- struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q);
- if (!eqe->evt)
- return false;
- else
- return true;
+ return 0;
}
static irqreturn_t be_intx(int irq, void *dev)
{
struct be_adapter *adapter = dev;
- struct be_rx_obj *rxo;
- int isr, i, tx = 0 , rx = 0;
-
- if (lancer_chip(adapter)) {
- if (event_peek(&adapter->tx_eq))
- tx = event_handle(adapter, &adapter->tx_eq, false);
- for_all_rx_queues(adapter, rxo, i) {
- if (event_peek(&rxo->rx_eq))
- rx |= event_handle(adapter, &rxo->rx_eq, true);
- }
-
- if (!(tx || rx))
- return IRQ_NONE;
-
- } else {
- isr = ioread32(adapter->csr + CEV_ISR0_OFFSET +
- (adapter->tx_eq.q.id / 8) * CEV_ISR_SIZE);
- if (!isr)
- return IRQ_NONE;
-
- if ((1 << adapter->tx_eq.eq_idx & isr))
- event_handle(adapter, &adapter->tx_eq, false);
-
- for_all_rx_queues(adapter, rxo, i) {
- if ((1 << rxo->rx_eq.eq_idx & isr))
- event_handle(adapter, &rxo->rx_eq, true);
- }
- }
+ int num_evts;
- return IRQ_HANDLED;
-}
-
-static irqreturn_t be_msix_rx(int irq, void *dev)
-{
- struct be_rx_obj *rxo = dev;
- struct be_adapter *adapter = rxo->adapter;
-
- event_handle(adapter, &rxo->rx_eq, true);
-
- return IRQ_HANDLED;
+ /* With INTx only one EQ is used */
+ num_evts = event_handle(&adapter->eq_obj[0]);
+ if (num_evts)
+ return IRQ_HANDLED;
+ else
+ return IRQ_NONE;
}
-static irqreturn_t be_msix_tx_mcc(int irq, void *dev)
+static irqreturn_t be_msix(int irq, void *dev)
{
- struct be_adapter *adapter = dev;
-
- event_handle(adapter, &adapter->tx_eq, false);
+ struct be_eq_obj *eqo = dev;
+ event_handle(eqo);
return IRQ_HANDLED;
}
@@ -1921,16 +1868,14 @@ static inline bool do_gro(struct be_rx_compl_info *rxcp)
return (rxcp->tcpf && !rxcp->err) ? true : false;
}
-static int be_poll_rx(struct napi_struct *napi, int budget)
+static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi,
+ int budget)
{
- struct be_eq_obj *rx_eq = container_of(napi, struct be_eq_obj, napi);
- struct be_rx_obj *rxo = container_of(rx_eq, struct be_rx_obj, rx_eq);
struct be_adapter *adapter = rxo->adapter;
struct be_queue_info *rx_cq = &rxo->cq;
struct be_rx_compl_info *rxcp;
u32 work_done;
- rx_stats(rxo)->rx_polls++;
for (work_done = 0; work_done < budget; work_done++) {
rxcp = be_rx_compl_get(rxo);
if (!rxcp)
@@ -1942,7 +1887,7 @@ static int be_poll_rx(struct napi_struct *napi, int budget)
/* Discard compl with partial DMA Lancer B0 */
if (unlikely(!rxcp->pkt_size)) {
- be_rx_compl_discard(adapter, rxo, rxcp);
+ be_rx_compl_discard(rxo, rxcp);
goto loop_continue;
}
@@ -1951,94 +1896,96 @@ static int be_poll_rx(struct napi_struct *napi, int budget)
*/
if (unlikely(rxcp->port != adapter->port_num &&
!lancer_chip(adapter))) {
- be_rx_compl_discard(adapter, rxo, rxcp);
+ be_rx_compl_discard(rxo, rxcp);
goto loop_continue;
}
if (do_gro(rxcp))
- be_rx_compl_process_gro(adapter, rxo, rxcp);
+ be_rx_compl_process_gro(rxo, napi, rxcp);
else
- be_rx_compl_process(adapter, rxo, rxcp);
+ be_rx_compl_process(rxo, rxcp);
loop_continue:
be_rx_stats_update(rxo, rxcp);
}
- be_cq_notify(adapter, rx_cq->id, false, work_done);
+ if (work_done) {
+ be_cq_notify(adapter, rx_cq->id, true, work_done);
- /* Refill the queue */
- if (work_done && atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM)
- be_post_rx_frags(rxo, GFP_ATOMIC);
-
- /* All consumed */
- if (work_done < budget) {
- napi_complete(napi);
- /* Arm CQ */
- be_cq_notify(adapter, rx_cq->id, true, 0);
+ if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM)
+ be_post_rx_frags(rxo, GFP_ATOMIC);
}
+
return work_done;
}
-/* As TX and MCC share the same EQ check for both TX and MCC completions.
- * For TX/MCC we don't honour budget; consume everything
- */
-static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
+static bool be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo,
+ int budget, int idx)
{
- struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi);
- struct be_adapter *adapter =
- container_of(tx_eq, struct be_adapter, tx_eq);
- struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
- struct be_tx_obj *txo;
struct be_eth_tx_compl *txcp;
- int tx_compl, mcc_compl, status = 0;
- u8 i;
- u16 num_wrbs;
+ int num_wrbs = 0, work_done;
- for_all_tx_queues(adapter, txo, i) {
- tx_compl = 0;
- num_wrbs = 0;
- while ((txcp = be_tx_compl_get(&txo->cq))) {
- num_wrbs += be_tx_compl_process(adapter, txo,
+ for (work_done = 0; work_done < budget; work_done++) {
+ txcp = be_tx_compl_get(&txo->cq);
+ if (!txcp)
+ break;
+ num_wrbs += be_tx_compl_process(adapter, txo,
AMAP_GET_BITS(struct amap_eth_tx_compl,
wrb_index, txcp));
- tx_compl++;
- }
- if (tx_compl) {
- be_cq_notify(adapter, txo->cq.id, true, tx_compl);
+ }
- atomic_sub(num_wrbs, &txo->q.used);
+ if (work_done) {
+ be_cq_notify(adapter, txo->cq.id, true, work_done);
+ atomic_sub(num_wrbs, &txo->q.used);
- /* As Tx wrbs have been freed up, wake up netdev queue
- * if it was stopped due to lack of tx wrbs. */
- if (__netif_subqueue_stopped(adapter->netdev, i) &&
- atomic_read(&txo->q.used) < txo->q.len / 2) {
- netif_wake_subqueue(adapter->netdev, i);
- }
-
- u64_stats_update_begin(&tx_stats(txo)->sync_compl);
- tx_stats(txo)->tx_compl += tx_compl;
- u64_stats_update_end(&tx_stats(txo)->sync_compl);
+ /* As Tx wrbs have been freed up, wake up netdev queue
+ * if it was stopped due to lack of tx wrbs. */
+ if (__netif_subqueue_stopped(adapter->netdev, idx) &&
+ atomic_read(&txo->q.used) < txo->q.len / 2) {
+ netif_wake_subqueue(adapter->netdev, idx);
}
+
+ u64_stats_update_begin(&tx_stats(txo)->sync_compl);
+ tx_stats(txo)->tx_compl += work_done;
+ u64_stats_update_end(&tx_stats(txo)->sync_compl);
}
+ return (work_done < budget); /* Done */
+}
- mcc_compl = be_process_mcc(adapter, &status);
+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;
+ bool tx_done;
- if (mcc_compl) {
- be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl);
+ /* 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],
+ eqo->tx_budget, i);
+ if (!tx_done)
+ max_work = budget;
}
- napi_complete(napi);
+ /* This loop will iterate twice for EQ0 in which
+ * completions of the last RXQ (default one) are also processed
+ * For other EQs the loop iterates only once
+ */
+ for (i = eqo->idx; i < adapter->num_rx_qs; i += adapter->num_evt_qs) {
+ work = be_process_rx(&adapter->rx_obj[i], napi, budget);
+ max_work = max(work, max_work);
+ }
- /* Arm CQ again to regenerate EQEs for Lancer in INTx mode */
- if (lancer_chip(adapter) && !msix_enabled(adapter)) {
- for_all_tx_queues(adapter, txo, i)
- be_cq_notify(adapter, txo->cq.id, true, 0);
+ if (is_mcc_eqo(eqo))
+ be_process_mcc(adapter);
- be_cq_notify(adapter, mcc_obj->cq.id, true, 0);
+ if (max_work < budget) {
+ napi_complete(napi);
+ be_eq_notify(adapter, eqo->q.id, true, false, 0);
+ } 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, tx_eq->q.id, true, false, 0);
- adapter->drv_stats.tx_events++;
- return 1;
+ return max_work;
}
void be_detect_dump_ue(struct be_adapter *adapter)
@@ -2113,12 +2060,24 @@ static void be_msix_disable(struct be_adapter *adapter)
}
}
+static uint be_num_rss_want(struct be_adapter *adapter)
+{
+ if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
+ adapter->num_vfs == 0 && be_physfn(adapter) &&
+ !be_is_mc(adapter))
+ return (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
+ else
+ return 0;
+}
+
static void be_msix_enable(struct be_adapter *adapter)
{
-#define BE_MIN_MSIX_VECTORS (1 + 1) /* Rx + Tx */
+#define BE_MIN_MSIX_VECTORS 1
int i, status, num_vec;
- num_vec = be_num_rxqs_want(adapter) + 1;
+ /* If RSS queues are not used, need a vec for default RX Q */
+ num_vec = min(be_num_rss_want(adapter), num_online_cpus());
+ num_vec = max(num_vec, BE_MIN_MSIX_VECTORS);
for (i = 0; i < num_vec; i++)
adapter->msix_entries[i].entry = i;
@@ -2186,60 +2145,31 @@ static void be_sriov_disable(struct be_adapter *adapter)
}
static inline int be_msix_vec_get(struct be_adapter *adapter,
- struct be_eq_obj *eq_obj)
-{
- return adapter->msix_entries[eq_obj->eq_idx].vector;
-}
-
-static int be_request_irq(struct be_adapter *adapter,
- struct be_eq_obj *eq_obj,
- void *handler, char *desc, void *context)
-{
- struct net_device *netdev = adapter->netdev;
- int vec;
-
- sprintf(eq_obj->desc, "%s-%s", netdev->name, desc);
- vec = be_msix_vec_get(adapter, eq_obj);
- return request_irq(vec, handler, 0, eq_obj->desc, context);
-}
-
-static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj,
- void *context)
+ struct be_eq_obj *eqo)
{
- int vec = be_msix_vec_get(adapter, eq_obj);
- free_irq(vec, context);
+ return adapter->msix_entries[eqo->idx].vector;
}
static int be_msix_register(struct be_adapter *adapter)
{
- struct be_rx_obj *rxo;
- int status, i;
- char qname[10];
-
- status = be_request_irq(adapter, &adapter->tx_eq, be_msix_tx_mcc, "tx",
- adapter);
- if (status)
- goto err;
+ struct net_device *netdev = adapter->netdev;
+ struct be_eq_obj *eqo;
+ int status, i, vec;
- for_all_rx_queues(adapter, rxo, i) {
- sprintf(qname, "rxq%d", i);
- status = be_request_irq(adapter, &rxo->rx_eq, be_msix_rx,
- qname, rxo);
+ for_all_evt_queues(adapter, eqo, i) {
+ sprintf(eqo->desc, "%s-q%d", netdev->name, i);
+ vec = be_msix_vec_get(adapter, eqo);
+ status = request_irq(vec, be_msix, 0, eqo->desc, eqo);
if (status)
goto err_msix;
}
return 0;
-
err_msix:
- be_free_irq(adapter, &adapter->tx_eq, adapter);
-
- for (i--, rxo = &adapter->rx_obj[i]; i >= 0; i--, rxo--)
- be_free_irq(adapter, &rxo->rx_eq, rxo);
-
-err:
- dev_warn(&adapter->pdev->dev,
- "MSIX Request IRQ failed - err %d\n", status);
+ for (i--, eqo = &adapter->eq_obj[i]; i >= 0; i--, eqo--)
+ free_irq(be_msix_vec_get(adapter, eqo), eqo);
+ dev_warn(&adapter->pdev->dev, "MSIX Request IRQ failed - err %d\n",
+ status);
be_msix_disable(adapter);
return status;
}
@@ -2275,7 +2205,7 @@ done:
static void be_irq_unregister(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- struct be_rx_obj *rxo;
+ struct be_eq_obj *eqo;
int i;
if (!adapter->isr_registered)
@@ -2288,16 +2218,14 @@ static void be_irq_unregister(struct be_adapter *adapter)
}
/* MSIx */
- be_free_irq(adapter, &adapter->tx_eq, adapter);
-
- for_all_rx_queues(adapter, rxo, i)
- be_free_irq(adapter, &rxo->rx_eq, rxo);
+ for_all_evt_queues(adapter, eqo, i)
+ free_irq(be_msix_vec_get(adapter, eqo), eqo);
done:
adapter->isr_registered = false;
}
-static void be_rx_queues_clear(struct be_adapter *adapter)
+static void be_rx_qs_destroy(struct be_adapter *adapter)
{
struct be_queue_info *q;
struct be_rx_obj *rxo;
@@ -2312,76 +2240,67 @@ static void be_rx_queues_clear(struct be_adapter *adapter)
* arrive
*/
mdelay(1);
- be_rx_q_clean(adapter, rxo);
+ be_rx_cq_clean(rxo);
}
-
- /* Clear any residual events */
- q = &rxo->rx_eq.q;
- if (q->created)
- be_eq_clean(adapter, &rxo->rx_eq);
+ be_queue_free(adapter, q);
}
}
static int be_close(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_rx_obj *rxo;
- struct be_tx_obj *txo;
- struct be_eq_obj *tx_eq = &adapter->tx_eq;
- int vec, i;
+ struct be_eq_obj *eqo;
+ int i;
be_async_mcc_disable(adapter);
if (!lancer_chip(adapter))
be_intr_set(adapter, false);
- for_all_rx_queues(adapter, rxo, i)
- napi_disable(&rxo->rx_eq.napi);
-
- napi_disable(&tx_eq->napi);
-
- if (lancer_chip(adapter)) {
- be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
- for_all_rx_queues(adapter, rxo, i)
- be_cq_notify(adapter, rxo->cq.id, false, 0);
- for_all_tx_queues(adapter, txo, i)
- be_cq_notify(adapter, txo->cq.id, false, 0);
+ for_all_evt_queues(adapter, eqo, i) {
+ napi_disable(&eqo->napi);
+ if (msix_enabled(adapter))
+ synchronize_irq(be_msix_vec_get(adapter, eqo));
+ else
+ synchronize_irq(netdev->irq);
+ be_eq_clean(eqo);
}
- if (msix_enabled(adapter)) {
- vec = be_msix_vec_get(adapter, tx_eq);
- synchronize_irq(vec);
-
- for_all_rx_queues(adapter, rxo, i) {
- vec = be_msix_vec_get(adapter, &rxo->rx_eq);
- synchronize_irq(vec);
- }
- } else {
- synchronize_irq(netdev->irq);
- }
be_irq_unregister(adapter);
/* Wait for all pending tx completions to arrive so that
* all tx skbs are freed.
*/
- for_all_tx_queues(adapter, txo, i)
- be_tx_compl_clean(adapter, txo);
+ be_tx_compl_clean(adapter);
- be_rx_queues_clear(adapter);
+ be_rx_qs_destroy(adapter);
return 0;
}
-static int be_rx_queues_setup(struct be_adapter *adapter)
+static int be_rx_qs_create(struct be_adapter *adapter)
{
struct be_rx_obj *rxo;
int rc, i, j;
u8 rsstable[128];
for_all_rx_queues(adapter, rxo, i) {
+ rc = be_queue_alloc(adapter, &rxo->q, RX_Q_LEN,
+ sizeof(struct be_eth_rx_d));
+ if (rc)
+ return rc;
+ }
+
+ /* The FW would like the default RXQ to be created first */
+ rxo = default_rxo(adapter);
+ rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id, rx_frag_size,
+ adapter->if_handle, false, &rxo->rss_id);
+ if (rc)
+ return rc;
+
+ for_all_rss_queues(adapter, rxo, i) {
rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id,
- rx_frag_size, BE_MAX_JUMBO_FRAME_SIZE,
- adapter->if_handle,
- (i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id);
+ rx_frag_size, adapter->if_handle,
+ true, &rxo->rss_id);
if (rc)
return rc;
}
@@ -2395,48 +2314,47 @@ static int be_rx_queues_setup(struct be_adapter *adapter)
}
}
rc = be_cmd_rss_config(adapter, rsstable, 128);
-
if (rc)
return rc;
}
/* First time posting */
- for_all_rx_queues(adapter, rxo, i) {
+ for_all_rx_queues(adapter, rxo, i)
be_post_rx_frags(rxo, GFP_KERNEL);
- napi_enable(&rxo->rx_eq.napi);
- }
return 0;
}
static int be_open(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_eq_obj *tx_eq = &adapter->tx_eq;
+ struct be_eq_obj *eqo;
struct be_rx_obj *rxo;
+ struct be_tx_obj *txo;
u8 link_status;
int status, i;
- status = be_rx_queues_setup(adapter);
+ status = be_rx_qs_create(adapter);
if (status)
goto err;
- napi_enable(&tx_eq->napi);
-
be_irq_register(adapter);
if (!lancer_chip(adapter))
be_intr_set(adapter, true);
- /* The evt queues are created in unarmed state; arm them */
- for_all_rx_queues(adapter, rxo, i) {
- be_eq_notify(adapter, rxo->rx_eq.q.id, true, false, 0);
+ for_all_rx_queues(adapter, rxo, i)
be_cq_notify(adapter, rxo->cq.id, true, 0);
- }
- be_eq_notify(adapter, tx_eq->q.id, true, false, 0);
- /* Now that interrupts are on we can process async mcc */
+ for_all_tx_queues(adapter, txo, i)
+ be_cq_notify(adapter, txo->cq.id, true, 0);
+
be_async_mcc_enable(adapter);
+ for_all_evt_queues(adapter, eqo, i) {
+ napi_enable(&eqo->napi);
+ be_eq_notify(adapter, eqo->q.id, true, false, 0);
+ }
+
status = be_cmd_link_status_query(adapter, NULL, NULL,
&link_status, 0);
if (!status)
@@ -2540,17 +2458,25 @@ static void be_vf_clear(struct be_adapter *adapter)
static int be_clear(struct be_adapter *adapter)
{
+ if (adapter->flags & BE_FLAGS_WORKER_SCHEDULED) {
+ cancel_delayed_work_sync(&adapter->work);
+ adapter->flags &= ~BE_FLAGS_WORKER_SCHEDULED;
+ }
+
if (sriov_enabled(adapter))
be_vf_clear(adapter);
be_cmd_if_destroy(adapter, adapter->if_handle, 0);
be_mcc_queues_destroy(adapter);
- be_rx_queues_destroy(adapter);
+ be_rx_cqs_destroy(adapter);
be_tx_queues_destroy(adapter);
+ be_evt_queues_destroy(adapter);
/* tell fw we're done with firing cmds */
be_cmd_fw_clean(adapter);
+
+ be_msix_disable(adapter);
return 0;
}
@@ -2609,19 +2535,28 @@ static void be_setup_init(struct be_adapter *adapter)
adapter->eq_next_idx = 0;
}
-static int be_configure_mac_from_list(struct be_adapter *adapter, u8 *mac)
+static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac)
{
u32 pmac_id;
- int status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id);
- if (status != 0)
- goto do_none;
- status = be_cmd_mac_addr_query(adapter, mac,
- MAC_ADDRESS_TYPE_NETWORK,
- false, adapter->if_handle, pmac_id);
+ int status;
+ bool pmac_id_active;
+
+ status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id_active,
+ &pmac_id, mac);
if (status != 0)
goto do_none;
- status = be_cmd_pmac_add(adapter, mac, adapter->if_handle,
- &adapter->pmac_id, 0);
+
+ if (pmac_id_active) {
+ status = be_cmd_mac_addr_query(adapter, mac,
+ MAC_ADDRESS_TYPE_NETWORK,
+ false, adapter->if_handle, pmac_id);
+
+ if (!status)
+ adapter->pmac_id = pmac_id;
+ } else {
+ status = be_cmd_pmac_add(adapter, mac,
+ adapter->if_handle, &adapter->pmac_id, 0);
+ }
do_none:
return status;
}
@@ -2631,24 +2566,29 @@ static int be_setup(struct be_adapter *adapter)
struct net_device *netdev = adapter->netdev;
u32 cap_flags, en_flags;
u32 tx_fc, rx_fc;
- int status, i;
+ int status;
u8 mac[ETH_ALEN];
- struct be_tx_obj *txo;
be_setup_init(adapter);
be_cmd_req_native_mode(adapter);
- status = be_tx_queues_create(adapter);
- if (status != 0)
+ be_msix_enable(adapter);
+
+ status = be_evt_queues_create(adapter);
+ if (status)
goto err;
- status = be_rx_queues_create(adapter);
- if (status != 0)
+ status = be_tx_cqs_create(adapter);
+ if (status)
+ goto err;
+
+ status = be_rx_cqs_create(adapter);
+ if (status)
goto err;
status = be_mcc_queues_create(adapter);
- if (status != 0)
+ if (status)
goto err;
memset(mac, 0, ETH_ALEN);
@@ -2674,19 +2614,13 @@ static int be_setup(struct be_adapter *adapter)
if (status != 0)
goto err;
- for_all_tx_queues(adapter, txo, i) {
- status = be_cmd_txq_create(adapter, &txo->q, &txo->cq);
- if (status)
- goto err;
- }
-
/* The VF's permanent mac queried from card is incorrect.
* For BEx: Query the mac configued by the PF using if_handle
* For Lancer: Get and use mac_list to obtain mac address.
*/
if (!be_physfn(adapter)) {
if (lancer_chip(adapter))
- status = be_configure_mac_from_list(adapter, mac);
+ status = be_add_mac_from_list(adapter, mac);
else
status = be_cmd_mac_addr_query(adapter, mac,
MAC_ADDRESS_TYPE_NETWORK, false,
@@ -2697,6 +2631,10 @@ static int be_setup(struct be_adapter *adapter)
}
}
+ status = be_tx_qs_create(adapter);
+ if (status)
+ goto err;
+
be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL);
status = be_vid_config(adapter, false, 0);
@@ -2726,6 +2664,9 @@ static int be_setup(struct be_adapter *adapter)
goto err;
}
+ schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
+ adapter->flags |= BE_FLAGS_WORKER_SCHEDULED;
+
return 0;
err:
be_clear(adapter);
@@ -2736,12 +2677,13 @@ err:
static void be_netpoll(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_rx_obj *rxo;
+ struct be_eq_obj *eqo;
int i;
- event_handle(adapter, &adapter->tx_eq, false);
- for_all_rx_queues(adapter, rxo, i)
- event_handle(adapter, &rxo->rx_eq, true);
+ for_all_evt_queues(adapter, eqo, i)
+ event_handle(eqo);
+
+ return;
}
#endif
@@ -3102,7 +3044,7 @@ static const struct net_device_ops be_netdev_ops = {
static void be_netdev_init(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_rx_obj *rxo;
+ struct be_eq_obj *eqo;
int i;
netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
@@ -3121,16 +3063,12 @@ static void be_netdev_init(struct net_device *netdev)
netif_set_gso_max_size(netdev, 65535);
- BE_SET_NETDEV_OPS(netdev, &be_netdev_ops);
+ netdev->netdev_ops = &be_netdev_ops;
SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
- for_all_rx_queues(adapter, rxo, i)
- netif_napi_add(netdev, &rxo->rx_eq.napi, be_poll_rx,
- BE_NAPI_WEIGHT);
-
- netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc,
- BE_NAPI_WEIGHT);
+ for_all_evt_queues(adapter, eqo, i)
+ netif_napi_add(netdev, &eqo->napi, be_poll, BE_NAPI_WEIGHT);
}
static void be_unmap_pci_bars(struct be_adapter *adapter)
@@ -3289,8 +3227,6 @@ static void __devexit be_remove(struct pci_dev *pdev)
if (!adapter)
return;
- cancel_delayed_work_sync(&adapter->work);
-
unregister_netdev(adapter->netdev);
be_clear(adapter);
@@ -3301,8 +3237,6 @@ static void __devexit be_remove(struct pci_dev *pdev)
be_sriov_disable(adapter);
- be_msix_disable(adapter);
-
pci_set_drvdata(pdev, NULL);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -3469,6 +3403,7 @@ static void be_worker(struct work_struct *work)
struct be_adapter *adapter =
container_of(work, struct be_adapter, work.work);
struct be_rx_obj *rxo;
+ struct be_eq_obj *eqo;
int i;
if (lancer_chip(adapter))
@@ -3479,15 +3414,7 @@ static void be_worker(struct work_struct *work)
/* when interrupts are not yet enabled, just reap any pending
* mcc completions */
if (!netif_running(adapter->netdev)) {
- int mcc_compl, status = 0;
-
- mcc_compl = be_process_mcc(adapter, &status);
-
- if (mcc_compl) {
- struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
- be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
- }
-
+ be_process_mcc(adapter);
goto reschedule;
}
@@ -3500,14 +3427,15 @@ static void be_worker(struct work_struct *work)
}
for_all_rx_queues(adapter, rxo, i) {
- be_rx_eqd_update(adapter, rxo);
-
if (rxo->rx_post_starved) {
rxo->rx_post_starved = false;
be_post_rx_frags(rxo, GFP_KERNEL);
}
}
+ for_all_evt_queues(adapter, eqo, i)
+ be_eqd_update(adapter, eqo);
+
reschedule:
adapter->work_counter++;
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
@@ -3593,6 +3521,12 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status)
goto ctrl_clean;
+ /* The INTR bit may be set in the card when probed by a kdump kernel
+ * after a crash.
+ */
+ if (!lancer_chip(adapter))
+ be_intr_set(adapter, false);
+
status = be_stats_init(adapter);
if (status)
goto ctrl_clean;
@@ -3601,14 +3535,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status)
goto stats_clean;
- /* The INTR bit may be set in the card when probed by a kdump kernel
- * after a crash.
- */
- if (!lancer_chip(adapter))
- be_intr_set(adapter, false);
-
- be_msix_enable(adapter);
-
INIT_DELAYED_WORK(&adapter->work, be_worker);
adapter->rx_fc = adapter->tx_fc = true;
@@ -3621,9 +3547,9 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status != 0)
goto unsetup;
- dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
+ dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev),
+ adapter->port_num);
- schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
return 0;
unsetup:
@@ -3653,7 +3579,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
struct be_adapter *adapter = pci_get_drvdata(pdev);
struct net_device *netdev = adapter->netdev;
- cancel_delayed_work_sync(&adapter->work);
if (adapter->wol)
be_setup_wol(adapter, true);
@@ -3665,7 +3590,6 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
}
be_clear(adapter);
- be_msix_disable(adapter);
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
@@ -3687,7 +3611,6 @@ static int be_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, 0);
pci_restore_state(pdev);
- be_msix_enable(adapter);
/* tell fw we're ready to fire cmds */
status = be_cmd_fw_init(adapter);
if (status)
@@ -3704,7 +3627,6 @@ static int be_resume(struct pci_dev *pdev)
if (adapter->wol)
be_setup_wol(adapter, false);
- schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
return 0;
}
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index 60f0e788cc25..a38167810546 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/net/ethoc.c
+ * linux/drivers/net/ethernet/ethoc.c
*
* Copyright (C) 2007-2008 Avionic Design Development GmbH
* Copyright (C) 2008-2009 Avionic Design GmbH
@@ -776,10 +776,16 @@ static int ethoc_set_mac_address(struct net_device *dev, void *addr)
struct ethoc *priv = netdev_priv(dev);
u8 *mac = (u8 *)addr;
+ if (!is_valid_ether_addr(mac))
+ return -EADDRNOTAVAIL;
+
ethoc_write(priv, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) |
(mac[4] << 8) | (mac[5] << 0));
ethoc_write(priv, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0));
+ memcpy(dev->dev_addr, mac, ETH_ALEN);
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
+
return 0;
}
@@ -909,11 +915,11 @@ static int __devinit ethoc_probe(struct platform_device *pdev)
unsigned int phy;
int num_bd;
int ret = 0;
+ bool random_mac = false;
/* allocate networking device */
netdev = alloc_etherdev(sizeof(struct ethoc));
if (!netdev) {
- dev_err(&pdev->dev, "cannot allocate network device\n");
ret = -ENOMEM;
goto out;
}
@@ -1050,10 +1056,19 @@ static int __devinit ethoc_probe(struct platform_device *pdev)
/* Check the MAC again for validity, if it still isn't choose and
* program a random one. */
- if (!is_valid_ether_addr(netdev->dev_addr))
+ if (!is_valid_ether_addr(netdev->dev_addr)) {
random_ether_addr(netdev->dev_addr);
+ random_mac = true;
+ }
+
+ ret = ethoc_set_mac_address(netdev, netdev->dev_addr);
+ if (ret) {
+ dev_err(&netdev->dev, "failed to set MAC address\n");
+ goto error;
+ }
- ethoc_set_mac_address(netdev, netdev->dev_addr);
+ if (random_mac)
+ netdev->addr_assign_type |= NET_ADDR_RANDOM;
/* register MII bus */
priv->mdio = mdiobus_alloc();
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 47f85c337cf7..16b07048274c 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1289,7 +1289,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
if (!is_valid_ether_addr(netdev->dev_addr)) {
- random_ether_addr(netdev->dev_addr);
+ eth_hw_addr_random(netdev);
netdev_info(netdev, "generated random MAC address %pM\n",
netdev->dev_addr);
}
diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c
index bb336a0959c9..829b1092fd78 100644
--- a/drivers/net/ethernet/faraday/ftmac100.c
+++ b/drivers/net/ethernet/faraday/ftmac100.c
@@ -1133,7 +1133,7 @@ static int ftmac100_probe(struct platform_device *pdev)
netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
if (!is_valid_ether_addr(netdev->dev_addr)) {
- random_ether_addr(netdev->dev_addr);
+ eth_hw_addr_random(netdev);
netdev_info(netdev, "generated random MAC address %pM\n",
netdev->dev_addr);
}
diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c
index c82d444b582d..1637b9862292 100644
--- a/drivers/net/ethernet/fealnx.c
+++ b/drivers/net/ethernet/fealnx.c
@@ -1070,14 +1070,13 @@ static void allocate_rx_buffers(struct net_device *dev)
while (np->really_rx_count != RX_RING_SIZE) {
struct sk_buff *skb;
- skb = dev_alloc_skb(np->rx_buf_sz);
+ skb = netdev_alloc_skb(dev, np->rx_buf_sz);
if (skb == NULL)
break; /* Better luck next round. */
while (np->lack_rxbuf->skbuff)
np->lack_rxbuf = np->lack_rxbuf->next_desc_logical;
- skb->dev = dev; /* Mark as being used by this device. */
np->lack_rxbuf->skbuff = skb;
np->lack_rxbuf->buffer = pci_map_single(np->pci_dev, skb->data,
np->rx_buf_sz, PCI_DMA_FROMDEVICE);
@@ -1265,7 +1264,7 @@ static void init_ring(struct net_device *dev)
/* allocate skb for rx buffers */
for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);
+ struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz);
if (skb == NULL) {
np->lack_rxbuf = &np->rx_ring[i];
@@ -1274,7 +1273,6 @@ static void init_ring(struct net_device *dev)
++np->really_rx_count;
np->rx_ring[i].skbuff = skb;
- skb->dev = dev; /* Mark as being used by this device. */
np->rx_ring[i].buffer = pci_map_single(np->pci_dev, skb->data,
np->rx_buf_sz, PCI_DMA_FROMDEVICE);
np->rx_ring[i].status = RXOWN;
@@ -1704,7 +1702,7 @@ static int netdev_rx(struct net_device *dev)
/* Check if the packet is long enough to accept without copying
to a minimally-sized skbuff. */
if (pkt_len < rx_copybreak &&
- (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
skb_reserve(skb, 2); /* 16 byte align the IP header */
pci_dma_sync_single_for_cpu(np->pci_dev,
np->cur_rx->buffer,
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index e92ef1bd732a..a12b3f5bc025 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -711,7 +711,7 @@ fec_enet_rx(struct net_device *ndev)
* include that when passing upstream as it messes up
* bridging applications.
*/
- skb = dev_alloc_skb(pkt_len - 4 + NET_IP_ALIGN);
+ skb = netdev_alloc_skb(ndev, pkt_len - 4 + NET_IP_ALIGN);
if (unlikely(!skb)) {
printk("%s: Memory squeeze, dropping packet.\n",
@@ -1210,7 +1210,7 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
bdp = fep->rx_bd_base;
for (i = 0; i < RX_RING_SIZE; i++) {
- skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE);
+ skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
if (!skb) {
fec_enet_free_buffers(ndev);
return -ENOMEM;
@@ -1739,21 +1739,6 @@ static struct platform_driver fec_driver = {
.remove = __devexit_p(fec_drv_remove),
};
-static int __init
-fec_enet_module_init(void)
-{
- printk(KERN_INFO "FEC Ethernet Driver\n");
-
- return platform_driver_register(&fec_driver);
-}
-
-static void __exit
-fec_enet_cleanup(void)
-{
- platform_driver_unregister(&fec_driver);
-}
-
-module_exit(fec_enet_cleanup);
-module_init(fec_enet_module_init);
+module_platform_driver(fec_driver);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 30745b56fe5d..7b34d8c698da 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -160,7 +160,7 @@ static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task
struct sk_buff *skb;
while (!bcom_queue_full(rxtsk)) {
- skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
+ skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE);
if (!skb)
return -EAGAIN;
@@ -416,7 +416,7 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id)
/* skbs are allocated on open, so now we allocate a new one,
* and remove the old (with the packet) */
- skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
+ skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE);
if (!skb) {
/* Can't get a new one : reuse the same & drop pkt */
dev_notice(&dev->dev, "Low memory - dropped packet.\n");
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.h b/drivers/net/ethernet/freescale/fec_mpc52xx.h
index 41d2dffde55b..10afa54dd062 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.h
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.h
@@ -1,5 +1,5 @@
/*
- * drivers/drivers/net/fec_mpc52xx/fec.h
+ * drivers/net/ethernet/freescale/fec_mpc52xx.h
*
* Driver for the MPC5200 Fast Ethernet Controller
*
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 910a8e18a9ae..999638a7c851 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -154,7 +154,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
if (pkt_len <= fpi->rx_copybreak) {
/* +2 to make IP header L1 cache aligned */
- skbn = dev_alloc_skb(pkt_len + 2);
+ skbn = netdev_alloc_skb(dev, pkt_len + 2);
if (skbn != NULL) {
skb_reserve(skbn, 2); /* align IP header */
skb_copy_from_linear_data(skb,
@@ -165,7 +165,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
skbn = skbt;
}
} else {
- skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+ skbn = netdev_alloc_skb(dev, ENET_RX_FRSIZE);
if (skbn)
skb_align(skbn, ENET_RX_ALIGN);
@@ -286,7 +286,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev)
if (pkt_len <= fpi->rx_copybreak) {
/* +2 to make IP header L1 cache aligned */
- skbn = dev_alloc_skb(pkt_len + 2);
+ skbn = netdev_alloc_skb(dev, pkt_len + 2);
if (skbn != NULL) {
skb_reserve(skbn, 2); /* align IP header */
skb_copy_from_linear_data(skb,
@@ -297,7 +297,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev)
skbn = skbt;
}
} else {
- skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+ skbn = netdev_alloc_skb(dev, ENET_RX_FRSIZE);
if (skbn)
skb_align(skbn, ENET_RX_ALIGN);
@@ -504,7 +504,7 @@ void fs_init_bds(struct net_device *dev)
* Initialize the receive buffer descriptors.
*/
for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
- skb = dev_alloc_skb(ENET_RX_FRSIZE);
+ skb = netdev_alloc_skb(dev, ENET_RX_FRSIZE);
if (skb == NULL) {
dev_warn(fep->dev,
"Memory squeeze, unable to allocate skb\n");
@@ -592,7 +592,7 @@ static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
struct fs_enet_private *fep = netdev_priv(dev);
/* Alloc new skb */
- new_skb = dev_alloc_skb(skb->len + 4);
+ new_skb = netdev_alloc_skb(dev, skb->len + 4);
if (!new_skb) {
if (net_ratelimit()) {
dev_warn(fep->dev,
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 39d160d353a4..adb0ae4e4195 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/gianfar.c
+ * drivers/net/ethernet/freescale/gianfar.c
*
* Gianfar Ethernet Driver
* This driver is designed for the non-CPM ethernet controllers
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 40c33a7554c0..4fe0f342acec 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1,5 +1,5 @@
/*
- * drivers/net/gianfar.h
+ * drivers/net/ethernet/freescale/gianfar.h
*
* Gianfar Ethernet Driver
* Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 5a3b2e5b2880..5a78d55f46e7 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/gianfar_ethtool.c
+ * drivers/net/ethernet/freescale/gianfar_ethtool.c
*
* Gianfar Ethernet Driver
* Ethtool support for Gianfar Enet
diff --git a/drivers/net/ethernet/freescale/gianfar_sysfs.c b/drivers/net/ethernet/freescale/gianfar_sysfs.c
index 64f4094ac7f1..cd14a4d449c2 100644
--- a/drivers/net/ethernet/freescale/gianfar_sysfs.c
+++ b/drivers/net/ethernet/freescale/gianfar_sysfs.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/gianfar_sysfs.c
+ * drivers/net/ethernet/freescale/gianfar_sysfs.c
*
* Gianfar Ethernet Driver
* This driver is designed for the non-CPM ethernet controllers
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index ba2dc083bfc0..ec0905461312 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -214,8 +214,9 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
skb = __skb_dequeue(&ugeth->rx_recycle);
if (!skb)
- skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length +
- UCC_GETH_RX_DATA_BUF_ALIGNMENT);
+ skb = netdev_alloc_skb(ugeth->ndev,
+ ugeth->ug_info->uf_info.max_rx_buf_length +
+ UCC_GETH_RX_DATA_BUF_ALIGNMENT);
if (skb == NULL)
return NULL;
@@ -227,8 +228,6 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
(((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT -
1)));
- skb->dev = ugeth->ndev;
-
out_be32(&((struct qe_bd __iomem *)bd)->buf,
dma_map_single(ugeth->dev,
skb->data,
diff --git a/drivers/net/ethernet/fujitsu/at1700.c b/drivers/net/ethernet/fujitsu/at1700.c
index 7c6c908bdf02..586b46fd4eed 100644
--- a/drivers/net/ethernet/fujitsu/at1700.c
+++ b/drivers/net/ethernet/fujitsu/at1700.c
@@ -757,7 +757,7 @@ net_rx(struct net_device *dev)
dev->stats.rx_errors++;
break;
}
- skb = dev_alloc_skb(pkt_len+3);
+ skb = netdev_alloc_skb(dev, pkt_len + 3);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet (len %d).\n",
dev->name, pkt_len);
diff --git a/drivers/net/ethernet/fujitsu/eth16i.c b/drivers/net/ethernet/fujitsu/eth16i.c
index b0e2313af3d1..c3f0178fb5cb 100644
--- a/drivers/net/ethernet/fujitsu/eth16i.c
+++ b/drivers/net/ethernet/fujitsu/eth16i.c
@@ -1164,7 +1164,7 @@ static void eth16i_rx(struct net_device *dev)
else { /* Ok so now we should have a good packet */
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len + 3);
+ skb = netdev_alloc_skb(dev, pkt_len + 3);
if( skb == NULL ) {
printk(KERN_WARNING "%s: Could'n allocate memory for packet (len %d)\n",
dev->name, pkt_len);
diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
index ee84b472cee6..0230319ddb59 100644
--- a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
+++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
@@ -1002,7 +1002,7 @@ static void fjn_rx(struct net_device *dev)
dev->stats.rx_errors++;
break;
}
- skb = dev_alloc_skb(pkt_len+2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb == NULL) {
netdev_notice(dev, "Memory squeeze, dropping packet (len %d)\n",
pkt_len);
diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c
index 6a5ee0776b28..d496673f0908 100644
--- a/drivers/net/ethernet/hp/hp100.c
+++ b/drivers/net/ethernet/hp/hp100.c
@@ -1274,7 +1274,7 @@ static int hp100_build_rx_pdl(hp100_ring_t * ringptr,
/* Note: This depends on the alloc_skb functions allocating more
* space than requested, i.e. aligning to 16bytes */
- ringptr->skb = dev_alloc_skb(roundup(MAX_ETHER_SIZE + 2, 4));
+ ringptr->skb = netdev_alloc_skb(dev, roundup(MAX_ETHER_SIZE + 2, 4));
if (NULL != ringptr->skb) {
/*
@@ -1284,7 +1284,6 @@ static int hp100_build_rx_pdl(hp100_ring_t * ringptr,
*/
skb_reserve(ringptr->skb, 2);
- ringptr->skb->dev = dev;
ringptr->skb->data = (u_char *) skb_put(ringptr->skb, MAX_ETHER_SIZE);
/* ringptr->pdl points to the beginning of the PDL, i.e. the PDH */
@@ -1817,7 +1816,7 @@ static void hp100_rx(struct net_device *dev)
#endif
/* Now we allocate the skb and transfer the data into it. */
- skb = dev_alloc_skb(pkt_len+2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb == NULL) { /* Not enough memory->drop packet */
#ifdef HP100_DEBUG
printk("hp100: %s: rx: couldn't allocate a sk_buff of size %d\n",
@@ -2992,7 +2991,6 @@ static int __init hp100_isa_init(void)
for (i = 0; i < HP100_DEVICES && hp100_port[i] != -1; ++i) {
dev = alloc_etherdev(sizeof(struct hp100_private));
if (!dev) {
- printk(KERN_WARNING "hp100: no memory for network device\n");
while (cards > 0)
cleanup_dev(hp100_devlist[--cards]);
diff --git a/drivers/net/ethernet/i825xx/3c505.c b/drivers/net/ethernet/i825xx/3c505.c
index ba82a266051d..6a5c21b82c51 100644
--- a/drivers/net/ethernet/i825xx/3c505.c
+++ b/drivers/net/ethernet/i825xx/3c505.c
@@ -583,7 +583,7 @@ static void receive_packet(struct net_device *dev, int len)
unsigned long flags;
rlen = (len + 1) & ~1;
- skb = dev_alloc_skb(rlen + 2);
+ skb = netdev_alloc_skb(dev, rlen + 2);
if (!skb) {
pr_warning("%s: memory squeeze, dropping packet\n", dev->name);
diff --git a/drivers/net/ethernet/i825xx/3c507.c b/drivers/net/ethernet/i825xx/3c507.c
index 1e945551c144..ed6925f11479 100644
--- a/drivers/net/ethernet/i825xx/3c507.c
+++ b/drivers/net/ethernet/i825xx/3c507.c
@@ -851,7 +851,7 @@ static void el16_rx(struct net_device *dev)
struct sk_buff *skb;
pkt_len &= 0x3fff;
- skb = dev_alloc_skb(pkt_len+2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb == NULL) {
pr_err("%s: Memory squeeze, dropping packet.\n",
dev->name);
diff --git a/drivers/net/ethernet/i825xx/3c523.c b/drivers/net/ethernet/i825xx/3c523.c
index d70d3df4c985..8451ecd4c1ec 100644
--- a/drivers/net/ethernet/i825xx/3c523.c
+++ b/drivers/net/ethernet/i825xx/3c523.c
@@ -983,7 +983,7 @@ static void elmc_rcv_int(struct net_device *dev)
if ((totlen = rbd->status) & RBD_LAST) { /* the first and the last buffer? */
totlen &= RBD_MASK; /* length of this frame */
rbd->status = 0;
- skb = (struct sk_buff *) dev_alloc_skb(totlen + 2);
+ skb = netdev_alloc_skb(dev, totlen + 2);
if (skb != NULL) {
skb_reserve(skb, 2); /* 16 byte alignment */
skb_put(skb,totlen);
diff --git a/drivers/net/ethernet/i825xx/3c527.c b/drivers/net/ethernet/i825xx/3c527.c
index 474b5e71a53a..ef43f3e951c5 100644
--- a/drivers/net/ethernet/i825xx/3c527.c
+++ b/drivers/net/ethernet/i825xx/3c527.c
@@ -1169,7 +1169,7 @@ static void mc32_rx_ring(struct net_device *dev)
/* Try to save time by avoiding a copy on big frames */
if ((length > RX_COPYBREAK) &&
- ((newskb=dev_alloc_skb(1532)) != NULL))
+ ((newskb = netdev_alloc_skb(dev, 1532)) != NULL))
{
skb=lp->rx_ring[rx_ring_tail].skb;
skb_put(skb, length);
@@ -1180,7 +1180,7 @@ static void mc32_rx_ring(struct net_device *dev)
}
else
{
- skb=dev_alloc_skb(length+2);
+ skb = netdev_alloc_skb(dev, length + 2);
if(skb==NULL) {
dev->stats.rx_dropped++;
diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c
index f2408a4d5d9c..6aa927af382c 100644
--- a/drivers/net/ethernet/i825xx/82596.c
+++ b/drivers/net/ethernet/i825xx/82596.c
@@ -549,14 +549,13 @@ static inline int init_rx_bufs(struct net_device *dev)
/* First build the Receive Buffer Descriptor List */
for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
- struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
+ struct sk_buff *skb = netdev_alloc_skb(dev, PKT_BUF_SZ);
if (skb == NULL) {
remove_rx_bufs(dev);
return -ENOMEM;
}
- skb->dev = dev;
rbd->v_next = rbd+1;
rbd->b_next = WSWAPrbd(virt_to_bus(rbd+1));
rbd->b_addr = WSWAPrbd(virt_to_bus(rbd));
@@ -810,7 +809,7 @@ static inline int i596_rx(struct net_device *dev)
struct sk_buff *newskb;
/* Get fresh skbuff to replace filled one. */
- newskb = dev_alloc_skb(PKT_BUF_SZ);
+ newskb = netdev_alloc_skb(dev, PKT_BUF_SZ);
if (newskb == NULL) {
skb = NULL; /* drop pkt */
goto memory_squeeze;
@@ -819,7 +818,6 @@ static inline int i596_rx(struct net_device *dev)
skb_put(skb, pkt_len);
rx_in_place = 1;
rbd->skb = newskb;
- newskb->dev = dev;
rbd->v_data = newskb->data;
rbd->b_data = WSWAPchar(virt_to_bus(newskb->data));
#ifdef __mc68000__
@@ -827,7 +825,7 @@ static inline int i596_rx(struct net_device *dev)
#endif
}
else
- skb = dev_alloc_skb(pkt_len + 2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
memory_squeeze:
if (skb == NULL) {
/* XXX tulip.c can defer packets here!! */
diff --git a/drivers/net/ethernet/i825xx/eepro.c b/drivers/net/ethernet/i825xx/eepro.c
index 114cda7721fe..7a4ad4a07917 100644
--- a/drivers/net/ethernet/i825xx/eepro.c
+++ b/drivers/net/ethernet/i825xx/eepro.c
@@ -1563,7 +1563,7 @@ eepro_rx(struct net_device *dev)
dev->stats.rx_bytes+=rcv_size;
rcv_size &= 0x3fff;
- skb = dev_alloc_skb(rcv_size+5);
+ skb = netdev_alloc_skb(dev, rcv_size + 5);
if (skb == NULL) {
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
dev->stats.rx_dropped++;
diff --git a/drivers/net/ethernet/i825xx/eexpress.c b/drivers/net/ethernet/i825xx/eexpress.c
index 3a9580f3d4dd..3fc649e54a32 100644
--- a/drivers/net/ethernet/i825xx/eexpress.c
+++ b/drivers/net/ethernet/i825xx/eexpress.c
@@ -955,7 +955,7 @@ static void eexp_hw_rx_pio(struct net_device *dev)
{
struct sk_buff *skb;
pkt_len &= 0x3fff;
- skb = dev_alloc_skb(pkt_len+16);
+ skb = netdev_alloc_skb(dev, pkt_len + 16);
if (skb == NULL)
{
printk(KERN_WARNING "%s: Memory squeeze, dropping packet\n",dev->name);
diff --git a/drivers/net/ethernet/i825xx/ether1.c b/drivers/net/ethernet/i825xx/ether1.c
index 42e90a97c7a5..406a12b46404 100644
--- a/drivers/net/ethernet/i825xx/ether1.c
+++ b/drivers/net/ethernet/i825xx/ether1.c
@@ -867,7 +867,7 @@ ether1_recv_done (struct net_device *dev)
struct sk_buff *skb;
length = (length + 1) & ~1;
- skb = dev_alloc_skb (length + 2);
+ skb = netdev_alloc_skb(dev, length + 2);
if (skb) {
skb_reserve (skb, 2);
diff --git a/drivers/net/ethernet/i825xx/lp486e.c b/drivers/net/ethernet/i825xx/lp486e.c
index 414044b3cb11..6c2952c8ea15 100644
--- a/drivers/net/ethernet/i825xx/lp486e.c
+++ b/drivers/net/ethernet/i825xx/lp486e.c
@@ -454,8 +454,6 @@ init_rx_bufs(struct net_device *dev, int num) {
}
rfd->rbd = rbd;
- } else {
- printk("Could not kmalloc rbd\n");
}
}
lp->rbd_tail->next = rfd->rbd;
@@ -658,7 +656,7 @@ i596_rx_one(struct net_device *dev, struct i596_private *lp,
if (rfd->stat & RFD_STAT_OK) {
/* a good frame */
int pkt_len = (rfd->count & 0x3fff);
- struct sk_buff *skb = dev_alloc_skb(pkt_len);
+ struct sk_buff *skb = netdev_alloc_skb(dev, pkt_len);
(*frames)++;
diff --git a/drivers/net/ethernet/i825xx/ni52.c b/drivers/net/ethernet/i825xx/ni52.c
index c0893715ef47..272976e1bb0f 100644
--- a/drivers/net/ethernet/i825xx/ni52.c
+++ b/drivers/net/ethernet/i825xx/ni52.c
@@ -964,7 +964,7 @@ static void ni52_rcv_int(struct net_device *dev)
/* the first and the last buffer? */
totlen &= RBD_MASK; /* length of this frame */
writew(0x00, &rbd->status);
- skb = (struct sk_buff *)dev_alloc_skb(totlen+2);
+ skb = netdev_alloc_skb(dev, totlen + 2);
if (skb != NULL) {
skb_reserve(skb, 2);
skb_put(skb, totlen);
diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c
index 6ef5e11d1c84..cae17f4bc93e 100644
--- a/drivers/net/ethernet/i825xx/sun3_82586.c
+++ b/drivers/net/ethernet/i825xx/sun3_82586.c
@@ -28,7 +28,6 @@ static int automatic_resume = 0; /* experimental .. better should be zero */
static int rfdadd = 0; /* rfdadd=1 may be better for 8K MEM cards */
static int fifo=0x8; /* don't change */
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -779,7 +778,7 @@ static void sun3_82586_rcv_int(struct net_device *dev)
{
totlen &= RBD_MASK; /* length of this frame */
rbd->status = 0;
- skb = (struct sk_buff *) dev_alloc_skb(totlen+2);
+ skb = netdev_alloc_skb(dev, totlen + 2);
if(skb != NULL)
{
skb_reserve(skb,2);
@@ -1151,28 +1150,6 @@ static void set_multicast_list(struct net_device *dev)
netif_wake_queue(dev);
}
-#ifdef MODULE
-#error This code is not currently supported as a module
-static struct net_device *dev_sun3_82586;
-
-int init_module(void)
-{
- dev_sun3_82586 = sun3_82586_probe(-1);
- if (IS_ERR(dev_sun3_82586))
- return PTR_ERR(dev_sun3_82586);
- return 0;
-}
-
-void cleanup_module(void)
-{
- unsigned long ioaddr = dev_sun3_82586->base_addr;
- unregister_netdev(dev_sun3_82586);
- release_region(ioaddr, SUN3_82586_TOTAL_SIZE);
- iounmap((void *)ioaddr);
- free_netdev(dev_sun3_82586);
-}
-#endif /* MODULE */
-
#if 0
/*
* DUMP .. we expect a not running CMD unit and enough space
@@ -1209,5 +1186,3 @@ void sun3_82586_dump(struct net_device *dev,void *ptr)
printk("\n");
}
#endif
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/i825xx/znet.c b/drivers/net/ethernet/i825xx/znet.c
index 962b4c421f3f..a43649735a04 100644
--- a/drivers/net/ethernet/i825xx/znet.c
+++ b/drivers/net/ethernet/i825xx/znet.c
@@ -762,7 +762,7 @@ static void znet_rx(struct net_device *dev)
/* Malloc up new buffer. */
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len);
+ skb = netdev_alloc_skb(dev, pkt_len);
if (skb == NULL) {
if (znet_debug)
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
diff --git a/drivers/net/ethernet/ibm/ehea/ehea.h b/drivers/net/ethernet/ibm/ehea/ehea.h
index 6650068c996c..b8e46cc31e53 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea.h
+++ b/drivers/net/ethernet/ibm/ehea/ehea.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/net/ehea/ehea.h
+ * linux/drivers/net/ethernet/ibm/ehea/ehea.h
*
* eHEA ethernet device driver for IBM eServer System p
*
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
index 6bdd8e36e564..95837b99a464 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/net/ehea/ehea_ethtool.c
+ * linux/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
*
* eHEA ethernet device driver for IBM eServer System p
*
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_hw.h b/drivers/net/ethernet/ibm/ehea/ehea_hw.h
index 1a2fe4dc3eb3..180d4128a711 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_hw.h
+++ b/drivers/net/ethernet/ibm/ehea/ehea_hw.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/net/ehea/ehea_hw.h
+ * linux/drivers/net/ethernet/ibm/ehea/ehea_hw.h
*
* eHEA ethernet device driver for IBM eServer System p
*
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index 5d5fb2627184..8b73dd472475 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/net/ehea/ehea_main.c
+ * linux/drivers/net/ethernet/ibm/ehea/ehea_main.c
*
* eHEA ethernet device driver for IBM eServer System p
*
@@ -2980,7 +2980,6 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
dev = alloc_etherdev_mq(sizeof(struct ehea_port), EHEA_MAX_PORT_RES);
if (!dev) {
- pr_err("no mem for net_device\n");
ret = -ENOMEM;
goto out_err;
}
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_phyp.c b/drivers/net/ethernet/ibm/ehea/ehea_phyp.c
index 0506967b9044..30f903332e92 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_phyp.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_phyp.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/net/ehea/ehea_phyp.c
+ * linux/drivers/net/ethernet/ibm/ehea/ehea_phyp.c
*
* eHEA ethernet device driver for IBM eServer System p
*
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_phyp.h b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
index 2f8174c248bc..52c456ec4d6c 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
+++ b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/net/ehea/ehea_phyp.h
+ * linux/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
*
* eHEA ethernet device driver for IBM eServer System p
*
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_qmr.c b/drivers/net/ethernet/ibm/ehea/ehea_qmr.c
index c25b05b94daa..4fb47f14dbfe 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_qmr.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_qmr.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/net/ehea/ehea_qmr.c
+ * linux/drivers/net/ethernet/ibm/ehea/ehea_qmr.c
*
* eHEA ethernet device driver for IBM eServer System p
*
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_qmr.h b/drivers/net/ethernet/ibm/ehea/ehea_qmr.h
index 337a47ecf4aa..8e4a70c20ab7 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_qmr.h
+++ b/drivers/net/ethernet/ibm/ehea/ehea_qmr.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/net/ehea/ehea_qmr.h
+ * linux/drivers/net/ethernet/ibm/ehea/ehea_qmr.h
*
* eHEA ethernet device driver for IBM eServer System p
*
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 2abce965c7bd..dac7ffb4eaf1 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/core.c
+ * drivers/net/ethernet/ibm/emac/core.c
*
* Driver for PowerPC 4xx on-chip ethernet controller.
*
@@ -2706,11 +2706,9 @@ static int __devinit emac_probe(struct platform_device *ofdev)
/* Allocate our net_device structure */
err = -ENOMEM;
ndev = alloc_etherdev(sizeof(struct emac_instance));
- if (!ndev) {
- printk(KERN_ERR "%s: could not allocate ethernet device!\n",
- np->full_name);
+ if (!ndev)
goto err_gone;
- }
+
dev = netdev_priv(ndev);
dev->ndev = ndev;
dev->ofdev = ofdev;
diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h
index fa3ec57935fa..bade29690c71 100644
--- a/drivers/net/ethernet/ibm/emac/core.h
+++ b/drivers/net/ethernet/ibm/emac/core.h
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/core.h
+ * drivers/net/ethernet/ibm/emac/core.h
*
* Driver for PowerPC 4xx on-chip ethernet controller.
*
diff --git a/drivers/net/ethernet/ibm/emac/debug.c b/drivers/net/ethernet/ibm/emac/debug.c
index 8c6c1e2a8750..b16b4828b64d 100644
--- a/drivers/net/ethernet/ibm/emac/debug.c
+++ b/drivers/net/ethernet/ibm/emac/debug.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/debug.c
+ * drivers/net/ethernet/ibm/emac/debug.c
*
* Driver for PowerPC 4xx on-chip ethernet controller, debug print routines.
*
diff --git a/drivers/net/ethernet/ibm/emac/debug.h b/drivers/net/ethernet/ibm/emac/debug.h
index 90477fe69d0c..59a92d5870b5 100644
--- a/drivers/net/ethernet/ibm/emac/debug.h
+++ b/drivers/net/ethernet/ibm/emac/debug.h
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/debug.h
+ * drivers/net/ethernet/ibm/emac/debug.h
*
* Driver for PowerPC 4xx on-chip ethernet controller, debug print routines.
*
diff --git a/drivers/net/ethernet/ibm/emac/emac.h b/drivers/net/ethernet/ibm/emac/emac.h
index 1568278d759a..b44bd243fb58 100644
--- a/drivers/net/ethernet/ibm/emac/emac.h
+++ b/drivers/net/ethernet/ibm/emac/emac.h
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/emac.h
+ * drivers/net/ethernet/ibm/emac/emac.h
*
* Register definitions for PowerPC 4xx on-chip ethernet contoller
*
diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
index f3c50b97ec61..479e43e2f1ef 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/mal.c
+ * drivers/net/ethernet/ibm/emac/mal.c
*
* Memory Access Layer (MAL) support
*
diff --git a/drivers/net/ethernet/ibm/emac/mal.h b/drivers/net/ethernet/ibm/emac/mal.h
index d06f985bda32..e431a32e3d69 100644
--- a/drivers/net/ethernet/ibm/emac/mal.h
+++ b/drivers/net/ethernet/ibm/emac/mal.h
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/mal.h
+ * drivers/net/ethernet/ibm/emac/mal.h
*
* Memory Access Layer (MAL) support
*
diff --git a/drivers/net/ethernet/ibm/emac/phy.c b/drivers/net/ethernet/ibm/emac/phy.c
index ab4e5969fe65..d3b9d103353e 100644
--- a/drivers/net/ethernet/ibm/emac/phy.c
+++ b/drivers/net/ethernet/ibm/emac/phy.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/phy.c
+ * drivers/net/ethernet/ibm/emac/phy.c
*
* Driver for PowerPC 4xx on-chip ethernet controller, PHY support.
* Borrowed from sungem_phy.c, though I only kept the generic MII
diff --git a/drivers/net/ethernet/ibm/emac/phy.h b/drivers/net/ethernet/ibm/emac/phy.h
index 5d2bf4cbe50b..d7e41ec37467 100644
--- a/drivers/net/ethernet/ibm/emac/phy.h
+++ b/drivers/net/ethernet/ibm/emac/phy.h
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/phy.h
+ * drivers/net/ethernet/ibm/emac/phy.h
*
* Driver for PowerPC 4xx on-chip ethernet controller, PHY support
*
diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c
index 4fa53f3def64..d3123282e18e 100644
--- a/drivers/net/ethernet/ibm/emac/rgmii.c
+++ b/drivers/net/ethernet/ibm/emac/rgmii.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/rgmii.c
+ * drivers/net/ethernet/ibm/emac/rgmii.c
*
* Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support.
*
@@ -237,11 +237,8 @@ static int __devinit rgmii_probe(struct platform_device *ofdev)
rc = -ENOMEM;
dev = kzalloc(sizeof(struct rgmii_instance), GFP_KERNEL);
- if (dev == NULL) {
- printk(KERN_ERR "%s: could not allocate RGMII device!\n",
- np->full_name);
+ if (dev == NULL)
goto err_gone;
- }
mutex_init(&dev->lock);
dev->ofdev = ofdev;
diff --git a/drivers/net/ethernet/ibm/emac/rgmii.h b/drivers/net/ethernet/ibm/emac/rgmii.h
index 9296b6c5f920..668bceeff4a2 100644
--- a/drivers/net/ethernet/ibm/emac/rgmii.h
+++ b/drivers/net/ethernet/ibm/emac/rgmii.h
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/rgmii.h
+ * drivers/net/ethernet/ibm/emac/rgmii.h
*
* Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support.
*
diff --git a/drivers/net/ethernet/ibm/emac/tah.c b/drivers/net/ethernet/ibm/emac/tah.c
index 5f51bf7c9dc5..872912ef518d 100644
--- a/drivers/net/ethernet/ibm/emac/tah.c
+++ b/drivers/net/ethernet/ibm/emac/tah.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/tah.c
+ * drivers/net/ethernet/ibm/emac/tah.c
*
* Driver for PowerPC 4xx on-chip ethernet controller, TAH support.
*
@@ -96,11 +96,8 @@ static int __devinit tah_probe(struct platform_device *ofdev)
rc = -ENOMEM;
dev = kzalloc(sizeof(struct tah_instance), GFP_KERNEL);
- if (dev == NULL) {
- printk(KERN_ERR "%s: could not allocate TAH device!\n",
- np->full_name);
+ if (dev == NULL)
goto err_gone;
- }
mutex_init(&dev->lock);
dev->ofdev = ofdev;
diff --git a/drivers/net/ethernet/ibm/emac/tah.h b/drivers/net/ethernet/ibm/emac/tah.h
index 3437ab4964c7..350b7096a041 100644
--- a/drivers/net/ethernet/ibm/emac/tah.h
+++ b/drivers/net/ethernet/ibm/emac/tah.h
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/tah.h
+ * drivers/net/ethernet/ibm/emac/tah.h
*
* Driver for PowerPC 4xx on-chip ethernet controller, TAH support.
*
diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c
index 97449e786d61..415e9b4d5408 100644
--- a/drivers/net/ethernet/ibm/emac/zmii.c
+++ b/drivers/net/ethernet/ibm/emac/zmii.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/zmii.c
+ * drivers/net/ethernet/ibm/emac/zmii.c
*
* Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support.
*
@@ -240,11 +240,8 @@ static int __devinit zmii_probe(struct platform_device *ofdev)
rc = -ENOMEM;
dev = kzalloc(sizeof(struct zmii_instance), GFP_KERNEL);
- if (dev == NULL) {
- printk(KERN_ERR "%s: could not allocate ZMII device!\n",
- np->full_name);
+ if (dev == NULL)
goto err_gone;
- }
mutex_init(&dev->lock);
dev->ofdev = ofdev;
diff --git a/drivers/net/ethernet/ibm/emac/zmii.h b/drivers/net/ethernet/ibm/emac/zmii.h
index ceaed823a83c..455bfb085493 100644
--- a/drivers/net/ethernet/ibm/emac/zmii.h
+++ b/drivers/net/ethernet/ibm/emac/zmii.h
@@ -1,5 +1,5 @@
/*
- * drivers/net/ibm_newemac/zmii.h
+ * drivers/net/ethernet/ibm/emac/zmii.h
*
* Driver for PowerPC 4xx on-chip ethernet controller, ZMII bridge support.
*
diff --git a/drivers/net/ethernet/ibm/iseries_veth.c b/drivers/net/ethernet/ibm/iseries_veth.c
index acc31af6594a..1cafa6562a06 100644
--- a/drivers/net/ethernet/ibm/iseries_veth.c
+++ b/drivers/net/ethernet/ibm/iseries_veth.c
@@ -1032,10 +1032,8 @@ static struct net_device *veth_probe_one(int vlan,
}
dev = alloc_etherdev(sizeof (struct veth_port));
- if (! dev) {
- veth_error("Unable to allocate net_device structure!\n");
+ if (!dev)
return NULL;
- }
port = netdev_priv(dev);
diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c
index 075451d0207d..1b563bb959c2 100644
--- a/drivers/net/ethernet/icplus/ipg.c
+++ b/drivers/net/ethernet/icplus/ipg.c
@@ -744,9 +744,6 @@ static int ipg_get_rxbuff(struct net_device *dev, int entry)
return -ENOMEM;
}
- /* Associate the receive buffer with the IPG NIC. */
- skb->dev = dev;
-
/* Save the address of the sk_buff structure. */
sp->rx_buff[entry] = skb;
@@ -2233,7 +2230,6 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
*/
dev = alloc_etherdev(sizeof(struct ipg_nic_private));
if (!dev) {
- pr_err("%s: alloc_etherdev failed\n", pci_name(pdev));
rc = -ENOMEM;
goto err_disable_0;
}
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 9436397e5725..485ab8cdac48 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -2751,11 +2751,8 @@ static int __devinit e100_probe(struct pci_dev *pdev,
struct nic *nic;
int err;
- if (!(netdev = alloc_etherdev(sizeof(struct nic)))) {
- if (((1 << debug) - 1) & NETIF_MSG_PROBE)
- pr_err("Etherdev alloc failed, aborting\n");
+ if (!(netdev = alloc_etherdev(sizeof(struct nic))))
return -ENOMEM;
- }
netdev->netdev_ops = &e100_netdev_ops;
SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h
index 1e1596990b5c..2b6cd02bfba0 100644
--- a/drivers/net/ethernet/intel/e1000/e1000.h
+++ b/drivers/net/ethernet/intel/e1000/e1000.h
@@ -254,6 +254,7 @@ struct e1000_adapter {
atomic_t tx_fifo_stall;
bool pcix_82544;
bool detect_tx_hung;
+ bool dump_buffers;
/* RX */
bool (*clean_rx)(struct e1000_adapter *adapter,
diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.c b/drivers/net/ethernet/intel/e1000/e1000_hw.c
index 36ee76bf4cba..c526279e4927 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_hw.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_hw.c
@@ -5253,6 +5253,78 @@ static s32 e1000_check_downshift(struct e1000_hw *hw)
return E1000_SUCCESS;
}
+static const u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
+ IGP01E1000_PHY_AGC_PARAM_A,
+ IGP01E1000_PHY_AGC_PARAM_B,
+ IGP01E1000_PHY_AGC_PARAM_C,
+ IGP01E1000_PHY_AGC_PARAM_D
+};
+
+static s32 e1000_1000Mb_check_cable_length(struct e1000_hw *hw)
+{
+ u16 min_length, max_length;
+ u16 phy_data, i;
+ s32 ret_val;
+
+ ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
+ if (ret_val)
+ return ret_val;
+
+ if (hw->dsp_config_state != e1000_dsp_config_enabled)
+ return 0;
+
+ if (min_length >= e1000_igp_cable_length_50) {
+ for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
+ ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i],
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
+
+ ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i],
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
+ hw->dsp_config_state = e1000_dsp_config_activated;
+ } else {
+ u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
+ u32 idle_errs = 0;
+
+ /* clear previous idle error counts */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ for (i = 0; i < ffe_idle_err_timeout; i++) {
+ udelay(1000);
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
+ if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
+ hw->ffe_config_state = e1000_ffe_config_active;
+
+ ret_val = e1000_write_phy_reg(hw,
+ IGP01E1000_PHY_DSP_FFE,
+ IGP01E1000_PHY_DSP_FFE_CM_CP);
+ if (ret_val)
+ return ret_val;
+ break;
+ }
+
+ if (idle_errs)
+ ffe_idle_err_timeout =
+ FFE_IDLE_ERR_COUNT_TIMEOUT_100;
+ }
+ }
+
+ return 0;
+}
+
/**
* e1000_config_dsp_after_link_change
* @hw: Struct containing variables accessed by shared code
@@ -5269,13 +5341,6 @@ static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
{
s32 ret_val;
u16 phy_data, phy_saved_data, speed, duplex, i;
- static const u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
- IGP01E1000_PHY_AGC_PARAM_A,
- IGP01E1000_PHY_AGC_PARAM_B,
- IGP01E1000_PHY_AGC_PARAM_C,
- IGP01E1000_PHY_AGC_PARAM_D
- };
- u16 min_length, max_length;
e_dbg("e1000_config_dsp_after_link_change");
@@ -5290,84 +5355,9 @@ static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
}
if (speed == SPEED_1000) {
-
- ret_val =
- e1000_get_cable_length(hw, &min_length,
- &max_length);
+ ret_val = e1000_1000Mb_check_cable_length(hw);
if (ret_val)
return ret_val;
-
- if ((hw->dsp_config_state == e1000_dsp_config_enabled)
- && min_length >= e1000_igp_cable_length_50) {
-
- for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
- ret_val =
- e1000_read_phy_reg(hw,
- dsp_reg_array[i],
- &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &=
- ~IGP01E1000_PHY_EDAC_MU_INDEX;
-
- ret_val =
- e1000_write_phy_reg(hw,
- dsp_reg_array
- [i], phy_data);
- if (ret_val)
- return ret_val;
- }
- hw->dsp_config_state =
- e1000_dsp_config_activated;
- }
-
- if ((hw->ffe_config_state == e1000_ffe_config_enabled)
- && (min_length < e1000_igp_cable_length_50)) {
-
- u16 ffe_idle_err_timeout =
- FFE_IDLE_ERR_COUNT_TIMEOUT_20;
- u32 idle_errs = 0;
-
- /* clear previous idle error counts */
- ret_val =
- e1000_read_phy_reg(hw, PHY_1000T_STATUS,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- for (i = 0; i < ffe_idle_err_timeout; i++) {
- udelay(1000);
- ret_val =
- e1000_read_phy_reg(hw,
- PHY_1000T_STATUS,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- idle_errs +=
- (phy_data &
- SR_1000T_IDLE_ERROR_CNT);
- if (idle_errs >
- SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT)
- {
- hw->ffe_config_state =
- e1000_ffe_config_active;
-
- ret_val =
- e1000_write_phy_reg(hw,
- IGP01E1000_PHY_DSP_FFE,
- IGP01E1000_PHY_DSP_FFE_CM_CP);
- if (ret_val)
- return ret_val;
- break;
- }
-
- if (idle_errs)
- ffe_idle_err_timeout =
- FFE_IDLE_ERR_COUNT_TIMEOUT_100;
- }
- }
}
} else {
if (hw->dsp_config_state == e1000_dsp_config_activated) {
diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.h b/drivers/net/ethernet/intel/e1000/e1000_hw.h
index f6c4d7e2560c..11578c8978db 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_hw.h
+++ b/drivers/net/ethernet/intel/e1000/e1000_hw.h
@@ -895,6 +895,11 @@ struct e1000_ffvt_entry {
#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
+#define E1000_RDFH 0x02410 /* RX Data FIFO Head - RW */
+#define E1000_RDFT 0x02418 /* RX Data FIFO Tail - RW */
+#define E1000_RDFHS 0x02420 /* RX Data FIFO Head Saved - RW */
+#define E1000_RDFTS 0x02428 /* RX Data FIFO Tail Saved - RW */
+#define E1000_RDFPC 0x02430 /* RX Data FIFO Packet Count - RW */
#define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */
#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */
#define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */
@@ -1074,6 +1079,11 @@ struct e1000_ffvt_entry {
#define E1000_82542_IMC E1000_IMC
#define E1000_82542_RCTL E1000_RCTL
#define E1000_82542_RDTR 0x00108
+#define E1000_82542_RDFH E1000_RDFH
+#define E1000_82542_RDFT E1000_RDFT
+#define E1000_82542_RDFHS E1000_RDFHS
+#define E1000_82542_RDFTS E1000_RDFTS
+#define E1000_82542_RDFPC E1000_RDFPC
#define E1000_82542_RDBAL 0x00110
#define E1000_82542_RDBAH 0x00114
#define E1000_82542_RDLEN 0x00118
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index d94d64b5d695..6419a88a69e6 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -730,10 +730,8 @@ static void e1000_dump_eeprom(struct e1000_adapter *adapter)
eeprom.offset = 0;
data = kmalloc(eeprom.len, GFP_KERNEL);
- if (!data) {
- pr_err("Unable to allocate memory to dump EEPROM data\n");
+ if (!data)
return;
- }
ops->get_eeprom(netdev, &eeprom, data);
@@ -1069,8 +1067,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
(hw->mac_type != e1000_82547))
netdev->hw_features |= NETIF_F_TSO;
+ netdev->priv_flags |= IFF_SUPP_NOFCS;
+
netdev->features |= netdev->hw_features;
netdev->hw_features |= NETIF_F_RXCSUM;
+ netdev->hw_features |= NETIF_F_RXFCS;
if (pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
@@ -2694,6 +2695,7 @@ set_itr_now:
#define E1000_TX_FLAGS_VLAN 0x00000002
#define E1000_TX_FLAGS_TSO 0x00000004
#define E1000_TX_FLAGS_IPV4 0x00000008
+#define E1000_TX_FLAGS_NO_FCS 0x00000010
#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000
#define E1000_TX_FLAGS_VLAN_SHIFT 16
@@ -2995,6 +2997,9 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
}
+ if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS))
+ txd_lower &= ~(E1000_TXD_CMD_IFCS);
+
i = tx_ring->next_to_use;
while (count--) {
@@ -3009,6 +3014,10 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
+ /* txd_cmd re-enables FCS, so we'll re-disable it here as desired. */
+ 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
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
@@ -3224,6 +3233,9 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
if (likely(skb->protocol == htons(ETH_P_IP)))
tx_flags |= E1000_TX_FLAGS_IPV4;
+ if (unlikely(skb->no_fcs))
+ tx_flags |= E1000_TX_FLAGS_NO_FCS;
+
count = e1000_tx_map(adapter, tx_ring, skb, first, max_per_txd,
nr_frags, mss);
@@ -3241,6 +3253,215 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+#define NUM_REGS 38 /* 1 based count */
+static void e1000_regdump(struct e1000_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 regs[NUM_REGS];
+ u32 *regs_buff = regs;
+ int i = 0;
+
+ static const char * const reg_name[] = {
+ "CTRL", "STATUS",
+ "RCTL", "RDLEN", "RDH", "RDT", "RDTR",
+ "TCTL", "TDBAL", "TDBAH", "TDLEN", "TDH", "TDT",
+ "TIDV", "TXDCTL", "TADV", "TARC0",
+ "TDBAL1", "TDBAH1", "TDLEN1", "TDH1", "TDT1",
+ "TXDCTL1", "TARC1",
+ "CTRL_EXT", "ERT", "RDBAL", "RDBAH",
+ "TDFH", "TDFT", "TDFHS", "TDFTS", "TDFPC",
+ "RDFH", "RDFT", "RDFHS", "RDFTS", "RDFPC"
+ };
+
+ regs_buff[0] = er32(CTRL);
+ regs_buff[1] = er32(STATUS);
+
+ regs_buff[2] = er32(RCTL);
+ regs_buff[3] = er32(RDLEN);
+ regs_buff[4] = er32(RDH);
+ regs_buff[5] = er32(RDT);
+ regs_buff[6] = er32(RDTR);
+
+ regs_buff[7] = er32(TCTL);
+ regs_buff[8] = er32(TDBAL);
+ regs_buff[9] = er32(TDBAH);
+ regs_buff[10] = er32(TDLEN);
+ regs_buff[11] = er32(TDH);
+ regs_buff[12] = er32(TDT);
+ regs_buff[13] = er32(TIDV);
+ regs_buff[14] = er32(TXDCTL);
+ regs_buff[15] = er32(TADV);
+ regs_buff[16] = er32(TARC0);
+
+ regs_buff[17] = er32(TDBAL1);
+ regs_buff[18] = er32(TDBAH1);
+ regs_buff[19] = er32(TDLEN1);
+ regs_buff[20] = er32(TDH1);
+ regs_buff[21] = er32(TDT1);
+ regs_buff[22] = er32(TXDCTL1);
+ regs_buff[23] = er32(TARC1);
+ regs_buff[24] = er32(CTRL_EXT);
+ regs_buff[25] = er32(ERT);
+ regs_buff[26] = er32(RDBAL0);
+ regs_buff[27] = er32(RDBAH0);
+ regs_buff[28] = er32(TDFH);
+ regs_buff[29] = er32(TDFT);
+ regs_buff[30] = er32(TDFHS);
+ regs_buff[31] = er32(TDFTS);
+ regs_buff[32] = er32(TDFPC);
+ regs_buff[33] = er32(RDFH);
+ regs_buff[34] = er32(RDFT);
+ regs_buff[35] = er32(RDFHS);
+ regs_buff[36] = er32(RDFTS);
+ regs_buff[37] = er32(RDFPC);
+
+ pr_info("Register dump\n");
+ for (i = 0; i < NUM_REGS; i++)
+ pr_info("%-15s %08x\n", reg_name[i], regs_buff[i]);
+}
+
+/*
+ * e1000_dump: Print registers, tx ring and rx ring
+ */
+static void e1000_dump(struct e1000_adapter *adapter)
+{
+ /* this code doesn't handle multiple rings */
+ struct e1000_tx_ring *tx_ring = adapter->tx_ring;
+ struct e1000_rx_ring *rx_ring = adapter->rx_ring;
+ int i;
+
+ if (!netif_msg_hw(adapter))
+ return;
+
+ /* Print Registers */
+ e1000_regdump(adapter);
+
+ /*
+ * transmit dump
+ */
+ pr_info("TX Desc ring0 dump\n");
+
+ /* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended)
+ *
+ * Legacy Transmit Descriptor
+ * +--------------------------------------------------------------+
+ * 0 | Buffer Address [63:0] (Reserved on Write Back) |
+ * +--------------------------------------------------------------+
+ * 8 | Special | CSS | Status | CMD | CSO | Length |
+ * +--------------------------------------------------------------+
+ * 63 48 47 36 35 32 31 24 23 16 15 0
+ *
+ * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload
+ * 63 48 47 40 39 32 31 16 15 8 7 0
+ * +----------------------------------------------------------------+
+ * 0 | TUCSE | TUCS0 | TUCSS | IPCSE | IPCS0 | IPCSS |
+ * +----------------------------------------------------------------+
+ * 8 | MSS | HDRLEN | RSV | STA | TUCMD | DTYP | PAYLEN |
+ * +----------------------------------------------------------------+
+ * 63 48 47 40 39 36 35 32 31 24 23 20 19 0
+ *
+ * Extended Data Descriptor (DTYP=0x1)
+ * +----------------------------------------------------------------+
+ * 0 | Buffer Address [63:0] |
+ * +----------------------------------------------------------------+
+ * 8 | VLAN tag | POPTS | Rsvd | Status | Command | DTYP | DTALEN |
+ * +----------------------------------------------------------------+
+ * 63 48 47 40 39 36 35 32 31 24 23 20 19 0
+ */
+ pr_info("Tc[desc] [Ce CoCsIpceCoS] [MssHlRSCm0Plen] [bi->dma ] leng ntw timestmp bi->skb\n");
+ pr_info("Td[desc] [address 63:0 ] [VlaPoRSCm1Dlen] [bi->dma ] leng ntw timestmp bi->skb\n");
+
+ if (!netif_msg_tx_done(adapter))
+ goto rx_ring_summary;
+
+ for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
+ struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);
+ struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i];
+ struct my_u { u64 a; u64 b; };
+ struct my_u *u = (struct my_u *)tx_desc;
+ const char *type;
+
+ if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean)
+ type = "NTC/U";
+ else if (i == tx_ring->next_to_use)
+ type = "NTU";
+ else if (i == tx_ring->next_to_clean)
+ type = "NTC";
+ else
+ type = "";
+
+ pr_info("T%c[0x%03X] %016llX %016llX %016llX %04X %3X %016llX %p %s\n",
+ ((le64_to_cpu(u->b) & (1<<20)) ? 'd' : 'c'), i,
+ le64_to_cpu(u->a), le64_to_cpu(u->b),
+ (u64)buffer_info->dma, buffer_info->length,
+ buffer_info->next_to_watch,
+ (u64)buffer_info->time_stamp, buffer_info->skb, type);
+ }
+
+rx_ring_summary:
+ /*
+ * receive dump
+ */
+ pr_info("\nRX Desc ring dump\n");
+
+ /* Legacy Receive Descriptor Format
+ *
+ * +-----------------------------------------------------+
+ * | Buffer Address [63:0] |
+ * +-----------------------------------------------------+
+ * | VLAN Tag | Errors | Status 0 | Packet csum | Length |
+ * +-----------------------------------------------------+
+ * 63 48 47 40 39 32 31 16 15 0
+ */
+ pr_info("R[desc] [address 63:0 ] [vl er S cks ln] [bi->dma ] [bi->skb]\n");
+
+ if (!netif_msg_rx_status(adapter))
+ goto exit;
+
+ for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
+ struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i);
+ struct e1000_buffer *buffer_info = &rx_ring->buffer_info[i];
+ struct my_u { u64 a; u64 b; };
+ struct my_u *u = (struct my_u *)rx_desc;
+ const char *type;
+
+ if (i == rx_ring->next_to_use)
+ type = "NTU";
+ else if (i == rx_ring->next_to_clean)
+ type = "NTC";
+ else
+ type = "";
+
+ pr_info("R[0x%03X] %016llX %016llX %016llX %p %s\n",
+ i, le64_to_cpu(u->a), le64_to_cpu(u->b),
+ (u64)buffer_info->dma, buffer_info->skb, type);
+ } /* for */
+
+ /* dump the descriptor caches */
+ /* rx */
+ pr_info("Rx descriptor cache in 64bit format\n");
+ for (i = 0x6000; i <= 0x63FF ; i += 0x10) {
+ pr_info("R%04X: %08X|%08X %08X|%08X\n",
+ i,
+ readl(adapter->hw.hw_addr + i+4),
+ readl(adapter->hw.hw_addr + i),
+ readl(adapter->hw.hw_addr + i+12),
+ readl(adapter->hw.hw_addr + i+8));
+ }
+ /* tx */
+ pr_info("Tx descriptor cache in 64bit format\n");
+ for (i = 0x7000; i <= 0x73FF ; i += 0x10) {
+ pr_info("T%04X: %08X|%08X %08X|%08X\n",
+ i,
+ readl(adapter->hw.hw_addr + i+4),
+ readl(adapter->hw.hw_addr + i),
+ readl(adapter->hw.hw_addr + i+12),
+ readl(adapter->hw.hw_addr + i+8));
+ }
+exit:
+ return;
+}
+
/**
* e1000_tx_timeout - Respond to a Tx Hang
* @netdev: network interface device structure
@@ -3262,6 +3483,7 @@ static void e1000_reset_task(struct work_struct *work)
if (test_bit(__E1000_DOWN, &adapter->flags))
return;
+ e_err(drv, "Reset adapter\n");
e1000_reinit_safe(adapter);
}
@@ -3679,6 +3901,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
eop,
jiffies,
eop_desc->upper.fields.status);
+ e1000_dump(adapter);
netif_stop_queue(netdev);
}
}
@@ -3902,10 +4125,9 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
((u32)(rx_desc->errors) << 24),
le16_to_cpu(rx_desc->csum), skb);
- pskb_trim(skb, skb->len - 4);
-
- /* probably a little skewed due to removing CRC */
- total_rx_bytes += skb->len;
+ total_rx_bytes += (skb->len - 4); /* don't count FCS */
+ if (likely(!(netdev->features & NETIF_F_RXFCS)))
+ pskb_trim(skb, skb->len - 4);
total_rx_packets++;
/* eth type trans needs skb->data to point to something */
@@ -4059,14 +4281,15 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
}
}
- /* adjust length to remove Ethernet CRC, this must be
- * done after the TBI_ACCEPT workaround above */
- length -= 4;
-
- /* probably a little skewed due to removing CRC */
- total_rx_bytes += length;
+ total_rx_bytes += (length - 4); /* don't count FCS */
total_rx_packets++;
+ if (likely(!(netdev->features & NETIF_F_RXFCS)))
+ /* adjust length to remove Ethernet CRC, this must be
+ * done after the TBI_ACCEPT workaround above
+ */
+ length -= 4;
+
e1000_check_copybreak(netdev, buffer_info, length, &skb);
skb_put(skb, length);
diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
index e1159e54334a..bac9dda31b6c 100644
--- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c
+++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -201,19 +201,23 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
* e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs.
* @hw: pointer to the HW structure
**/
-static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
+static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw)
{
- struct e1000_hw *hw = &adapter->hw;
struct e1000_mac_info *mac = &hw->mac;
- struct e1000_mac_operations *func = &mac->ops;
- /* Set media type */
- switch (adapter->pdev->device) {
+ /* Set media type and media-dependent function pointers */
+ switch (hw->adapter->pdev->device) {
case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
hw->phy.media_type = e1000_media_type_internal_serdes;
+ mac->ops.check_for_link = e1000e_check_for_serdes_link;
+ mac->ops.setup_physical_interface =
+ e1000e_setup_fiber_serdes_link;
break;
default:
hw->phy.media_type = e1000_media_type_copper;
+ mac->ops.check_for_link = e1000e_check_for_copper_link;
+ mac->ops.setup_physical_interface =
+ e1000_setup_copper_link_80003es2lan;
break;
}
@@ -230,25 +234,6 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
/* Adaptive IFS not supported */
mac->adaptive_ifs = false;
- /* check for link */
- switch (hw->phy.media_type) {
- case e1000_media_type_copper:
- func->setup_physical_interface = e1000_setup_copper_link_80003es2lan;
- func->check_for_link = e1000e_check_for_copper_link;
- break;
- case e1000_media_type_fiber:
- func->setup_physical_interface = e1000e_setup_fiber_serdes_link;
- func->check_for_link = e1000e_check_for_fiber_link;
- break;
- case e1000_media_type_internal_serdes:
- func->setup_physical_interface = e1000e_setup_fiber_serdes_link;
- func->check_for_link = e1000e_check_for_serdes_link;
- break;
- default:
- return -E1000_ERR_CONFIG;
- break;
- }
-
/* set lan id for port to determine which phy lock to use */
hw->mac.ops.set_lan_id(hw);
@@ -260,7 +245,7 @@ static s32 e1000_get_variants_80003es2lan(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
s32 rc;
- rc = e1000_init_mac_params_80003es2lan(adapter);
+ rc = e1000_init_mac_params_80003es2lan(hw);
if (rc)
return rc;
@@ -304,7 +289,7 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
}
/**
- * e1000_acquire_mac_csr_80003es2lan - Acquire rights to access Kumeran register
+ * e1000_acquire_mac_csr_80003es2lan - Acquire right to access Kumeran register
* @hw: pointer to the HW structure
*
* Acquire the semaphore to access the Kumeran interface.
@@ -320,7 +305,7 @@ static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw)
}
/**
- * e1000_release_mac_csr_80003es2lan - Release rights to access Kumeran Register
+ * e1000_release_mac_csr_80003es2lan - Release right to access Kumeran Register
* @hw: pointer to the HW structure
*
* Release the semaphore used to access the Kumeran interface
@@ -473,7 +458,7 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
return ret_val;
}
- if (hw->dev_spec.e80003es2lan.mdic_wa_enable == true) {
+ if (hw->dev_spec.e80003es2lan.mdic_wa_enable) {
/*
* The "ready" bit in the MDIC register may be incorrectly set
* before the device has completed the "Page Select" MDI
@@ -485,9 +470,8 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
- ret_val = -E1000_ERR_PHY;
e1000_release_phy_80003es2lan(hw);
- return ret_val;
+ return -E1000_ERR_PHY;
}
udelay(200);
@@ -545,7 +529,7 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
return ret_val;
}
- if (hw->dev_spec.e80003es2lan.mdic_wa_enable == true) {
+ if (hw->dev_spec.e80003es2lan.mdic_wa_enable) {
/*
* The "ready" bit in the MDIC register may be incorrectly set
* before the device has completed the "Page Select" MDI
@@ -667,8 +651,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
udelay(1);
if (hw->phy.autoneg_wait_to_complete) {
- e_dbg("Waiting for forced speed/duplex link "
- "on GG82563 phy.\n");
+ e_dbg("Waiting for forced speed/duplex link on GG82563 phy.\n");
ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
100000, &link);
@@ -731,22 +714,19 @@ static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
ret_val = e1e_rphy(hw, GG82563_PHY_DSP_DISTANCE, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
index = phy_data & GG82563_DSPD_CABLE_LENGTH;
- if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5) {
- ret_val = -E1000_ERR_PHY;
- goto out;
- }
+ if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5)
+ return -E1000_ERR_PHY;
phy->min_cable_length = e1000_gg82563_cable_length_table[index];
phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5];
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
-out:
- return ret_val;
+ return 0;
}
/**
@@ -820,9 +800,7 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
ew32(IMC, 0xffffffff);
er32(ICR);
- ret_val = e1000_check_alt_mac_addr_generic(hw);
-
- return ret_val;
+ return e1000_check_alt_mac_addr_generic(hw);
}
/**
@@ -842,7 +820,7 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
e1000_initialize_hw_bits_80003es2lan(hw);
/* Initialize identification LED */
- ret_val = e1000e_id_led_init(hw);
+ ret_val = mac->ops.id_led_init(hw);
if (ret_val)
e_dbg("Error initializing identification LED\n");
/* This is not fatal and we should not stop init due to this */
@@ -860,7 +838,7 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
/* Setup link and flow control */
- ret_val = e1000e_setup_link(hw);
+ ret_val = mac->ops.setup_link(hw);
/* Disable IBIST slave mode (far-end loopback) */
e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
@@ -1078,7 +1056,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
* firmware will have already initialized them. We only initialize
* them if the HW is not in IAMT mode.
*/
- if (!e1000e_check_mng_mode(hw)) {
+ if (!hw->mac.ops.check_mng_mode(hw)) {
/* Enable Electrical Idle on the PHY */
data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
ret_val = e1e_wphy(hw, GG82563_PHY_PWR_MGMT_CTRL, data);
@@ -1163,9 +1141,7 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- ret_val = e1000e_setup_copper_link(hw);
-
- return 0;
+ return e1000e_setup_copper_link(hw);
}
/**
@@ -1241,9 +1217,7 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
else
reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
- ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
-
- return 0;
+ return e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
}
/**
@@ -1285,9 +1259,8 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
- ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
- return ret_val;
+ return e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
}
/**
@@ -1372,12 +1345,9 @@ static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw)
*/
ret_val = e1000_check_alt_mac_addr_generic(hw);
if (ret_val)
- goto out;
-
- ret_val = e1000_read_mac_addr_generic(hw);
+ return ret_val;
-out:
- return ret_val;
+ return e1000_read_mac_addr_generic(hw);
}
/**
@@ -1443,7 +1413,7 @@ static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw)
static const struct e1000_mac_operations es2_mac_ops = {
.read_mac_addr = e1000_read_mac_addr_80003es2lan,
- .id_led_init = e1000e_id_led_init,
+ .id_led_init = e1000e_id_led_init_generic,
.blink_led = e1000e_blink_led_generic,
.check_mng_mode = e1000e_check_mng_mode_generic,
/* check_for_link dependent on media type */
@@ -1459,9 +1429,10 @@ static const struct e1000_mac_operations es2_mac_ops = {
.clear_vfta = e1000_clear_vfta_generic,
.reset_hw = e1000_reset_hw_80003es2lan,
.init_hw = e1000_init_hw_80003es2lan,
- .setup_link = e1000e_setup_link,
+ .setup_link = e1000e_setup_link_generic,
/* setup_physical_interface dependent on media type */
.setup_led = e1000e_setup_led_generic,
+ .config_collision_dist = e1000e_config_collision_dist_generic,
};
static const struct e1000_phy_operations es2_phy_ops = {
@@ -1486,6 +1457,7 @@ static const struct e1000_nvm_operations es2_nvm_ops = {
.acquire = e1000_acquire_nvm_80003es2lan,
.read = e1000e_read_nvm_eerd,
.release = e1000_release_nvm_80003es2lan,
+ .reload = e1000e_reload_nvm_generic,
.update = e1000e_update_nvm_checksum_generic,
.valid_led_default = e1000e_valid_led_default,
.validate = e1000e_validate_nvm_checksum_generic,
@@ -1502,8 +1474,7 @@ const struct e1000_info e1000_es2_info = {
| FLAG_RX_NEEDS_RESTART /* errata */
| FLAG_TARC_SET_BIT_ZERO /* errata */
| FLAG_APME_CHECK_PORT_B
- | FLAG_DISABLE_FC_PAUSE_TIME /* errata */
- | FLAG_TIPG_MEDIUM_FOR_80003ESLAN,
+ | FLAG_DISABLE_FC_PAUSE_TIME, /* errata */
.flags2 = FLAG2_DMA_BURST,
.pba = 38,
.max_hw_frame_size = DEFAULT_JUMBO,
diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c
index a3e65fd26e09..086dad709179 100644
--- a/drivers/net/ethernet/intel/e1000e/82571.c
+++ b/drivers/net/ethernet/intel/e1000e/82571.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -235,30 +235,42 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
* e1000_init_mac_params_82571 - Init MAC func ptrs.
* @hw: pointer to the HW structure
**/
-static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
+static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
{
- struct e1000_hw *hw = &adapter->hw;
struct e1000_mac_info *mac = &hw->mac;
- struct e1000_mac_operations *func = &mac->ops;
u32 swsm = 0;
u32 swsm2 = 0;
bool force_clear_smbi = false;
- /* Set media type */
- switch (adapter->pdev->device) {
+ /* Set media type and media-dependent function pointers */
+ switch (hw->adapter->pdev->device) {
case E1000_DEV_ID_82571EB_FIBER:
case E1000_DEV_ID_82572EI_FIBER:
case E1000_DEV_ID_82571EB_QUAD_FIBER:
hw->phy.media_type = e1000_media_type_fiber;
+ mac->ops.setup_physical_interface =
+ e1000_setup_fiber_serdes_link_82571;
+ mac->ops.check_for_link = e1000e_check_for_fiber_link;
+ mac->ops.get_link_up_info =
+ e1000e_get_speed_and_duplex_fiber_serdes;
break;
case E1000_DEV_ID_82571EB_SERDES:
- case E1000_DEV_ID_82572EI_SERDES:
case E1000_DEV_ID_82571EB_SERDES_DUAL:
case E1000_DEV_ID_82571EB_SERDES_QUAD:
+ case E1000_DEV_ID_82572EI_SERDES:
hw->phy.media_type = e1000_media_type_internal_serdes;
+ mac->ops.setup_physical_interface =
+ e1000_setup_fiber_serdes_link_82571;
+ mac->ops.check_for_link = e1000_check_for_serdes_link_82571;
+ mac->ops.get_link_up_info =
+ e1000e_get_speed_and_duplex_fiber_serdes;
break;
default:
hw->phy.media_type = e1000_media_type_copper;
+ mac->ops.setup_physical_interface =
+ e1000_setup_copper_link_82571;
+ mac->ops.check_for_link = e1000e_check_for_copper_link;
+ mac->ops.get_link_up_info = e1000e_get_speed_and_duplex_copper;
break;
}
@@ -269,38 +281,13 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
/* Adaptive IFS supported */
mac->adaptive_ifs = true;
- /* check for link */
- switch (hw->phy.media_type) {
- case e1000_media_type_copper:
- func->setup_physical_interface = e1000_setup_copper_link_82571;
- func->check_for_link = e1000e_check_for_copper_link;
- func->get_link_up_info = e1000e_get_speed_and_duplex_copper;
- break;
- case e1000_media_type_fiber:
- func->setup_physical_interface =
- e1000_setup_fiber_serdes_link_82571;
- func->check_for_link = e1000e_check_for_fiber_link;
- func->get_link_up_info =
- e1000e_get_speed_and_duplex_fiber_serdes;
- break;
- case e1000_media_type_internal_serdes:
- func->setup_physical_interface =
- e1000_setup_fiber_serdes_link_82571;
- func->check_for_link = e1000_check_for_serdes_link_82571;
- func->get_link_up_info =
- e1000e_get_speed_and_duplex_fiber_serdes;
- break;
- default:
- return -E1000_ERR_CONFIG;
- break;
- }
-
+ /* MAC-specific function pointers */
switch (hw->mac.type) {
case e1000_82573:
- func->set_lan_id = e1000_set_lan_id_single_port;
- func->check_mng_mode = e1000e_check_mng_mode_generic;
- func->led_on = e1000e_led_on_generic;
- func->blink_led = e1000e_blink_led_generic;
+ mac->ops.set_lan_id = e1000_set_lan_id_single_port;
+ mac->ops.check_mng_mode = e1000e_check_mng_mode_generic;
+ mac->ops.led_on = e1000e_led_on_generic;
+ mac->ops.blink_led = e1000e_blink_led_generic;
/* FWSM register */
mac->has_fwsm = true;
@@ -314,14 +301,14 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
break;
case e1000_82574:
case e1000_82583:
- func->set_lan_id = e1000_set_lan_id_single_port;
- func->check_mng_mode = e1000_check_mng_mode_82574;
- func->led_on = e1000_led_on_82574;
+ mac->ops.set_lan_id = e1000_set_lan_id_single_port;
+ mac->ops.check_mng_mode = e1000_check_mng_mode_82574;
+ mac->ops.led_on = e1000_led_on_82574;
break;
default:
- func->check_mng_mode = e1000e_check_mng_mode_generic;
- func->led_on = e1000e_led_on_generic;
- func->blink_led = e1000e_blink_led_generic;
+ mac->ops.check_mng_mode = e1000e_check_mng_mode_generic;
+ mac->ops.led_on = e1000e_led_on_generic;
+ mac->ops.blink_led = e1000e_blink_led_generic;
/* FWSM register */
mac->has_fwsm = true;
@@ -342,11 +329,11 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
if (!(swsm2 & E1000_SWSM2_LOCK)) {
/* Only do this for the first interface on this card */
- ew32(SWSM2,
- swsm2 | E1000_SWSM2_LOCK);
+ ew32(SWSM2, swsm2 | E1000_SWSM2_LOCK);
force_clear_smbi = true;
- } else
+ } else {
force_clear_smbi = false;
+ }
break;
default:
force_clear_smbi = true;
@@ -383,7 +370,7 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1;
s32 rc;
- rc = e1000_init_mac_params_82571(adapter);
+ rc = e1000_init_mac_params_82571(hw);
if (rc)
return rc;
@@ -577,7 +564,6 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw)
{
u32 extcnf_ctrl;
- s32 ret_val = 0;
s32 i = 0;
extcnf_ctrl = er32(EXTCNF_CTRL);
@@ -599,12 +585,10 @@ static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw)
/* Release semaphores */
e1000_put_hw_semaphore_82573(hw);
e_dbg("Driver can't access the PHY\n");
- ret_val = -E1000_ERR_PHY;
- goto out;
+ return -E1000_ERR_PHY;
}
-out:
- return ret_val;
+ return 0;
}
/**
@@ -809,7 +793,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
* otherwise, commit the checksum to the flash NVM.
*/
if (hw->nvm.type != e1000_nvm_flash_hw)
- return ret_val;
+ return 0;
/* Check for pending operations. */
for (i = 0; i < E1000_FLASH_UPDATES; i++) {
@@ -1134,7 +1118,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
e1000_initialize_hw_bits_82571(hw);
/* Initialize identification LED */
- ret_val = e1000e_id_led_init(hw);
+ ret_val = mac->ops.id_led_init(hw);
if (ret_val)
e_dbg("Error initializing identification LED\n");
/* This is not fatal and we should not stop init due to this */
@@ -1159,7 +1143,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
/* Setup link and flow control */
- ret_val = e1000_setup_link_82571(hw);
+ ret_val = mac->ops.setup_link(hw);
/* Set the transmit descriptor write-back policy */
reg_data = er32(TXDCTL(0));
@@ -1227,6 +1211,10 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
case e1000_82572:
reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26);
break;
+ case e1000_82574:
+ case e1000_82583:
+ reg |= (1 << 26);
+ break;
default:
break;
}
@@ -1418,7 +1406,6 @@ bool e1000_check_phy_82574(struct e1000_hw *hw)
{
u16 status_1kbt = 0;
u16 receive_errors = 0;
- bool phy_hung = false;
s32 ret_val = 0;
/*
@@ -1426,19 +1413,18 @@ bool e1000_check_phy_82574(struct e1000_hw *hw)
* read the Base1000T status register If both are max then PHY is hung.
*/
ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors);
-
if (ret_val)
- goto out;
+ return false;
if (receive_errors == E1000_RECEIVE_ERROR_MAX) {
ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt);
if (ret_val)
- goto out;
+ return false;
if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) ==
E1000_IDLE_ERROR_COUNT_MASK)
- phy_hung = true;
+ return true;
}
-out:
- return phy_hung;
+
+ return false;
}
/**
@@ -1469,7 +1455,7 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
break;
}
- return e1000e_setup_link(hw);
+ return e1000e_setup_link_generic(hw);
}
/**
@@ -1506,9 +1492,7 @@ static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- ret_val = e1000e_setup_copper_link(hw);
-
- return ret_val;
+ return e1000e_setup_copper_link(hw);
}
/**
@@ -1842,9 +1826,9 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
**/
static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw)
{
- s32 ret_val = 0;
-
if (hw->mac.type == e1000_82571) {
+ s32 ret_val = 0;
+
/*
* If there's an alternate MAC address place it in RAR0
* so that it will override the Si installed default perm
@@ -1852,13 +1836,10 @@ static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw)
*/
ret_val = e1000_check_alt_mac_addr_generic(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
- ret_val = e1000_read_mac_addr_generic(hw);
-
-out:
- return ret_val;
+ return e1000_read_mac_addr_generic(hw);
}
/**
@@ -1873,7 +1854,7 @@ static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw)
struct e1000_phy_info *phy = &hw->phy;
struct e1000_mac_info *mac = &hw->mac;
- if (!(phy->ops.check_reset_block))
+ if (!phy->ops.check_reset_block)
return;
/* If the management interface is not enabled, then power down */
@@ -1930,7 +1911,7 @@ static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw)
static const struct e1000_mac_operations e82571_mac_ops = {
/* .check_mng_mode: mac type dependent */
/* .check_for_link: media type dependent */
- .id_led_init = e1000e_id_led_init,
+ .id_led_init = e1000e_id_led_init_generic,
.cleanup_led = e1000e_cleanup_led_generic,
.clear_hw_cntrs = e1000_clear_hw_cntrs_82571,
.get_bus_info = e1000e_get_bus_info_pcie,
@@ -1946,6 +1927,7 @@ static const struct e1000_mac_operations e82571_mac_ops = {
.setup_link = e1000_setup_link_82571,
/* .setup_physical_interface: media type dependent */
.setup_led = e1000e_setup_led_generic,
+ .config_collision_dist = e1000e_config_collision_dist_generic,
.read_mac_addr = e1000_read_mac_addr_82571,
};
@@ -2007,6 +1989,7 @@ static const struct e1000_nvm_operations e82571_nvm_ops = {
.acquire = e1000_acquire_nvm_82571,
.read = e1000e_read_nvm_eerd,
.release = e1000_release_nvm_82571,
+ .reload = e1000e_reload_nvm_generic,
.update = e1000_update_nvm_checksum_82571,
.valid_led_default = e1000_valid_led_default_82571,
.validate = e1000_validate_nvm_checksum_82571,
diff --git a/drivers/net/ethernet/intel/e1000e/Makefile b/drivers/net/ethernet/intel/e1000e/Makefile
index 948c05db5d68..591b71324505 100644
--- a/drivers/net/ethernet/intel/e1000e/Makefile
+++ b/drivers/net/ethernet/intel/e1000e/Makefile
@@ -1,7 +1,7 @@
################################################################################
#
# Intel PRO/1000 Linux driver
-# Copyright(c) 1999 - 2011 Intel Corporation.
+# Copyright(c) 1999 - 2012 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
@@ -33,5 +33,6 @@
obj-$(CONFIG_E1000E) += e1000e.o
e1000e-objs := 82571.o ich8lan.o 80003es2lan.o \
- lib.o phy.o param.o ethtool.o netdev.o
+ mac.o manage.o nvm.o phy.o \
+ param.o ethtool.o netdev.o
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h
index c516a7440bec..3a5025917163 100644
--- a/drivers/net/ethernet/intel/e1000e/defines.h
+++ b/drivers/net/ethernet/intel/e1000e/defines.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -126,6 +126,13 @@
E1000_RXDEXT_STATERR_CXE | \
E1000_RXDEXT_STATERR_RXE)
+#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
+#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
+#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
+#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
+#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
+
#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000
/* Management Control */
@@ -170,6 +177,7 @@
#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */
#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */
#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */
+#define E1000_RCTL_DPF 0x00400000 /* Discard Pause Frames */
#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */
#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
@@ -326,6 +334,7 @@
/* Receive Checksum Control */
#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */
#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
+#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
/* Header split receive */
#define E1000_RFCTL_NFSW_DIS 0x00000040
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index f478a22ed577..86cdd4793992 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -234,6 +234,7 @@ struct e1000_buffer {
};
struct e1000_ring {
+ struct e1000_adapter *adapter; /* back pointer to adapter */
void *desc; /* pointer to ring memory */
dma_addr_t dma; /* phys address of ring */
unsigned int size; /* length of ring in bytes */
@@ -242,8 +243,8 @@ struct e1000_ring {
u16 next_to_use;
u16 next_to_clean;
- u16 head;
- u16 tail;
+ void __iomem *head;
+ void __iomem *tail;
/* array of buffer information structs */
struct e1000_buffer *buffer_info;
@@ -251,7 +252,7 @@ struct e1000_ring {
char name[IFNAMSIZ + 5];
u32 ims_val;
u32 itr_val;
- u16 itr_register;
+ void __iomem *itr_register;
int set_itr;
struct sk_buff *rx_skb_top;
@@ -334,11 +335,10 @@ struct e1000_adapter {
/*
* Rx
*/
- bool (*clean_rx) (struct e1000_adapter *adapter,
- int *work_done, int work_to_do)
- ____cacheline_aligned_in_smp;
- void (*alloc_rx_buf) (struct e1000_adapter *adapter,
- int cleaned_count, gfp_t gfp);
+ bool (*clean_rx) (struct e1000_ring *ring, int *work_done,
+ int work_to_do) ____cacheline_aligned_in_smp;
+ void (*alloc_rx_buf) (struct e1000_ring *ring, int cleaned_count,
+ gfp_t gfp);
struct e1000_ring *rx_ring;
u32 rx_int_delay;
@@ -398,6 +398,9 @@ struct e1000_adapter {
bool idle_check;
int phy_hang_count;
+
+ u16 tx_ring_count;
+ u16 rx_ring_count;
};
struct e1000_info {
@@ -417,7 +420,7 @@ struct e1000_info {
#define FLAG_HAS_FLASH (1 << 1)
#define FLAG_HAS_HW_VLAN_FILTER (1 << 2)
#define FLAG_HAS_WOL (1 << 3)
-#define FLAG_HAS_ERT (1 << 4)
+/* reserved bit4 */
#define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5)
#define FLAG_HAS_SWSM_ON_LOAD (1 << 6)
#define FLAG_HAS_JUMBO_FRAMES (1 << 7)
@@ -427,7 +430,7 @@ struct e1000_info {
#define FLAG_HAS_SMART_POWER_DOWN (1 << 11)
#define FLAG_IS_QUAD_PORT_A (1 << 12)
#define FLAG_IS_QUAD_PORT (1 << 13)
-#define FLAG_TIPG_MEDIUM_FOR_80003ESLAN (1 << 14)
+/* reserved bit14 */
#define FLAG_APME_IN_WUC (1 << 15)
#define FLAG_APME_IN_CTRL3 (1 << 16)
#define FLAG_APME_CHECK_PORT_B (1 << 17)
@@ -458,6 +461,7 @@ struct e1000_info {
#define FLAG2_CHECK_PHY_HANG (1 << 9)
#define FLAG2_NO_DISABLE_RX (1 << 10)
#define FLAG2_PCIM2PCI_ARBITER_WA (1 << 11)
+#define FLAG2_DFLT_CRC_STRIPPING (1 << 12)
#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
@@ -492,10 +496,10 @@ extern void e1000e_down(struct e1000_adapter *adapter);
extern void e1000e_reinit_locked(struct e1000_adapter *adapter);
extern void e1000e_reset(struct e1000_adapter *adapter);
extern void e1000e_power_up_phy(struct e1000_adapter *adapter);
-extern int e1000e_setup_rx_resources(struct e1000_adapter *adapter);
-extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter);
-extern void e1000e_free_rx_resources(struct e1000_adapter *adapter);
-extern void e1000e_free_tx_resources(struct e1000_adapter *adapter);
+extern int e1000e_setup_rx_resources(struct e1000_ring *ring);
+extern int e1000e_setup_tx_resources(struct e1000_ring *ring);
+extern void e1000e_free_rx_resources(struct e1000_ring *ring);
+extern void e1000e_free_tx_resources(struct e1000_ring *ring);
extern struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64
*stats);
@@ -555,12 +559,12 @@ extern s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u
extern s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex);
extern s32 e1000e_disable_pcie_master(struct e1000_hw *hw);
extern s32 e1000e_get_auto_rd_done(struct e1000_hw *hw);
-extern s32 e1000e_id_led_init(struct e1000_hw *hw);
+extern s32 e1000e_id_led_init_generic(struct e1000_hw *hw);
extern void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw);
extern s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw);
extern s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw);
extern s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw);
-extern s32 e1000e_setup_link(struct e1000_hw *hw);
+extern s32 e1000e_setup_link_generic(struct e1000_hw *hw);
extern void e1000_clear_vfta_generic(struct e1000_hw *hw);
extern void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
extern void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
@@ -571,7 +575,7 @@ extern s32 e1000e_set_fc_watermarks(struct e1000_hw *hw);
extern void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop);
extern s32 e1000e_get_hw_semaphore(struct e1000_hw *hw);
extern s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data);
-extern void e1000e_config_collision_dist(struct e1000_hw *hw);
+extern void e1000e_config_collision_dist_generic(struct e1000_hw *hw);
extern s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw);
extern s32 e1000e_force_mac_fc(struct e1000_hw *hw);
extern s32 e1000e_blink_led_generic(struct e1000_hw *hw);
@@ -658,11 +662,6 @@ static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
return hw->phy.ops.reset(hw);
}
-static inline s32 e1000_check_reset_block(struct e1000_hw *hw)
-{
- return hw->phy.ops.check_reset_block(hw);
-}
-
static inline s32 e1e_rphy(struct e1000_hw *hw, u32 offset, u16 *data)
{
return hw->phy.ops.read_reg(hw, offset, data);
@@ -685,7 +684,7 @@ extern s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg);
extern s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
extern s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw);
extern void e1000e_release_nvm(struct e1000_hw *hw);
-extern void e1000e_reload_nvm(struct e1000_hw *hw);
+extern void e1000e_reload_nvm_generic(struct e1000_hw *hw);
extern s32 e1000_read_mac_addr_generic(struct e1000_hw *hw);
static inline s32 e1000e_read_mac_addr(struct e1000_hw *hw)
@@ -721,11 +720,6 @@ static inline s32 e1000_get_phy_info(struct e1000_hw *hw)
return hw->phy.ops.get_info(hw);
}
-static inline s32 e1000e_check_mng_mode(struct e1000_hw *hw)
-{
- return hw->mac.ops.check_mng_mode(hw);
-}
-
extern bool e1000e_check_mng_mode_generic(struct e1000_hw *hw);
extern bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw);
extern s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length);
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index fb2c28e799a2..db35dd5d96de 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -34,6 +34,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/vmalloc.h>
#include "e1000.h"
@@ -257,7 +258,7 @@ static int e1000_set_settings(struct net_device *netdev,
* When SoL/IDER sessions are active, autoneg/speed/duplex
* cannot be changed
*/
- if (e1000_check_reset_block(hw)) {
+ if (hw->phy.ops.check_reset_block(hw)) {
e_err("Cannot change link characteristics when SoL/IDER is "
"active.\n");
return -EINVAL;
@@ -536,7 +537,7 @@ static int e1000_set_eeprom(struct net_device *netdev,
ret_val = e1000_read_nvm(hw, first_word, 1, &eeprom_buff[0]);
ptr++;
}
- if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0))
+ if (((eeprom->offset + eeprom->len) & 1) && (!ret_val))
/* need read/modify/write of last changed EEPROM word */
/* only the first byte of the word is being modified */
ret_val = e1000_read_nvm(hw, last_word, 1,
@@ -552,7 +553,7 @@ static int e1000_set_eeprom(struct net_device *netdev,
memcpy(ptr, bytes, eeprom->len);
for (i = 0; i < last_word - first_word + 1; i++)
- eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);
+ cpu_to_le16s(&eeprom_buff[i]);
ret_val = e1000_write_nvm(hw, first_word,
last_word - first_word + 1, eeprom_buff);
@@ -605,94 +606,112 @@ static void e1000_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_ring *tx_ring = adapter->tx_ring;
- struct e1000_ring *rx_ring = adapter->rx_ring;
ring->rx_max_pending = E1000_MAX_RXD;
ring->tx_max_pending = E1000_MAX_TXD;
- ring->rx_pending = rx_ring->count;
- ring->tx_pending = tx_ring->count;
+ ring->rx_pending = adapter->rx_ring_count;
+ ring->tx_pending = adapter->tx_ring_count;
}
static int e1000_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_ring *tx_ring, *tx_old;
- struct e1000_ring *rx_ring, *rx_old;
- int err;
+ struct e1000_ring *temp_tx = NULL, *temp_rx = NULL;
+ int err = 0, size = sizeof(struct e1000_ring);
+ bool set_tx = false, set_rx = false;
+ u16 new_rx_count, new_tx_count;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
- while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
- usleep_range(1000, 2000);
+ new_rx_count = clamp_t(u32, ring->rx_pending, E1000_MIN_RXD,
+ E1000_MAX_RXD);
+ new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
- if (netif_running(adapter->netdev))
- e1000e_down(adapter);
+ new_tx_count = clamp_t(u32, ring->tx_pending, E1000_MIN_TXD,
+ E1000_MAX_TXD);
+ new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
- tx_old = adapter->tx_ring;
- rx_old = adapter->rx_ring;
+ if ((new_tx_count == adapter->tx_ring_count) &&
+ (new_rx_count == adapter->rx_ring_count))
+ /* nothing to do */
+ return 0;
- err = -ENOMEM;
- tx_ring = kmemdup(tx_old, sizeof(struct e1000_ring), GFP_KERNEL);
- if (!tx_ring)
- goto err_alloc_tx;
+ while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
+ usleep_range(1000, 2000);
- rx_ring = kmemdup(rx_old, sizeof(struct e1000_ring), GFP_KERNEL);
- if (!rx_ring)
- goto err_alloc_rx;
+ if (!netif_running(adapter->netdev)) {
+ /* Set counts now and allocate resources during open() */
+ adapter->tx_ring->count = new_tx_count;
+ adapter->rx_ring->count = new_rx_count;
+ adapter->tx_ring_count = new_tx_count;
+ adapter->rx_ring_count = new_rx_count;
+ goto clear_reset;
+ }
- adapter->tx_ring = tx_ring;
- adapter->rx_ring = rx_ring;
+ set_tx = (new_tx_count != adapter->tx_ring_count);
+ set_rx = (new_rx_count != adapter->rx_ring_count);
- rx_ring->count = max(ring->rx_pending, (u32)E1000_MIN_RXD);
- rx_ring->count = min(rx_ring->count, (u32)(E1000_MAX_RXD));
- rx_ring->count = ALIGN(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE);
+ /* Allocate temporary storage for ring updates */
+ if (set_tx) {
+ temp_tx = vmalloc(size);
+ if (!temp_tx) {
+ err = -ENOMEM;
+ goto free_temp;
+ }
+ }
+ if (set_rx) {
+ temp_rx = vmalloc(size);
+ if (!temp_rx) {
+ err = -ENOMEM;
+ goto free_temp;
+ }
+ }
- tx_ring->count = max(ring->tx_pending, (u32)E1000_MIN_TXD);
- tx_ring->count = min(tx_ring->count, (u32)(E1000_MAX_TXD));
- tx_ring->count = ALIGN(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+ e1000e_down(adapter);
- if (netif_running(adapter->netdev)) {
- /* Try to get new resources before deleting old */
- err = e1000e_setup_rx_resources(adapter);
+ /*
+ * We can't just free everything and then setup again, because the
+ * ISRs in MSI-X mode get passed pointers to the Tx and Rx ring
+ * structs. First, attempt to allocate new resources...
+ */
+ if (set_tx) {
+ memcpy(temp_tx, adapter->tx_ring, size);
+ temp_tx->count = new_tx_count;
+ err = e1000e_setup_tx_resources(temp_tx);
if (err)
- goto err_setup_rx;
- err = e1000e_setup_tx_resources(adapter);
+ goto err_setup;
+ }
+ if (set_rx) {
+ memcpy(temp_rx, adapter->rx_ring, size);
+ temp_rx->count = new_rx_count;
+ err = e1000e_setup_rx_resources(temp_rx);
if (err)
- goto err_setup_tx;
+ goto err_setup_rx;
+ }
- /*
- * restore the old in order to free it,
- * then add in the new
- */
- adapter->rx_ring = rx_old;
- adapter->tx_ring = tx_old;
- e1000e_free_rx_resources(adapter);
- e1000e_free_tx_resources(adapter);
- kfree(tx_old);
- kfree(rx_old);
- adapter->rx_ring = rx_ring;
- adapter->tx_ring = tx_ring;
- err = e1000e_up(adapter);
- if (err)
- goto err_setup;
+ /* ...then free the old resources and copy back any new ring data */
+ if (set_tx) {
+ e1000e_free_tx_resources(adapter->tx_ring);
+ memcpy(adapter->tx_ring, temp_tx, size);
+ adapter->tx_ring_count = new_tx_count;
+ }
+ if (set_rx) {
+ e1000e_free_rx_resources(adapter->rx_ring);
+ memcpy(adapter->rx_ring, temp_rx, size);
+ adapter->rx_ring_count = new_rx_count;
}
- clear_bit(__E1000_RESETTING, &adapter->state);
- return 0;
-err_setup_tx:
- e1000e_free_rx_resources(adapter);
err_setup_rx:
- adapter->rx_ring = rx_old;
- adapter->tx_ring = tx_old;
- kfree(rx_ring);
-err_alloc_rx:
- kfree(tx_ring);
-err_alloc_tx:
- e1000e_up(adapter);
+ if (err && set_tx)
+ e1000e_free_tx_resources(temp_tx);
err_setup:
+ e1000e_up(adapter);
+free_temp:
+ vfree(temp_tx);
+ vfree(temp_rx);
+clear_reset:
clear_bit(__E1000_RESETTING, &adapter->state);
return err;
}
@@ -1069,7 +1088,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
tx_ring->buffer_info = kcalloc(tx_ring->count,
sizeof(struct e1000_buffer),
GFP_KERNEL);
- if (!(tx_ring->buffer_info)) {
+ if (!tx_ring->buffer_info) {
ret_val = 1;
goto err_nomem;
}
@@ -1131,7 +1150,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
rx_ring->buffer_info = kcalloc(rx_ring->count,
sizeof(struct e1000_buffer),
GFP_KERNEL);
- if (!(rx_ring->buffer_info)) {
+ if (!rx_ring->buffer_info) {
ret_val = 5;
goto err_nomem;
}
@@ -1579,11 +1598,13 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
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
*/
- if (e1000_check_reset_block(&adapter->hw)) {
+ if (hw->phy.ops.check_reset_block(hw)) {
e_err("Cannot do PHY loopback test when SoL/IDER is active.\n");
*data = 0;
goto out;
@@ -1837,11 +1858,11 @@ static int e1000_set_phys_id(struct net_device *netdev,
break;
case ETHTOOL_ID_ON:
- adapter->hw.mac.ops.led_on(&adapter->hw);
+ hw->mac.ops.led_on(hw);
break;
case ETHTOOL_ID_OFF:
- adapter->hw.mac.ops.led_off(&adapter->hw);
+ hw->mac.ops.led_off(hw);
break;
}
return 0;
@@ -1955,6 +1976,53 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset,
}
}
+static int e1000_get_rxnfc(struct net_device *netdev,
+ struct ethtool_rxnfc *info, u32 *rule_locs)
+{
+ info->data = 0;
+
+ switch (info->cmd) {
+ case ETHTOOL_GRXFH: {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ u32 mrqc = er32(MRQC);
+
+ if (!(mrqc & E1000_MRQC_RSS_FIELD_MASK))
+ return 0;
+
+ switch (info->flow_type) {
+ case TCP_V4_FLOW:
+ if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_TCP)
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ /* fall through */
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ case AH_ESP_V4_FLOW:
+ case IPV4_FLOW:
+ if (mrqc & E1000_MRQC_RSS_FIELD_IPV4)
+ info->data |= RXH_IP_SRC | RXH_IP_DST;
+ break;
+ case TCP_V6_FLOW:
+ if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP)
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ /* fall through */
+ case UDP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ case AH_ESP_V6_FLOW:
+ case IPV6_FLOW:
+ if (mrqc & E1000_MRQC_RSS_FIELD_IPV6)
+ info->data |= RXH_IP_SRC | RXH_IP_DST;
+ break;
+ default:
+ break;
+ }
+ return 0;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static const struct ethtool_ops e1000_ethtool_ops = {
.get_settings = e1000_get_settings,
.set_settings = e1000_set_settings,
@@ -1981,6 +2049,7 @@ static const struct ethtool_ops e1000_ethtool_ops = {
.get_sset_count = e1000e_get_sset_count,
.get_coalesce = e1000_get_coalesce,
.set_coalesce = e1000_set_coalesce,
+ .get_rxnfc = e1000_get_rxnfc,
};
void e1000e_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index 29670397079b..f82ecf536c8b 100644
--- a/drivers/net/ethernet/intel/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -204,6 +204,7 @@ enum e1e_registers {
E1000_WUC = 0x05800, /* Wakeup Control - RW */
E1000_WUFC = 0x05808, /* Wakeup Filter Control - RW */
E1000_WUS = 0x05810, /* Wakeup Status - RO */
+ E1000_MRQC = 0x05818, /* Multiple Receive Control - RW */
E1000_MANC = 0x05820, /* Management Control - RW */
E1000_FFLT = 0x05F00, /* Flexible Filter Length Table - RW Array */
E1000_HOST_IF = 0x08800, /* Host Interface */
@@ -219,6 +220,10 @@ enum e1e_registers {
E1000_SWSM = 0x05B50, /* SW Semaphore */
E1000_FWSM = 0x05B54, /* FW Semaphore */
E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */
+ E1000_RETA_BASE = 0x05C00, /* Redirection Table - RW */
+#define E1000_RETA(_n) (E1000_RETA_BASE + ((_n) * 4))
+ E1000_RSSRK_BASE = 0x05C80, /* RSS Random Key - RW */
+#define E1000_RSSRK(_n) (E1000_RSSRK_BASE + ((_n) * 4))
E1000_FFLT_DBG = 0x05F04, /* Debug Register */
E1000_PCH_RAICC_BASE = 0x05F50, /* Receive Address Initial CRC */
#define E1000_PCH_RAICC(_n) (E1000_PCH_RAICC_BASE + ((_n) * 4))
@@ -776,6 +781,7 @@ struct e1000_mac_operations {
s32 (*setup_physical_interface)(struct e1000_hw *);
s32 (*setup_led)(struct e1000_hw *);
void (*write_vfta)(struct e1000_hw *, u32, u32);
+ void (*config_collision_dist)(struct e1000_hw *);
s32 (*read_mac_addr)(struct e1000_hw *);
};
@@ -824,6 +830,7 @@ struct e1000_nvm_operations {
s32 (*acquire)(struct e1000_hw *);
s32 (*read)(struct e1000_hw *, u16, u16, u16 *);
void (*release)(struct e1000_hw *);
+ void (*reload)(struct e1000_hw *);
s32 (*update)(struct e1000_hw *);
s32 (*valid_led_default)(struct e1000_hw *, u16 *);
s32 (*validate)(struct e1000_hw *);
@@ -964,8 +971,8 @@ struct e1000_dev_spec_ich8lan {
struct e1000_hw {
struct e1000_adapter *adapter;
- u8 __iomem *hw_addr;
- u8 __iomem *flash_address;
+ void __iomem *hw_addr;
+ void __iomem *flash_address;
struct e1000_mac_info mac;
struct e1000_fc_info fc;
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index e2a80a283fd3..8e9af624d54a 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -145,6 +145,8 @@
#define I82579_EMI_ADDR 0x10
#define I82579_EMI_DATA 0x11
#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */
+#define I82579_MSE_THRESHOLD 0x084F /* Mean Square Error Threshold */
+#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */
/* Strapping Option Register - RO */
#define E1000_STRAP 0x0000C
@@ -278,8 +280,8 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
#define er16flash(reg) __er16flash(hw, (reg))
#define er32flash(reg) __er32flash(hw, (reg))
-#define ew16flash(reg,val) __ew16flash(hw, (reg), (val))
-#define ew32flash(reg,val) __ew32flash(hw, (reg), (val))
+#define ew16flash(reg, val) __ew16flash(hw, (reg), (val))
+#define ew32flash(reg, val) __ew32flash(hw, (reg), (val))
static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw)
{
@@ -304,7 +306,6 @@ static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw)
static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- u32 fwsm;
s32 ret_val = 0;
phy->addr = 1;
@@ -323,14 +324,14 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
- /*
- * The MAC-PHY interconnect may still be in SMBus mode
- * after Sx->S0. If the manageability engine (ME) is
- * disabled, then toggle the LANPHYPC Value bit to force
- * the interconnect to PCIe mode.
- */
- fwsm = er32(FWSM);
- if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && !e1000_check_reset_block(hw)) {
+ if (!hw->phy.ops.check_reset_block(hw)) {
+ u32 fwsm = er32(FWSM);
+
+ /*
+ * The MAC-PHY interconnect may still be in SMBus mode after
+ * Sx->S0. If resetting the PHY is not blocked, toggle the
+ * LANPHYPC Value bit to force the interconnect to PCIe mode.
+ */
e1000_toggle_lanphypc_value_ich8lan(hw);
msleep(50);
@@ -338,25 +339,26 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
* Gate automatic PHY configuration by hardware on
* non-managed 82579
*/
- if (hw->mac.type == e1000_pch2lan)
+ if ((hw->mac.type == e1000_pch2lan) &&
+ !(fwsm & E1000_ICH_FWSM_FW_VALID))
e1000_gate_hw_phy_config_ich8lan(hw, true);
- }
- /*
- * Reset the PHY before any access to it. Doing so, ensures that
- * the PHY is in a known good state before we read/write PHY registers.
- * The generic reset is sufficient here, because we haven't determined
- * the PHY type yet.
- */
- ret_val = e1000e_phy_hw_reset_generic(hw);
- if (ret_val)
- goto out;
+ /*
+ * Reset the PHY before any access to it. Doing so, ensures
+ * that the PHY is in a known good state before we read/write
+ * PHY registers. The generic reset is sufficient here,
+ * because we haven't determined the PHY type yet.
+ */
+ ret_val = e1000e_phy_hw_reset_generic(hw);
+ if (ret_val)
+ return ret_val;
- /* Ungate automatic PHY configuration on non-managed 82579 */
- if ((hw->mac.type == e1000_pch2lan) &&
- !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
- usleep_range(10000, 20000);
- e1000_gate_hw_phy_config_ich8lan(hw, false);
+ /* Ungate automatic PHY configuration on non-managed 82579 */
+ if ((hw->mac.type == e1000_pch2lan) &&
+ !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
+ usleep_range(10000, 20000);
+ e1000_gate_hw_phy_config_ich8lan(hw, false);
+ }
}
phy->id = e1000_phy_unknown;
@@ -364,7 +366,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
default:
ret_val = e1000e_get_phy_id(hw);
if (ret_val)
- goto out;
+ return ret_val;
if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
break;
/* fall-through */
@@ -375,10 +377,10 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
*/
ret_val = e1000_set_mdio_slow_mode_hv(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000e_get_phy_id(hw);
if (ret_val)
- goto out;
+ return ret_val;
break;
}
phy->type = e1000e_get_phy_type_from_id(phy->id);
@@ -404,7 +406,6 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
break;
}
-out:
return ret_val;
}
@@ -551,9 +552,8 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
* Initialize family-specific MAC parameters and function
* pointers.
**/
-static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
+static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
{
- struct e1000_hw *hw = &adapter->hw;
struct e1000_mac_info *mac = &hw->mac;
/* Set media type function pointer */
@@ -580,7 +580,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
/* check management mode */
mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan;
/* ID LED init */
- mac->ops.id_led_init = e1000e_id_led_init;
+ mac->ops.id_led_init = e1000e_id_led_init_generic;
/* blink LED */
mac->ops.blink_led = e1000e_blink_led_generic;
/* setup LED */
@@ -634,20 +634,18 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
u16 phy_reg;
if (hw->phy.type != e1000_phy_82579)
- goto out;
+ return 0;
ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
if (ret_val)
- goto out;
+ return ret_val;
if (hw->dev_spec.ich8lan.eee_disable)
phy_reg &= ~I82579_LPI_CTRL_ENABLE_MASK;
else
phy_reg |= I82579_LPI_CTRL_ENABLE_MASK;
- ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
-out:
- return ret_val;
+ return e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
}
/**
@@ -671,10 +669,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
* get_link_status flag is set upon receiving a Link Status
* Change or Rx Sequence Error interrupt.
*/
- if (!mac->get_link_status) {
- ret_val = 0;
- goto out;
- }
+ if (!mac->get_link_status)
+ return 0;
/*
* First we want to see if the MII Status Register reports
@@ -683,16 +679,16 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
*/
ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (hw->mac.type == e1000_pchlan) {
ret_val = e1000_k1_gig_workaround_hv(hw, link);
if (ret_val)
- goto out;
+ return ret_val;
}
if (!link)
- goto out; /* No link detected */
+ return 0; /* No link detected */
mac->get_link_status = false;
@@ -700,13 +696,13 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
case e1000_pch2lan:
ret_val = e1000_k1_workaround_lv(hw);
if (ret_val)
- goto out;
+ return ret_val;
/* fall-thru */
case e1000_pchlan:
if (hw->phy.type == e1000_phy_82578) {
ret_val = e1000_link_stall_workaround_hv(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
/*
@@ -736,23 +732,21 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
/* Enable/Disable EEE after link up */
ret_val = e1000_set_eee_pchlan(hw);
if (ret_val)
- goto out;
+ return ret_val;
/*
* If we are forcing speed/duplex, then we simply return since
* we have already determined whether we have link or not.
*/
- if (!mac->autoneg) {
- ret_val = -E1000_ERR_CONFIG;
- goto out;
- }
+ if (!mac->autoneg)
+ return -E1000_ERR_CONFIG;
/*
* 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.
*/
- e1000e_config_collision_dist(hw);
+ mac->ops.config_collision_dist(hw);
/*
* Configure Flow Control now that Auto-Neg has completed.
@@ -764,7 +758,6 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
if (ret_val)
e_dbg("Error configuring flow control\n");
-out:
return ret_val;
}
@@ -773,7 +766,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
s32 rc;
- rc = e1000_init_mac_params_ich8lan(adapter);
+ rc = e1000_init_mac_params_ich8lan(hw);
if (rc)
return rc;
@@ -900,8 +893,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
}
if (!timeout) {
- e_dbg("Failed to acquire the semaphore, FW or HW has it: "
- "FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n",
+ e_dbg("Failed to acquire the semaphore, FW or HW has it: FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n",
er32(FWSM), extcnf_ctrl);
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
@@ -1008,15 +1000,13 @@ static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy_data &= ~HV_SMB_ADDR_MASK;
phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT);
phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
- ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data);
-out:
- return ret_val;
+ return e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data);
}
/**
@@ -1065,7 +1055,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
data = er32(FEXTNVM);
if (!(data & sw_cfg_mask))
- goto out;
+ goto release;
/*
* Make sure HW does not configure LCD from PHY
@@ -1074,14 +1064,14 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
data = er32(EXTCNF_CTRL);
if (!(hw->mac.type == e1000_pch2lan)) {
if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
- goto out;
+ goto release;
}
cnf_size = er32(EXTCNF_SIZE);
cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
if (!cnf_size)
- goto out;
+ goto release;
cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
@@ -1097,13 +1087,13 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
*/
ret_val = e1000_write_smbus_addr(hw);
if (ret_val)
- goto out;
+ goto release;
data = er32(LEDCTL);
ret_val = e1000_write_phy_reg_hv_locked(hw, HV_LED_CONFIG,
(u16)data);
if (ret_val)
- goto out;
+ goto release;
}
/* Configure LCD from extended configuration region. */
@@ -1115,12 +1105,12 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1,
&reg_data);
if (ret_val)
- goto out;
+ goto release;
ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1),
1, &reg_addr);
if (ret_val)
- goto out;
+ goto release;
/* Save off the PHY page for future writes. */
if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
@@ -1134,10 +1124,10 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr,
reg_data);
if (ret_val)
- goto out;
+ goto release;
}
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -1159,12 +1149,12 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled;
if (hw->mac.type != e1000_pchlan)
- goto out;
+ return 0;
/* Wrap the whole flow with the sw flag */
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
/* Disable K1 when link is 1Gbps, otherwise use the NVM setting */
if (link) {
@@ -1218,7 +1208,7 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
release:
hw->phy.ops.release(hw);
-out:
+
return ret_val;
}
@@ -1244,7 +1234,7 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
E1000_KMRNCTRLSTA_K1_CONFIG,
&kmrn_reg);
if (ret_val)
- goto out;
+ return ret_val;
if (k1_enable)
kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE;
@@ -1255,7 +1245,7 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
E1000_KMRNCTRLSTA_K1_CONFIG,
kmrn_reg);
if (ret_val)
- goto out;
+ return ret_val;
udelay(20);
ctrl_ext = er32(CTRL_EXT);
@@ -1273,8 +1263,7 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
e1e_flush();
udelay(20);
-out:
- return ret_val;
+ return 0;
}
/**
@@ -1302,18 +1291,18 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
if (!(hw->mac.type == e1000_pch2lan)) {
mac_reg = er32(EXTCNF_CTRL);
if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
- goto out;
+ goto release;
}
mac_reg = er32(FEXTNVM);
if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
- goto out;
+ goto release;
mac_reg = er32(PHY_CTRL);
ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg);
if (ret_val)
- goto out;
+ goto release;
oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU);
@@ -1325,7 +1314,7 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
oem_reg |= HV_OEM_BITS_LPLU;
/* Set Restart auto-neg to activate the bits */
- if (!e1000_check_reset_block(hw))
+ if (!hw->phy.ops.check_reset_block(hw))
oem_reg |= HV_OEM_BITS_RESTART_AN;
} else {
if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE |
@@ -1339,7 +1328,7 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
@@ -1376,13 +1365,13 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
u16 phy_data;
if (hw->mac.type != e1000_pchlan)
- return ret_val;
+ return 0;
/* Set MDIO slow mode before any other MDIO access */
if (hw->phy.type == e1000_phy_82577) {
ret_val = e1000_set_mdio_slow_mode_hv(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
if (((hw->phy.type == e1000_phy_82577) &&
@@ -1419,7 +1408,7 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
hw->phy.ops.release(hw);
if (ret_val)
- goto out;
+ return ret_val;
/*
* Configure the K1 Si workaround during phy reset assuming there is
@@ -1427,12 +1416,12 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
*/
ret_val = e1000_k1_gig_workaround_hv(hw, true);
if (ret_val)
- goto out;
+ return ret_val;
/* Workaround for link disconnects on a busy hub in half duplex */
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data);
if (ret_val)
goto release;
@@ -1440,7 +1429,7 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
phy_data & 0x00FF);
release:
hw->phy.ops.release(hw);
-out:
+
return ret_val;
}
@@ -1497,13 +1486,13 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
u16 i;
if (hw->mac.type != e1000_pch2lan)
- goto out;
+ return 0;
/* disable Rx path while enabling/disabling workaround */
e1e_rphy(hw, PHY_REG(769, 20), &phy_reg);
ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg | (1 << 14));
if (ret_val)
- goto out;
+ return ret_val;
if (enable) {
/*
@@ -1545,24 +1534,24 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
E1000_KMRNCTRLSTA_CTRL_OFFSET,
&data);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000e_write_kmrn_reg(hw,
E1000_KMRNCTRLSTA_CTRL_OFFSET,
data | (1 << 0));
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000e_read_kmrn_reg(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
&data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~(0xF << 8);
data |= (0xB << 8);
ret_val = e1000e_write_kmrn_reg(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
data);
if (ret_val)
- goto out;
+ return ret_val;
/* Enable jumbo frame workaround in the PHY */
e1e_rphy(hw, PHY_REG(769, 23), &data);
@@ -1570,25 +1559,25 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
data |= (0x37 << 5);
ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
if (ret_val)
- goto out;
+ return ret_val;
e1e_rphy(hw, PHY_REG(769, 16), &data);
data &= ~(1 << 13);
ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
if (ret_val)
- goto out;
+ return ret_val;
e1e_rphy(hw, PHY_REG(776, 20), &data);
data &= ~(0x3FF << 2);
data |= (0x1A << 2);
ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0xF100);
if (ret_val)
- goto out;
+ return ret_val;
e1e_rphy(hw, HV_PM_CTRL, &data);
ret_val = e1e_wphy(hw, HV_PM_CTRL, data | (1 << 10));
if (ret_val)
- goto out;
+ return ret_val;
} else {
/* Write MAC register values back to h/w defaults */
mac_reg = er32(FFLT_DBG);
@@ -1603,56 +1592,53 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
E1000_KMRNCTRLSTA_CTRL_OFFSET,
&data);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000e_write_kmrn_reg(hw,
E1000_KMRNCTRLSTA_CTRL_OFFSET,
data & ~(1 << 0));
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000e_read_kmrn_reg(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
&data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~(0xF << 8);
data |= (0xB << 8);
ret_val = e1000e_write_kmrn_reg(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
data);
if (ret_val)
- goto out;
+ return ret_val;
/* Write PHY register values back to h/w defaults */
e1e_rphy(hw, PHY_REG(769, 23), &data);
data &= ~(0x7F << 5);
ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
if (ret_val)
- goto out;
+ return ret_val;
e1e_rphy(hw, PHY_REG(769, 16), &data);
data |= (1 << 13);
ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
if (ret_val)
- goto out;
+ return ret_val;
e1e_rphy(hw, PHY_REG(776, 20), &data);
data &= ~(0x3FF << 2);
data |= (0x8 << 2);
ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0x7E00);
if (ret_val)
- goto out;
+ return ret_val;
e1e_rphy(hw, HV_PM_CTRL, &data);
ret_val = e1e_wphy(hw, HV_PM_CTRL, data & ~(1 << 10));
if (ret_val)
- goto out;
+ return ret_val;
}
/* re-enable Rx path after enabling/disabling workaround */
- ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14));
-
-out:
- return ret_val;
+ return e1e_wphy(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14));
}
/**
@@ -1664,12 +1650,31 @@ static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw)
s32 ret_val = 0;
if (hw->mac.type != e1000_pch2lan)
- goto out;
+ return 0;
/* Set MDIO slow mode before any other MDIO access */
ret_val = e1000_set_mdio_slow_mode_hv(hw);
-out:
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+ ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR,
+ I82579_MSE_THRESHOLD);
+ if (ret_val)
+ goto release;
+ /* set MSE higher to enable link to stay up when noise is high */
+ ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, 0x0034);
+ if (ret_val)
+ goto release;
+ ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR,
+ I82579_MSE_LINK_DOWN);
+ if (ret_val)
+ goto release;
+ /* drop link after 5 times MSE threshold was reached */
+ ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, 0x0005);
+release:
+ hw->phy.ops.release(hw);
+
return ret_val;
}
@@ -1687,12 +1692,12 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
u16 phy_reg;
if (hw->mac.type != e1000_pch2lan)
- goto out;
+ return 0;
/* Set K1 beacon duration based on 1Gbps speed or otherwise */
ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg);
if (ret_val)
- goto out;
+ return ret_val;
if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE))
== (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) {
@@ -1701,7 +1706,7 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
if (ret_val)
- goto out;
+ return ret_val;
if (status_reg & HV_M_STATUS_SPEED_1000) {
mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
@@ -1714,7 +1719,6 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
}
-out:
return ret_val;
}
@@ -1741,7 +1745,6 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate)
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
- return;
}
/**
@@ -1785,8 +1788,8 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
s32 ret_val = 0;
u16 reg;
- if (e1000_check_reset_block(hw))
- goto out;
+ if (hw->phy.ops.check_reset_block(hw))
+ return 0;
/* Allow time for h/w to get to quiescent state after reset */
usleep_range(10000, 20000);
@@ -1796,12 +1799,12 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
case e1000_pchlan:
ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
if (ret_val)
- goto out;
+ return ret_val;
break;
case e1000_pch2lan:
ret_val = e1000_lv_phy_workarounds_ich8lan(hw);
if (ret_val)
- goto out;
+ return ret_val;
break;
default:
break;
@@ -1817,7 +1820,7 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
/* Configure the LCD with the extended configuration region in NVM */
ret_val = e1000_sw_lcd_config_ich8lan(hw);
if (ret_val)
- goto out;
+ return ret_val;
/* Configure the LCD with the OEM bits in NVM */
ret_val = e1000_oem_bits_config_ich8lan(hw, true);
@@ -1832,18 +1835,16 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
/* Set EEE LPI Update Timer to 200usec */
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR,
I82579_LPI_UPDATE_TIMER);
- if (ret_val)
- goto release;
- ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA,
- 0x1387);
-release:
+ if (!ret_val)
+ ret_val = hw->phy.ops.write_reg_locked(hw,
+ I82579_EMI_DATA,
+ 0x1387);
hw->phy.ops.release(hw);
}
-out:
return ret_val;
}
@@ -1866,12 +1867,9 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
ret_val = e1000e_phy_hw_reset_generic(hw);
if (ret_val)
- goto out;
-
- ret_val = e1000_post_phy_reset_ich8lan(hw);
+ return ret_val;
-out:
- return ret_val;
+ return e1000_post_phy_reset_ich8lan(hw);
}
/**
@@ -1892,18 +1890,17 @@ static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active)
ret_val = e1e_rphy(hw, HV_OEM_BITS, &oem_reg);
if (ret_val)
- goto out;
+ return ret_val;
if (active)
oem_reg |= HV_OEM_BITS_LPLU;
else
oem_reg &= ~HV_OEM_BITS_LPLU;
- oem_reg |= HV_OEM_BITS_RESTART_AN;
- ret_val = e1e_wphy(hw, HV_OEM_BITS, oem_reg);
+ if (!hw->phy.ops.check_reset_block(hw))
+ oem_reg |= HV_OEM_BITS_RESTART_AN;
-out:
- return ret_val;
+ return e1e_wphy(hw, HV_OEM_BITS, oem_reg);
}
/**
@@ -1927,7 +1924,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
u16 data;
if (phy->type == e1000_phy_ife)
- return ret_val;
+ return 0;
phy_ctrl = er32(PHY_CTRL);
@@ -2009,7 +2006,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
{
struct e1000_phy_info *phy = &hw->phy;
u32 phy_ctrl;
- s32 ret_val;
+ s32 ret_val = 0;
u16 data;
phy_ctrl = er32(PHY_CTRL);
@@ -2075,7 +2072,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data);
}
- return 0;
+ return ret_val;
}
/**
@@ -2093,7 +2090,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
u8 sig_byte = 0;
- s32 ret_val = 0;
+ s32 ret_val;
switch (hw->mac.type) {
case e1000_ich8lan:
@@ -2108,8 +2105,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
return 0;
}
- e_dbg("Unable to determine valid NVM bank via EEC - "
- "reading flash signature\n");
+ e_dbg("Unable to determine valid NVM bank via EEC - reading flash signature\n");
/* fall-thru */
default:
/* set bank to 0 in case flash read fails */
@@ -2141,8 +2137,6 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
e_dbg("ERROR: No valid NVM bank present\n");
return -E1000_ERR_NVM;
}
-
- return 0;
}
/**
@@ -2221,8 +2215,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
/* Check if the flash descriptor is valid */
if (hsfsts.hsf_status.fldesvalid == 0) {
- e_dbg("Flash descriptor invalid. "
- "SW Sequencing must be used.\n");
+ e_dbg("Flash descriptor invalid. SW Sequencing must be used.\n");
return -E1000_ERR_NVM;
}
@@ -2251,21 +2244,21 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
ret_val = 0;
} else {
- s32 i = 0;
+ s32 i;
/*
* 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++) {
- hsfsts.regval = __er16flash(hw, ICH_FLASH_HSFSTS);
+ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.flcinprog == 0) {
ret_val = 0;
break;
}
udelay(1);
}
- if (ret_val == 0) {
+ if (!ret_val) {
/*
* Successful in waiting for previous cycle to timeout,
* now set the Flash Cycle Done.
@@ -2291,7 +2284,6 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
{
union ich8_hws_flash_ctrl hsflctl;
union ich8_hws_flash_status hsfsts;
- s32 ret_val = -E1000_ERR_NVM;
u32 i = 0;
/* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
@@ -2310,7 +2302,7 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0)
return 0;
- return ret_val;
+ return -E1000_ERR_NVM;
}
/**
@@ -2383,7 +2375,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
udelay(1);
/* Steps */
ret_val = e1000_flash_cycle_init_ich8lan(hw);
- if (ret_val != 0)
+ if (ret_val)
break;
hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
@@ -2403,7 +2395,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
* read in (shift in) the Flash Data0, the order is
* least significant byte first msb to lsb
*/
- if (ret_val == 0) {
+ if (!ret_val) {
flash_data = er32flash(ICH_FLASH_FDATA0);
if (size == 1)
*data = (u8)(flash_data & 0x000000FF);
@@ -2422,8 +2414,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
/* Repeat for some time before giving up. */
continue;
} else if (hsfsts.hsf_status.flcdone == 0) {
- e_dbg("Timeout error - flash cycle "
- "did not complete.\n");
+ e_dbg("Timeout error - flash cycle did not complete.\n");
break;
}
}
@@ -2618,7 +2609,7 @@ release:
* until after the next adapter reset.
*/
if (!ret_val) {
- e1000e_reload_nvm(hw);
+ nvm->ops.reload(hw);
usleep_range(10000, 20000);
}
@@ -2774,8 +2765,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
/* Repeat for some time before giving up. */
continue;
if (hsfsts.hsf_status.flcdone == 0) {
- e_dbg("Timeout error - flash cycle "
- "did not complete.");
+ e_dbg("Timeout error - flash cycle did not complete.\n");
break;
}
} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
@@ -2917,7 +2907,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
ret_val = e1000_flash_cycle_ich8lan(hw,
ICH_FLASH_ERASE_COMMAND_TIMEOUT);
- if (ret_val == 0)
+ if (!ret_val)
break;
/*
@@ -2972,7 +2962,7 @@ static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data)
*
* PCH also does not have an "always on" or "always off" mode which
* complicates the ID feature. Instead of using the "on" mode to indicate
- * in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init()),
+ * in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init_generic()),
* use "link_up" mode. The LEDs will still ID on request if there is no
* link based on logic in e1000_led_[on|off]_pchlan().
**/
@@ -2987,7 +2977,7 @@ static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw)
/* Get default ID LED modes */
ret_val = hw->nvm.ops.valid_led_default(hw, &data);
if (ret_val)
- goto out;
+ return ret_val;
mac->ledctl_default = er32(LEDCTL);
mac->ledctl_mode1 = mac->ledctl_default;
@@ -3032,8 +3022,7 @@ static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw)
}
}
-out:
- return ret_val;
+ return 0;
}
/**
@@ -3120,7 +3109,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ctrl = er32(CTRL);
- if (!e1000_check_reset_block(hw)) {
+ if (!hw->phy.ops.check_reset_block(hw)) {
/*
* Full-chip reset requires MAC and PHY reset at the same
* time to make sure the interface between MAC and the
@@ -3148,11 +3137,11 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
if (ctrl & E1000_CTRL_PHY_RST) {
ret_val = hw->phy.ops.get_cfg_done(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1000_post_phy_reset_ich8lan(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
/*
@@ -3170,8 +3159,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
kab |= E1000_KABGTXD_BGSQLBIAS;
ew32(KABGTXD, kab);
-out:
- return ret_val;
+ return 0;
}
/**
@@ -3224,7 +3212,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
}
/* Setup link and flow control */
- ret_val = e1000_setup_link_ich8lan(hw);
+ ret_val = mac->ops.setup_link(hw);
/* Set the transmit descriptor write-back policy for both queues */
txdctl = er32(TXDCTL(0));
@@ -3262,7 +3250,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
*/
e1000_clear_hw_cntrs_ich8lan(hw);
- return 0;
+ return ret_val;
}
/**
* e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits
@@ -3339,7 +3327,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
{
s32 ret_val;
- if (e1000_check_reset_block(hw))
+ if (hw->phy.ops.check_reset_block(hw))
return 0;
/*
@@ -3365,7 +3353,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
hw->fc.current_mode);
/* Continue to configure the copper link. */
- ret_val = e1000_setup_copper_link_ich8lan(hw);
+ ret_val = hw->mac.ops.setup_physical_interface(hw);
if (ret_val)
return ret_val;
@@ -3465,6 +3453,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
default:
break;
}
+
return e1000e_setup_copper_link(hw);
}
@@ -3566,7 +3555,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
}
/**
- * e1000_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state
+ * e1000e_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state
* @hw: pointer to the HW structure
* @state: boolean value used to set the current Kumeran workaround state
*
@@ -3676,9 +3665,10 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
*
* During S0 to Sx transition, it is possible the link remains at gig
* instead of negotiating to a lower speed. Before going to Sx, set
- * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
- * to a lower speed. For PCH and newer parts, the OEM bits PHY register
- * (LED, GbE disable and LPLU configurations) also needs to be written.
+ * 'Gig Disable' to force link speed negotiation to a lower speed based on
+ * the LPLU setting in the NVM or custom setting. For PCH and newer parts,
+ * the OEM bits PHY register (LED, GbE disable and LPLU configurations) also
+ * needs to be written.
**/
void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
{
@@ -3686,7 +3676,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
s32 ret_val;
phy_ctrl = er32(PHY_CTRL);
- phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE;
+ phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE;
ew32(PHY_CTRL, phy_ctrl);
if (hw->mac.type == e1000_ich8lan)
@@ -3714,47 +3704,41 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
**/
void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
{
- u32 fwsm;
+ u16 phy_id1, phy_id2;
+ s32 ret_val;
- if (hw->mac.type != e1000_pch2lan)
+ if ((hw->mac.type != e1000_pch2lan) ||
+ hw->phy.ops.check_reset_block(hw))
return;
- fwsm = er32(FWSM);
- if (!(fwsm & E1000_ICH_FWSM_FW_VALID) || !e1000_check_reset_block(hw)) {
- u16 phy_id1, phy_id2;
- s32 ret_val;
-
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val) {
- e_dbg("Failed to acquire PHY semaphore in resume\n");
- return;
- }
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ e_dbg("Failed to acquire PHY semaphore in resume\n");
+ return;
+ }
- /* Test access to the PHY registers by reading the ID regs */
- ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1);
- if (ret_val)
- goto release;
- ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2);
- if (ret_val)
- goto release;
+ /* Test access to the PHY registers by reading the ID regs */
+ ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1);
+ if (ret_val)
+ goto release;
+ ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2);
+ if (ret_val)
+ goto release;
- if (hw->phy.id == ((u32)(phy_id1 << 16) |
- (u32)(phy_id2 & PHY_REVISION_MASK)))
- goto release;
+ if (hw->phy.id == ((u32)(phy_id1 << 16) |
+ (u32)(phy_id2 & PHY_REVISION_MASK)))
+ goto release;
- e1000_toggle_lanphypc_value_ich8lan(hw);
+ e1000_toggle_lanphypc_value_ich8lan(hw);
- hw->phy.ops.release(hw);
- msleep(50);
- e1000_phy_hw_reset(hw);
- msleep(50);
- return;
- }
+ hw->phy.ops.release(hw);
+ msleep(50);
+ e1000_phy_hw_reset(hw);
+ msleep(50);
+ return;
release:
hw->phy.ops.release(hw);
-
- return;
}
/**
@@ -4023,7 +4007,6 @@ release:
}
static const struct e1000_mac_operations ich8_mac_ops = {
- .id_led_init = e1000e_id_led_init,
/* check_mng_mode dependent on mac type */
.check_for_link = e1000_check_for_copper_link_ich8lan,
/* cleanup_led dependent on mac type */
@@ -4039,6 +4022,7 @@ static const struct e1000_mac_operations ich8_mac_ops = {
.setup_link = e1000_setup_link_ich8lan,
.setup_physical_interface= e1000_setup_copper_link_ich8lan,
/* id_led_init dependent on mac type */
+ .config_collision_dist = e1000e_config_collision_dist_generic,
};
static const struct e1000_phy_operations ich8_phy_ops = {
@@ -4059,6 +4043,7 @@ static const struct e1000_nvm_operations ich8_nvm_ops = {
.acquire = e1000_acquire_nvm_ich8lan,
.read = e1000_read_nvm_ich8lan,
.release = e1000_release_nvm_ich8lan,
+ .reload = e1000e_reload_nvm_generic,
.update = e1000_update_nvm_checksum_ich8lan,
.valid_led_default = e1000_valid_led_default_ich8lan,
.validate = e1000_validate_nvm_checksum_ich8lan,
@@ -4088,10 +4073,9 @@ const struct e1000_info e1000_ich9_info = {
| FLAG_HAS_WOL
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_HAS_AMT
- | FLAG_HAS_ERT
| FLAG_HAS_FLASH
| FLAG_APME_IN_WUC,
- .pba = 10,
+ .pba = 18,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_ich8lan,
.mac_ops = &ich8_mac_ops,
@@ -4106,10 +4090,9 @@ const struct e1000_info e1000_ich10_info = {
| FLAG_HAS_WOL
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_HAS_AMT
- | FLAG_HAS_ERT
| FLAG_HAS_FLASH
| FLAG_APME_IN_WUC,
- .pba = 10,
+ .pba = 18,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_ich8lan,
.mac_ops = &ich8_mac_ops,
diff --git a/drivers/net/ethernet/intel/e1000e/lib.c b/drivers/net/ethernet/intel/e1000e/mac.c
index 0893ab107adf..59ac9f6353de 100644
--- a/drivers/net/ethernet/intel/e1000e/lib.c
+++ b/drivers/net/ethernet/intel/e1000e/mac.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -28,19 +28,6 @@
#include "e1000.h"
-enum e1000_mng_mode {
- e1000_mng_mode_none = 0,
- e1000_mng_mode_asf,
- e1000_mng_mode_pt,
- e1000_mng_mode_ipmi,
- e1000_mng_mode_host_if_only
-};
-
-#define E1000_FACTPS_MNGCG 0x20000000
-
-/* Intel(R) Active Management Technology signature */
-#define E1000_IAMT_SIGNATURE 0x544D4149
-
/**
* e1000e_get_bus_info_pcie - Get PCIe bus information
* @hw: pointer to the HW structure
@@ -151,7 +138,7 @@ void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value)
void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
{
u32 i;
- u8 mac_addr[ETH_ALEN] = {0};
+ u8 mac_addr[ETH_ALEN] = { 0 };
/* Setup the receive address */
e_dbg("Programming MAC Address into RAR[0]\n");
@@ -159,7 +146,7 @@ void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
e1000e_rar_set(hw, hw->mac.addr, 0);
/* Zero out the other (rar_entry_count - 1) receive addresses */
- e_dbg("Clearing RAR[1-%u]\n", rar_count-1);
+ e_dbg("Clearing RAR[1-%u]\n", rar_count - 1);
for (i = 1; i < rar_count; i++)
e1000e_rar_set(hw, mac_addr, i);
}
@@ -185,26 +172,23 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data);
if (ret_val)
- goto out;
+ return ret_val;
- /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */
- if (!((nvm_data & NVM_COMPAT_LOM) ||
- (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) ||
- (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) ||
- (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES)))
- goto out;
+ /* not supported on 82573 */
+ if (hw->mac.type == e1000_82573)
+ return 0;
ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
- &nvm_alt_mac_addr_offset);
+ &nvm_alt_mac_addr_offset);
if (ret_val) {
e_dbg("NVM Read Error\n");
- goto out;
+ return ret_val;
}
if ((nvm_alt_mac_addr_offset == 0xFFFF) ||
(nvm_alt_mac_addr_offset == 0x0000))
/* There is no Alternate MAC Address */
- goto out;
+ return 0;
if (hw->bus.func == E1000_FUNC_1)
nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
@@ -213,7 +197,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data);
if (ret_val) {
e_dbg("NVM Read Error\n");
- goto out;
+ return ret_val;
}
alt_mac_addr[i] = (u8)(nvm_data & 0xFF);
@@ -223,7 +207,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
/* if multicast bit is set, the alternate address will not be used */
if (is_multicast_ether_addr(alt_mac_addr)) {
e_dbg("Ignoring Alternate Mac Address with MC bit set\n");
- goto out;
+ return 0;
}
/*
@@ -233,8 +217,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
*/
e1000e_rar_set(hw, alt_mac_addr, 0);
-out:
- return ret_val;
+ return 0;
}
/**
@@ -254,11 +237,10 @@ void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
* HW expects these in little endian so we reverse the byte order
* from network order (big endian) to little endian
*/
- rar_low = ((u32) addr[0] |
- ((u32) addr[1] << 8) |
- ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+ rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
+ ((u32)addr[2] << 16) | ((u32)addr[3] << 24));
- rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+ rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
/* If MAC address zero, no need to set the AV bit */
if (rar_low || rar_high)
@@ -281,8 +263,7 @@ void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
* @mc_addr: pointer to a multicast address
*
* Generates a multicast address hash value which is used to determine
- * the multicast filter table array address and new table value. See
- * e1000_mta_set_generic()
+ * the multicast filter table array address and new table value.
**/
static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
{
@@ -318,7 +299,7 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
* values resulting from each mc_filter_type...
* [0] [1] [2] [3] [4] [5]
* 01 AA 00 12 34 56
- * LSB MSB
+ * LSB MSB
*
* case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563
* case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6
@@ -341,7 +322,7 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
}
hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
- (((u16) mc_addr[5]) << bit_shift)));
+ (((u16)mc_addr[5]) << bit_shift)));
return hash_value;
}
@@ -365,7 +346,7 @@ void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
/* update mta_shadow from mc_addr_list */
- for (i = 0; (u32) i < mc_addr_count; i++) {
+ for (i = 0; (u32)i < mc_addr_count; i++) {
hash_value = e1000_hash_mc_addr(hw, mc_addr_list);
hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
@@ -461,7 +442,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
return ret_val;
if (!link)
- return ret_val; /* No link detected */
+ return 0; /* No link detected */
mac->get_link_status = false;
@@ -475,17 +456,15 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
* If we are forcing speed/duplex, then we simply return since
* we have already determined whether we have link or not.
*/
- if (!mac->autoneg) {
- ret_val = -E1000_ERR_CONFIG;
- return ret_val;
- }
+ if (!mac->autoneg)
+ return -E1000_ERR_CONFIG;
/*
* 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.
*/
- e1000e_config_collision_dist(hw);
+ mac->ops.config_collision_dist(hw);
/*
* Configure Flow Control now that Auto-Neg has completed.
@@ -528,10 +507,10 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
* was just plugged in. The autoneg_failed flag does this.
*/
/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
- if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) &&
- (!(rxcw & E1000_RXCW_C))) {
- if (mac->autoneg_failed == 0) {
- mac->autoneg_failed = 1;
+ if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) &&
+ !(rxcw & E1000_RXCW_C)) {
+ if (!mac->autoneg_failed) {
+ mac->autoneg_failed = true;
return 0;
}
e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
@@ -594,9 +573,9 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
* time to complete.
*/
/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
- if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
- if (mac->autoneg_failed == 0) {
- mac->autoneg_failed = 1;
+ if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) {
+ if (!mac->autoneg_failed) {
+ mac->autoneg_failed = true;
return 0;
}
e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
@@ -656,12 +635,10 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
if (rxcw & E1000_RXCW_SYNCH) {
if (!(rxcw & E1000_RXCW_IV)) {
mac->serdes_has_link = true;
- e_dbg("SERDES: Link up - autoneg "
- "completed successfully.\n");
+ e_dbg("SERDES: Link up - autoneg completed successfully.\n");
} else {
mac->serdes_has_link = false;
- e_dbg("SERDES: Link down - invalid"
- "codewords detected in autoneg.\n");
+ e_dbg("SERDES: Link down - invalid codewords detected in autoneg.\n");
}
} else {
mac->serdes_has_link = false;
@@ -706,8 +683,7 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
hw->fc.requested_mode = e1000_fc_none;
- else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
- NVM_WORD0F_ASM_DIR)
+ else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == NVM_WORD0F_ASM_DIR)
hw->fc.requested_mode = e1000_fc_tx_pause;
else
hw->fc.requested_mode = e1000_fc_full;
@@ -716,7 +692,7 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
}
/**
- * e1000e_setup_link - Setup flow control and link settings
+ * e1000e_setup_link_generic - Setup flow control and link settings
* @hw: pointer to the HW structure
*
* Determines which flow control settings to use, then configures flow
@@ -725,16 +701,15 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
* should be established. Assumes the hardware has previously been reset
* and the transmitter and receiver are not enabled.
**/
-s32 e1000e_setup_link(struct e1000_hw *hw)
+s32 e1000e_setup_link_generic(struct e1000_hw *hw)
{
- struct e1000_mac_info *mac = &hw->mac;
s32 ret_val;
/*
* In the case of the phy reset being blocked, we already have a link.
* We do not need to set it up again.
*/
- if (e1000_check_reset_block(hw))
+ if (hw->phy.ops.check_reset_block(hw))
return 0;
/*
@@ -753,11 +728,10 @@ s32 e1000e_setup_link(struct e1000_hw *hw)
*/
hw->fc.current_mode = hw->fc.requested_mode;
- e_dbg("After fix-ups FlowControl is now = %x\n",
- hw->fc.current_mode);
+ e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode);
/* Call the necessary media_type subroutine to configure the link. */
- ret_val = mac->ops.setup_physical_interface(hw);
+ ret_val = hw->mac.ops.setup_physical_interface(hw);
if (ret_val)
return ret_val;
@@ -876,7 +850,7 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
}
if (i == FIBER_LINK_UP_LIMIT) {
e_dbg("Never got a valid link from auto-neg!!!\n");
- mac->autoneg_failed = 1;
+ mac->autoneg_failed = true;
/*
* AutoNeg failed to achieve a link, so we'll call
* mac->check_for_link. This routine will force the
@@ -888,9 +862,9 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
e_dbg("Error while checking for link\n");
return ret_val;
}
- mac->autoneg_failed = 0;
+ mac->autoneg_failed = false;
} else {
- mac->autoneg_failed = 0;
+ mac->autoneg_failed = false;
e_dbg("Valid Link Found\n");
}
@@ -914,7 +888,7 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
/* Take the link out of reset */
ctrl &= ~E1000_CTRL_LRST;
- e1000e_config_collision_dist(hw);
+ hw->mac.ops.config_collision_dist(hw);
ret_val = e1000_commit_fc_settings_generic(hw);
if (ret_val)
@@ -945,18 +919,17 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
e_dbg("No signal detected\n");
}
- return 0;
+ return ret_val;
}
/**
- * e1000e_config_collision_dist - Configure collision distance
+ * e1000e_config_collision_dist_generic - Configure collision distance
* @hw: pointer to the HW structure
*
* Configures the collision distance to the default value and is used
- * during link setup. Currently no func pointer exists and all
- * implementations are handled in the generic version of this function.
+ * during link setup.
**/
-void e1000e_config_collision_dist(struct e1000_hw *hw)
+void e1000e_config_collision_dist_generic(struct e1000_hw *hw)
{
u32 tctl;
@@ -995,7 +968,9 @@ s32 e1000e_set_fc_watermarks(struct e1000_hw *hw)
* XON frames.
*/
fcrtl = hw->fc.low_water;
- fcrtl |= E1000_FCRTL_XONE;
+ if (hw->fc.send_xon)
+ fcrtl |= E1000_FCRTL_XONE;
+
fcrth = hw->fc.high_water;
}
ew32(FCRTL, fcrtl);
@@ -1121,8 +1096,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
return ret_val;
if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
- e_dbg("Copper PHY and Auto Neg "
- "has not completed.\n");
+ e_dbg("Copper PHY and Auto Neg has not completed.\n");
return ret_val;
}
@@ -1186,11 +1160,10 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
*/
if (hw->fc.requested_mode == e1000_fc_full) {
hw->fc.current_mode = e1000_fc_full;
- e_dbg("Flow Control = FULL.\r\n");
+ e_dbg("Flow Control = FULL.\n");
} else {
hw->fc.current_mode = e1000_fc_rx_pause;
- e_dbg("Flow Control = "
- "Rx PAUSE frames only.\r\n");
+ e_dbg("Flow Control = Rx PAUSE frames only.\n");
}
}
/*
@@ -1202,11 +1175,11 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
* 0 | 1 | 1 | 1 | e1000_fc_tx_pause
*/
else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
- (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+ (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
hw->fc.current_mode = e1000_fc_tx_pause;
- e_dbg("Flow Control = Tx PAUSE frames only.\r\n");
+ e_dbg("Flow Control = Tx PAUSE frames only.\n");
}
/*
* For transmitting PAUSE frames ONLY.
@@ -1221,14 +1194,14 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
!(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
(mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
hw->fc.current_mode = e1000_fc_rx_pause;
- e_dbg("Flow Control = Rx PAUSE frames only.\r\n");
+ e_dbg("Flow Control = Rx PAUSE frames only.\n");
} else {
/*
* Per the IEEE spec, at this point flow control
* should be disabled.
*/
hw->fc.current_mode = e1000_fc_none;
- e_dbg("Flow Control = NONE.\r\n");
+ e_dbg("Flow Control = NONE.\n");
}
/*
@@ -1268,7 +1241,8 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
* Read the status register for the current speed/duplex and store the current
* speed and duplex for copper connections.
**/
-s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex)
+s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed,
+ u16 *duplex)
{
u32 status;
@@ -1301,7 +1275,8 @@ s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *dup
* Sets the speed and duplex to gigabit full duplex (the only possible option)
* for fiber/serdes links.
**/
-s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex)
+s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed,
+ u16 *duplex)
{
*speed = SPEED_1000;
*duplex = FULL_DUPLEX;
@@ -1423,11 +1398,11 @@ s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data)
}
/**
- * e1000e_id_led_init -
+ * e1000e_id_led_init_generic -
* @hw: pointer to the HW structure
*
**/
-s32 e1000e_id_led_init(struct e1000_hw *hw)
+s32 e1000e_id_led_init_generic(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
s32 ret_val;
@@ -1504,11 +1479,10 @@ s32 e1000e_setup_led_generic(struct e1000_hw *hw)
ledctl = er32(LEDCTL);
hw->mac.ledctl_default = ledctl;
/* Turn off LED0 */
- ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
- E1000_LEDCTL_LED0_BLINK |
- E1000_LEDCTL_LED0_MODE_MASK);
+ ledctl &= ~(E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_LED0_BLINK |
+ E1000_LEDCTL_LED0_MODE_MASK);
ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
- E1000_LEDCTL_LED0_MODE_SHIFT);
+ E1000_LEDCTL_LED0_MODE_SHIFT);
ew32(LEDCTL, ledctl);
} else if (hw->phy.media_type == e1000_media_type_copper) {
ew32(LEDCTL, hw->mac.ledctl_mode1);
@@ -1544,7 +1518,7 @@ s32 e1000e_blink_led_generic(struct e1000_hw *hw)
if (hw->phy.media_type == e1000_media_type_fiber) {
/* always blink LED0 for PCI-E fiber */
ledctl_blink = E1000_LEDCTL_LED0_BLINK |
- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
+ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
} else {
/*
* set the blink bit for each LED that's "on" (0x0E)
@@ -1657,8 +1631,7 @@ s32 e1000e_disable_pcie_master(struct e1000_hw *hw)
ew32(CTRL, ctrl);
while (timeout) {
- if (!(er32(STATUS) &
- E1000_STATUS_GIO_MASTER_ENABLE))
+ if (!(er32(STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
break;
udelay(100);
timeout--;
@@ -1684,7 +1657,7 @@ void e1000e_reset_adaptive(struct e1000_hw *hw)
if (!mac->adaptive_ifs) {
e_dbg("Not in Adaptive IFS mode!\n");
- goto out;
+ return;
}
mac->current_ifs_val = 0;
@@ -1695,8 +1668,6 @@ void e1000e_reset_adaptive(struct e1000_hw *hw)
mac->in_ifs_mode = false;
ew32(AIT, 0);
-out:
- return;
}
/**
@@ -1712,7 +1683,7 @@ void e1000e_update_adaptive(struct e1000_hw *hw)
if (!mac->adaptive_ifs) {
e_dbg("Not in Adaptive IFS mode!\n");
- goto out;
+ return;
}
if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) {
@@ -1723,7 +1694,7 @@ void e1000e_update_adaptive(struct e1000_hw *hw)
mac->current_ifs_val = mac->ifs_min_val;
else
mac->current_ifs_val +=
- mac->ifs_step_size;
+ mac->ifs_step_size;
ew32(AIT, mac->current_ifs_val);
}
}
@@ -1735,959 +1706,4 @@ void e1000e_update_adaptive(struct e1000_hw *hw)
ew32(AIT, 0);
}
}
-out:
- return;
-}
-
-/**
- * e1000_raise_eec_clk - Raise EEPROM clock
- * @hw: pointer to the HW structure
- * @eecd: pointer to the EEPROM
- *
- * Enable/Raise the EEPROM clock bit.
- **/
-static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
-{
- *eecd = *eecd | E1000_EECD_SK;
- ew32(EECD, *eecd);
- e1e_flush();
- udelay(hw->nvm.delay_usec);
-}
-
-/**
- * e1000_lower_eec_clk - Lower EEPROM clock
- * @hw: pointer to the HW structure
- * @eecd: pointer to the EEPROM
- *
- * Clear/Lower the EEPROM clock bit.
- **/
-static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
-{
- *eecd = *eecd & ~E1000_EECD_SK;
- ew32(EECD, *eecd);
- e1e_flush();
- udelay(hw->nvm.delay_usec);
-}
-
-/**
- * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM
- * @hw: pointer to the HW structure
- * @data: data to send to the EEPROM
- * @count: number of bits to shift out
- *
- * We need to shift 'count' bits out to the EEPROM. So, the value in the
- * "data" parameter will be shifted out to the EEPROM one bit at a time.
- * In order to do this, "data" must be broken down into bits.
- **/
-static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
-{
- struct e1000_nvm_info *nvm = &hw->nvm;
- u32 eecd = er32(EECD);
- u32 mask;
-
- mask = 0x01 << (count - 1);
- if (nvm->type == e1000_nvm_eeprom_spi)
- eecd |= E1000_EECD_DO;
-
- do {
- eecd &= ~E1000_EECD_DI;
-
- if (data & mask)
- eecd |= E1000_EECD_DI;
-
- ew32(EECD, eecd);
- e1e_flush();
-
- udelay(nvm->delay_usec);
-
- e1000_raise_eec_clk(hw, &eecd);
- e1000_lower_eec_clk(hw, &eecd);
-
- mask >>= 1;
- } while (mask);
-
- eecd &= ~E1000_EECD_DI;
- ew32(EECD, eecd);
-}
-
-/**
- * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM
- * @hw: pointer to the HW structure
- * @count: number of bits to shift in
- *
- * In order to read a register from the EEPROM, we need to shift 'count' bits
- * in from the EEPROM. Bits are "shifted in" by raising the clock input to
- * the EEPROM (setting the SK bit), and then reading the value of the data out
- * "DO" bit. During this "shifting in" process the data in "DI" bit should
- * always be clear.
- **/
-static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
-{
- u32 eecd;
- u32 i;
- u16 data;
-
- eecd = er32(EECD);
-
- eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
- data = 0;
-
- for (i = 0; i < count; i++) {
- data <<= 1;
- e1000_raise_eec_clk(hw, &eecd);
-
- eecd = er32(EECD);
-
- eecd &= ~E1000_EECD_DI;
- if (eecd & E1000_EECD_DO)
- data |= 1;
-
- e1000_lower_eec_clk(hw, &eecd);
- }
-
- return data;
-}
-
-/**
- * e1000e_poll_eerd_eewr_done - Poll for EEPROM read/write completion
- * @hw: pointer to the HW structure
- * @ee_reg: EEPROM flag for polling
- *
- * Polls the EEPROM status bit for either read or write completion based
- * upon the value of 'ee_reg'.
- **/
-s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
-{
- u32 attempts = 100000;
- u32 i, reg = 0;
-
- for (i = 0; i < attempts; i++) {
- if (ee_reg == E1000_NVM_POLL_READ)
- reg = er32(EERD);
- else
- reg = er32(EEWR);
-
- if (reg & E1000_NVM_RW_REG_DONE)
- return 0;
-
- udelay(5);
- }
-
- return -E1000_ERR_NVM;
-}
-
-/**
- * e1000e_acquire_nvm - Generic request for access to EEPROM
- * @hw: pointer to the HW structure
- *
- * Set the EEPROM access request bit and wait for EEPROM access grant bit.
- * Return successful if access grant bit set, else clear the request for
- * EEPROM access and return -E1000_ERR_NVM (-1).
- **/
-s32 e1000e_acquire_nvm(struct e1000_hw *hw)
-{
- u32 eecd = er32(EECD);
- s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
-
- ew32(EECD, eecd | E1000_EECD_REQ);
- eecd = er32(EECD);
-
- while (timeout) {
- if (eecd & E1000_EECD_GNT)
- break;
- udelay(5);
- eecd = er32(EECD);
- timeout--;
- }
-
- if (!timeout) {
- eecd &= ~E1000_EECD_REQ;
- ew32(EECD, eecd);
- e_dbg("Could not acquire NVM grant\n");
- return -E1000_ERR_NVM;
- }
-
- return 0;
-}
-
-/**
- * e1000_standby_nvm - Return EEPROM to standby state
- * @hw: pointer to the HW structure
- *
- * Return the EEPROM to a standby state.
- **/
-static void e1000_standby_nvm(struct e1000_hw *hw)
-{
- struct e1000_nvm_info *nvm = &hw->nvm;
- u32 eecd = er32(EECD);
-
- if (nvm->type == e1000_nvm_eeprom_spi) {
- /* Toggle CS to flush commands */
- eecd |= E1000_EECD_CS;
- ew32(EECD, eecd);
- e1e_flush();
- udelay(nvm->delay_usec);
- eecd &= ~E1000_EECD_CS;
- ew32(EECD, eecd);
- e1e_flush();
- udelay(nvm->delay_usec);
- }
-}
-
-/**
- * e1000_stop_nvm - Terminate EEPROM command
- * @hw: pointer to the HW structure
- *
- * Terminates the current command by inverting the EEPROM's chip select pin.
- **/
-static void e1000_stop_nvm(struct e1000_hw *hw)
-{
- u32 eecd;
-
- eecd = er32(EECD);
- if (hw->nvm.type == e1000_nvm_eeprom_spi) {
- /* Pull CS high */
- eecd |= E1000_EECD_CS;
- e1000_lower_eec_clk(hw, &eecd);
- }
-}
-
-/**
- * e1000e_release_nvm - Release exclusive access to EEPROM
- * @hw: pointer to the HW structure
- *
- * Stop any current commands to the EEPROM and clear the EEPROM request bit.
- **/
-void e1000e_release_nvm(struct e1000_hw *hw)
-{
- u32 eecd;
-
- e1000_stop_nvm(hw);
-
- eecd = er32(EECD);
- eecd &= ~E1000_EECD_REQ;
- ew32(EECD, eecd);
-}
-
-/**
- * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write
- * @hw: pointer to the HW structure
- *
- * Setups the EEPROM for reading and writing.
- **/
-static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
-{
- struct e1000_nvm_info *nvm = &hw->nvm;
- u32 eecd = er32(EECD);
- u8 spi_stat_reg;
-
- if (nvm->type == e1000_nvm_eeprom_spi) {
- u16 timeout = NVM_MAX_RETRY_SPI;
-
- /* Clear SK and CS */
- eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
- ew32(EECD, eecd);
- e1e_flush();
- udelay(1);
-
- /*
- * Read "Status Register" repeatedly until the LSB is cleared.
- * The EEPROM will signal that the command has been completed
- * by clearing bit 0 of the internal status register. If it's
- * not cleared within 'timeout', then error out.
- */
- while (timeout) {
- e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
- hw->nvm.opcode_bits);
- spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
- if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
- break;
-
- udelay(5);
- e1000_standby_nvm(hw);
- timeout--;
- }
-
- if (!timeout) {
- e_dbg("SPI NVM Status error\n");
- return -E1000_ERR_NVM;
- }
- }
-
- return 0;
-}
-
-/**
- * e1000e_read_nvm_eerd - Reads EEPROM using EERD register
- * @hw: pointer to the HW structure
- * @offset: offset of word in the EEPROM to read
- * @words: number of words to read
- * @data: word read from the EEPROM
- *
- * Reads a 16 bit word from the EEPROM using the EERD register.
- **/
-s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
-{
- struct e1000_nvm_info *nvm = &hw->nvm;
- u32 i, eerd = 0;
- s32 ret_val = 0;
-
- /*
- * A check for invalid values: offset too large, too many words,
- * too many words for the offset, and not enough words.
- */
- if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
- (words == 0)) {
- e_dbg("nvm parameter(s) out of bounds\n");
- return -E1000_ERR_NVM;
- }
-
- for (i = 0; i < words; i++) {
- eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) +
- E1000_NVM_RW_REG_START;
-
- ew32(EERD, eerd);
- ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
- if (ret_val)
- break;
-
- data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA);
- }
-
- return ret_val;
-}
-
-/**
- * e1000e_write_nvm_spi - Write to EEPROM using SPI
- * @hw: pointer to the HW structure
- * @offset: offset within the EEPROM to be written to
- * @words: number of words to write
- * @data: 16 bit word(s) to be written to the EEPROM
- *
- * Writes data to EEPROM at offset using SPI interface.
- *
- * If e1000e_update_nvm_checksum is not called after this function , the
- * EEPROM will most likely contain an invalid checksum.
- **/
-s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
-{
- struct e1000_nvm_info *nvm = &hw->nvm;
- s32 ret_val;
- u16 widx = 0;
-
- /*
- * A check for invalid values: offset too large, too many words,
- * and not enough words.
- */
- if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
- (words == 0)) {
- e_dbg("nvm parameter(s) out of bounds\n");
- return -E1000_ERR_NVM;
- }
-
- ret_val = nvm->ops.acquire(hw);
- if (ret_val)
- return ret_val;
-
- while (widx < words) {
- u8 write_opcode = NVM_WRITE_OPCODE_SPI;
-
- ret_val = e1000_ready_nvm_eeprom(hw);
- if (ret_val) {
- nvm->ops.release(hw);
- return ret_val;
- }
-
- e1000_standby_nvm(hw);
-
- /* Send the WRITE ENABLE command (8 bit opcode) */
- e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
- nvm->opcode_bits);
-
- e1000_standby_nvm(hw);
-
- /*
- * Some SPI eeproms use the 8th address bit embedded in the
- * opcode
- */
- if ((nvm->address_bits == 8) && (offset >= 128))
- write_opcode |= NVM_A8_OPCODE_SPI;
-
- /* Send the Write command (8-bit opcode + addr) */
- e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
- e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
- nvm->address_bits);
-
- /* Loop to allow for up to whole page write of eeprom */
- while (widx < words) {
- u16 word_out = data[widx];
- word_out = (word_out >> 8) | (word_out << 8);
- e1000_shift_out_eec_bits(hw, word_out, 16);
- widx++;
-
- if ((((offset + widx) * 2) % nvm->page_size) == 0) {
- e1000_standby_nvm(hw);
- break;
- }
- }
- }
-
- usleep_range(10000, 20000);
- nvm->ops.release(hw);
- return 0;
-}
-
-/**
- * e1000_read_pba_string_generic - Read device part number
- * @hw: pointer to the HW structure
- * @pba_num: pointer to device part number
- * @pba_num_size: size of part number buffer
- *
- * Reads the product board assembly (PBA) number from the EEPROM and stores
- * the value in pba_num.
- **/
-s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
- u32 pba_num_size)
-{
- s32 ret_val;
- u16 nvm_data;
- u16 pba_ptr;
- u16 offset;
- u16 length;
-
- if (pba_num == NULL) {
- e_dbg("PBA string buffer was null\n");
- ret_val = E1000_ERR_INVALID_ARGUMENT;
- goto out;
- }
-
- ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
- if (ret_val) {
- e_dbg("NVM Read Error\n");
- goto out;
- }
-
- ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
- if (ret_val) {
- e_dbg("NVM Read Error\n");
- goto out;
- }
-
- /*
- * if nvm_data is not ptr guard the PBA must be in legacy format which
- * means pba_ptr is actually our second data word for the PBA number
- * and we can decode it into an ascii string
- */
- if (nvm_data != NVM_PBA_PTR_GUARD) {
- e_dbg("NVM PBA number is not stored as string\n");
-
- /* we will need 11 characters to store the PBA */
- if (pba_num_size < 11) {
- e_dbg("PBA string buffer too small\n");
- return E1000_ERR_NO_SPACE;
- }
-
- /* extract hex string from data and pba_ptr */
- pba_num[0] = (nvm_data >> 12) & 0xF;
- pba_num[1] = (nvm_data >> 8) & 0xF;
- pba_num[2] = (nvm_data >> 4) & 0xF;
- pba_num[3] = nvm_data & 0xF;
- pba_num[4] = (pba_ptr >> 12) & 0xF;
- pba_num[5] = (pba_ptr >> 8) & 0xF;
- pba_num[6] = '-';
- pba_num[7] = 0;
- pba_num[8] = (pba_ptr >> 4) & 0xF;
- pba_num[9] = pba_ptr & 0xF;
-
- /* put a null character on the end of our string */
- pba_num[10] = '\0';
-
- /* switch all the data but the '-' to hex char */
- for (offset = 0; offset < 10; offset++) {
- if (pba_num[offset] < 0xA)
- pba_num[offset] += '0';
- else if (pba_num[offset] < 0x10)
- pba_num[offset] += 'A' - 0xA;
- }
-
- goto out;
- }
-
- ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length);
- if (ret_val) {
- e_dbg("NVM Read Error\n");
- goto out;
- }
-
- if (length == 0xFFFF || length == 0) {
- e_dbg("NVM PBA number section invalid length\n");
- ret_val = E1000_ERR_NVM_PBA_SECTION;
- goto out;
- }
- /* check if pba_num buffer is big enough */
- if (pba_num_size < (((u32)length * 2) - 1)) {
- e_dbg("PBA string buffer too small\n");
- ret_val = E1000_ERR_NO_SPACE;
- goto out;
- }
-
- /* trim pba length from start of string */
- pba_ptr++;
- length--;
-
- for (offset = 0; offset < length; offset++) {
- ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data);
- if (ret_val) {
- e_dbg("NVM Read Error\n");
- goto out;
- }
- pba_num[offset * 2] = (u8)(nvm_data >> 8);
- pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
- }
- pba_num[offset * 2] = '\0';
-
-out:
- return ret_val;
-}
-
-/**
- * e1000_read_mac_addr_generic - Read device MAC address
- * @hw: pointer to the HW structure
- *
- * Reads the device MAC address from the EEPROM and stores the value.
- * Since devices with two ports use the same EEPROM, we increment the
- * last bit in the MAC address for the second port.
- **/
-s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
-{
- u32 rar_high;
- u32 rar_low;
- u16 i;
-
- rar_high = er32(RAH(0));
- rar_low = er32(RAL(0));
-
- for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
- hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
-
- for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
- hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
-
- for (i = 0; i < ETH_ALEN; i++)
- hw->mac.addr[i] = hw->mac.perm_addr[i];
-
- return 0;
-}
-
-/**
- * e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum
- * @hw: pointer to the HW structure
- *
- * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
- * and then verifies that the sum of the EEPROM is equal to 0xBABA.
- **/
-s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw)
-{
- s32 ret_val;
- u16 checksum = 0;
- u16 i, nvm_data;
-
- for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
- ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
- if (ret_val) {
- e_dbg("NVM Read Error\n");
- return ret_val;
- }
- checksum += nvm_data;
- }
-
- if (checksum != (u16) NVM_SUM) {
- e_dbg("NVM Checksum Invalid\n");
- return -E1000_ERR_NVM;
- }
-
- return 0;
-}
-
-/**
- * e1000e_update_nvm_checksum_generic - Update EEPROM checksum
- * @hw: pointer to the HW structure
- *
- * Updates the EEPROM checksum by reading/adding each word of the EEPROM
- * up to the checksum. Then calculates the EEPROM checksum and writes the
- * value to the EEPROM.
- **/
-s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw)
-{
- s32 ret_val;
- u16 checksum = 0;
- u16 i, nvm_data;
-
- for (i = 0; i < NVM_CHECKSUM_REG; i++) {
- ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
- if (ret_val) {
- e_dbg("NVM Read Error while updating checksum.\n");
- return ret_val;
- }
- checksum += nvm_data;
- }
- checksum = (u16) NVM_SUM - checksum;
- ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum);
- if (ret_val)
- e_dbg("NVM Write Error while updating checksum.\n");
-
- return ret_val;
-}
-
-/**
- * e1000e_reload_nvm - Reloads EEPROM
- * @hw: pointer to the HW structure
- *
- * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
- * extended control register.
- **/
-void e1000e_reload_nvm(struct e1000_hw *hw)
-{
- u32 ctrl_ext;
-
- udelay(10);
- ctrl_ext = er32(CTRL_EXT);
- ctrl_ext |= E1000_CTRL_EXT_EE_RST;
- ew32(CTRL_EXT, ctrl_ext);
- e1e_flush();
-}
-
-/**
- * e1000_calculate_checksum - Calculate checksum for buffer
- * @buffer: pointer to EEPROM
- * @length: size of EEPROM to calculate a checksum for
- *
- * Calculates the checksum for some buffer on a specified length. The
- * checksum calculated is returned.
- **/
-static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
-{
- u32 i;
- u8 sum = 0;
-
- if (!buffer)
- return 0;
-
- for (i = 0; i < length; i++)
- sum += buffer[i];
-
- return (u8) (0 - sum);
-}
-
-/**
- * e1000_mng_enable_host_if - Checks host interface is enabled
- * @hw: pointer to the HW structure
- *
- * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
- *
- * This function checks whether the HOST IF is enabled for command operation
- * and also checks whether the previous command is completed. It busy waits
- * in case of previous command is not completed.
- **/
-static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
-{
- u32 hicr;
- u8 i;
-
- if (!(hw->mac.arc_subsystem_valid)) {
- e_dbg("ARC subsystem not valid.\n");
- return -E1000_ERR_HOST_INTERFACE_COMMAND;
- }
-
- /* Check that the host interface is enabled. */
- hicr = er32(HICR);
- if ((hicr & E1000_HICR_EN) == 0) {
- e_dbg("E1000_HOST_EN bit disabled.\n");
- return -E1000_ERR_HOST_INTERFACE_COMMAND;
- }
- /* check the previous command is completed */
- for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
- hicr = er32(HICR);
- if (!(hicr & E1000_HICR_C))
- break;
- mdelay(1);
- }
-
- if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
- e_dbg("Previous command timeout failed .\n");
- return -E1000_ERR_HOST_INTERFACE_COMMAND;
- }
-
- return 0;
-}
-
-/**
- * e1000e_check_mng_mode_generic - check management mode
- * @hw: pointer to the HW structure
- *
- * Reads the firmware semaphore register and returns true (>0) if
- * manageability is enabled, else false (0).
- **/
-bool e1000e_check_mng_mode_generic(struct e1000_hw *hw)
-{
- u32 fwsm = er32(FWSM);
-
- return (fwsm & E1000_FWSM_MODE_MASK) ==
- (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
-}
-
-/**
- * e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx
- * @hw: pointer to the HW structure
- *
- * Enables packet filtering on transmit packets if manageability is enabled
- * and host interface is enabled.
- **/
-bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
-{
- struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
- u32 *buffer = (u32 *)&hw->mng_cookie;
- u32 offset;
- s32 ret_val, hdr_csum, csum;
- u8 i, len;
-
- hw->mac.tx_pkt_filtering = true;
-
- /* No manageability, no filtering */
- if (!e1000e_check_mng_mode(hw)) {
- hw->mac.tx_pkt_filtering = false;
- goto out;
- }
-
- /*
- * If we can't read from the host interface for whatever
- * reason, disable filtering.
- */
- ret_val = e1000_mng_enable_host_if(hw);
- if (ret_val) {
- hw->mac.tx_pkt_filtering = false;
- goto out;
- }
-
- /* Read in the header. Length and offset are in dwords. */
- len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
- offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
- for (i = 0; i < len; i++)
- *(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset + i);
- hdr_csum = hdr->checksum;
- hdr->checksum = 0;
- csum = e1000_calculate_checksum((u8 *)hdr,
- E1000_MNG_DHCP_COOKIE_LENGTH);
- /*
- * If either the checksums or signature don't match, then
- * the cookie area isn't considered valid, in which case we
- * take the safe route of assuming Tx filtering is enabled.
- */
- if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
- hw->mac.tx_pkt_filtering = true;
- goto out;
- }
-
- /* Cookie area is valid, make the final check for filtering. */
- if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) {
- hw->mac.tx_pkt_filtering = false;
- goto out;
- }
-
-out:
- return hw->mac.tx_pkt_filtering;
-}
-
-/**
- * e1000_mng_write_cmd_header - Writes manageability command header
- * @hw: pointer to the HW structure
- * @hdr: pointer to the host interface command header
- *
- * Writes the command header after does the checksum calculation.
- **/
-static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
- struct e1000_host_mng_command_header *hdr)
-{
- u16 i, length = sizeof(struct e1000_host_mng_command_header);
-
- /* Write the whole command header structure with new checksum. */
-
- hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
-
- length >>= 2;
- /* Write the relevant command block into the ram area. */
- for (i = 0; i < length; i++) {
- E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i,
- *((u32 *) hdr + i));
- e1e_flush();
- }
-
- return 0;
-}
-
-/**
- * e1000_mng_host_if_write - Write to the manageability host interface
- * @hw: pointer to the HW structure
- * @buffer: pointer to the host interface buffer
- * @length: size of the buffer
- * @offset: location in the buffer to write to
- * @sum: sum of the data (not checksum)
- *
- * This function writes the buffer content at the offset given on the host if.
- * It also does alignment considerations to do the writes in most efficient
- * way. Also fills up the sum of the buffer in *buffer parameter.
- **/
-static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer,
- u16 length, u16 offset, u8 *sum)
-{
- u8 *tmp;
- u8 *bufptr = buffer;
- u32 data = 0;
- u16 remaining, i, j, prev_bytes;
-
- /* sum = only sum of the data and it is not checksum */
-
- if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
- return -E1000_ERR_PARAM;
-
- tmp = (u8 *)&data;
- prev_bytes = offset & 0x3;
- offset >>= 2;
-
- if (prev_bytes) {
- data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset);
- for (j = prev_bytes; j < sizeof(u32); j++) {
- *(tmp + j) = *bufptr++;
- *sum += *(tmp + j);
- }
- E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data);
- length -= j - prev_bytes;
- offset++;
- }
-
- remaining = length & 0x3;
- length -= remaining;
-
- /* Calculate length in DWORDs */
- length >>= 2;
-
- /*
- * The device driver writes the relevant command block into the
- * ram area.
- */
- for (i = 0; i < length; i++) {
- for (j = 0; j < sizeof(u32); j++) {
- *(tmp + j) = *bufptr++;
- *sum += *(tmp + j);
- }
-
- E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
- }
- if (remaining) {
- for (j = 0; j < sizeof(u32); j++) {
- if (j < remaining)
- *(tmp + j) = *bufptr++;
- else
- *(tmp + j) = 0;
-
- *sum += *(tmp + j);
- }
- E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
- }
-
- return 0;
-}
-
-/**
- * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface
- * @hw: pointer to the HW structure
- * @buffer: pointer to the host interface
- * @length: size of the buffer
- *
- * Writes the DHCP information to the host interface.
- **/
-s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
-{
- struct e1000_host_mng_command_header hdr;
- s32 ret_val;
- u32 hicr;
-
- hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
- hdr.command_length = length;
- hdr.reserved1 = 0;
- hdr.reserved2 = 0;
- hdr.checksum = 0;
-
- /* Enable the host interface */
- ret_val = e1000_mng_enable_host_if(hw);
- if (ret_val)
- return ret_val;
-
- /* Populate the host interface with the contents of "buffer". */
- ret_val = e1000_mng_host_if_write(hw, buffer, length,
- sizeof(hdr), &(hdr.checksum));
- if (ret_val)
- return ret_val;
-
- /* Write the manageability command header */
- ret_val = e1000_mng_write_cmd_header(hw, &hdr);
- if (ret_val)
- return ret_val;
-
- /* Tell the ARC a new command is pending. */
- hicr = er32(HICR);
- ew32(HICR, hicr | E1000_HICR_C);
-
- return 0;
-}
-
-/**
- * e1000e_enable_mng_pass_thru - Check if management passthrough is needed
- * @hw: pointer to the HW structure
- *
- * Verifies the hardware needs to leave interface enabled so that frames can
- * be directed to and from the management interface.
- **/
-bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
-{
- u32 manc;
- u32 fwsm, factps;
- bool ret_val = false;
-
- manc = er32(MANC);
-
- if (!(manc & E1000_MANC_RCV_TCO_EN))
- goto out;
-
- if (hw->mac.has_fwsm) {
- fwsm = er32(FWSM);
- factps = er32(FACTPS);
-
- if (!(factps & E1000_FACTPS_MNGCG) &&
- ((fwsm & E1000_FWSM_MODE_MASK) ==
- (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
- ret_val = true;
- goto out;
- }
- } else if ((hw->mac.type == e1000_82574) ||
- (hw->mac.type == e1000_82583)) {
- u16 data;
-
- factps = er32(FACTPS);
- e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
-
- if (!(factps & E1000_FACTPS_MNGCG) &&
- ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
- (e1000_mng_mode_pt << 13))) {
- ret_val = true;
- goto out;
- }
- } else if ((manc & E1000_MANC_SMBUS_EN) &&
- !(manc & E1000_MANC_ASF_EN)) {
- ret_val = true;
- goto out;
- }
-
-out:
- return ret_val;
}
diff --git a/drivers/net/ethernet/intel/e1000e/manage.c b/drivers/net/ethernet/intel/e1000e/manage.c
new file mode 100644
index 000000000000..473f8e711510
--- /dev/null
+++ b/drivers/net/ethernet/intel/e1000e/manage.c
@@ -0,0 +1,367 @@
+/*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+ Copyright(c) 1999 - 2012 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include "e1000.h"
+
+enum e1000_mng_mode {
+ e1000_mng_mode_none = 0,
+ e1000_mng_mode_asf,
+ e1000_mng_mode_pt,
+ e1000_mng_mode_ipmi,
+ e1000_mng_mode_host_if_only
+};
+
+#define E1000_FACTPS_MNGCG 0x20000000
+
+/* Intel(R) Active Management Technology signature */
+#define E1000_IAMT_SIGNATURE 0x544D4149
+
+/**
+ * e1000_calculate_checksum - Calculate checksum for buffer
+ * @buffer: pointer to EEPROM
+ * @length: size of EEPROM to calculate a checksum for
+ *
+ * Calculates the checksum for some buffer on a specified length. The
+ * checksum calculated is returned.
+ **/
+static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
+{
+ u32 i;
+ u8 sum = 0;
+
+ if (!buffer)
+ return 0;
+
+ for (i = 0; i < length; i++)
+ sum += buffer[i];
+
+ return (u8)(0 - sum);
+}
+
+/**
+ * e1000_mng_enable_host_if - Checks host interface is enabled
+ * @hw: pointer to the HW structure
+ *
+ * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
+ *
+ * This function checks whether the HOST IF is enabled for command operation
+ * and also checks whether the previous command is completed. It busy waits
+ * in case of previous command is not completed.
+ **/
+static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
+{
+ u32 hicr;
+ u8 i;
+
+ if (!hw->mac.arc_subsystem_valid) {
+ e_dbg("ARC subsystem not valid.\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+
+ /* Check that the host interface is enabled. */
+ hicr = er32(HICR);
+ if ((hicr & E1000_HICR_EN) == 0) {
+ e_dbg("E1000_HOST_EN bit disabled.\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+ /* check the previous command is completed */
+ for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
+ hicr = er32(HICR);
+ if (!(hicr & E1000_HICR_C))
+ break;
+ mdelay(1);
+ }
+
+ if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
+ e_dbg("Previous command timeout failed .\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+
+ return 0;
+}
+
+/**
+ * e1000e_check_mng_mode_generic - Generic check management mode
+ * @hw: pointer to the HW structure
+ *
+ * Reads the firmware semaphore register and returns true (>0) if
+ * manageability is enabled, else false (0).
+ **/
+bool e1000e_check_mng_mode_generic(struct e1000_hw *hw)
+{
+ u32 fwsm = er32(FWSM);
+
+ return (fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
+}
+
+/**
+ * e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx
+ * @hw: pointer to the HW structure
+ *
+ * Enables packet filtering on transmit packets if manageability is enabled
+ * and host interface is enabled.
+ **/
+bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
+{
+ struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
+ u32 *buffer = (u32 *)&hw->mng_cookie;
+ u32 offset;
+ s32 ret_val, hdr_csum, csum;
+ u8 i, len;
+
+ hw->mac.tx_pkt_filtering = true;
+
+ /* No manageability, no filtering */
+ if (!hw->mac.ops.check_mng_mode(hw)) {
+ hw->mac.tx_pkt_filtering = false;
+ return hw->mac.tx_pkt_filtering;
+ }
+
+ /*
+ * If we can't read from the host interface for whatever
+ * reason, disable filtering.
+ */
+ ret_val = e1000_mng_enable_host_if(hw);
+ if (ret_val) {
+ hw->mac.tx_pkt_filtering = false;
+ return hw->mac.tx_pkt_filtering;
+ }
+
+ /* Read in the header. Length and offset are in dwords. */
+ len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
+ offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
+ for (i = 0; i < len; i++)
+ *(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF,
+ offset + i);
+ hdr_csum = hdr->checksum;
+ hdr->checksum = 0;
+ csum = e1000_calculate_checksum((u8 *)hdr,
+ E1000_MNG_DHCP_COOKIE_LENGTH);
+ /*
+ * If either the checksums or signature don't match, then
+ * the cookie area isn't considered valid, in which case we
+ * take the safe route of assuming Tx filtering is enabled.
+ */
+ if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
+ hw->mac.tx_pkt_filtering = true;
+ return hw->mac.tx_pkt_filtering;
+ }
+
+ /* Cookie area is valid, make the final check for filtering. */
+ if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
+ hw->mac.tx_pkt_filtering = false;
+
+ return hw->mac.tx_pkt_filtering;
+}
+
+/**
+ * e1000_mng_write_cmd_header - Writes manageability command header
+ * @hw: pointer to the HW structure
+ * @hdr: pointer to the host interface command header
+ *
+ * Writes the command header after does the checksum calculation.
+ **/
+static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
+ struct e1000_host_mng_command_header *hdr)
+{
+ u16 i, length = sizeof(struct e1000_host_mng_command_header);
+
+ /* Write the whole command header structure with new checksum. */
+
+ hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
+
+ length >>= 2;
+ /* Write the relevant command block into the ram area. */
+ for (i = 0; i < length; i++) {
+ E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i, *((u32 *)hdr + i));
+ e1e_flush();
+ }
+
+ return 0;
+}
+
+/**
+ * e1000_mng_host_if_write - Write to the manageability host interface
+ * @hw: pointer to the HW structure
+ * @buffer: pointer to the host interface buffer
+ * @length: size of the buffer
+ * @offset: location in the buffer to write to
+ * @sum: sum of the data (not checksum)
+ *
+ * This function writes the buffer content at the offset given on the host if.
+ * It also does alignment considerations to do the writes in most efficient
+ * way. Also fills up the sum of the buffer in *buffer parameter.
+ **/
+static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer,
+ u16 length, u16 offset, u8 *sum)
+{
+ u8 *tmp;
+ u8 *bufptr = buffer;
+ u32 data = 0;
+ u16 remaining, i, j, prev_bytes;
+
+ /* sum = only sum of the data and it is not checksum */
+
+ if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
+ return -E1000_ERR_PARAM;
+
+ tmp = (u8 *)&data;
+ prev_bytes = offset & 0x3;
+ offset >>= 2;
+
+ if (prev_bytes) {
+ data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset);
+ for (j = prev_bytes; j < sizeof(u32); j++) {
+ *(tmp + j) = *bufptr++;
+ *sum += *(tmp + j);
+ }
+ E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data);
+ length -= j - prev_bytes;
+ offset++;
+ }
+
+ remaining = length & 0x3;
+ length -= remaining;
+
+ /* Calculate length in DWORDs */
+ length >>= 2;
+
+ /*
+ * The device driver writes the relevant command block into the
+ * ram area.
+ */
+ for (i = 0; i < length; i++) {
+ for (j = 0; j < sizeof(u32); j++) {
+ *(tmp + j) = *bufptr++;
+ *sum += *(tmp + j);
+ }
+
+ E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
+ }
+ if (remaining) {
+ for (j = 0; j < sizeof(u32); j++) {
+ if (j < remaining)
+ *(tmp + j) = *bufptr++;
+ else
+ *(tmp + j) = 0;
+
+ *sum += *(tmp + j);
+ }
+ E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
+ }
+
+ return 0;
+}
+
+/**
+ * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface
+ * @hw: pointer to the HW structure
+ * @buffer: pointer to the host interface
+ * @length: size of the buffer
+ *
+ * Writes the DHCP information to the host interface.
+ **/
+s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
+{
+ struct e1000_host_mng_command_header hdr;
+ s32 ret_val;
+ u32 hicr;
+
+ hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
+ hdr.command_length = length;
+ hdr.reserved1 = 0;
+ hdr.reserved2 = 0;
+ hdr.checksum = 0;
+
+ /* Enable the host interface */
+ ret_val = e1000_mng_enable_host_if(hw);
+ if (ret_val)
+ return ret_val;
+
+ /* Populate the host interface with the contents of "buffer". */
+ ret_val = e1000_mng_host_if_write(hw, buffer, length,
+ sizeof(hdr), &(hdr.checksum));
+ if (ret_val)
+ return ret_val;
+
+ /* Write the manageability command header */
+ ret_val = e1000_mng_write_cmd_header(hw, &hdr);
+ if (ret_val)
+ return ret_val;
+
+ /* Tell the ARC a new command is pending. */
+ hicr = er32(HICR);
+ ew32(HICR, hicr | E1000_HICR_C);
+
+ return 0;
+}
+
+/**
+ * e1000e_enable_mng_pass_thru - Check if management passthrough is needed
+ * @hw: pointer to the HW structure
+ *
+ * Verifies the hardware needs to leave interface enabled so that frames can
+ * be directed to and from the management interface.
+ **/
+bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
+{
+ u32 manc;
+ u32 fwsm, factps;
+
+ manc = er32(MANC);
+
+ if (!(manc & E1000_MANC_RCV_TCO_EN))
+ return false;
+
+ if (hw->mac.has_fwsm) {
+ fwsm = er32(FWSM);
+ factps = er32(FACTPS);
+
+ if (!(factps & E1000_FACTPS_MNGCG) &&
+ ((fwsm & E1000_FWSM_MODE_MASK) ==
+ (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)))
+ return true;
+ } else if ((hw->mac.type == e1000_82574) ||
+ (hw->mac.type == e1000_82583)) {
+ u16 data;
+
+ factps = er32(FACTPS);
+ e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+
+ if (!(factps & E1000_FACTPS_MNGCG) &&
+ ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
+ (e1000_mng_mode_pt << 13)))
+ return true;
+ } else if ((manc & E1000_MANC_SMBUS_EN) &&
+ !(manc & E1000_MANC_ASF_EN)) {
+ return true;
+ }
+
+ return false;
+}
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 3911401ed65d..8b62870e2c25 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -56,7 +56,7 @@
#define DRV_EXTRAVERSION "-k"
-#define DRV_VERSION "1.5.1" DRV_EXTRAVERSION
+#define DRV_VERSION "1.9.5" DRV_EXTRAVERSION
char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION;
@@ -137,7 +137,7 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = {
{E1000_TDFPC, "TDFPC"},
/* List Terminator */
- {}
+ {0, NULL}
};
/*
@@ -183,18 +183,18 @@ static void e1000e_dump(struct e1000_adapter *adapter)
struct e1000_ring *tx_ring = adapter->tx_ring;
struct e1000_tx_desc *tx_desc;
struct my_u0 {
- u64 a;
- u64 b;
+ __le64 a;
+ __le64 b;
} *u0;
struct e1000_buffer *buffer_info;
struct e1000_ring *rx_ring = adapter->rx_ring;
union e1000_rx_desc_packet_split *rx_desc_ps;
union e1000_rx_desc_extended *rx_desc;
struct my_u1 {
- u64 a;
- u64 b;
- u64 c;
- u64 d;
+ __le64 a;
+ __le64 b;
+ __le64 c;
+ __le64 d;
} *u1;
u32 staterr;
int i = 0;
@@ -221,7 +221,7 @@ static void e1000e_dump(struct e1000_adapter *adapter)
/* Print Tx Ring Summary */
if (!netdev || !netif_running(netdev))
- goto exit;
+ return;
dev_info(&adapter->pdev->dev, "Tx Ring Summary\n");
pr_info("Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n");
@@ -308,7 +308,7 @@ rx_ring_summary:
/* Print Rx Ring */
if (!netif_msg_rx_status(adapter))
- goto exit;
+ return;
dev_info(&adapter->pdev->dev, "Rx Ring Dump\n");
switch (adapter->rx_ps_pages) {
@@ -449,9 +449,6 @@ rx_ring_summary:
}
}
}
-
-exit:
- return;
}
/**
@@ -487,22 +484,27 @@ static void e1000_receive_skb(struct e1000_adapter *adapter,
/**
* e1000_rx_checksum - Receive Checksum Offload
- * @adapter: board private structure
- * @status_err: receive descriptor status and error fields
- * @csum: receive descriptor csum field
- * @sk_buff: socket buffer with received data
+ * @adapter: board private structure
+ * @status_err: receive descriptor status and error fields
+ * @csum: receive descriptor csum field
+ * @sk_buff: socket buffer with received data
**/
static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
- u32 csum, struct sk_buff *skb)
+ __le16 csum, struct sk_buff *skb)
{
u16 status = (u16)status_err;
u8 errors = (u8)(status_err >> 24);
skb_checksum_none_assert(skb);
+ /* Rx checksum disabled */
+ if (!(adapter->netdev->features & NETIF_F_RXCSUM))
+ return;
+
/* Ignore Checksum bit is set */
if (status & E1000_RXD_STAT_IXSM)
return;
+
/* TCP/UDP checksum error bit is set */
if (errors & E1000_RXD_ERR_TCPE) {
/* let the stack verify checksum errors */
@@ -524,7 +526,7 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
* Hardware complements the payload checksum, so we undo it
* and then put the value in host order for further stack use.
*/
- __sum16 sum = (__force __sum16)htons(csum);
+ __sum16 sum = (__force __sum16)swab16((__force u16)csum);
skb->csum = csum_unfold(~sum);
skb->ip_summed = CHECKSUM_COMPLETE;
}
@@ -545,7 +547,7 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
* which has bit 24 set while ME is accessing Host CSR registers, wait
* if it is set and try again a number of times.
**/
-static inline s32 e1000e_update_tail_wa(struct e1000_hw *hw, u8 __iomem * tail,
+static inline s32 e1000e_update_tail_wa(struct e1000_hw *hw, void __iomem *tail,
unsigned int i)
{
unsigned int j = 0;
@@ -562,12 +564,12 @@ static inline s32 e1000e_update_tail_wa(struct e1000_hw *hw, u8 __iomem * tail,
return 0;
}
-static void e1000e_update_rdt_wa(struct e1000_adapter *adapter, unsigned int i)
+static void e1000e_update_rdt_wa(struct e1000_ring *rx_ring, unsigned int i)
{
- u8 __iomem *tail = (adapter->hw.hw_addr + adapter->rx_ring->tail);
+ struct e1000_adapter *adapter = rx_ring->adapter;
struct e1000_hw *hw = &adapter->hw;
- if (e1000e_update_tail_wa(hw, tail, i)) {
+ if (e1000e_update_tail_wa(hw, rx_ring->tail, i)) {
u32 rctl = er32(RCTL);
ew32(RCTL, rctl & ~E1000_RCTL_EN);
e_err("ME firmware caused invalid RDT - resetting\n");
@@ -575,12 +577,12 @@ static void e1000e_update_rdt_wa(struct e1000_adapter *adapter, unsigned int i)
}
}
-static void e1000e_update_tdt_wa(struct e1000_adapter *adapter, unsigned int i)
+static void e1000e_update_tdt_wa(struct e1000_ring *tx_ring, unsigned int i)
{
- u8 __iomem *tail = (adapter->hw.hw_addr + adapter->tx_ring->tail);
+ struct e1000_adapter *adapter = tx_ring->adapter;
struct e1000_hw *hw = &adapter->hw;
- if (e1000e_update_tail_wa(hw, tail, i)) {
+ if (e1000e_update_tail_wa(hw, tx_ring->tail, i)) {
u32 tctl = er32(TCTL);
ew32(TCTL, tctl & ~E1000_TCTL_EN);
e_err("ME firmware caused invalid TDT - resetting\n");
@@ -590,14 +592,14 @@ static void e1000e_update_tdt_wa(struct e1000_adapter *adapter, unsigned int i)
/**
* e1000_alloc_rx_buffers - Replace used receive buffers
- * @adapter: address of board private structure
+ * @rx_ring: Rx descriptor ring
**/
-static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+static void e1000_alloc_rx_buffers(struct e1000_ring *rx_ring,
int cleaned_count, gfp_t gfp)
{
+ struct e1000_adapter *adapter = rx_ring->adapter;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_ring *rx_ring = adapter->rx_ring;
union e1000_rx_desc_extended *rx_desc;
struct e1000_buffer *buffer_info;
struct sk_buff *skb;
@@ -644,9 +646,9 @@ map_skb:
*/
wmb();
if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
- e1000e_update_rdt_wa(adapter, i);
+ e1000e_update_rdt_wa(rx_ring, i);
else
- writel(i, adapter->hw.hw_addr + rx_ring->tail);
+ writel(i, rx_ring->tail);
}
i++;
if (i == rx_ring->count)
@@ -659,15 +661,15 @@ map_skb:
/**
* e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split
- * @adapter: address of board private structure
+ * @rx_ring: Rx descriptor ring
**/
-static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring,
int cleaned_count, gfp_t gfp)
{
+ struct e1000_adapter *adapter = rx_ring->adapter;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union e1000_rx_desc_packet_split *rx_desc;
- struct e1000_ring *rx_ring = adapter->rx_ring;
struct e1000_buffer *buffer_info;
struct e1000_ps_page *ps_page;
struct sk_buff *skb;
@@ -747,10 +749,9 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
*/
wmb();
if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
- e1000e_update_rdt_wa(adapter, i << 1);
+ e1000e_update_rdt_wa(rx_ring, i << 1);
else
- writel(i << 1,
- adapter->hw.hw_addr + rx_ring->tail);
+ writel(i << 1, rx_ring->tail);
}
i++;
@@ -765,17 +766,17 @@ no_buffers:
/**
* e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers
- * @adapter: address of board private structure
+ * @rx_ring: Rx descriptor ring
* @cleaned_count: number of buffers to allocate this pass
**/
-static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
+static void e1000_alloc_jumbo_rx_buffers(struct e1000_ring *rx_ring,
int cleaned_count, gfp_t gfp)
{
+ struct e1000_adapter *adapter = rx_ring->adapter;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union e1000_rx_desc_extended *rx_desc;
- struct e1000_ring *rx_ring = adapter->rx_ring;
struct e1000_buffer *buffer_info;
struct sk_buff *skb;
unsigned int i;
@@ -834,26 +835,33 @@ check_page:
* such as IA-64). */
wmb();
if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
- e1000e_update_rdt_wa(adapter, i);
+ e1000e_update_rdt_wa(rx_ring, i);
else
- writel(i, adapter->hw.hw_addr + rx_ring->tail);
+ writel(i, rx_ring->tail);
}
}
+static inline void e1000_rx_hash(struct net_device *netdev, __le32 rss,
+ struct sk_buff *skb)
+{
+ if (netdev->features & NETIF_F_RXHASH)
+ skb->rxhash = le32_to_cpu(rss);
+}
+
/**
- * e1000_clean_rx_irq - Send received data up the network stack; legacy
- * @adapter: board private structure
+ * e1000_clean_rx_irq - Send received data up the network stack
+ * @rx_ring: Rx descriptor ring
*
* the return value indicates whether actual cleaning was done, there
* is no guarantee that everything was cleaned
**/
-static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
- int *work_done, int work_to_do)
+static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
+ int work_to_do)
{
+ struct e1000_adapter *adapter = rx_ring->adapter;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_hw *hw = &adapter->hw;
- struct e1000_ring *rx_ring = adapter->rx_ring;
union e1000_rx_desc_extended *rx_desc, *next_rxd;
struct e1000_buffer *buffer_info, *next_buffer;
u32 length, staterr;
@@ -918,15 +926,24 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
goto next_desc;
}
- if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
+ if (unlikely((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) &&
+ !(netdev->features & NETIF_F_RXALL))) {
/* recycle */
buffer_info->skb = skb;
goto next_desc;
}
/* adjust length to remove Ethernet CRC */
- if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
- length -= 4;
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) {
+ /* If configured to store CRC, don't subtract FCS,
+ * but keep the FCS bytes out of the total_rx_bytes
+ * counter
+ */
+ if (netdev->features & NETIF_F_RXFCS)
+ total_rx_bytes -= 4;
+ else
+ length -= 4;
+ }
total_rx_bytes += length;
total_rx_packets++;
@@ -957,8 +974,9 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
/* Receive Checksum Offload */
e1000_rx_checksum(adapter, staterr,
- le16_to_cpu(rx_desc->wb.lower.hi_dword.
- csum_ip.csum), skb);
+ rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
+
+ e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb);
e1000_receive_skb(adapter, netdev, skb, staterr,
rx_desc->wb.upper.vlan);
@@ -968,7 +986,7 @@ next_desc:
/* return some buffers to hardware, one at a time is too slow */
if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
- adapter->alloc_rx_buf(adapter, cleaned_count,
+ adapter->alloc_rx_buf(rx_ring, cleaned_count,
GFP_ATOMIC);
cleaned_count = 0;
}
@@ -983,16 +1001,18 @@ next_desc:
cleaned_count = e1000_desc_unused(rx_ring);
if (cleaned_count)
- adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
+ adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC);
adapter->total_rx_bytes += total_rx_bytes;
adapter->total_rx_packets += total_rx_packets;
return cleaned;
}
-static void e1000_put_txbuf(struct e1000_adapter *adapter,
- struct e1000_buffer *buffer_info)
+static void e1000_put_txbuf(struct e1000_ring *tx_ring,
+ struct e1000_buffer *buffer_info)
{
+ struct e1000_adapter *adapter = tx_ring->adapter;
+
if (buffer_info->dma) {
if (buffer_info->mapped_as_page)
dma_unmap_page(&adapter->pdev->dev, buffer_info->dma,
@@ -1063,8 +1083,8 @@ static void e1000_print_hw_hang(struct work_struct *work)
"PHY 1000BASE-T Status <%x>\n"
"PHY Extended Status <%x>\n"
"PCI Status <%x>\n",
- readl(adapter->hw.hw_addr + tx_ring->head),
- readl(adapter->hw.hw_addr + tx_ring->tail),
+ readl(tx_ring->head),
+ readl(tx_ring->tail),
tx_ring->next_to_use,
tx_ring->next_to_clean,
tx_ring->buffer_info[eop].time_stamp,
@@ -1080,16 +1100,16 @@ static void e1000_print_hw_hang(struct work_struct *work)
/**
* e1000_clean_tx_irq - Reclaim resources after transmit completes
- * @adapter: board private structure
+ * @tx_ring: Tx descriptor ring
*
* the return value indicates whether actual cleaning was done, there
* is no guarantee that everything was cleaned
**/
-static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
+static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring)
{
+ struct e1000_adapter *adapter = tx_ring->adapter;
struct net_device *netdev = adapter->netdev;
struct e1000_hw *hw = &adapter->hw;
- struct e1000_ring *tx_ring = adapter->tx_ring;
struct e1000_tx_desc *tx_desc, *eop_desc;
struct e1000_buffer *buffer_info;
unsigned int i, eop;
@@ -1119,7 +1139,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
}
}
- e1000_put_txbuf(adapter, buffer_info);
+ e1000_put_txbuf(tx_ring, buffer_info);
tx_desc->upper.data = 0;
i++;
@@ -1173,19 +1193,19 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
/**
* e1000_clean_rx_irq_ps - Send received data up the network stack; packet split
- * @adapter: board private structure
+ * @rx_ring: Rx descriptor ring
*
* the return value indicates whether actual cleaning was done, there
* is no guarantee that everything was cleaned
**/
-static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- int *work_done, int work_to_do)
+static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
+ int work_to_do)
{
+ struct e1000_adapter *adapter = rx_ring->adapter;
struct e1000_hw *hw = &adapter->hw;
union e1000_rx_desc_packet_split *rx_desc, *next_rxd;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_ring *rx_ring = adapter->rx_ring;
struct e1000_buffer *buffer_info, *next_buffer;
struct e1000_ps_page *ps_page;
struct sk_buff *skb;
@@ -1236,7 +1256,8 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
goto next_desc;
}
- if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
+ if (unlikely((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) &&
+ !(netdev->features & NETIF_F_RXALL))) {
dev_kfree_skb_irq(skb);
goto next_desc;
}
@@ -1253,43 +1274,51 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
skb_put(skb, length);
{
- /*
- * this looks ugly, but it seems compiler issues make it
- * more efficient than reusing j
- */
- int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]);
-
- /*
- * page alloc/put takes too long and effects small packet
- * throughput, so unsplit small packets and save the alloc/put
- * only valid in softirq (napi) context to call kmap_*
- */
- if (l1 && (l1 <= copybreak) &&
- ((length + l1) <= adapter->rx_ps_bsize0)) {
- u8 *vaddr;
-
- ps_page = &buffer_info->ps_pages[0];
+ /*
+ * this looks ugly, but it seems compiler issues make
+ * it more efficient than reusing j
+ */
+ int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]);
/*
- * there is no documentation about how to call
- * kmap_atomic, so we can't hold the mapping
- * very long
+ * page alloc/put takes too long and effects small
+ * packet throughput, so unsplit small packets and
+ * save the alloc/put only valid in softirq (napi)
+ * context to call kmap_*
*/
- dma_sync_single_for_cpu(&pdev->dev, ps_page->dma,
- PAGE_SIZE, DMA_FROM_DEVICE);
- vaddr = kmap_atomic(ps_page->page, KM_SKB_DATA_SOFTIRQ);
- memcpy(skb_tail_pointer(skb), vaddr, l1);
- kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
- dma_sync_single_for_device(&pdev->dev, ps_page->dma,
- PAGE_SIZE, DMA_FROM_DEVICE);
-
- /* remove the CRC */
- if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
- l1 -= 4;
-
- skb_put(skb, l1);
- goto copydone;
- } /* if */
+ if (l1 && (l1 <= copybreak) &&
+ ((length + l1) <= adapter->rx_ps_bsize0)) {
+ u8 *vaddr;
+
+ ps_page = &buffer_info->ps_pages[0];
+
+ /*
+ * there is no documentation about how to call
+ * kmap_atomic, so we can't hold the mapping
+ * very long
+ */
+ dma_sync_single_for_cpu(&pdev->dev,
+ ps_page->dma,
+ PAGE_SIZE,
+ DMA_FROM_DEVICE);
+ vaddr = kmap_atomic(ps_page->page,
+ KM_SKB_DATA_SOFTIRQ);
+ memcpy(skb_tail_pointer(skb), vaddr, l1);
+ kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
+ dma_sync_single_for_device(&pdev->dev,
+ ps_page->dma,
+ PAGE_SIZE,
+ DMA_FROM_DEVICE);
+
+ /* remove the CRC */
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) {
+ if (!(netdev->features & NETIF_F_RXFCS))
+ l1 -= 4;
+ }
+
+ skb_put(skb, l1);
+ goto copydone;
+ } /* if */
}
for (j = 0; j < PS_PAGE_BUFFERS; j++) {
@@ -1311,15 +1340,19 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
/* strip the ethernet crc, problem is we're using pages now so
* this whole operation can get a little cpu intensive
*/
- if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
- pskb_trim(skb, skb->len - 4);
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) {
+ if (!(netdev->features & NETIF_F_RXFCS))
+ pskb_trim(skb, skb->len - 4);
+ }
copydone:
total_rx_bytes += skb->len;
total_rx_packets++;
- e1000_rx_checksum(adapter, staterr, le16_to_cpu(
- rx_desc->wb.lower.hi_dword.csum_ip.csum), skb);
+ e1000_rx_checksum(adapter, staterr,
+ rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
+
+ e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb);
if (rx_desc->wb.upper.header_status &
cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))
@@ -1334,7 +1367,7 @@ next_desc:
/* return some buffers to hardware, one at a time is too slow */
if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
- adapter->alloc_rx_buf(adapter, cleaned_count,
+ adapter->alloc_rx_buf(rx_ring, cleaned_count,
GFP_ATOMIC);
cleaned_count = 0;
}
@@ -1349,7 +1382,7 @@ next_desc:
cleaned_count = e1000_desc_unused(rx_ring);
if (cleaned_count)
- adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
+ adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC);
adapter->total_rx_bytes += total_rx_bytes;
adapter->total_rx_packets += total_rx_packets;
@@ -1375,13 +1408,12 @@ static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
* the return value indicates whether actual cleaning was done, there
* is no guarantee that everything was cleaned
**/
-
-static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
- int *work_done, int work_to_do)
+static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
+ int work_to_do)
{
+ struct e1000_adapter *adapter = rx_ring->adapter;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_ring *rx_ring = adapter->rx_ring;
union e1000_rx_desc_extended *rx_desc, *next_rxd;
struct e1000_buffer *buffer_info, *next_buffer;
u32 length, staterr;
@@ -1424,7 +1456,8 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
/* errors is only valid for DD + EOP descriptors */
if (unlikely((staterr & E1000_RXD_STAT_EOP) &&
- (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK))) {
+ ((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) &&
+ !(netdev->features & NETIF_F_RXALL)))) {
/* recycle both page and skb */
buffer_info->skb = skb;
/* an error means any chain goes out the window too */
@@ -1491,8 +1524,9 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
/* Receive Checksum Offload XXX recompute due to CRC strip? */
e1000_rx_checksum(adapter, staterr,
- le16_to_cpu(rx_desc->wb.lower.hi_dword.
- csum_ip.csum), skb);
+ rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
+
+ e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb);
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
@@ -1513,7 +1547,7 @@ next_desc:
/* return some buffers to hardware, one at a time is too slow */
if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
- adapter->alloc_rx_buf(adapter, cleaned_count,
+ adapter->alloc_rx_buf(rx_ring, cleaned_count,
GFP_ATOMIC);
cleaned_count = 0;
}
@@ -1528,7 +1562,7 @@ next_desc:
cleaned_count = e1000_desc_unused(rx_ring);
if (cleaned_count)
- adapter->alloc_rx_buf(adapter, cleaned_count, GFP_ATOMIC);
+ adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC);
adapter->total_rx_bytes += total_rx_bytes;
adapter->total_rx_packets += total_rx_packets;
@@ -1537,11 +1571,11 @@ next_desc:
/**
* e1000_clean_rx_ring - Free Rx Buffers per Queue
- * @adapter: board private structure
+ * @rx_ring: Rx descriptor ring
**/
-static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
+static void e1000_clean_rx_ring(struct e1000_ring *rx_ring)
{
- struct e1000_ring *rx_ring = adapter->rx_ring;
+ struct e1000_adapter *adapter = rx_ring->adapter;
struct e1000_buffer *buffer_info;
struct e1000_ps_page *ps_page;
struct pci_dev *pdev = adapter->pdev;
@@ -1601,8 +1635,8 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
rx_ring->next_to_use = 0;
adapter->flags2 &= ~FLAG2_IS_DISCARDING;
- writel(0, adapter->hw.hw_addr + rx_ring->head);
- writel(0, adapter->hw.hw_addr + rx_ring->tail);
+ writel(0, rx_ring->head);
+ writel(0, rx_ring->tail);
}
static void e1000e_downshift_workaround(struct work_struct *work)
@@ -1633,7 +1667,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
*/
if (icr & E1000_ICR_LSC) {
- hw->mac.get_link_status = 1;
+ hw->mac.get_link_status = true;
/*
* ICH8 workaround-- Call gig speed drop workaround on cable
* disconnect (LSC) before accessing any PHY registers
@@ -1699,7 +1733,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
*/
if (icr & E1000_ICR_LSC) {
- hw->mac.get_link_status = 1;
+ hw->mac.get_link_status = true;
/*
* ICH8 workaround-- Call gig speed drop workaround on cable
* disconnect (LSC) before accessing any PHY registers
@@ -1756,7 +1790,7 @@ static irqreturn_t e1000_msix_other(int irq, void *data)
if (icr & E1000_ICR_OTHER) {
if (!(icr & E1000_ICR_LSC))
goto no_link_interrupt;
- hw->mac.get_link_status = 1;
+ hw->mac.get_link_status = true;
/* guard against interrupt when we're going down */
if (!test_bit(__E1000_DOWN, &adapter->state))
mod_timer(&adapter->watchdog_timer, jiffies + 1);
@@ -1781,7 +1815,7 @@ static irqreturn_t e1000_intr_msix_tx(int irq, void *data)
adapter->total_tx_bytes = 0;
adapter->total_tx_packets = 0;
- if (!e1000_clean_tx_irq(adapter))
+ if (!e1000_clean_tx_irq(tx_ring))
/* Ring was not completely cleaned, so fire another interrupt */
ew32(ICS, tx_ring->ims_val);
@@ -1792,14 +1826,15 @@ static irqreturn_t e1000_intr_msix_rx(int irq, void *data)
{
struct net_device *netdev = data;
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_ring *rx_ring = adapter->rx_ring;
/* Write the ITR value calculated at the end of the
* previous interrupt.
*/
- if (adapter->rx_ring->set_itr) {
- writel(1000000000 / (adapter->rx_ring->itr_val * 256),
- adapter->hw.hw_addr + adapter->rx_ring->itr_register);
- adapter->rx_ring->set_itr = 0;
+ if (rx_ring->set_itr) {
+ writel(1000000000 / (rx_ring->itr_val * 256),
+ rx_ring->itr_register);
+ rx_ring->set_itr = 0;
}
if (napi_schedule_prep(&adapter->napi)) {
@@ -1839,9 +1874,9 @@ static void e1000_configure_msix(struct e1000_adapter *adapter)
adapter->eiac_mask |= rx_ring->ims_val;
if (rx_ring->itr_val)
writel(1000000000 / (rx_ring->itr_val * 256),
- hw->hw_addr + rx_ring->itr_register);
+ rx_ring->itr_register);
else
- writel(1, hw->hw_addr + rx_ring->itr_register);
+ writel(1, rx_ring->itr_register);
ivar = E1000_IVAR_INT_ALLOC_VALID | vector;
/* Configure Tx vector */
@@ -1849,9 +1884,9 @@ static void e1000_configure_msix(struct e1000_adapter *adapter)
vector++;
if (tx_ring->itr_val)
writel(1000000000 / (tx_ring->itr_val * 256),
- hw->hw_addr + tx_ring->itr_register);
+ tx_ring->itr_register);
else
- writel(1, hw->hw_addr + tx_ring->itr_register);
+ writel(1, tx_ring->itr_register);
adapter->eiac_mask |= tx_ring->ims_val;
ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 8);
@@ -1965,8 +2000,9 @@ static int e1000_request_msix(struct e1000_adapter *adapter)
e1000_intr_msix_rx, 0, adapter->rx_ring->name,
netdev);
if (err)
- goto out;
- adapter->rx_ring->itr_register = E1000_EITR_82574(vector);
+ return err;
+ adapter->rx_ring->itr_register = adapter->hw.hw_addr +
+ E1000_EITR_82574(vector);
adapter->rx_ring->itr_val = adapter->itr;
vector++;
@@ -1980,20 +2016,20 @@ static int e1000_request_msix(struct e1000_adapter *adapter)
e1000_intr_msix_tx, 0, adapter->tx_ring->name,
netdev);
if (err)
- goto out;
- adapter->tx_ring->itr_register = E1000_EITR_82574(vector);
+ return err;
+ adapter->tx_ring->itr_register = adapter->hw.hw_addr +
+ E1000_EITR_82574(vector);
adapter->tx_ring->itr_val = adapter->itr;
vector++;
err = request_irq(adapter->msix_entries[vector].vector,
e1000_msix_other, 0, netdev->name, netdev);
if (err)
- goto out;
+ return err;
e1000_configure_msix(adapter);
+
return 0;
-out:
- return err;
}
/**
@@ -2162,13 +2198,13 @@ static int e1000_alloc_ring_dma(struct e1000_adapter *adapter,
/**
* e1000e_setup_tx_resources - allocate Tx resources (Descriptors)
- * @adapter: board private structure
+ * @tx_ring: Tx descriptor ring
*
* Return 0 on success, negative on failure
**/
-int e1000e_setup_tx_resources(struct e1000_adapter *adapter)
+int e1000e_setup_tx_resources(struct e1000_ring *tx_ring)
{
- struct e1000_ring *tx_ring = adapter->tx_ring;
+ struct e1000_adapter *adapter = tx_ring->adapter;
int err = -ENOMEM, size;
size = sizeof(struct e1000_buffer) * tx_ring->count;
@@ -2196,13 +2232,13 @@ err:
/**
* e1000e_setup_rx_resources - allocate Rx resources (Descriptors)
- * @adapter: board private structure
+ * @rx_ring: Rx descriptor ring
*
* Returns 0 on success, negative on failure
**/
-int e1000e_setup_rx_resources(struct e1000_adapter *adapter)
+int e1000e_setup_rx_resources(struct e1000_ring *rx_ring)
{
- struct e1000_ring *rx_ring = adapter->rx_ring;
+ struct e1000_adapter *adapter = rx_ring->adapter;
struct e1000_buffer *buffer_info;
int i, size, desc_len, err = -ENOMEM;
@@ -2249,18 +2285,18 @@ err:
/**
* e1000_clean_tx_ring - Free Tx Buffers
- * @adapter: board private structure
+ * @tx_ring: Tx descriptor ring
**/
-static void e1000_clean_tx_ring(struct e1000_adapter *adapter)
+static void e1000_clean_tx_ring(struct e1000_ring *tx_ring)
{
- struct e1000_ring *tx_ring = adapter->tx_ring;
+ struct e1000_adapter *adapter = tx_ring->adapter;
struct e1000_buffer *buffer_info;
unsigned long size;
unsigned int i;
for (i = 0; i < tx_ring->count; i++) {
buffer_info = &tx_ring->buffer_info[i];
- e1000_put_txbuf(adapter, buffer_info);
+ e1000_put_txbuf(tx_ring, buffer_info);
}
netdev_reset_queue(adapter->netdev);
@@ -2272,22 +2308,22 @@ static void e1000_clean_tx_ring(struct e1000_adapter *adapter)
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
- writel(0, adapter->hw.hw_addr + tx_ring->head);
- writel(0, adapter->hw.hw_addr + tx_ring->tail);
+ writel(0, tx_ring->head);
+ writel(0, tx_ring->tail);
}
/**
* e1000e_free_tx_resources - Free Tx Resources per Queue
- * @adapter: board private structure
+ * @tx_ring: Tx descriptor ring
*
* Free all transmit software resources
**/
-void e1000e_free_tx_resources(struct e1000_adapter *adapter)
+void e1000e_free_tx_resources(struct e1000_ring *tx_ring)
{
+ struct e1000_adapter *adapter = tx_ring->adapter;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_ring *tx_ring = adapter->tx_ring;
- e1000_clean_tx_ring(adapter);
+ e1000_clean_tx_ring(tx_ring);
vfree(tx_ring->buffer_info);
tx_ring->buffer_info = NULL;
@@ -2299,18 +2335,17 @@ void e1000e_free_tx_resources(struct e1000_adapter *adapter)
/**
* e1000e_free_rx_resources - Free Rx Resources
- * @adapter: board private structure
+ * @rx_ring: Rx descriptor ring
*
* Free all receive software resources
**/
-
-void e1000e_free_rx_resources(struct e1000_adapter *adapter)
+void e1000e_free_rx_resources(struct e1000_ring *rx_ring)
{
+ struct e1000_adapter *adapter = rx_ring->adapter;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_ring *rx_ring = adapter->rx_ring;
int i;
- e1000_clean_rx_ring(adapter);
+ e1000_clean_rx_ring(rx_ring);
for (i = 0; i < rx_ring->count; i++)
kfree(rx_ring->buffer_info[i].ps_pages);
@@ -2346,7 +2381,7 @@ static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
unsigned int retval = itr_setting;
if (packets == 0)
- goto update_itr_done;
+ return itr_setting;
switch (itr_setting) {
case lowest_latency:
@@ -2381,7 +2416,6 @@ static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
break;
}
-update_itr_done:
return retval;
}
@@ -2464,13 +2498,19 @@ set_itr_now:
**/
static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
{
- adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+ int size = sizeof(struct e1000_ring);
+
+ adapter->tx_ring = kzalloc(size, GFP_KERNEL);
if (!adapter->tx_ring)
goto err;
+ adapter->tx_ring->count = adapter->tx_ring_count;
+ adapter->tx_ring->adapter = adapter;
- adapter->rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+ adapter->rx_ring = kzalloc(size, GFP_KERNEL);
if (!adapter->rx_ring)
goto err;
+ adapter->rx_ring->count = adapter->rx_ring_count;
+ adapter->rx_ring->adapter = adapter;
return 0;
err:
@@ -2498,10 +2538,10 @@ static int e1000_clean(struct napi_struct *napi, int budget)
!(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val))
goto clean_rx;
- tx_cleaned = e1000_clean_tx_irq(adapter);
+ tx_cleaned = e1000_clean_tx_irq(adapter->tx_ring);
clean_rx:
- adapter->clean_rx(adapter, &work_done, budget);
+ adapter->clean_rx(adapter->rx_ring, &work_done, budget);
if (!tx_cleaned)
work_done = budget;
@@ -2746,8 +2786,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
struct e1000_ring *tx_ring = adapter->tx_ring;
u64 tdba;
- u32 tdlen, tctl, tipg, tarc;
- u32 ipgr1, ipgr2;
+ u32 tdlen, tarc;
/* Setup the HW Tx Head and Tail descriptor pointers */
tdba = tx_ring->dma;
@@ -2757,20 +2796,8 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
ew32(TDLEN, tdlen);
ew32(TDH, 0);
ew32(TDT, 0);
- tx_ring->head = E1000_TDH;
- tx_ring->tail = E1000_TDT;
-
- /* Set the default values for the Tx Inter Packet Gap timer */
- tipg = DEFAULT_82543_TIPG_IPGT_COPPER; /* 8 */
- ipgr1 = DEFAULT_82543_TIPG_IPGR1; /* 8 */
- ipgr2 = DEFAULT_82543_TIPG_IPGR2; /* 6 */
-
- if (adapter->flags & FLAG_TIPG_MEDIUM_FOR_80003ESLAN)
- ipgr2 = DEFAULT_80003ES2LAN_TIPG_IPGR2; /* 7 */
-
- tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
- tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
- ew32(TIPG, tipg);
+ tx_ring->head = adapter->hw.hw_addr + E1000_TDH;
+ tx_ring->tail = adapter->hw.hw_addr + E1000_TDT;
/* Set the Tx Interrupt Delay register */
ew32(TIDV, adapter->tx_int_delay);
@@ -2793,15 +2820,9 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
*/
txdctl |= E1000_TXDCTL_DMA_BURST_ENABLE;
ew32(TXDCTL(0), txdctl);
- /* erratum work around: set txdctl the same for both queues */
- ew32(TXDCTL(1), txdctl);
}
-
- /* Program the Transmit Control Register */
- tctl = er32(TCTL);
- tctl &= ~E1000_TCTL_CT;
- tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
- (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
+ /* erratum work around: set txdctl the same for both queues */
+ ew32(TXDCTL(1), er32(TXDCTL(0)));
if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) {
tarc = er32(TARC(0));
@@ -2834,9 +2855,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
/* enable Report Status bit */
adapter->txd_cmd |= E1000_TXD_CMD_RS;
- ew32(TCTL, tctl);
-
- e1000e_config_collision_dist(hw);
+ hw->mac.ops.config_collision_dist(hw);
}
/**
@@ -2944,8 +2963,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
* per packet.
*/
pages = PAGE_USE_COUNT(adapter->netdev->mtu);
- if (!(adapter->flags & FLAG_HAS_ERT) && (pages <= 3) &&
- (PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE))
+ if ((pages <= 3) && (PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE))
adapter->rx_ps_pages = pages;
else
adapter->rx_ps_pages = 0;
@@ -2982,6 +3000,22 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
ew32(PSRCTL, psrctl);
}
+ /* 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 */
+ rctl |= (E1000_RCTL_SBP | /* Receive bad packets */
+ E1000_RCTL_BAM | /* RX All Bcast Pkts */
+ E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */
+
+ rctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */
+ E1000_RCTL_DPF | /* Allow filtered pause */
+ E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */
+ /* Do not mess with E1000_CTRL_VME, it affects transmit as well,
+ * and that breaks VLANs.
+ */
+ }
+
ew32(RFCTL, rfctl);
ew32(RCTL, rctl);
/* just started the receive unit, no need to restart */
@@ -3072,8 +3106,8 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
ew32(RDLEN, rdlen);
ew32(RDH, 0);
ew32(RDT, 0);
- rx_ring->head = E1000_RDH;
- rx_ring->tail = E1000_RDT;
+ rx_ring->head = adapter->hw.hw_addr + E1000_RDH;
+ rx_ring->tail = adapter->hw.hw_addr + E1000_RDT;
/* Enable Receive Checksum Offload for TCP and UDP */
rxcsum = er32(RXCSUM);
@@ -3092,23 +3126,14 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
}
ew32(RXCSUM, rxcsum);
- /*
- * Enable early receives on supported devices, only takes effect when
- * packet size is equal or larger than the specified value (in 8 byte
- * units), e.g. using jumbo frames when setting to E1000_ERT_2048
- */
- if ((adapter->flags & FLAG_HAS_ERT) ||
- (adapter->hw.mac.type == e1000_pch2lan)) {
+ if (adapter->hw.mac.type == e1000_pch2lan) {
+ /*
+ * With jumbo frames, excessive C-state transition
+ * latencies result in dropped transactions.
+ */
if (adapter->netdev->mtu > ETH_DATA_LEN) {
u32 rxdctl = er32(RXDCTL(0));
ew32(RXDCTL(0), rxdctl | 0x3);
- if (adapter->flags & FLAG_HAS_ERT)
- ew32(ERT, E1000_ERT_2048 | (1 << 13));
- /*
- * With jumbo frames and early-receive enabled,
- * excessive C-state transition latencies result in
- * dropped transactions.
- */
pm_qos_update_request(&adapter->netdev->pm_qos_req, 55);
} else {
pm_qos_update_request(&adapter->netdev->pm_qos_req,
@@ -3268,22 +3293,62 @@ static void e1000e_set_rx_mode(struct net_device *netdev)
e1000e_vlan_strip_disable(adapter);
}
+static void e1000e_setup_rss_hash(struct e1000_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 mrqc, rxcsum;
+ int i;
+ static const u32 rsskey[10] = {
+ 0xda565a6d, 0xc20e5b25, 0x3d256741, 0xb08fa343, 0xcb2bcad0,
+ 0xb4307bae, 0xa32dcb77, 0x0cf23080, 0x3bb7426a, 0xfa01acbe
+ };
+
+ /* Fill out hash function seed */
+ for (i = 0; i < 10; i++)
+ ew32(RSSRK(i), rsskey[i]);
+
+ /* Direct all traffic to queue 0 */
+ for (i = 0; i < 32; i++)
+ ew32(RETA(i), 0);
+
+ /*
+ * Disable raw packet checksumming so that RSS hash is placed in
+ * descriptor on writeback.
+ */
+ rxcsum = er32(RXCSUM);
+ rxcsum |= E1000_RXCSUM_PCSD;
+
+ ew32(RXCSUM, rxcsum);
+
+ mrqc = (E1000_MRQC_RSS_FIELD_IPV4 |
+ E1000_MRQC_RSS_FIELD_IPV4_TCP |
+ E1000_MRQC_RSS_FIELD_IPV6 |
+ E1000_MRQC_RSS_FIELD_IPV6_TCP |
+ E1000_MRQC_RSS_FIELD_IPV6_TCP_EX);
+
+ ew32(MRQC, mrqc);
+}
+
/**
* e1000_configure - configure the hardware for Rx and Tx
* @adapter: private board structure
**/
static void e1000_configure(struct e1000_adapter *adapter)
{
+ struct e1000_ring *rx_ring = adapter->rx_ring;
+
e1000e_set_rx_mode(adapter->netdev);
e1000_restore_vlan(adapter);
e1000_init_manageability_pt(adapter);
e1000_configure_tx(adapter);
+
+ if (adapter->netdev->features & NETIF_F_RXHASH)
+ e1000e_setup_rss_hash(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
- adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring),
- GFP_KERNEL);
+ adapter->alloc_rx_buf(rx_ring, e1000_desc_unused(rx_ring), GFP_KERNEL);
}
/**
@@ -3379,9 +3444,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
* if short on Rx space, Rx wins and must trump Tx
* adjustment or use Early Receive if available
*/
- if ((pba < min_rx_space) &&
- (!(adapter->flags & FLAG_HAS_ERT)))
- /* ERT enabled in e1000_configure_rx */
+ if (pba < min_rx_space)
pba = min_rx_space;
}
@@ -3395,26 +3458,29 @@ void e1000e_reset(struct e1000_adapter *adapter)
* (or the size used for early receive) above it in the Rx FIFO.
* Set it to the lower of:
* - 90% of the Rx FIFO size, and
- * - the full Rx FIFO size minus the early receive size (for parts
- * with ERT support assuming ERT set to E1000_ERT_2048), or
* - the full Rx FIFO size minus one full frame
*/
if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME)
fc->pause_time = 0xFFFF;
else
fc->pause_time = E1000_FC_PAUSE_TIME;
- fc->send_xon = 1;
+ fc->send_xon = true;
fc->current_mode = fc->requested_mode;
switch (hw->mac.type) {
+ case e1000_ich9lan:
+ case e1000_ich10lan:
+ if (adapter->netdev->mtu > ETH_DATA_LEN) {
+ pba = 14;
+ ew32(PBA, pba);
+ fc->high_water = 0x2800;
+ fc->low_water = fc->high_water - 8;
+ break;
+ }
+ /* fall-through */
default:
- if ((adapter->flags & FLAG_HAS_ERT) &&
- (adapter->netdev->mtu > ETH_DATA_LEN))
- hwm = min(((pba << 10) * 9 / 10),
- ((pba << 10) - (E1000_ERT_2048 << 3)));
- else
- hwm = min(((pba << 10) * 9 / 10),
- ((pba << 10) - adapter->max_frame_size));
+ hwm = min(((pba << 10) * 9 / 10),
+ ((pba << 10) - adapter->max_frame_size));
fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */
fc->low_water = fc->high_water - 8;
@@ -3447,11 +3513,10 @@ void e1000e_reset(struct e1000_adapter *adapter)
/*
* Disable Adaptive Interrupt Moderation if 2 full packets cannot
- * fit in receive buffer and early-receive not supported.
+ * fit in receive buffer.
*/
if (adapter->itr_setting & 0x3) {
- if (((adapter->max_frame_size * 2) > (pba << 10)) &&
- !(adapter->flags & FLAG_HAS_ERT)) {
+ if ((adapter->max_frame_size * 2) > (pba << 10)) {
if (!(adapter->flags2 & FLAG2_DISABLE_AIM)) {
dev_info(&adapter->pdev->dev,
"Interrupt Throttle Rate turned off\n");
@@ -3593,8 +3658,8 @@ void e1000e_down(struct e1000_adapter *adapter)
spin_unlock(&adapter->stats64_lock);
e1000e_flush_descriptors(adapter);
- e1000_clean_tx_ring(adapter);
- e1000_clean_rx_ring(adapter);
+ e1000_clean_tx_ring(adapter->tx_ring);
+ e1000_clean_rx_ring(adapter->rx_ring);
adapter->link_speed = 0;
adapter->link_duplex = 0;
@@ -3634,6 +3699,8 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
adapter->rx_ps_bsize0 = 128;
adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+ adapter->tx_ring_count = E1000_DEFAULT_TXD;
+ adapter->rx_ring_count = E1000_DEFAULT_RXD;
spin_lock_init(&adapter->stats64_lock);
@@ -3721,8 +3788,9 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
if (adapter->flags & FLAG_MSI_TEST_FAILED) {
adapter->int_mode = E1000E_INT_MODE_LEGACY;
e_info("MSI interrupt test failed, using legacy interrupt.\n");
- } else
+ } else {
e_dbg("MSI interrupt test succeeded!\n");
+ }
free_irq(adapter->pdev->irq, netdev);
pci_disable_msi(adapter->pdev);
@@ -3792,12 +3860,12 @@ static int e1000_open(struct net_device *netdev)
netif_carrier_off(netdev);
/* allocate transmit descriptors */
- err = e1000e_setup_tx_resources(adapter);
+ err = e1000e_setup_tx_resources(adapter->tx_ring);
if (err)
goto err_setup_tx;
/* allocate receive descriptors */
- err = e1000e_setup_rx_resources(adapter);
+ err = e1000e_setup_rx_resources(adapter->rx_ring);
if (err)
goto err_setup_rx;
@@ -3817,9 +3885,8 @@ static int e1000_open(struct net_device *netdev)
E1000_MNG_DHCP_COOKIE_STATUS_VLAN))
e1000_update_mng_vlan(adapter);
- /* DMA latency requirement to workaround early-receive/jumbo issue */
- if ((adapter->flags & FLAG_HAS_ERT) ||
- (adapter->hw.mac.type == e1000_pch2lan))
+ /* DMA latency requirement to workaround jumbo issue */
+ if (adapter->hw.mac.type == e1000_pch2lan)
pm_qos_add_request(&adapter->netdev->pm_qos_req,
PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
@@ -3873,9 +3940,9 @@ static int e1000_open(struct net_device *netdev)
err_req_irq:
e1000e_release_hw_control(adapter);
e1000_power_down_phy(adapter);
- e1000e_free_rx_resources(adapter);
+ e1000e_free_rx_resources(adapter->rx_ring);
err_setup_rx:
- e1000e_free_tx_resources(adapter);
+ e1000e_free_tx_resources(adapter->tx_ring);
err_setup_tx:
e1000e_reset(adapter);
pm_runtime_put_sync(&pdev->dev);
@@ -3911,8 +3978,8 @@ static int e1000_close(struct net_device *netdev)
}
e1000_power_down_phy(adapter);
- e1000e_free_tx_resources(adapter);
- e1000e_free_rx_resources(adapter);
+ e1000e_free_tx_resources(adapter->tx_ring);
+ e1000e_free_rx_resources(adapter->rx_ring);
/*
* kill manageability vlan ID if supported, but not if a vlan with
@@ -3930,8 +3997,7 @@ static int e1000_close(struct net_device *netdev)
!test_bit(__E1000_TESTING, &adapter->state))
e1000e_release_hw_control(adapter);
- if ((adapter->flags & FLAG_HAS_ERT) ||
- (adapter->hw.mac.type == e1000_pch2lan))
+ if (adapter->hw.mac.type == e1000_pch2lan)
pm_qos_remove_request(&adapter->netdev->pm_qos_req);
pm_runtime_put_sync(&pdev->dev);
@@ -4566,13 +4632,12 @@ link_up:
#define E1000_TX_FLAGS_VLAN 0x00000002
#define E1000_TX_FLAGS_TSO 0x00000004
#define E1000_TX_FLAGS_IPV4 0x00000008
+#define E1000_TX_FLAGS_NO_FCS 0x00000010
#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000
#define E1000_TX_FLAGS_VLAN_SHIFT 16
-static int e1000_tso(struct e1000_adapter *adapter,
- struct sk_buff *skb)
+static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb)
{
- struct e1000_ring *tx_ring = adapter->tx_ring;
struct e1000_context_desc *context_desc;
struct e1000_buffer *buffer_info;
unsigned int i;
@@ -4641,9 +4706,9 @@ static int e1000_tso(struct e1000_adapter *adapter,
return 1;
}
-static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
+static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb)
{
- struct e1000_ring *tx_ring = adapter->tx_ring;
+ struct e1000_adapter *adapter = tx_ring->adapter;
struct e1000_context_desc *context_desc;
struct e1000_buffer *buffer_info;
unsigned int i;
@@ -4704,12 +4769,11 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
#define E1000_MAX_PER_TXD 8192
#define E1000_MAX_TXD_PWR 12
-static int e1000_tx_map(struct e1000_adapter *adapter,
- struct sk_buff *skb, unsigned int first,
- unsigned int max_per_txd, unsigned int nr_frags,
- unsigned int mss)
+static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb,
+ unsigned int first, unsigned int max_per_txd,
+ unsigned int nr_frags, unsigned int mss)
{
- struct e1000_ring *tx_ring = adapter->tx_ring;
+ struct e1000_adapter *adapter = tx_ring->adapter;
struct pci_dev *pdev = adapter->pdev;
struct e1000_buffer *buffer_info;
unsigned int len = skb_headlen(skb);
@@ -4795,16 +4859,15 @@ dma_error:
i += tx_ring->count;
i--;
buffer_info = &tx_ring->buffer_info[i];
- e1000_put_txbuf(adapter, buffer_info);
+ e1000_put_txbuf(tx_ring, buffer_info);
}
return 0;
}
-static void e1000_tx_queue(struct e1000_adapter *adapter,
- int tx_flags, int count)
+static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count)
{
- struct e1000_ring *tx_ring = adapter->tx_ring;
+ struct e1000_adapter *adapter = tx_ring->adapter;
struct e1000_tx_desc *tx_desc = NULL;
struct e1000_buffer *buffer_info;
u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
@@ -4829,6 +4892,9 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
}
+ if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS))
+ txd_lower &= ~(E1000_TXD_CMD_IFCS);
+
i = tx_ring->next_to_use;
do {
@@ -4846,6 +4912,10 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
+ /* txd_cmd re-enables FCS, so we'll re-disable it here as desired. */
+ 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
* know there are new descriptors to fetch. (Only
@@ -4857,9 +4927,9 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
tx_ring->next_to_use = i;
if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
- e1000e_update_tdt_wa(adapter, i);
+ e1000e_update_tdt_wa(tx_ring, i);
else
- writel(i, adapter->hw.hw_addr + tx_ring->tail);
+ writel(i, tx_ring->tail);
/*
* we need this if more than one processor can write to our tail
@@ -4907,11 +4977,11 @@ static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter,
return 0;
}
-static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
+static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_adapter *adapter = tx_ring->adapter;
- netif_stop_queue(netdev);
+ netif_stop_queue(adapter->netdev);
/*
* Herbert's original patch had:
* smp_mb__after_netif_stop_queue();
@@ -4923,25 +4993,23 @@ static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
* We need to check again in a case another CPU has just
* made room available.
*/
- if (e1000_desc_unused(adapter->tx_ring) < size)
+ if (e1000_desc_unused(tx_ring) < size)
return -EBUSY;
/* A reprieve! */
- netif_start_queue(netdev);
+ netif_start_queue(adapter->netdev);
++adapter->restart_queue;
return 0;
}
-static int e1000_maybe_stop_tx(struct net_device *netdev, int size)
+static int e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size)
{
- struct e1000_adapter *adapter = netdev_priv(netdev);
-
- if (e1000_desc_unused(adapter->tx_ring) >= size)
+ if (e1000_desc_unused(tx_ring) >= size)
return 0;
- return __e1000_maybe_stop_tx(netdev, size);
+ return __e1000_maybe_stop_tx(tx_ring, size);
}
-#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
+#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1)
static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
struct net_device *netdev)
{
@@ -4995,7 +5063,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
if (skb->data_len && (hdr_len == len)) {
unsigned int pull_size;
- pull_size = min((unsigned int)4, skb->data_len);
+ pull_size = min_t(unsigned int, 4, skb->data_len);
if (!__pskb_pull_tail(skb, pull_size)) {
e_err("__pskb_pull_tail failed.\n");
dev_kfree_skb_any(skb);
@@ -5024,7 +5092,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
* need: count + 2 desc gap to keep tail from touching
* head, otherwise try next time
*/
- if (e1000_maybe_stop_tx(netdev, count + 2))
+ if (e1000_maybe_stop_tx(tx_ring, count + 2))
return NETDEV_TX_BUSY;
if (vlan_tx_tag_present(skb)) {
@@ -5034,7 +5102,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
first = tx_ring->next_to_use;
- tso = e1000_tso(adapter, skb);
+ tso = e1000_tso(tx_ring, skb);
if (tso < 0) {
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
@@ -5042,7 +5110,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
if (tso)
tx_flags |= E1000_TX_FLAGS_TSO;
- else if (e1000_tx_csum(adapter, skb))
+ else if (e1000_tx_csum(tx_ring, skb))
tx_flags |= E1000_TX_FLAGS_CSUM;
/*
@@ -5053,13 +5121,16 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
if (skb->protocol == htons(ETH_P_IP))
tx_flags |= E1000_TX_FLAGS_IPV4;
+ if (unlikely(skb->no_fcs))
+ tx_flags |= E1000_TX_FLAGS_NO_FCS;
+
/* if count is 0 then mapping error has occurred */
- count = e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss);
+ count = e1000_tx_map(tx_ring, skb, first, max_per_txd, nr_frags, mss);
if (count) {
netdev_sent_queue(netdev, skb->len);
- e1000_tx_queue(adapter, tx_flags, count);
+ e1000_tx_queue(tx_ring, tx_flags, count);
/* Make sure there is space in the ring for the next send. */
- e1000_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 2);
+ e1000_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 2);
} else {
dev_kfree_skb_any(skb);
@@ -5165,10 +5236,22 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
/* Jumbo frame support */
- if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) &&
- !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
- e_err("Jumbo Frames not supported.\n");
- return -EINVAL;
+ if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) {
+ if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
+ e_err("Jumbo Frames not supported.\n");
+ return -EINVAL;
+ }
+
+ /*
+ * IP payload checksum (enabled with jumbos/packet-split when
+ * Rx checksum is enabled) and generation of RSS hash is
+ * mutually exclusive in the hardware.
+ */
+ if ((netdev->features & NETIF_F_RXCSUM) &&
+ (netdev->features & NETIF_F_RXHASH)) {
+ e_err("Jumbo frames cannot be enabled when both receive checksum offload and receive hashing are enabled. Disable one of the receive offload features before enabling jumbos.\n");
+ return -EINVAL;
+ }
}
/* Supported frame sizes */
@@ -5322,7 +5405,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
/* Enable access to wakeup registers on and set page to BM_WUC_PAGE */
retval = e1000_enable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
if (retval)
- goto out;
+ goto release;
/* copy MAC MTA to PHY MTA - only needed for pchlan */
for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) {
@@ -5366,7 +5449,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
retval = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable);
if (retval)
e_err("Could not set PHY Host Wakeup bit\n");
-out:
+release:
hw->phy.ops.release(hw);
return retval;
@@ -5908,7 +5991,7 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
ret_val = e1000_read_pba_string_generic(hw, pba_str,
E1000_PBANUM_LENGTH);
if (ret_val)
- strncpy((char *)pba_str, "Unknown", sizeof(pba_str) - 1);
+ strlcpy((char *)pba_str, "Unknown", sizeof(pba_str));
e_info("MAC: %d, PHY: %d, PBA No: %s\n",
hw->mac.type, hw->phy.type, pba_str);
}
@@ -5923,7 +6006,8 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
return;
ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf);
- if (!ret_val && (!(le16_to_cpu(buf) & (1 << 0)))) {
+ le16_to_cpus(&buf);
+ if (!ret_val && (!(buf & (1 << 0)))) {
/* Deep Smart Power Down (DSPD) */
dev_warn(&adapter->pdev->dev,
"Warning: detected DSPD enabled in EEPROM\n");
@@ -5931,7 +6015,7 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
}
static int e1000_set_features(struct net_device *netdev,
- netdev_features_t features)
+ netdev_features_t features)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
netdev_features_t changed = features ^ netdev->features;
@@ -5940,9 +6024,37 @@ static int e1000_set_features(struct net_device *netdev,
adapter->flags |= FLAG_TSO_FORCE;
if (!(changed & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX |
- NETIF_F_RXCSUM)))
+ NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_RXFCS |
+ NETIF_F_RXALL)))
return 0;
+ /*
+ * IP payload checksum (enabled with jumbos/packet-split when Rx
+ * checksum is enabled) and generation of RSS hash is mutually
+ * exclusive in the hardware.
+ */
+ if (adapter->rx_ps_pages &&
+ (features & NETIF_F_RXCSUM) && (features & NETIF_F_RXHASH)) {
+ e_err("Enabling both receive checksum offload and receive hashing is not possible with jumbo frames. Disable jumbos or enable only one of the receive offload features.\n");
+ return -EINVAL;
+ }
+
+ if (changed & NETIF_F_RXFCS) {
+ if (features & NETIF_F_RXFCS) {
+ adapter->flags2 &= ~FLAG2_CRC_STRIPPING;
+ } else {
+ /* We need to take it back to defaults, which might mean
+ * stripping is still disabled at the adapter level.
+ */
+ if (adapter->flags2 & FLAG2_DFLT_CRC_STRIPPING)
+ adapter->flags2 |= FLAG2_CRC_STRIPPING;
+ else
+ adapter->flags2 &= ~FLAG2_CRC_STRIPPING;
+ }
+ }
+
+ netdev->features = features;
+
if (netif_running(netdev))
e1000e_reinit_locked(adapter);
else
@@ -6087,7 +6199,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
e1000e_set_ethtool_ops(netdev);
netdev->watchdog_timeo = 5 * HZ;
netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
- strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
+ strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
netdev->mem_start = mmio_start;
netdev->mem_end = mmio_start + mmio_len;
@@ -6124,7 +6236,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
adapter->hw.phy.ms_type = e1000_ms_hw_default;
}
- if (e1000_check_reset_block(&adapter->hw))
+ if (hw->phy.ops.check_reset_block(hw))
e_info("PHY reset is blocked due to SOL/IDER session.\n");
/* Set initial default active device features */
@@ -6133,11 +6245,15 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
NETIF_F_HW_VLAN_TX |
NETIF_F_TSO |
NETIF_F_TSO6 |
+ NETIF_F_RXHASH |
NETIF_F_RXCSUM |
NETIF_F_HW_CSUM);
/* Set user-changeable features (subset of all device features) */
netdev->hw_features = netdev->features;
+ netdev->hw_features |= NETIF_F_RXFCS;
+ netdev->priv_flags |= IFF_SUPP_NOFCS;
+ netdev->hw_features |= NETIF_F_RXALL;
if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER)
netdev->features |= NETIF_F_HW_VLAN_FILTER;
@@ -6268,7 +6384,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
if (!(adapter->flags & FLAG_HAS_AMT))
e1000e_get_hw_control(adapter);
- strncpy(netdev->name, "eth%d", sizeof(netdev->name) - 1);
+ strlcpy(netdev->name, "eth%d", sizeof(netdev->name));
err = register_netdev(netdev);
if (err)
goto err_register;
@@ -6287,7 +6403,7 @@ err_register:
if (!(adapter->flags & FLAG_HAS_AMT))
e1000e_release_hw_control(adapter);
err_eeprom:
- if (!e1000_check_reset_block(&adapter->hw))
+ if (!hw->phy.ops.check_reset_block(hw))
e1000_phy_hw_reset(&adapter->hw);
err_hw_init:
kfree(adapter->tx_ring);
@@ -6449,7 +6565,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_LM), board_pch2lan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_V), board_pch2lan },
- { } /* terminate list */
+ { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
@@ -6468,7 +6584,9 @@ static struct pci_driver e1000_driver = {
.probe = e1000_probe,
.remove = __devexit_p(e1000_remove),
#ifdef CONFIG_PM
- .driver.pm = &e1000_pm_ops,
+ .driver = {
+ .pm = &e1000_pm_ops,
+ },
#endif
.shutdown = e1000_shutdown,
.err_handler = &e1000_err_handler
@@ -6485,7 +6603,7 @@ static int __init e1000_init_module(void)
int ret;
pr_info("Intel(R) PRO/1000 Network Driver - %s\n",
e1000e_driver_version);
- pr_info("Copyright(c) 1999 - 2011 Intel Corporation.\n");
+ pr_info("Copyright(c) 1999 - 2012 Intel Corporation.\n");
ret = pci_register_driver(&e1000_driver);
return ret;
diff --git a/drivers/net/ethernet/intel/e1000e/nvm.c b/drivers/net/ethernet/intel/e1000e/nvm.c
new file mode 100644
index 000000000000..a969f1af1b4e
--- /dev/null
+++ b/drivers/net/ethernet/intel/e1000e/nvm.c
@@ -0,0 +1,643 @@
+/*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+ Copyright(c) 1999 - 2012 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include "e1000.h"
+
+/**
+ * e1000_raise_eec_clk - Raise EEPROM clock
+ * @hw: pointer to the HW structure
+ * @eecd: pointer to the EEPROM
+ *
+ * Enable/Raise the EEPROM clock bit.
+ **/
+static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd)
+{
+ *eecd = *eecd | E1000_EECD_SK;
+ ew32(EECD, *eecd);
+ e1e_flush();
+ udelay(hw->nvm.delay_usec);
+}
+
+/**
+ * e1000_lower_eec_clk - Lower EEPROM clock
+ * @hw: pointer to the HW structure
+ * @eecd: pointer to the EEPROM
+ *
+ * Clear/Lower the EEPROM clock bit.
+ **/
+static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd)
+{
+ *eecd = *eecd & ~E1000_EECD_SK;
+ ew32(EECD, *eecd);
+ e1e_flush();
+ udelay(hw->nvm.delay_usec);
+}
+
+/**
+ * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM
+ * @hw: pointer to the HW structure
+ * @data: data to send to the EEPROM
+ * @count: number of bits to shift out
+ *
+ * We need to shift 'count' bits out to the EEPROM. So, the value in the
+ * "data" parameter will be shifted out to the EEPROM one bit at a time.
+ * In order to do this, "data" must be broken down into bits.
+ **/
+static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ u32 eecd = er32(EECD);
+ u32 mask;
+
+ mask = 0x01 << (count - 1);
+ if (nvm->type == e1000_nvm_eeprom_spi)
+ eecd |= E1000_EECD_DO;
+
+ do {
+ eecd &= ~E1000_EECD_DI;
+
+ if (data & mask)
+ eecd |= E1000_EECD_DI;
+
+ ew32(EECD, eecd);
+ e1e_flush();
+
+ udelay(nvm->delay_usec);
+
+ e1000_raise_eec_clk(hw, &eecd);
+ e1000_lower_eec_clk(hw, &eecd);
+
+ mask >>= 1;
+ } while (mask);
+
+ eecd &= ~E1000_EECD_DI;
+ ew32(EECD, eecd);
+}
+
+/**
+ * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM
+ * @hw: pointer to the HW structure
+ * @count: number of bits to shift in
+ *
+ * In order to read a register from the EEPROM, we need to shift 'count' bits
+ * in from the EEPROM. Bits are "shifted in" by raising the clock input to
+ * the EEPROM (setting the SK bit), and then reading the value of the data out
+ * "DO" bit. During this "shifting in" process the data in "DI" bit should
+ * always be clear.
+ **/
+static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count)
+{
+ u32 eecd;
+ u32 i;
+ u16 data;
+
+ eecd = er32(EECD);
+
+ eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
+ data = 0;
+
+ for (i = 0; i < count; i++) {
+ data <<= 1;
+ e1000_raise_eec_clk(hw, &eecd);
+
+ eecd = er32(EECD);
+
+ eecd &= ~E1000_EECD_DI;
+ if (eecd & E1000_EECD_DO)
+ data |= 1;
+
+ e1000_lower_eec_clk(hw, &eecd);
+ }
+
+ return data;
+}
+
+/**
+ * e1000e_poll_eerd_eewr_done - Poll for EEPROM read/write completion
+ * @hw: pointer to the HW structure
+ * @ee_reg: EEPROM flag for polling
+ *
+ * Polls the EEPROM status bit for either read or write completion based
+ * upon the value of 'ee_reg'.
+ **/
+s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
+{
+ u32 attempts = 100000;
+ u32 i, reg = 0;
+
+ for (i = 0; i < attempts; i++) {
+ if (ee_reg == E1000_NVM_POLL_READ)
+ reg = er32(EERD);
+ else
+ reg = er32(EEWR);
+
+ if (reg & E1000_NVM_RW_REG_DONE)
+ return 0;
+
+ udelay(5);
+ }
+
+ return -E1000_ERR_NVM;
+}
+
+/**
+ * e1000e_acquire_nvm - Generic request for access to EEPROM
+ * @hw: pointer to the HW structure
+ *
+ * Set the EEPROM access request bit and wait for EEPROM access grant bit.
+ * Return successful if access grant bit set, else clear the request for
+ * EEPROM access and return -E1000_ERR_NVM (-1).
+ **/
+s32 e1000e_acquire_nvm(struct e1000_hw *hw)
+{
+ u32 eecd = er32(EECD);
+ s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
+
+ ew32(EECD, eecd | E1000_EECD_REQ);
+ eecd = er32(EECD);
+
+ while (timeout) {
+ if (eecd & E1000_EECD_GNT)
+ break;
+ udelay(5);
+ eecd = er32(EECD);
+ timeout--;
+ }
+
+ if (!timeout) {
+ eecd &= ~E1000_EECD_REQ;
+ ew32(EECD, eecd);
+ e_dbg("Could not acquire NVM grant\n");
+ return -E1000_ERR_NVM;
+ }
+
+ return 0;
+}
+
+/**
+ * e1000_standby_nvm - Return EEPROM to standby state
+ * @hw: pointer to the HW structure
+ *
+ * Return the EEPROM to a standby state.
+ **/
+static void e1000_standby_nvm(struct e1000_hw *hw)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ u32 eecd = er32(EECD);
+
+ if (nvm->type == e1000_nvm_eeprom_spi) {
+ /* Toggle CS to flush commands */
+ eecd |= E1000_EECD_CS;
+ ew32(EECD, eecd);
+ e1e_flush();
+ udelay(nvm->delay_usec);
+ eecd &= ~E1000_EECD_CS;
+ ew32(EECD, eecd);
+ e1e_flush();
+ udelay(nvm->delay_usec);
+ }
+}
+
+/**
+ * e1000_stop_nvm - Terminate EEPROM command
+ * @hw: pointer to the HW structure
+ *
+ * Terminates the current command by inverting the EEPROM's chip select pin.
+ **/
+static void e1000_stop_nvm(struct e1000_hw *hw)
+{
+ u32 eecd;
+
+ eecd = er32(EECD);
+ if (hw->nvm.type == e1000_nvm_eeprom_spi) {
+ /* Pull CS high */
+ eecd |= E1000_EECD_CS;
+ e1000_lower_eec_clk(hw, &eecd);
+ }
+}
+
+/**
+ * e1000e_release_nvm - Release exclusive access to EEPROM
+ * @hw: pointer to the HW structure
+ *
+ * Stop any current commands to the EEPROM and clear the EEPROM request bit.
+ **/
+void e1000e_release_nvm(struct e1000_hw *hw)
+{
+ u32 eecd;
+
+ e1000_stop_nvm(hw);
+
+ eecd = er32(EECD);
+ eecd &= ~E1000_EECD_REQ;
+ ew32(EECD, eecd);
+}
+
+/**
+ * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write
+ * @hw: pointer to the HW structure
+ *
+ * Setups the EEPROM for reading and writing.
+ **/
+static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ u32 eecd = er32(EECD);
+ u8 spi_stat_reg;
+
+ if (nvm->type == e1000_nvm_eeprom_spi) {
+ u16 timeout = NVM_MAX_RETRY_SPI;
+
+ /* Clear SK and CS */
+ eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
+ ew32(EECD, eecd);
+ e1e_flush();
+ udelay(1);
+
+ /*
+ * Read "Status Register" repeatedly until the LSB is cleared.
+ * The EEPROM will signal that the command has been completed
+ * by clearing bit 0 of the internal status register. If it's
+ * not cleared within 'timeout', then error out.
+ */
+ while (timeout) {
+ e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
+ hw->nvm.opcode_bits);
+ spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
+ if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
+ break;
+
+ udelay(5);
+ e1000_standby_nvm(hw);
+ timeout--;
+ }
+
+ if (!timeout) {
+ e_dbg("SPI NVM Status error\n");
+ return -E1000_ERR_NVM;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * e1000e_read_nvm_eerd - Reads EEPROM using EERD register
+ * @hw: pointer to the HW structure
+ * @offset: offset of word in the EEPROM to read
+ * @words: number of words to read
+ * @data: word read from the EEPROM
+ *
+ * Reads a 16 bit word from the EEPROM using the EERD register.
+ **/
+s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ u32 i, eerd = 0;
+ s32 ret_val = 0;
+
+ /*
+ * A check for invalid values: offset too large, too many words,
+ * too many words for the offset, and not enough words.
+ */
+ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+ (words == 0)) {
+ e_dbg("nvm parameter(s) out of bounds\n");
+ return -E1000_ERR_NVM;
+ }
+
+ for (i = 0; i < words; i++) {
+ eerd = ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) +
+ E1000_NVM_RW_REG_START;
+
+ ew32(EERD, eerd);
+ ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
+ if (ret_val)
+ break;
+
+ data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA);
+ }
+
+ return ret_val;
+}
+
+/**
+ * e1000e_write_nvm_spi - Write to EEPROM using SPI
+ * @hw: pointer to the HW structure
+ * @offset: offset within the EEPROM to be written to
+ * @words: number of words to write
+ * @data: 16 bit word(s) to be written to the EEPROM
+ *
+ * Writes data to EEPROM at offset using SPI interface.
+ *
+ * If e1000e_update_nvm_checksum is not called after this function , the
+ * EEPROM will most likely contain an invalid checksum.
+ **/
+s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ s32 ret_val;
+ u16 widx = 0;
+
+ /*
+ * A check for invalid values: offset too large, too many words,
+ * and not enough words.
+ */
+ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+ (words == 0)) {
+ e_dbg("nvm parameter(s) out of bounds\n");
+ return -E1000_ERR_NVM;
+ }
+
+ ret_val = nvm->ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ while (widx < words) {
+ u8 write_opcode = NVM_WRITE_OPCODE_SPI;
+
+ ret_val = e1000_ready_nvm_eeprom(hw);
+ if (ret_val)
+ goto release;
+
+ e1000_standby_nvm(hw);
+
+ /* Send the WRITE ENABLE command (8 bit opcode) */
+ e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
+ nvm->opcode_bits);
+
+ e1000_standby_nvm(hw);
+
+ /*
+ * Some SPI eeproms use the 8th address bit embedded in the
+ * opcode
+ */
+ if ((nvm->address_bits == 8) && (offset >= 128))
+ write_opcode |= NVM_A8_OPCODE_SPI;
+
+ /* Send the Write command (8-bit opcode + addr) */
+ e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
+ e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
+ nvm->address_bits);
+
+ /* Loop to allow for up to whole page write of eeprom */
+ while (widx < words) {
+ u16 word_out = data[widx];
+ word_out = (word_out >> 8) | (word_out << 8);
+ e1000_shift_out_eec_bits(hw, word_out, 16);
+ widx++;
+
+ if ((((offset + widx) * 2) % nvm->page_size) == 0) {
+ e1000_standby_nvm(hw);
+ break;
+ }
+ }
+ }
+
+ usleep_range(10000, 20000);
+release:
+ nvm->ops.release(hw);
+
+ return ret_val;
+}
+
+/**
+ * e1000_read_pba_string_generic - Read device part number
+ * @hw: pointer to the HW structure
+ * @pba_num: pointer to device part number
+ * @pba_num_size: size of part number buffer
+ *
+ * Reads the product board assembly (PBA) number from the EEPROM and stores
+ * the value in pba_num.
+ **/
+s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
+ u32 pba_num_size)
+{
+ s32 ret_val;
+ u16 nvm_data;
+ u16 pba_ptr;
+ u16 offset;
+ u16 length;
+
+ if (pba_num == NULL) {
+ e_dbg("PBA string buffer was null\n");
+ return -E1000_ERR_INVALID_ARGUMENT;
+ }
+
+ ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
+ if (ret_val) {
+ e_dbg("NVM Read Error\n");
+ return ret_val;
+ }
+
+ ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
+ if (ret_val) {
+ e_dbg("NVM Read Error\n");
+ return ret_val;
+ }
+
+ /*
+ * if nvm_data is not ptr guard the PBA must be in legacy format which
+ * means pba_ptr is actually our second data word for the PBA number
+ * and we can decode it into an ascii string
+ */
+ if (nvm_data != NVM_PBA_PTR_GUARD) {
+ e_dbg("NVM PBA number is not stored as string\n");
+
+ /* we will need 11 characters to store the PBA */
+ if (pba_num_size < 11) {
+ e_dbg("PBA string buffer too small\n");
+ return E1000_ERR_NO_SPACE;
+ }
+
+ /* extract hex string from data and pba_ptr */
+ pba_num[0] = (nvm_data >> 12) & 0xF;
+ pba_num[1] = (nvm_data >> 8) & 0xF;
+ pba_num[2] = (nvm_data >> 4) & 0xF;
+ pba_num[3] = nvm_data & 0xF;
+ pba_num[4] = (pba_ptr >> 12) & 0xF;
+ pba_num[5] = (pba_ptr >> 8) & 0xF;
+ pba_num[6] = '-';
+ pba_num[7] = 0;
+ pba_num[8] = (pba_ptr >> 4) & 0xF;
+ pba_num[9] = pba_ptr & 0xF;
+
+ /* put a null character on the end of our string */
+ pba_num[10] = '\0';
+
+ /* switch all the data but the '-' to hex char */
+ for (offset = 0; offset < 10; offset++) {
+ if (pba_num[offset] < 0xA)
+ pba_num[offset] += '0';
+ else if (pba_num[offset] < 0x10)
+ pba_num[offset] += 'A' - 0xA;
+ }
+
+ return 0;
+ }
+
+ ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length);
+ if (ret_val) {
+ e_dbg("NVM Read Error\n");
+ return ret_val;
+ }
+
+ if (length == 0xFFFF || length == 0) {
+ e_dbg("NVM PBA number section invalid length\n");
+ return -E1000_ERR_NVM_PBA_SECTION;
+ }
+ /* check if pba_num buffer is big enough */
+ if (pba_num_size < (((u32)length * 2) - 1)) {
+ e_dbg("PBA string buffer too small\n");
+ return -E1000_ERR_NO_SPACE;
+ }
+
+ /* trim pba length from start of string */
+ pba_ptr++;
+ length--;
+
+ for (offset = 0; offset < length; offset++) {
+ ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data);
+ if (ret_val) {
+ e_dbg("NVM Read Error\n");
+ return ret_val;
+ }
+ pba_num[offset * 2] = (u8)(nvm_data >> 8);
+ pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
+ }
+ pba_num[offset * 2] = '\0';
+
+ return 0;
+}
+
+/**
+ * e1000_read_mac_addr_generic - Read device MAC address
+ * @hw: pointer to the HW structure
+ *
+ * Reads the device MAC address from the EEPROM and stores the value.
+ * Since devices with two ports use the same EEPROM, we increment the
+ * last bit in the MAC address for the second port.
+ **/
+s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
+{
+ u32 rar_high;
+ u32 rar_low;
+ u16 i;
+
+ rar_high = er32(RAH(0));
+ rar_low = er32(RAL(0));
+
+ for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
+ hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8));
+
+ for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
+ hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8));
+
+ for (i = 0; i < ETH_ALEN; i++)
+ hw->mac.addr[i] = hw->mac.perm_addr[i];
+
+ return 0;
+}
+
+/**
+ * e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
+ * and then verifies that the sum of the EEPROM is equal to 0xBABA.
+ **/
+s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ u16 checksum = 0;
+ u16 i, nvm_data;
+
+ for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
+ ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
+ if (ret_val) {
+ e_dbg("NVM Read Error\n");
+ return ret_val;
+ }
+ checksum += nvm_data;
+ }
+
+ if (checksum != (u16)NVM_SUM) {
+ e_dbg("NVM Checksum Invalid\n");
+ return -E1000_ERR_NVM;
+ }
+
+ return 0;
+}
+
+/**
+ * e1000e_update_nvm_checksum_generic - Update EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ * up to the checksum. Then calculates the EEPROM checksum and writes the
+ * value to the EEPROM.
+ **/
+s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ u16 checksum = 0;
+ u16 i, nvm_data;
+
+ for (i = 0; i < NVM_CHECKSUM_REG; i++) {
+ ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
+ if (ret_val) {
+ e_dbg("NVM Read Error while updating checksum.\n");
+ return ret_val;
+ }
+ checksum += nvm_data;
+ }
+ checksum = (u16)NVM_SUM - checksum;
+ ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum);
+ if (ret_val)
+ e_dbg("NVM Write Error while updating checksum.\n");
+
+ return ret_val;
+}
+
+/**
+ * e1000e_reload_nvm_generic - Reloads EEPROM
+ * @hw: pointer to the HW structure
+ *
+ * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
+ * extended control register.
+ **/
+void e1000e_reload_nvm_generic(struct e1000_hw *hw)
+{
+ u32 ctrl_ext;
+
+ udelay(10);
+ ctrl_ext = er32(CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+ ew32(CTRL_EXT, ctrl_ext);
+ e1e_flush();
+}
diff --git a/drivers/net/ethernet/intel/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c
index 20e93b08e7f3..ff796e42c3eb 100644
--- a/drivers/net/ethernet/intel/e1000e/param.c
+++ b/drivers/net/ethernet/intel/e1000e/param.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -113,11 +113,20 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
#define MAX_ITR 100000
#define MIN_ITR 100
-/* IntMode (Interrupt Mode)
+/*
+ * IntMode (Interrupt Mode)
+ *
+ * Valid Range: varies depending on kernel configuration & hardware support
+ *
+ * legacy=0, MSI=1, MSI-X=2
*
- * Valid Range: 0 - 2
+ * When MSI/MSI-X support is enabled in kernel-
+ * Default Value: 2 (MSI-X) when supported by hardware, 1 (MSI) otherwise
+ * When MSI/MSI-X support is not enabled in kernel-
+ * Default Value: 0 (legacy)
*
- * Default Value: 2 (MSI-X)
+ * When a mode is specified that is not allowed/supported, it will be
+ * demoted to the most advanced interrupt mode available.
*/
E1000_PARAM(IntMode, "Interrupt Mode");
#define MAX_INTMODE 2
@@ -388,12 +397,33 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
static struct e1000_option opt = {
.type = range_option,
.name = "Interrupt Mode",
- .err = "defaulting to 2 (MSI-X)",
- .def = E1000E_INT_MODE_MSIX,
- .arg = { .r = { .min = MIN_INTMODE,
- .max = MAX_INTMODE } }
+#ifndef CONFIG_PCI_MSI
+ .err = "defaulting to 0 (legacy)",
+ .def = E1000E_INT_MODE_LEGACY,
+ .arg = { .r = { .min = 0,
+ .max = 0 } }
+#endif
};
+#ifdef CONFIG_PCI_MSI
+ if (adapter->flags & FLAG_HAS_MSIX) {
+ opt.err = kstrdup("defaulting to 2 (MSI-X)",
+ GFP_KERNEL);
+ opt.def = E1000E_INT_MODE_MSIX;
+ opt.arg.r.max = E1000E_INT_MODE_MSIX;
+ } else {
+ opt.err = kstrdup("defaulting to 1 (MSI)", GFP_KERNEL);
+ opt.def = E1000E_INT_MODE_MSI;
+ opt.arg.r.max = E1000E_INT_MODE_MSI;
+ }
+
+ if (!opt.err) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to allocate memory\n");
+ return;
+ }
+#endif
+
if (num_IntMode > bd) {
unsigned int int_mode = IntMode[bd];
e1000_validate_option(&int_mode, &opt, adapter);
@@ -401,6 +431,10 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
} else {
adapter->int_mode = opt.def;
}
+
+#ifdef CONFIG_PCI_MSI
+ kfree(opt.err);
+#endif
}
{ /* Smart Power Down */
static const struct e1000_option opt = {
@@ -429,10 +463,13 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
if (num_CrcStripping > bd) {
unsigned int crc_stripping = CrcStripping[bd];
e1000_validate_option(&crc_stripping, &opt, adapter);
- if (crc_stripping == OPTION_ENABLED)
+ if (crc_stripping == OPTION_ENABLED) {
adapter->flags2 |= FLAG2_CRC_STRIPPING;
+ adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING;
+ }
} else {
adapter->flags2 |= FLAG2_CRC_STRIPPING;
+ adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING;
}
}
{ /* Kumeran Lock Loss Workaround */
diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
index 8666476cb9be..683abac4a049 100644
--- a/drivers/net/ethernet/intel/e1000e/phy.c
+++ b/drivers/net/ethernet/intel/e1000e/phy.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel PRO/1000 Linux driver
- Copyright(c) 1999 - 2011 Intel Corporation.
+ Copyright(c) 1999 - 2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -132,30 +132,30 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw)
u16 phy_id;
u16 retry_count = 0;
- if (!(phy->ops.read_reg))
- goto out;
+ if (!phy->ops.read_reg)
+ return 0;
while (retry_count < 2) {
ret_val = e1e_rphy(hw, PHY_ID1, &phy_id);
if (ret_val)
- goto out;
+ return ret_val;
phy->id = (u32)(phy_id << 16);
udelay(20);
ret_val = e1e_rphy(hw, PHY_ID2, &phy_id);
if (ret_val)
- goto out;
+ return ret_val;
phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
if (phy->id != 0 && phy->id != PHY_REVISION_MASK)
- goto out;
+ return 0;
retry_count++;
}
-out:
- return ret_val;
+
+ return 0;
}
/**
@@ -382,29 +382,25 @@ static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
s32 ret_val = 0;
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!hw->phy.ops.acquire)
+ return 0;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
- if (offset > MAX_PHY_MULTI_PAGE_REG) {
+ if (offset > MAX_PHY_MULTI_PAGE_REG)
ret_val = e1000e_write_phy_reg_mdic(hw,
IGP01E1000_PHY_PAGE_SELECT,
(u16)offset);
- if (ret_val)
- goto release;
- }
-
- ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
-
-release:
+ if (!ret_val)
+ ret_val = e1000e_read_phy_reg_mdic(hw,
+ MAX_PHY_REG_ADDRESS & offset,
+ data);
if (!locked)
hw->phy.ops.release(hw);
-out:
+
return ret_val;
}
@@ -453,30 +449,25 @@ static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
s32 ret_val = 0;
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!hw->phy.ops.acquire)
+ return 0;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
- if (offset > MAX_PHY_MULTI_PAGE_REG) {
+ if (offset > MAX_PHY_MULTI_PAGE_REG)
ret_val = e1000e_write_phy_reg_mdic(hw,
IGP01E1000_PHY_PAGE_SELECT,
(u16)offset);
- if (ret_val)
- goto release;
- }
-
- ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
-
-release:
+ if (!ret_val)
+ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS &
+ offset,
+ data);
if (!locked)
hw->phy.ops.release(hw);
-out:
return ret_val;
}
@@ -523,15 +514,16 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
bool locked)
{
u32 kmrnctrlsta;
- s32 ret_val = 0;
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ s32 ret_val = 0;
+
+ if (!hw->phy.ops.acquire)
+ return 0;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
@@ -547,8 +539,7 @@ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
if (!locked)
hw->phy.ops.release(hw);
-out:
- return ret_val;
+ return 0;
}
/**
@@ -596,15 +587,16 @@ static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
bool locked)
{
u32 kmrnctrlsta;
- s32 ret_val = 0;
if (!locked) {
- if (!(hw->phy.ops.acquire))
- goto out;
+ s32 ret_val = 0;
+
+ if (!hw->phy.ops.acquire)
+ return 0;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- goto out;
+ return ret_val;
}
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
@@ -617,8 +609,7 @@ static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
if (!locked)
hw->phy.ops.release(hw);
-out:
- return ret_val;
+ return 0;
}
/**
@@ -663,17 +654,14 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
/* Enable CRS on Tx. This must be set for half-duplex operation. */
ret_val = e1e_rphy(hw, I82577_CFG_REG, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
/* Enable downshift */
phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
- ret_val = e1e_wphy(hw, I82577_CFG_REG, phy_data);
-
-out:
- return ret_val;
+ return e1e_wphy(hw, I82577_CFG_REG, phy_data);
}
/**
@@ -1064,8 +1052,7 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
break;
default:
e_dbg("Flow control param set incorrectly\n");
- ret_val = -E1000_ERR_CONFIG;
- return ret_val;
+ return -E1000_ERR_CONFIG;
}
ret_val = e1e_wphy(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
@@ -1136,13 +1123,12 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
if (phy->autoneg_wait_to_complete) {
ret_val = e1000_wait_autoneg(hw);
if (ret_val) {
- e_dbg("Error while waiting for "
- "autoneg to complete\n");
+ e_dbg("Error while waiting for autoneg to complete\n");
return ret_val;
}
}
- hw->mac.get_link_status = 1;
+ hw->mac.get_link_status = true;
return ret_val;
}
@@ -1195,7 +1181,7 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw)
if (link) {
e_dbg("Valid link established!!!\n");
- e1000e_config_collision_dist(hw);
+ hw->mac.ops.config_collision_dist(hw);
ret_val = e1000e_config_fc_after_link_up(hw);
} else {
e_dbg("Unable to establish link!!!\n");
@@ -1266,8 +1252,6 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
PHY_FORCE_LIMIT,
100000,
&link);
- if (ret_val)
- return ret_val;
}
return ret_val;
@@ -1401,25 +1385,25 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
ret_val = e1e_rphy(hw, PHY_CONTROL, &data);
if (ret_val)
- goto out;
+ return ret_val;
e1000e_phy_force_speed_duplex_setup(hw, &data);
ret_val = e1e_wphy(hw, PHY_CONTROL, data);
if (ret_val)
- goto out;
+ return ret_val;
/* Disable MDI-X support for 10/100 */
ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= ~IFE_PMC_AUTO_MDIX;
data &= ~IFE_PMC_FORCE_MDIX;
ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, data);
if (ret_val)
- goto out;
+ return ret_val;
e_dbg("IFE PMC: %X\n", data);
@@ -1433,7 +1417,7 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
100000,
&link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link)
e_dbg("Link taking longer than expected.\n");
@@ -1444,11 +1428,10 @@ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
100000,
&link);
if (ret_val)
- goto out;
+ return ret_val;
}
-out:
- return ret_val;
+ return 0;
}
/**
@@ -1506,7 +1489,7 @@ void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
e_dbg("Forcing 10mb\n");
}
- e1000e_config_collision_dist(hw);
+ hw->mac.ops.config_collision_dist(hw);
ew32(CTRL, ctrl);
}
@@ -1833,22 +1816,20 @@ s32 e1000e_get_cable_length_m88(struct e1000_hw *hw)
ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
M88E1000_PSSR_CABLE_LENGTH_SHIFT;
- if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
- ret_val = -E1000_ERR_PHY;
- goto out;
- }
+
+ if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
+ return -E1000_ERR_PHY;
phy->min_cable_length = e1000_m88_cable_length_table[index];
phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
-out:
- return ret_val;
+ return 0;
}
/**
@@ -1918,7 +1899,7 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw)
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
- return ret_val;
+ return 0;
}
/**
@@ -2073,24 +2054,23 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
e_dbg("Phy info is only valid if link is up\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data);
if (ret_val)
- goto out;
+ return ret_val;
phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE)
? false : true;
if (phy->polarity_correction) {
ret_val = e1000_check_polarity_ife(hw);
if (ret_val)
- goto out;
+ return ret_val;
} else {
/* Polarity is forced */
phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)
@@ -2100,7 +2080,7 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data);
if (ret_val)
- goto out;
+ return ret_val;
phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? true : false;
@@ -2109,8 +2089,7 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
phy->local_rx = e1000_1000t_rx_status_undefined;
phy->remote_rx = e1000_1000t_rx_status_undefined;
-out:
- return ret_val;
+ return 0;
}
/**
@@ -2154,7 +2133,7 @@ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw)
s32 ret_val;
u32 ctrl;
- ret_val = e1000_check_reset_block(hw);
+ ret_val = phy->ops.check_reset_block(hw);
if (ret_val)
return 0;
@@ -2369,7 +2348,6 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id)
**/
s32 e1000e_determine_phy_address(struct e1000_hw *hw)
{
- s32 ret_val = -E1000_ERR_PHY_TYPE;
u32 phy_addr = 0;
u32 i;
enum e1000_phy_type phy_type = e1000_phy_unknown;
@@ -2388,17 +2366,15 @@ s32 e1000e_determine_phy_address(struct e1000_hw *hw)
* If phy_type is valid, break - we found our
* PHY address
*/
- if (phy_type != e1000_phy_unknown) {
- ret_val = 0;
- goto out;
- }
+ if (phy_type != e1000_phy_unknown)
+ return 0;
+
usleep_range(1000, 2000);
i++;
} while (i < 10);
}
-out:
- return ret_val;
+ return -E1000_ERR_PHY_TYPE;
}
/**
@@ -2439,7 +2415,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
false, false);
- goto out;
+ goto release;
}
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
@@ -2464,13 +2440,13 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
(page << page_shift));
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -2498,7 +2474,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
true, false);
- goto out;
+ goto release;
}
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
@@ -2523,12 +2499,12 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
(page << page_shift));
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -2556,7 +2532,7 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
true, false);
- goto out;
+ goto release;
}
hw->phy.addr = 1;
@@ -2568,12 +2544,12 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
page);
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -2600,7 +2576,7 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
false, false);
- goto out;
+ goto release;
}
hw->phy.addr = 1;
@@ -2611,13 +2587,13 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
page);
if (ret_val)
- goto out;
+ goto release;
}
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
-out:
+release:
hw->phy.ops.release(hw);
return ret_val;
}
@@ -2642,14 +2618,14 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
if (ret_val) {
e_dbg("Could not set Port Control page\n");
- goto out;
+ return ret_val;
}
ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
if (ret_val) {
e_dbg("Could not read PHY register %d.%d\n",
BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
- goto out;
+ return ret_val;
}
/*
@@ -2664,15 +2640,14 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
if (ret_val) {
e_dbg("Could not write PHY register %d.%d\n",
BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
- goto out;
+ return ret_val;
}
- /* Select Host Wakeup Registers page */
- ret_val = e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
-
- /* caller now able to write registers on the Wakeup registers page */
-out:
- return ret_val;
+ /*
+ * 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));
}
/**
@@ -2694,7 +2669,7 @@ s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
if (ret_val) {
e_dbg("Could not set Port Control page\n");
- goto out;
+ return ret_val;
}
/* Restore 769.17 to its original value */
@@ -2702,7 +2677,7 @@ s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
if (ret_val)
e_dbg("Could not restore PHY register %d.%d\n",
BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
-out:
+
return ret_val;
}
@@ -2750,7 +2725,7 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
if (ret_val) {
e_dbg("Could not enable PHY wakeup reg access\n");
- goto out;
+ return ret_val;
}
}
@@ -2760,7 +2735,7 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
if (ret_val) {
e_dbg("Could not write address opcode to page %d\n", page);
- goto out;
+ return ret_val;
}
if (read) {
@@ -2775,13 +2750,12 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
if (ret_val) {
e_dbg("Could not access PHY reg %d.%d\n", page, reg);
- goto out;
+ return ret_val;
}
if (!page_set)
ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
-out:
return ret_val;
}
@@ -3137,7 +3111,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
if (ret_val) {
e_dbg("Could not write the Address Offset port register\n");
- goto out;
+ return ret_val;
}
/* Read or write the data value next */
@@ -3146,12 +3120,9 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
else
ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data);
- if (ret_val) {
+ if (ret_val)
e_dbg("Could not access the Data port register\n");
- goto out;
- }
-out:
return ret_val;
}
@@ -3172,17 +3143,17 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
u16 data;
if (hw->phy.type != e1000_phy_82578)
- goto out;
+ return 0;
/* Do not apply workaround if in PHY loopback bit 14 set */
e1e_rphy(hw, PHY_CONTROL, &data);
if (data & PHY_CONTROL_LB)
- goto out;
+ return 0;
/* check if link is up and at 1Gbps */
ret_val = e1e_rphy(hw, BM_CS_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
data &= BM_CS_STATUS_LINK_UP |
BM_CS_STATUS_RESOLVED |
@@ -3191,7 +3162,7 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
if (data != (BM_CS_STATUS_LINK_UP |
BM_CS_STATUS_RESOLVED |
BM_CS_STATUS_SPEED_1000))
- goto out;
+ return 0;
mdelay(200);
@@ -3199,12 +3170,9 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC |
HV_MUX_DATA_CTRL_FORCE_SPEED);
if (ret_val)
- goto out;
-
- ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC);
+ return ret_val;
-out:
- return ret_val;
+ return e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC);
}
/**
@@ -3246,13 +3214,13 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
e1000e_phy_force_speed_duplex_setup(hw, &phy_data);
ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data);
if (ret_val)
- goto out;
+ return ret_val;
udelay(1);
@@ -3264,7 +3232,7 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
100000,
&link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link)
e_dbg("Link taking longer than expected.\n");
@@ -3274,11 +3242,8 @@ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
PHY_FORCE_LIMIT,
100000,
&link);
- if (ret_val)
- goto out;
}
-out:
return ret_val;
}
@@ -3300,23 +3265,22 @@ s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
- goto out;
+ return ret_val;
if (!link) {
e_dbg("Phy info is only valid if link is up\n");
- ret_val = -E1000_ERR_CONFIG;
- goto out;
+ return -E1000_ERR_CONFIG;
}
phy->polarity_correction = true;
ret_val = e1000_check_polarity_82577(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data);
if (ret_val)
- goto out;
+ return ret_val;
phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? true : false;
@@ -3324,11 +3288,11 @@ s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
I82577_PHY_STATUS2_SPEED_1000MBPS) {
ret_val = hw->phy.ops.get_cable_length(hw);
if (ret_val)
- goto out;
+ return ret_val;
ret_val = e1e_rphy(hw, PHY_1000T_STATUS, &data);
if (ret_val)
- goto out;
+ return ret_val;
phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
? e1000_1000t_rx_status_ok
@@ -3343,8 +3307,7 @@ s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
phy->remote_rx = e1000_1000t_rx_status_undefined;
}
-out:
- return ret_val;
+ return 0;
}
/**
@@ -3362,7 +3325,7 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
ret_val = e1e_rphy(hw, I82577_PHY_DIAG_STATUS, &phy_data);
if (ret_val)
- goto out;
+ return ret_val;
length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
I82577_DSTATUS_CABLE_LENGTH_SHIFT;
@@ -3372,6 +3335,5 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
phy->cable_length = length;
-out:
- return ret_val;
+ return 0;
}
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 94be6c32fa7d..fda824735e18 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -173,7 +173,9 @@ static int igb_check_vf_assignment(struct igb_adapter *adapter);
#endif
#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int igb_suspend(struct device *);
+#endif
static int igb_resume(struct device *);
#ifdef CONFIG_PM_RUNTIME
static int igb_runtime_suspend(struct device *dev);
@@ -6710,6 +6712,7 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake,
}
#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int igb_suspend(struct device *dev)
{
int retval;
@@ -6729,6 +6732,7 @@ static int igb_suspend(struct device *dev)
return 0;
}
+#endif /* CONFIG_PM_SLEEP */
static int igb_resume(struct device *dev)
{
diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c
index db7dce2351c2..8ce67064b9c5 100644
--- a/drivers/net/ethernet/intel/igbvf/ethtool.c
+++ b/drivers/net/ethernet/intel/igbvf/ethtool.c
@@ -343,10 +343,10 @@ static int igbvf_get_coalesce(struct net_device *netdev,
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
- if (adapter->itr_setting <= 3)
- ec->rx_coalesce_usecs = adapter->itr_setting;
+ if (adapter->requested_itr <= 3)
+ ec->rx_coalesce_usecs = adapter->requested_itr;
else
- ec->rx_coalesce_usecs = adapter->itr_setting >> 2;
+ ec->rx_coalesce_usecs = adapter->current_itr >> 2;
return 0;
}
@@ -365,15 +365,16 @@ static int igbvf_set_coalesce(struct net_device *netdev,
/* convert to rate of irq's per second */
if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) {
- adapter->itr = IGBVF_START_ITR;
- adapter->itr_setting = ec->rx_coalesce_usecs;
+ adapter->current_itr = IGBVF_START_ITR;
+ adapter->requested_itr = ec->rx_coalesce_usecs;
} else {
- adapter->itr = ec->rx_coalesce_usecs << 2;
- adapter->itr_setting = adapter->itr;
+ adapter->current_itr = ec->rx_coalesce_usecs << 2;
+ adapter->requested_itr = 1000000000 /
+ (adapter->current_itr * 256);
}
- writel(adapter->itr,
- hw->hw_addr + adapter->rx_ring[0].itr_register);
+ writel(adapter->current_itr,
+ hw->hw_addr + adapter->rx_ring->itr_register);
return 0;
}
diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h
index 2c6d87e4d3d9..a895e2f7b34d 100644
--- a/drivers/net/ethernet/intel/igbvf/igbvf.h
+++ b/drivers/net/ethernet/intel/igbvf/igbvf.h
@@ -43,7 +43,18 @@ struct igbvf_info;
struct igbvf_adapter;
/* Interrupt defines */
-#define IGBVF_START_ITR 648 /* ~6000 ints/sec */
+#define IGBVF_START_ITR 488 /* ~8000 ints/sec */
+#define IGBVF_4K_ITR 980
+#define IGBVF_20K_ITR 196
+#define IGBVF_70K_ITR 56
+
+enum latency_range {
+ lowest_latency = 0,
+ low_latency = 1,
+ bulk_latency = 2,
+ latency_invalid = 255
+};
+
/* Interrupt modes, as used by the IntMode parameter */
#define IGBVF_INT_MODE_LEGACY 0
@@ -155,6 +166,7 @@ struct igbvf_ring {
char name[IFNAMSIZ + 5];
u32 eims_value;
u32 itr_val;
+ enum latency_range itr_range;
u16 itr_register;
int set_itr;
@@ -187,10 +199,8 @@ struct igbvf_adapter {
unsigned long state;
/* Interrupt Throttle Rate */
- u32 itr;
- u32 itr_setting;
- u16 tx_itr;
- u16 rx_itr;
+ u32 requested_itr; /* ints/sec or adaptive */
+ u32 current_itr; /* Actual ITR register value, not ints/sec */
/*
* Tx
@@ -299,13 +309,6 @@ enum igbvf_state_t {
__IGBVF_DOWN
};
-enum latency_range {
- lowest_latency = 0,
- low_latency = 1,
- bulk_latency = 2,
- latency_invalid = 255
-};
-
extern char igbvf_driver_name[];
extern const char igbvf_driver_version[];
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 4e9141cfe81d..217c143686d2 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -632,14 +632,13 @@ void igbvf_free_rx_resources(struct igbvf_ring *rx_ring)
* traffic pattern. Constants in this function were computed
* based on theoretical maximum wire speed and thresholds were set based
* on testing data as well as attempting to minimize response time
- * while increasing bulk throughput. This functionality is controlled
- * by the InterruptThrottleRate module parameter.
+ * while increasing bulk throughput.
**/
-static unsigned int igbvf_update_itr(struct igbvf_adapter *adapter,
- u16 itr_setting, int packets,
- int bytes)
+static enum latency_range igbvf_update_itr(struct igbvf_adapter *adapter,
+ enum latency_range itr_setting,
+ int packets, int bytes)
{
- unsigned int retval = itr_setting;
+ enum latency_range retval = itr_setting;
if (packets == 0)
goto update_itr_done;
@@ -675,65 +674,87 @@ static unsigned int igbvf_update_itr(struct igbvf_adapter *adapter,
retval = low_latency;
}
break;
+ default:
+ break;
}
update_itr_done:
return retval;
}
-static void igbvf_set_itr(struct igbvf_adapter *adapter)
+static int igbvf_range_to_itr(enum latency_range current_range)
{
- struct e1000_hw *hw = &adapter->hw;
- u16 current_itr;
- u32 new_itr = adapter->itr;
-
- adapter->tx_itr = igbvf_update_itr(adapter, adapter->tx_itr,
- adapter->total_tx_packets,
- adapter->total_tx_bytes);
- /* conservative mode (itr 3) eliminates the lowest_latency setting */
- if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency)
- adapter->tx_itr = low_latency;
-
- adapter->rx_itr = igbvf_update_itr(adapter, adapter->rx_itr,
- adapter->total_rx_packets,
- adapter->total_rx_bytes);
- /* conservative mode (itr 3) eliminates the lowest_latency setting */
- if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency)
- adapter->rx_itr = low_latency;
-
- current_itr = max(adapter->rx_itr, adapter->tx_itr);
+ int new_itr;
- switch (current_itr) {
+ switch (current_range) {
/* counts and packets in update_itr are dependent on these numbers */
case lowest_latency:
- new_itr = 70000;
+ new_itr = IGBVF_70K_ITR;
break;
case low_latency:
- new_itr = 20000; /* aka hwitr = ~200 */
+ new_itr = IGBVF_20K_ITR;
break;
case bulk_latency:
- new_itr = 4000;
+ new_itr = IGBVF_4K_ITR;
break;
default:
+ new_itr = IGBVF_START_ITR;
break;
}
+ return new_itr;
+}
+
+static void igbvf_set_itr(struct igbvf_adapter *adapter)
+{
+ u32 new_itr;
+
+ adapter->tx_ring->itr_range =
+ igbvf_update_itr(adapter,
+ adapter->tx_ring->itr_val,
+ adapter->total_tx_packets,
+ adapter->total_tx_bytes);
+
+ /* conservative mode (itr 3) eliminates the lowest_latency setting */
+ if (adapter->requested_itr == 3 &&
+ adapter->tx_ring->itr_range == lowest_latency)
+ adapter->tx_ring->itr_range = low_latency;
+
+ new_itr = igbvf_range_to_itr(adapter->tx_ring->itr_range);
+
- if (new_itr != adapter->itr) {
+ if (new_itr != adapter->tx_ring->itr_val) {
+ u32 current_itr = adapter->tx_ring->itr_val;
/*
* this attempts to bias the interrupt rate towards Bulk
* by adding intermediate steps when interrupt rate is
* increasing
*/
- new_itr = new_itr > adapter->itr ?
- min(adapter->itr + (new_itr >> 2), new_itr) :
- new_itr;
- adapter->itr = new_itr;
- adapter->rx_ring->itr_val = 1952;
-
- if (adapter->msix_entries)
- adapter->rx_ring->set_itr = 1;
- else
- ew32(ITR, 1952);
+ new_itr = new_itr > current_itr ?
+ min(current_itr + (new_itr >> 2), new_itr) :
+ new_itr;
+ adapter->tx_ring->itr_val = new_itr;
+
+ adapter->tx_ring->set_itr = 1;
+ }
+
+ adapter->rx_ring->itr_range =
+ igbvf_update_itr(adapter, adapter->rx_ring->itr_val,
+ adapter->total_rx_packets,
+ adapter->total_rx_bytes);
+ if (adapter->requested_itr == 3 &&
+ adapter->rx_ring->itr_range == lowest_latency)
+ adapter->rx_ring->itr_range = low_latency;
+
+ new_itr = igbvf_range_to_itr(adapter->rx_ring->itr_range);
+
+ if (new_itr != adapter->rx_ring->itr_val) {
+ u32 current_itr = adapter->rx_ring->itr_val;
+ new_itr = new_itr > current_itr ?
+ min(current_itr + (new_itr >> 2), new_itr) :
+ new_itr;
+ adapter->rx_ring->itr_val = new_itr;
+
+ adapter->rx_ring->set_itr = 1;
}
}
@@ -835,6 +856,11 @@ static irqreturn_t igbvf_intr_msix_tx(int irq, void *data)
struct e1000_hw *hw = &adapter->hw;
struct igbvf_ring *tx_ring = adapter->tx_ring;
+ if (tx_ring->set_itr) {
+ writel(tx_ring->itr_val,
+ adapter->hw.hw_addr + tx_ring->itr_register);
+ adapter->tx_ring->set_itr = 0;
+ }
adapter->total_tx_bytes = 0;
adapter->total_tx_packets = 0;
@@ -937,19 +963,10 @@ static void igbvf_configure_msix(struct igbvf_adapter *adapter)
igbvf_assign_vector(adapter, IGBVF_NO_QUEUE, 0, vector++);
adapter->eims_enable_mask |= tx_ring->eims_value;
- if (tx_ring->itr_val)
- writel(tx_ring->itr_val,
- hw->hw_addr + tx_ring->itr_register);
- else
- writel(1952, hw->hw_addr + tx_ring->itr_register);
-
+ writel(tx_ring->itr_val, hw->hw_addr + tx_ring->itr_register);
igbvf_assign_vector(adapter, 0, IGBVF_NO_QUEUE, vector++);
adapter->eims_enable_mask |= rx_ring->eims_value;
- if (rx_ring->itr_val)
- writel(rx_ring->itr_val,
- hw->hw_addr + rx_ring->itr_register);
- else
- writel(1952, hw->hw_addr + rx_ring->itr_register);
+ writel(rx_ring->itr_val, hw->hw_addr + rx_ring->itr_register);
/* set vector for other causes, i.e. link changes */
@@ -1027,7 +1044,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)
goto out;
adapter->tx_ring->itr_register = E1000_EITR(vector);
- adapter->tx_ring->itr_val = 1952;
+ adapter->tx_ring->itr_val = adapter->current_itr;
vector++;
err = request_irq(adapter->msix_entries[vector].vector,
@@ -1037,7 +1054,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)
goto out;
adapter->rx_ring->itr_register = E1000_EITR(vector);
- adapter->rx_ring->itr_val = 1952;
+ adapter->rx_ring->itr_val = adapter->current_itr;
vector++;
err = request_irq(adapter->msix_entries[vector].vector,
@@ -1151,7 +1168,7 @@ static int igbvf_poll(struct napi_struct *napi, int budget)
if (work_done < budget) {
napi_complete(napi);
- if (adapter->itr_setting & 3)
+ if (adapter->requested_itr & 3)
igbvf_set_itr(adapter);
if (!test_bit(__IGBVF_DOWN, &adapter->state))
@@ -1521,8 +1538,8 @@ static int __devinit igbvf_sw_init(struct igbvf_adapter *adapter)
adapter->tx_abs_int_delay = 32;
adapter->rx_int_delay = 0;
adapter->rx_abs_int_delay = 8;
- adapter->itr_setting = 3;
- adapter->itr = 20000;
+ adapter->requested_itr = 3;
+ adapter->current_itr = IGBVF_START_ITR;
/* Set various function pointers */
adapter->ei->init_ops(&adapter->hw);
@@ -1695,6 +1712,7 @@ static int igbvf_set_mac(struct net_device *netdev, void *p)
return -EADDRNOTAVAIL;
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
return 0;
}
@@ -2695,18 +2713,19 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
dev_info(&pdev->dev,
"PF still in reset state, assigning new address."
" Is the PF interface up?\n");
- dev_hw_addr_random(adapter->netdev, hw->mac.addr);
+ eth_hw_addr_random(netdev);
+ memcpy(adapter->hw.mac.addr, netdev->dev_addr,
+ netdev->addr_len);
} else {
err = hw->mac.ops.read_mac_addr(hw);
if (err) {
dev_err(&pdev->dev, "Error reading MAC address\n");
goto err_hw_init;
}
+ memcpy(netdev->dev_addr, adapter->hw.mac.addr,
+ netdev->addr_len);
}
- memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
- memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
-
if (!is_valid_ether_addr(netdev->perm_addr)) {
dev_err(&pdev->dev, "Invalid MAC Address: %pM\n",
netdev->dev_addr);
@@ -2714,6 +2733,8 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
goto err_hw_init;
}
+ memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
+
setup_timer(&adapter->watchdog_timer, &igbvf_watchdog,
(unsigned long) adapter);
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_ee.c b/drivers/net/ethernet/intel/ixgb/ixgb_ee.c
index 2ed925f38811..eca216b9b859 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_ee.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_ee.c
@@ -533,10 +533,8 @@ __le16
ixgb_get_eeprom_word(struct ixgb_hw *hw, u16 index)
{
- if ((index < IXGB_EEPROM_SIZE) &&
- (ixgb_check_and_get_eeprom_data(hw) == true)) {
- return hw->eeprom[index];
- }
+ if (index < IXGB_EEPROM_SIZE && ixgb_check_and_get_eeprom_data(hw))
+ return hw->eeprom[index];
return 0;
}
@@ -558,7 +556,7 @@ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
ENTER();
- if (ixgb_check_and_get_eeprom_data(hw) == true) {
+ if (ixgb_check_and_get_eeprom_data(hw)) {
for (i = 0; i < ETH_ALEN; i++) {
mac_addr[i] = ee_map->mac_addr[i];
}
@@ -578,7 +576,7 @@ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
u32
ixgb_get_ee_pba_number(struct ixgb_hw *hw)
{
- if (ixgb_check_and_get_eeprom_data(hw) == true)
+ if (ixgb_check_and_get_eeprom_data(hw))
return le16_to_cpu(hw->eeprom[EEPROM_PBA_1_2_REG])
| (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG])<<16);
@@ -599,7 +597,7 @@ ixgb_get_ee_device_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
- if (ixgb_check_and_get_eeprom_data(hw) == true)
+ if (ixgb_check_and_get_eeprom_data(hw))
return le16_to_cpu(ee_map->device_id);
return 0;
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 9bd5faf64a85..002478801a1b 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -1136,10 +1136,8 @@ ixgb_set_multi(struct net_device *netdev)
u8 *mta = kmalloc(IXGB_MAX_NUM_MULTICAST_ADDRESSES *
ETH_ALEN, GFP_ATOMIC);
u8 *addr;
- if (!mta) {
- pr_err("allocation of multicast memory failed\n");
+ if (!mta)
goto alloc_failed;
- }
IXGB_WRITE_REG(hw, RCTL, rctl);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index e6aeb64105a4..2807a25e04e6 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -190,6 +190,7 @@ struct ixgbe_rx_queue_stats {
u64 non_eop_descs;
u64 alloc_rx_page_failed;
u64 alloc_rx_buff_failed;
+ u64 csum_err;
};
enum ixbge_ring_state_t {
@@ -198,6 +199,7 @@ enum ixbge_ring_state_t {
__IXGBE_HANG_CHECK_ARMED,
__IXGBE_RX_PS_ENABLED,
__IXGBE_RX_RSC_ENABLED,
+ __IXGBE_RX_CSUM_UDP_ZERO_ERR,
};
#define ring_is_ps_enabled(ring) \
@@ -329,6 +331,13 @@ struct ixgbe_q_vector {
#define IXGBE_10K_ITR 400
#define IXGBE_8K_ITR 500
+/* ixgbe_test_staterr - tests bits in Rx descriptor status and error fields */
+static inline __le32 ixgbe_test_staterr(union ixgbe_adv_rx_desc *rx_desc,
+ const u32 stat_err_bits)
+{
+ return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits);
+}
+
static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring)
{
u16 ntc = ring->next_to_clean;
@@ -337,11 +346,11 @@ static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring)
return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
}
-#define IXGBE_RX_DESC_ADV(R, i) \
+#define IXGBE_RX_DESC(R, i) \
(&(((union ixgbe_adv_rx_desc *)((R)->desc))[i]))
-#define IXGBE_TX_DESC_ADV(R, i) \
+#define IXGBE_TX_DESC(R, i) \
(&(((union ixgbe_adv_tx_desc *)((R)->desc))[i]))
-#define IXGBE_TX_CTXTDESC_ADV(R, i) \
+#define IXGBE_TX_CTXTDESC(R, i) \
(&(((struct ixgbe_adv_tx_context_desc *)((R)->desc))[i]))
#define IXGBE_MAX_JUMBO_FRAME_SIZE 16128
@@ -372,7 +381,6 @@ struct ixgbe_adapter {
* thus the additional *_CAPABLE flags.
*/
u32 flags;
-#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1)
#define IXGBE_FLAG_MSI_CAPABLE (u32)(1 << 1)
#define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 2)
#define IXGBE_FLAG_MSIX_CAPABLE (u32)(1 << 3)
@@ -535,12 +543,16 @@ enum ixbge_state_t {
__IXGBE_IN_SFP_INIT,
};
-struct ixgbe_rsc_cb {
+struct ixgbe_cb {
+ union { /* Union defining head/tail partner */
+ struct sk_buff *head;
+ struct sk_buff *tail;
+ };
dma_addr_t dma;
- u16 skb_cnt;
+ u16 append_cnt;
bool delay_unmap;
};
-#define IXGBE_RSC_CB(skb) ((struct ixgbe_rsc_cb *)(skb)->cb)
+#define IXGBE_CB(skb) ((struct ixgbe_cb *)(skb)->cb)
enum ixgbe_boards {
board_82598,
@@ -614,8 +626,7 @@ extern int ixgbe_fso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter);
extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
union ixgbe_adv_rx_desc *rx_desc,
- struct sk_buff *skb,
- u32 staterr);
+ struct sk_buff *skb);
extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
struct scatterlist *sgl, unsigned int sgc);
extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index b406c367b190..752dbe6f0f54 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -617,7 +617,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
*link_up = false;
}
- if (*link_up == false)
+ if (!*link_up)
goto out;
}
@@ -645,7 +645,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
else
*speed = IXGBE_LINK_SPEED_1GB_FULL;
- if ((hw->device_id == IXGBE_DEV_ID_82598AT2) && (*link_up == true) &&
+ if ((hw->device_id == IXGBE_DEV_ID_82598AT2) && *link_up &&
(ixgbe_validate_link_ready(hw) != 0))
*link_up = false;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index a62975480e37..8e2e4732b1a7 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -1739,7 +1739,7 @@ static u16 ixgbe_clean_test_rings(struct ixgbe_ring *rx_ring,
/* initialize next to clean and descriptor values */
rx_ntc = rx_ring->next_to_clean;
tx_ntc = tx_ring->next_to_clean;
- rx_desc = IXGBE_RX_DESC_ADV(rx_ring, rx_ntc);
+ rx_desc = IXGBE_RX_DESC(rx_ring, rx_ntc);
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
while (staterr & IXGBE_RXD_STAT_DD) {
@@ -1770,7 +1770,7 @@ static u16 ixgbe_clean_test_rings(struct ixgbe_ring *rx_ring,
tx_ntc = 0;
/* fetch next descriptor */
- rx_desc = IXGBE_RX_DESC_ADV(rx_ring, rx_ntc);
+ rx_desc = IXGBE_RX_DESC(rx_ring, rx_ntc);
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index 4bc794249801..da7da752b6b4 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -357,22 +357,20 @@ int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
*/
int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
union ixgbe_adv_rx_desc *rx_desc,
- struct sk_buff *skb,
- u32 staterr)
+ struct sk_buff *skb)
{
- u16 xid;
- u32 fctl;
- u32 fceofe, fcerr, fcstat;
int rc = -EINVAL;
struct ixgbe_fcoe *fcoe;
struct ixgbe_fcoe_ddp *ddp;
struct fc_frame_header *fh;
struct fcoe_crc_eof *crc;
+ __le32 fcerr = ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_FCERR);
+ __le32 ddp_err;
+ u32 fctl;
+ u16 xid;
- fcerr = (staterr & IXGBE_RXDADV_ERR_FCERR);
- fceofe = (staterr & IXGBE_RXDADV_ERR_FCEOFE);
- if (fcerr == IXGBE_FCERR_BADCRC)
- skb_checksum_none_assert(skb);
+ if (fcerr == cpu_to_le32(IXGBE_FCERR_BADCRC))
+ skb->ip_summed = CHECKSUM_NONE;
else
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -382,6 +380,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
else
fh = (struct fc_frame_header *)(skb->data +
sizeof(struct fcoe_hdr));
+
fctl = ntoh24(fh->fh_f_ctl);
if (fctl & FC_FC_EX_CTX)
xid = be16_to_cpu(fh->fh_ox_id);
@@ -396,27 +395,39 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
if (!ddp->udl)
goto ddp_out;
- if (fcerr | fceofe)
+ ddp_err = ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_FCEOFE |
+ IXGBE_RXDADV_ERR_FCERR);
+ if (ddp_err)
goto ddp_out;
- fcstat = (staterr & IXGBE_RXDADV_STAT_FCSTAT);
- if (fcstat) {
+ switch (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_FCSTAT)) {
+ /* return 0 to bypass going to ULD for DDPed data */
+ case __constant_cpu_to_le32(IXGBE_RXDADV_STAT_FCSTAT_DDP):
/* update length of DDPed data */
ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
- /* unmap the sg list when FCP_RSP is received */
- if (fcstat == IXGBE_RXDADV_STAT_FCSTAT_FCPRSP) {
- pci_unmap_sg(adapter->pdev, ddp->sgl,
- ddp->sgc, DMA_FROM_DEVICE);
- ddp->err = (fcerr | fceofe);
- ddp->sgl = NULL;
- ddp->sgc = 0;
- }
- /* return 0 to bypass going to ULD for DDPed data */
- if (fcstat == IXGBE_RXDADV_STAT_FCSTAT_DDP)
- rc = 0;
- else if (ddp->len)
+ rc = 0;
+ break;
+ /* unmap the sg list when FCPRSP is received */
+ case __constant_cpu_to_le32(IXGBE_RXDADV_STAT_FCSTAT_FCPRSP):
+ pci_unmap_sg(adapter->pdev, ddp->sgl,
+ ddp->sgc, DMA_FROM_DEVICE);
+ ddp->err = ddp_err;
+ ddp->sgl = NULL;
+ ddp->sgc = 0;
+ /* fall through */
+ /* if DDP length is present pass it through to ULD */
+ case __constant_cpu_to_le32(IXGBE_RXDADV_STAT_FCSTAT_NODDP):
+ /* update length of DDPed data */
+ ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
+ if (ddp->len)
rc = ddp->len;
+ break;
+ /* no match will return as an error */
+ case __constant_cpu_to_le32(IXGBE_RXDADV_STAT_FCSTAT_NOMTCH):
+ default:
+ break;
}
+
/* In target mode, check the last data frame of the sequence.
* For DDP in target mode, data is already DDPed but the header
* indication of the last data frame ould allow is to tell if we
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 3dc6cef58107..4e55860fdcd4 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -131,6 +131,11 @@ MODULE_PARM_DESC(max_vfs,
"Maximum number of virtual functions to allocate per physical function");
#endif /* CONFIG_PCI_IOV */
+static unsigned int allow_unsupported_sfp;
+module_param(allow_unsupported_sfp, uint, 0);
+MODULE_PARM_DESC(allow_unsupported_sfp,
+ "Allow unsupported and untested SFP+ modules on 82599-based adapters");
+
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
MODULE_LICENSE("GPL");
@@ -361,7 +366,7 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
"leng ntw timestamp bi->skb\n");
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
- tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
+ tx_desc = IXGBE_TX_DESC(tx_ring, i);
tx_buffer_info = &tx_ring->tx_buffer_info[i];
u0 = (struct my_u0 *)tx_desc;
pr_info("T [0x%03X] %016llX %016llX %016llX"
@@ -442,7 +447,7 @@ rx_ring_summary:
for (i = 0; i < rx_ring->count; i++) {
rx_buffer_info = &rx_ring->rx_buffer_info[i];
- rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
+ rx_desc = IXGBE_RX_DESC(rx_ring, i);
u0 = (struct my_u0 *)rx_desc;
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
if (staterr & IXGBE_RXD_STAT_DD) {
@@ -749,7 +754,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
u16 i = tx_ring->next_to_clean;
tx_buffer = &tx_ring->tx_buffer_info[i];
- tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
+ tx_desc = IXGBE_TX_DESC(tx_ring, i);
for (; budget; budget--) {
union ixgbe_adv_tx_desc *eop_desc = tx_buffer->next_to_watch;
@@ -790,7 +795,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
i = 0;
tx_buffer = tx_ring->tx_buffer_info;
- tx_desc = IXGBE_TX_DESC_ADV(tx_ring, 0);
+ tx_desc = IXGBE_TX_DESC(tx_ring, 0);
}
} while (eop_desc);
@@ -807,7 +812,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) {
/* schedule immediate reset if we believe we hung */
struct ixgbe_hw *hw = &adapter->hw;
- tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
+ tx_desc = IXGBE_TX_DESC(tx_ring, i);
e_err(drv, "Detected Tx Unit Hang\n"
" Tx Queue <%d>\n"
" TDH, TDT <%x>, <%x>\n"
@@ -986,10 +991,12 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
}
#endif /* CONFIG_IXGBE_DCA */
-static inline void ixgbe_rx_hash(union ixgbe_adv_rx_desc *rx_desc,
+static inline void ixgbe_rx_hash(struct ixgbe_ring *ring,
+ union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
- skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
+ if (ring->netdev->features & NETIF_F_RXHASH)
+ skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
}
/**
@@ -1011,72 +1018,43 @@ static inline bool ixgbe_rx_is_fcoe(struct ixgbe_adapter *adapter,
}
/**
- * ixgbe_receive_skb - Send a completed packet up the stack
- * @adapter: board private structure
- * @skb: packet to send up
- * @status: hardware indication of status of receive
- * @rx_ring: rx descriptor ring (for a specific queue) to setup
- * @rx_desc: rx descriptor
- **/
-static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
- struct sk_buff *skb, u8 status,
- struct ixgbe_ring *ring,
- union ixgbe_adv_rx_desc *rx_desc)
-{
- struct ixgbe_adapter *adapter = q_vector->adapter;
- struct napi_struct *napi = &q_vector->napi;
- bool is_vlan = (status & IXGBE_RXD_STAT_VP);
- u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
-
- if (is_vlan && (tag & VLAN_VID_MASK))
- __vlan_hwaccel_put_tag(skb, tag);
-
- if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
- napi_gro_receive(napi, skb);
- else
- netif_rx(skb);
-}
-
-/**
* ixgbe_rx_checksum - indicate in skb if hw indicated a good cksum
- * @adapter: address of board private structure
- * @status_err: hardware indication of status of receive
+ * @ring: structure containing ring specific data
+ * @rx_desc: current Rx descriptor being processed
* @skb: skb currently being received and modified
- * @status_err: status error value of last descriptor in packet
**/
-static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
+static inline void ixgbe_rx_checksum(struct ixgbe_ring *ring,
union ixgbe_adv_rx_desc *rx_desc,
- struct sk_buff *skb,
- u32 status_err)
+ struct sk_buff *skb)
{
- skb->ip_summed = CHECKSUM_NONE;
+ skb_checksum_none_assert(skb);
/* Rx csum disabled */
- if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
+ if (!(ring->netdev->features & NETIF_F_RXCSUM))
return;
/* if IP and error */
- if ((status_err & IXGBE_RXD_STAT_IPCS) &&
- (status_err & IXGBE_RXDADV_ERR_IPE)) {
- adapter->hw_csum_rx_error++;
+ if (ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_IPCS) &&
+ ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_IPE)) {
+ ring->rx_stats.csum_err++;
return;
}
- if (!(status_err & IXGBE_RXD_STAT_L4CS))
+ if (!ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_L4CS))
return;
- if (status_err & IXGBE_RXDADV_ERR_TCPE) {
+ if (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_TCPE)) {
u16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
/*
* 82599 errata, UDP frames with a 0 checksum can be marked as
* checksum errors.
*/
- if ((pkt_info & IXGBE_RXDADV_PKTTYPE_UDP) &&
- (adapter->hw.mac.type == ixgbe_mac_82599EB))
+ if ((pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_UDP)) &&
+ test_bit(__IXGBE_RX_CSUM_UDP_ZERO_ERR, &ring->state))
return;
- adapter->hw_csum_rx_error++;
+ ring->rx_stats.csum_err++;
return;
}
@@ -1086,6 +1064,7 @@ static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
static inline void ixgbe_release_rx_desc(struct ixgbe_ring *rx_ring, u32 val)
{
+ rx_ring->next_to_use = val;
/*
* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
@@ -1096,8 +1075,72 @@ static inline void ixgbe_release_rx_desc(struct ixgbe_ring *rx_ring, u32 val)
writel(val, rx_ring->tail);
}
+static bool ixgbe_alloc_mapped_skb(struct ixgbe_ring *rx_ring,
+ struct ixgbe_rx_buffer *bi)
+{
+ struct sk_buff *skb = bi->skb;
+ dma_addr_t dma = bi->dma;
+
+ if (dma)
+ return true;
+
+ if (likely(!skb)) {
+ skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
+ rx_ring->rx_buf_len);
+ bi->skb = skb;
+ if (!skb) {
+ rx_ring->rx_stats.alloc_rx_buff_failed++;
+ return false;
+ }
+ }
+
+ dma = dma_map_single(rx_ring->dev, skb->data,
+ rx_ring->rx_buf_len, DMA_FROM_DEVICE);
+
+ if (dma_mapping_error(rx_ring->dev, dma)) {
+ rx_ring->rx_stats.alloc_rx_buff_failed++;
+ return false;
+ }
+
+ bi->dma = dma;
+ return true;
+}
+
+static bool ixgbe_alloc_mapped_page(struct ixgbe_ring *rx_ring,
+ struct ixgbe_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);
+
+ if (page_dma)
+ return true;
+
+ if (!page) {
+ page = alloc_page(GFP_ATOMIC | __GFP_COLD);
+ bi->page = page;
+ if (unlikely(!page)) {
+ rx_ring->rx_stats.alloc_rx_page_failed++;
+ return false;
+ }
+ }
+
+ page_dma = dma_map_page(rx_ring->dev, page,
+ page_offset, PAGE_SIZE / 2,
+ DMA_FROM_DEVICE);
+
+ if (dma_mapping_error(rx_ring->dev, page_dma)) {
+ rx_ring->rx_stats.alloc_rx_page_failed++;
+ return false;
+ }
+
+ bi->page_dma = page_dma;
+ bi->page_offset = page_offset;
+ return true;
+}
+
/**
- * ixgbe_alloc_rx_buffers - Replace used receive buffers; packet split
+ * ixgbe_alloc_rx_buffers - Replace used receive buffers
* @rx_ring: ring to place buffers on
* @cleaned_count: number of buffers to replace
**/
@@ -1105,86 +1148,50 @@ void ixgbe_alloc_rx_buffers(struct ixgbe_ring *rx_ring, u16 cleaned_count)
{
union ixgbe_adv_rx_desc *rx_desc;
struct ixgbe_rx_buffer *bi;
- struct sk_buff *skb;
u16 i = rx_ring->next_to_use;
- /* do nothing if no valid netdev defined */
- if (!rx_ring->netdev)
+ /* nothing to do or no valid netdev defined */
+ if (!cleaned_count || !rx_ring->netdev)
return;
- while (cleaned_count--) {
- rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
- bi = &rx_ring->rx_buffer_info[i];
- skb = bi->skb;
-
- if (!skb) {
- skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
- rx_ring->rx_buf_len);
- if (!skb) {
- rx_ring->rx_stats.alloc_rx_buff_failed++;
- goto no_buffers;
- }
- /* initialize queue mapping */
- skb_record_rx_queue(skb, rx_ring->queue_index);
- bi->skb = skb;
- }
+ rx_desc = IXGBE_RX_DESC(rx_ring, i);
+ bi = &rx_ring->rx_buffer_info[i];
+ i -= rx_ring->count;
- if (!bi->dma) {
- bi->dma = dma_map_single(rx_ring->dev,
- skb->data,
- rx_ring->rx_buf_len,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(rx_ring->dev, bi->dma)) {
- rx_ring->rx_stats.alloc_rx_buff_failed++;
- bi->dma = 0;
- goto no_buffers;
- }
- }
+ while (cleaned_count--) {
+ if (!ixgbe_alloc_mapped_skb(rx_ring, bi))
+ break;
+ /* Refresh the desc even if buffer_addrs didn't change
+ * because each write-back erases this info. */
if (ring_is_ps_enabled(rx_ring)) {
- if (!bi->page) {
- bi->page = alloc_page(GFP_ATOMIC | __GFP_COLD);
- if (!bi->page) {
- rx_ring->rx_stats.alloc_rx_page_failed++;
- goto no_buffers;
- }
- }
+ rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
- if (!bi->page_dma) {
- /* use a half page if we're re-using */
- bi->page_offset ^= PAGE_SIZE / 2;
- bi->page_dma = dma_map_page(rx_ring->dev,
- bi->page,
- bi->page_offset,
- PAGE_SIZE / 2,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(rx_ring->dev,
- bi->page_dma)) {
- rx_ring->rx_stats.alloc_rx_page_failed++;
- bi->page_dma = 0;
- goto no_buffers;
- }
- }
+ if (!ixgbe_alloc_mapped_page(rx_ring, bi))
+ break;
- /* 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->page_dma);
- rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
} else {
rx_desc->read.pkt_addr = cpu_to_le64(bi->dma);
- rx_desc->read.hdr_addr = 0;
}
+ rx_desc++;
+ bi++;
i++;
- if (i == rx_ring->count)
- i = 0;
+ if (unlikely(!i)) {
+ rx_desc = IXGBE_RX_DESC(rx_ring, 0);
+ bi = rx_ring->rx_buffer_info;
+ i -= rx_ring->count;
+ }
+
+ /* clear the hdr_addr for the next_to_use descriptor */
+ rx_desc->read.hdr_addr = 0;
}
-no_buffers:
- if (rx_ring->next_to_use != i) {
- rx_ring->next_to_use = i;
+ i += rx_ring->count;
+
+ if (rx_ring->next_to_use != i)
ixgbe_release_rx_desc(rx_ring, i);
- }
}
static inline u16 ixgbe_get_hlen(union ixgbe_adv_rx_desc *rx_desc)
@@ -1202,65 +1209,283 @@ static inline u16 ixgbe_get_hlen(union ixgbe_adv_rx_desc *rx_desc)
}
/**
- * ixgbe_transform_rsc_queue - change rsc queue into a full packet
- * @skb: pointer to the last skb in the rsc queue
+ * ixgbe_merge_active_tail - merge active tail into lro skb
+ * @tail: pointer to active tail in frag_list
+ *
+ * This function merges the length and data of an active tail into the
+ * skb containing the frag_list. It resets the tail's pointer to the head,
+ * but it leaves the heads pointer to tail intact.
+ **/
+static inline struct sk_buff *ixgbe_merge_active_tail(struct sk_buff *tail)
+{
+ struct sk_buff *head = IXGBE_CB(tail)->head;
+
+ if (!head)
+ return tail;
+
+ head->len += tail->len;
+ head->data_len += tail->len;
+ head->truesize += tail->len;
+
+ IXGBE_CB(tail)->head = NULL;
+
+ return head;
+}
+
+/**
+ * ixgbe_add_active_tail - adds an active tail into the skb frag_list
+ * @head: pointer to the start of the skb
+ * @tail: pointer to active tail to add to frag_list
+ *
+ * This function adds an active tail to the end of the frag list. This tail
+ * will still be receiving data so we cannot yet ad it's stats to the main
+ * skb. That is done via ixgbe_merge_active_tail.
+ **/
+static inline void ixgbe_add_active_tail(struct sk_buff *head,
+ struct sk_buff *tail)
+{
+ struct sk_buff *old_tail = IXGBE_CB(head)->tail;
+
+ if (old_tail) {
+ ixgbe_merge_active_tail(old_tail);
+ old_tail->next = tail;
+ } else {
+ skb_shinfo(head)->frag_list = tail;
+ }
+
+ IXGBE_CB(tail)->head = head;
+ IXGBE_CB(head)->tail = tail;
+}
+
+/**
+ * ixgbe_close_active_frag_list - cleanup pointers on a frag_list skb
+ * @head: pointer to head of an active frag list
+ *
+ * This function will clear the frag_tail_tracker pointer on an active
+ * frag_list and returns true if the pointer was actually set
+ **/
+static inline bool ixgbe_close_active_frag_list(struct sk_buff *head)
+{
+ struct sk_buff *tail = IXGBE_CB(head)->tail;
+
+ if (!tail)
+ return false;
+
+ ixgbe_merge_active_tail(tail);
+
+ IXGBE_CB(head)->tail = NULL;
+
+ return true;
+}
+
+/**
+ * ixgbe_get_headlen - determine size of header for RSC/LRO/GRO/FCOE
+ * @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, GRO, and RSC 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 ixgbe_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;
+ } 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 */
+ nexthdr = hdr.ipv4->protocol;
+ hdr.network += hlen;
+#ifdef CONFIG_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;
+#endif
+ } else {
+ return hdr.network - data;
+ }
+
+ /* 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;
+ }
+
+ /*
+ * 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.
+ */
+ if ((hdr.network - data) < max_len)
+ return hdr.network - data;
+ else
+ return max_len;
+}
+
+static void ixgbe_get_rsc_cnt(struct ixgbe_ring *rx_ring,
+ union ixgbe_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ __le32 rsc_enabled;
+ u32 rsc_cnt;
+
+ if (!ring_is_rsc_enabled(rx_ring))
+ return;
+
+ rsc_enabled = rx_desc->wb.lower.lo_dword.data &
+ cpu_to_le32(IXGBE_RXDADV_RSCCNT_MASK);
+
+ /* If this is an RSC frame rsc_cnt should be non-zero */
+ if (!rsc_enabled)
+ return;
+
+ rsc_cnt = le32_to_cpu(rsc_enabled);
+ rsc_cnt >>= IXGBE_RXDADV_RSCCNT_SHIFT;
+
+ IXGBE_CB(skb)->append_cnt += rsc_cnt - 1;
+}
+
+static void ixgbe_set_rsc_gso_size(struct ixgbe_ring *ring,
+ struct sk_buff *skb)
+{
+ u16 hdr_len = ixgbe_get_headlen(skb->data, skb_headlen(skb));
+
+ /* set gso_size to avoid messing up TCP MSS */
+ skb_shinfo(skb)->gso_size = DIV_ROUND_UP((skb->len - hdr_len),
+ IXGBE_CB(skb)->append_cnt);
+}
+
+static void ixgbe_update_rsc_stats(struct ixgbe_ring *rx_ring,
+ struct sk_buff *skb)
+{
+ /* if append_cnt is 0 then frame is not RSC */
+ if (!IXGBE_CB(skb)->append_cnt)
+ return;
+
+ rx_ring->rx_stats.rsc_count += IXGBE_CB(skb)->append_cnt;
+ rx_ring->rx_stats.rsc_flush++;
+
+ ixgbe_set_rsc_gso_size(rx_ring, skb);
+
+ /* gso_size is computed using append_cnt so always clear it last */
+ IXGBE_CB(skb)->append_cnt = 0;
+}
+
+/**
+ * ixgbe_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 changes a queue full of hw rsc buffers into a completed
- * packet. It uses the ->prev pointers to find the first packet and then
- * turns it into the frag list owner.
+ * 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 inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb)
+static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
+ union ixgbe_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
{
- unsigned int frag_list_size = 0;
- unsigned int skb_cnt = 1;
+ ixgbe_update_rsc_stats(rx_ring, skb);
+
+ ixgbe_rx_hash(rx_ring, rx_desc, skb);
- while (skb->prev) {
- struct sk_buff *prev = skb->prev;
- frag_list_size += skb->len;
- skb->prev = NULL;
- skb = prev;
- skb_cnt++;
+ ixgbe_rx_checksum(rx_ring, rx_desc, skb);
+
+ if (ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) {
+ u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan);
+ __vlan_hwaccel_put_tag(skb, vid);
}
- skb_shinfo(skb)->frag_list = skb->next;
- skb->next = NULL;
- skb->len += frag_list_size;
- skb->data_len += frag_list_size;
- skb->truesize += frag_list_size;
- IXGBE_RSC_CB(skb)->skb_cnt = skb_cnt;
+ skb_record_rx_queue(skb, rx_ring->queue_index);
- return skb;
+ skb->protocol = eth_type_trans(skb, rx_ring->netdev);
}
-static inline bool ixgbe_get_rsc_state(union ixgbe_adv_rx_desc *rx_desc)
+static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector,
+ struct sk_buff *skb)
{
- return !!(le32_to_cpu(rx_desc->wb.lower.lo_dword.data) &
- IXGBE_RXDADV_RSCCNT_MASK);
+ struct ixgbe_adapter *adapter = q_vector->adapter;
+
+ if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
+ napi_gro_receive(&q_vector->napi, skb);
+ else
+ netif_rx(skb);
}
static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
struct ixgbe_ring *rx_ring,
int budget)
{
- struct ixgbe_adapter *adapter = q_vector->adapter;
union ixgbe_adv_rx_desc *rx_desc, *next_rxd;
- struct ixgbe_rx_buffer *rx_buffer_info, *next_buffer;
+ struct ixgbe_rx_buffer *rx_buffer_info;
struct sk_buff *skb;
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
const int current_node = numa_node_id();
#ifdef IXGBE_FCOE
+ struct ixgbe_adapter *adapter = q_vector->adapter;
int ddp_bytes = 0;
#endif /* IXGBE_FCOE */
- u32 staterr;
u16 i;
u16 cleaned_count = 0;
- bool pkt_is_rsc = false;
i = rx_ring->next_to_clean;
- rx_desc = IXGBE_RX_DESC_ADV(rx_ring, i);
- staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+ rx_desc = IXGBE_RX_DESC(rx_ring, i);
- while (staterr & IXGBE_RXD_STAT_DD) {
+ while (ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_DD)) {
u32 upper_len = 0;
rmb(); /* read descriptor and rx_buffer_info after status DD */
@@ -1271,32 +1496,9 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
rx_buffer_info->skb = NULL;
prefetch(skb->data);
- if (ring_is_rsc_enabled(rx_ring))
- pkt_is_rsc = ixgbe_get_rsc_state(rx_desc);
-
/* linear means we are building an skb from multiple pages */
if (!skb_is_nonlinear(skb)) {
u16 hlen;
- if (pkt_is_rsc &&
- !(staterr & IXGBE_RXD_STAT_EOP) &&
- !skb->prev) {
- /*
- * When HWRSC is enabled, delay unmapping
- * of the first packet. It carries the
- * header information, HW may still
- * access the header after the writeback.
- * Only unmap it when EOP is reached
- */
- IXGBE_RSC_CB(skb)->delay_unmap = true;
- IXGBE_RSC_CB(skb)->dma = rx_buffer_info->dma;
- } else {
- dma_unmap_single(rx_ring->dev,
- rx_buffer_info->dma,
- rx_ring->rx_buf_len,
- DMA_FROM_DEVICE);
- }
- rx_buffer_info->dma = 0;
-
if (ring_is_ps_enabled(rx_ring)) {
hlen = ixgbe_get_hlen(rx_desc);
upper_len = le16_to_cpu(rx_desc->wb.upper.length);
@@ -1305,6 +1507,23 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
}
skb_put(skb, hlen);
+
+ /*
+ * Delay unmapping of the first packet. It carries the
+ * header information, HW may still access the header
+ * after writeback. Only unmap it when EOP is reached
+ */
+ if (!IXGBE_CB(skb)->head) {
+ IXGBE_CB(skb)->delay_unmap = true;
+ IXGBE_CB(skb)->dma = rx_buffer_info->dma;
+ } else {
+ skb = ixgbe_merge_active_tail(skb);
+ dma_unmap_single(rx_ring->dev,
+ rx_buffer_info->dma,
+ rx_ring->rx_buf_len,
+ DMA_FROM_DEVICE);
+ }
+ rx_buffer_info->dma = 0;
} else {
/* assume packet split since header is unmapped */
upper_len = le16_to_cpu(rx_desc->wb.upper.length);
@@ -1332,98 +1551,86 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
skb->truesize += PAGE_SIZE / 2;
}
+ ixgbe_get_rsc_cnt(rx_ring, rx_desc, skb);
+
i++;
if (i == rx_ring->count)
i = 0;
- next_rxd = IXGBE_RX_DESC_ADV(rx_ring, i);
+ next_rxd = IXGBE_RX_DESC(rx_ring, i);
prefetch(next_rxd);
cleaned_count++;
- if (pkt_is_rsc) {
- u32 nextp = (staterr & IXGBE_RXDADV_NEXTP_MASK) >>
- IXGBE_RXDADV_NEXTP_SHIFT;
+ if ((!ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_EOP))) {
+ struct ixgbe_rx_buffer *next_buffer;
+ u32 nextp;
+
+ if (IXGBE_CB(skb)->append_cnt) {
+ nextp = le32_to_cpu(
+ rx_desc->wb.upper.status_error);
+ nextp >>= IXGBE_RXDADV_NEXTP_SHIFT;
+ } else {
+ nextp = i;
+ }
+
next_buffer = &rx_ring->rx_buffer_info[nextp];
- } else {
- next_buffer = &rx_ring->rx_buffer_info[i];
- }
- if (!(staterr & IXGBE_RXD_STAT_EOP)) {
if (ring_is_ps_enabled(rx_ring)) {
rx_buffer_info->skb = next_buffer->skb;
rx_buffer_info->dma = next_buffer->dma;
next_buffer->skb = skb;
next_buffer->dma = 0;
} else {
- skb->next = next_buffer->skb;
- skb->next->prev = skb;
+ struct sk_buff *next_skb = next_buffer->skb;
+ ixgbe_add_active_tail(skb, next_skb);
+ IXGBE_CB(next_skb)->head = skb;
}
rx_ring->rx_stats.non_eop_descs++;
goto next_desc;
}
- if (skb->prev) {
- skb = ixgbe_transform_rsc_queue(skb);
- /* if we got here without RSC the packet is invalid */
- if (!pkt_is_rsc) {
- __pskb_trim(skb, 0);
- rx_buffer_info->skb = skb;
- goto next_desc;
- }
- }
+ dma_unmap_single(rx_ring->dev,
+ IXGBE_CB(skb)->dma,
+ rx_ring->rx_buf_len,
+ DMA_FROM_DEVICE);
+ IXGBE_CB(skb)->dma = 0;
+ IXGBE_CB(skb)->delay_unmap = false;
- if (ring_is_rsc_enabled(rx_ring)) {
- if (IXGBE_RSC_CB(skb)->delay_unmap) {
- dma_unmap_single(rx_ring->dev,
- IXGBE_RSC_CB(skb)->dma,
- rx_ring->rx_buf_len,
- DMA_FROM_DEVICE);
- IXGBE_RSC_CB(skb)->dma = 0;
- IXGBE_RSC_CB(skb)->delay_unmap = false;
- }
- }
- if (pkt_is_rsc) {
- if (ring_is_ps_enabled(rx_ring))
- rx_ring->rx_stats.rsc_count +=
- skb_shinfo(skb)->nr_frags;
- else
- rx_ring->rx_stats.rsc_count +=
- IXGBE_RSC_CB(skb)->skb_cnt;
- rx_ring->rx_stats.rsc_flush++;
+ if (ixgbe_close_active_frag_list(skb) &&
+ !IXGBE_CB(skb)->append_cnt) {
+ /* if we got here without RSC the packet is invalid */
+ dev_kfree_skb_any(skb);
+ goto next_desc;
}
/* ERR_MASK will only have valid bits if EOP set */
- if (unlikely(staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)) {
+ if (unlikely(ixgbe_test_staterr(rx_desc,
+ IXGBE_RXDADV_ERR_FRAME_ERR_MASK))) {
dev_kfree_skb_any(skb);
goto next_desc;
}
- ixgbe_rx_checksum(adapter, rx_desc, skb, staterr);
- if (adapter->netdev->features & NETIF_F_RXHASH)
- ixgbe_rx_hash(rx_desc, skb);
-
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
total_rx_packets++;
- skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+ /* populate checksum, timestamp, VLAN, and protocol */
+ ixgbe_process_skb_fields(rx_ring, rx_desc, skb);
+
#ifdef IXGBE_FCOE
/* if ddp, not passing to ULD unless for FCP_RSP or error */
if (ixgbe_rx_is_fcoe(adapter, rx_desc)) {
- ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb,
- staterr);
+ ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb);
if (!ddp_bytes) {
dev_kfree_skb_any(skb);
goto next_desc;
}
}
#endif /* IXGBE_FCOE */
- ixgbe_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc);
+ ixgbe_rx_skb(q_vector, skb);
budget--;
next_desc:
- rx_desc->wb.upper.status_error = 0;
-
if (!budget)
break;
@@ -1435,7 +1642,6 @@ next_desc:
/* use prefetched values */
rx_desc = next_rxd;
- staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
}
rx_ring->next_to_clean = i;
@@ -3876,19 +4082,18 @@ static void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring)
if (rx_buffer_info->skb) {
struct sk_buff *skb = rx_buffer_info->skb;
rx_buffer_info->skb = NULL;
- do {
- struct sk_buff *this = skb;
- if (IXGBE_RSC_CB(this)->delay_unmap) {
- dma_unmap_single(dev,
- IXGBE_RSC_CB(this)->dma,
- rx_ring->rx_buf_len,
- DMA_FROM_DEVICE);
- IXGBE_RSC_CB(this)->dma = 0;
- IXGBE_RSC_CB(skb)->delay_unmap = false;
- }
- skb = skb->prev;
- dev_kfree_skb(this);
- } while (skb);
+ /* We need to clean up RSC frag lists */
+ skb = ixgbe_merge_active_tail(skb);
+ ixgbe_close_active_frag_list(skb);
+ if (IXGBE_CB(skb)->delay_unmap) {
+ dma_unmap_single(dev,
+ IXGBE_CB(skb)->dma,
+ rx_ring->rx_buf_len,
+ DMA_FROM_DEVICE);
+ IXGBE_CB(skb)->dma = 0;
+ IXGBE_CB(skb)->delay_unmap = false;
+ }
+ dev_kfree_skb(skb);
}
if (!rx_buffer_info->page)
continue;
@@ -4661,6 +4866,13 @@ static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
ring->dev = &adapter->pdev->dev;
ring->netdev = adapter->netdev;
+ /*
+ * 82599 errata, UDP frames with a 0 checksum can be marked as
+ * checksum errors.
+ */
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+ set_bit(__IXGBE_RX_CSUM_UDP_ZERO_ERR, &ring->state);
+
adapter->rx_ring[rx] = ring;
}
@@ -5065,9 +5277,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
return -EIO;
}
- /* enable rx csum by default */
- adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
-
/* get assigned NUMA node */
adapter->node = dev_to_node(&pdev->dev);
@@ -5558,7 +5767,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
u64 non_eop_descs = 0, restart_queue = 0, tx_busy = 0;
u64 alloc_rx_page_failed = 0, alloc_rx_buff_failed = 0;
- u64 bytes = 0, packets = 0;
+ u64 bytes = 0, packets = 0, hw_csum_rx_error = 0;
#ifdef IXGBE_FCOE
struct ixgbe_fcoe *fcoe = &adapter->fcoe;
unsigned int cpu;
@@ -5588,12 +5797,14 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
non_eop_descs += rx_ring->rx_stats.non_eop_descs;
alloc_rx_page_failed += rx_ring->rx_stats.alloc_rx_page_failed;
alloc_rx_buff_failed += rx_ring->rx_stats.alloc_rx_buff_failed;
+ hw_csum_rx_error += rx_ring->rx_stats.csum_err;
bytes += rx_ring->stats.bytes;
packets += rx_ring->stats.packets;
}
adapter->non_eop_descs = non_eop_descs;
adapter->alloc_rx_page_failed = alloc_rx_page_failed;
adapter->alloc_rx_buff_failed = alloc_rx_buff_failed;
+ adapter->hw_csum_rx_error = hw_csum_rx_error;
netdev->stats.rx_bytes = bytes;
netdev->stats.rx_packets = packets;
@@ -6279,7 +6490,7 @@ void ixgbe_tx_ctxtdesc(struct ixgbe_ring *tx_ring, u32 vlan_macip_lens,
struct ixgbe_adv_tx_context_desc *context_desc;
u16 i = tx_ring->next_to_use;
- context_desc = IXGBE_TX_CTXTDESC_ADV(tx_ring, i);
+ context_desc = IXGBE_TX_CTXTDESC(tx_ring, i);
i++;
tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
@@ -6512,7 +6723,7 @@ static void ixgbe_tx_map(struct ixgbe_ring *tx_ring,
cmd_type = ixgbe_tx_cmd_type(tx_flags);
olinfo_status = ixgbe_tx_olinfo_status(tx_flags, paylen);
- tx_desc = IXGBE_TX_DESC_ADV(tx_ring, i);
+ tx_desc = IXGBE_TX_DESC(tx_ring, i);
for (;;) {
while (size > IXGBE_MAX_DATA_PER_TXD) {
@@ -6527,7 +6738,7 @@ static void ixgbe_tx_map(struct ixgbe_ring *tx_ring,
tx_desc++;
i++;
if (i == tx_ring->count) {
- tx_desc = IXGBE_TX_DESC_ADV(tx_ring, 0);
+ tx_desc = IXGBE_TX_DESC(tx_ring, 0);
i = 0;
}
}
@@ -6563,7 +6774,7 @@ static void ixgbe_tx_map(struct ixgbe_ring *tx_ring,
tx_desc++;
i++;
if (i == tx_ring->count) {
- tx_desc = IXGBE_TX_DESC_ADV(tx_ring, 0);
+ tx_desc = IXGBE_TX_DESC(tx_ring, 0);
i = 0;
}
}
@@ -7222,12 +7433,6 @@ static int ixgbe_set_features(struct net_device *netdev,
struct ixgbe_adapter *adapter = netdev_priv(netdev);
bool need_reset = false;
- /* If Rx checksum is disabled, then RSC/LRO should also be disabled */
- if (!(data & NETIF_F_RXCSUM))
- adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
- else
- adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
-
/* Make sure RSC matches LRO, reset if change */
if (!!(data & NETIF_F_LRO) !=
!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) {
@@ -7493,6 +7698,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
e_crit(probe, "Fan has stopped, replace the adapter\n");
}
+ if (allow_unsupported_sfp)
+ hw->allow_unsupported_sfp = allow_unsupported_sfp;
+
/* reset_hw fills in the perm_addr as well */
hw->phy.reset_if_overtemp = true;
err = hw->mac.ops.reset_hw(hw);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index b91773551a38..bf9f82f4b1ae 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -834,6 +834,7 @@ out:
**/
s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
{
+ struct ixgbe_adapter *adapter = hw->back;
s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
u32 vendor_oui = 0;
enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
@@ -1068,9 +1069,16 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
if (hw->phy.type == ixgbe_phy_sfp_intel) {
status = 0;
} else {
- hw_dbg(hw, "SFP+ module not supported\n");
- hw->phy.type = ixgbe_phy_sfp_unsupported;
- status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+ if (hw->allow_unsupported_sfp) {
+ e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.");
+ status = 0;
+ } else {
+ hw_dbg(hw,
+ "SFP+ module not supported\n");
+ hw->phy.type =
+ ixgbe_phy_sfp_unsupported;
+ status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+ }
}
} else {
status = 0;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index b01ecb4d2bb1..88a58cb08569 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -258,7 +258,7 @@ static void ixgbe_restore_vf_macvlans(struct ixgbe_adapter *adapter)
list_for_each(pos, &adapter->vf_mvs.l) {
entry = list_entry(pos, struct vf_macvlans, l);
- if (entry->free == false)
+ if (!entry->free)
hw->mac.ops.set_rar(hw, entry->rar_entry,
entry->vf_macvlan,
entry->vf, IXGBE_RAH_AV);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 9b95bef60970..4c060292395f 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -2892,6 +2892,7 @@ struct ixgbe_hw {
u8 revision_id;
bool adapter_stopped;
bool force_full_reset;
+ bool allow_unsupported_sfp;
};
struct ixgbe_info {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index f838a2be8cfb..5e9f05fa0134 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -760,7 +760,7 @@ static s32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index)
* This will be reversed when we stop the blinking.
*/
hw->mac.ops.check_link(hw, &speed, &link_up, false);
- if (link_up == false) {
+ if (!link_up) {
macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
macc_reg |= IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS;
IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index e51d552410ae..581c65976bb4 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -2199,13 +2199,17 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
if (err) {
dev_info(&pdev->dev,
"PF still in reset state, assigning new address\n");
- dev_hw_addr_random(adapter->netdev, hw->mac.addr);
+ eth_hw_addr_random(adapter->netdev);
+ memcpy(adapter->hw.mac.addr, adapter->netdev->dev_addr,
+ adapter->netdev->addr_len);
} else {
err = hw->mac.ops.init_hw(hw);
if (err) {
pr_err("init_shared_code failed: %d\n", err);
goto out;
}
+ memcpy(adapter->netdev->dev_addr, adapter->hw.mac.addr,
+ adapter->netdev->addr_len);
}
/* Enable dynamic interrupt throttling rates */
@@ -2224,6 +2228,7 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
set_bit(__IXGBEVF_DOWN, &adapter->state);
+ return 0;
out:
return err;
@@ -2521,12 +2526,8 @@ int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter,
size = sizeof(struct ixgbevf_rx_buffer) * rx_ring->count;
rx_ring->rx_buffer_info = vzalloc(size);
- if (!rx_ring->rx_buffer_info) {
- hw_dbg(&adapter->hw,
- "Unable to vmalloc buffer memory for "
- "the receive descriptor ring\n");
+ if (!rx_ring->rx_buffer_info)
goto alloc_failed;
- }
/* Round up to nearest 4K */
rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
@@ -3398,6 +3399,17 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
/* setup the private structure */
err = ixgbevf_sw_init(adapter);
+ if (err)
+ goto err_sw_init;
+
+ /* The HW MAC address was set and/or determined in sw_init */
+ memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
+
+ if (!is_valid_ether_addr(netdev->dev_addr)) {
+ pr_err("invalid MAC address\n");
+ err = -EIO;
+ goto err_sw_init;
+ }
netdev->hw_features = NETIF_F_SG |
NETIF_F_IP_CSUM |
@@ -3422,16 +3434,6 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
netdev->priv_flags |= IFF_UNICAST_FLT;
- /* The HW MAC address was set and/or determined in sw_init */
- memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
- memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
-
- if (!is_valid_ether_addr(netdev->dev_addr)) {
- pr_err("invalid MAC address\n");
- err = -EIO;
- goto err_sw_init;
- }
-
init_timer(&adapter->watchdog_timer);
adapter->watchdog_timer.function = ixgbevf_watchdog;
adapter->watchdog_timer.data = (unsigned long)adapter;
@@ -3460,13 +3462,7 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
ixgbevf_init_last_counter_stats(adapter);
/* print the MAC address */
- hw_dbg(hw, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
- netdev->dev_addr[0],
- netdev->dev_addr[1],
- netdev->dev_addr[2],
- netdev->dev_addr[3],
- netdev->dev_addr[4],
- netdev->dev_addr[5]);
+ hw_dbg(hw, "%pM\n", netdev->dev_addr);
hw_dbg(hw, "MAC: %d\n", hw->mac.type);
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index 55cbf65512c3..4ea6580d3ae8 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -2991,7 +2991,6 @@ jme_init_one(struct pci_dev *pdev,
*/
netdev = alloc_etherdev(sizeof(*jme));
if (!netdev) {
- pr_err("Cannot allocate netdev structure\n");
rc = -ENOMEM;
goto err_out_release_regions;
}
diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 6ad094f176f8..f30db1c46600 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -1108,10 +1108,9 @@ static int korina_probe(struct platform_device *pdev)
int rc;
dev = alloc_etherdev(sizeof(struct korina_private));
- if (!dev) {
- printk(KERN_ERR DRV_NAME ": alloc_etherdev failed\n");
+ if (!dev)
return -ENOMEM;
- }
+
SET_NETDEV_DEV(dev, &pdev->dev);
lp = netdev_priv(dev);
@@ -1150,7 +1149,6 @@ static int korina_probe(struct platform_device *pdev)
lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL);
if (!lp->td_ring) {
- printk(KERN_ERR DRV_NAME ": cannot allocate descriptors\n");
rc = -ENXIO;
goto probe_err_td_ring;
}
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 85e2c6cd9708..5dc9cbd51514 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -114,7 +114,7 @@ struct ltq_etop_priv {
static int
ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
{
- ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN);
+ ch->skb[ch->dma.desc] = netdev_alloc_skb(ch->netdev, MAX_DMA_DATA_LEN);
if (!ch->skb[ch->dma.desc])
return -ENOMEM;
ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
@@ -634,6 +634,7 @@ ltq_etop_init(struct net_device *dev)
struct ltq_etop_priv *priv = netdev_priv(dev);
struct sockaddr mac;
int err;
+ bool random_mac = false;
ether_setup(dev);
dev->watchdog_timeo = 10 * HZ;
@@ -646,11 +647,17 @@ ltq_etop_init(struct net_device *dev)
if (!is_valid_ether_addr(mac.sa_data)) {
pr_warn("etop: invalid MAC, using random\n");
random_ether_addr(mac.sa_data);
+ random_mac = true;
}
err = ltq_etop_set_mac_address(dev, &mac);
if (err)
goto err_netdev;
+
+ /* Set addr_assign_type here, ltq_etop_set_mac_address would reset it. */
+ if (random_mac)
+ dev->addr_assign_type |= NET_ADDR_RANDOM;
+
ltq_etop_set_multicast_list(dev);
err = ltq_etop_mdio_init(dev);
if (err)
@@ -731,6 +738,10 @@ ltq_etop_probe(struct platform_device *pdev)
}
dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
+ if (!dev) {
+ err = -ENOMEM;
+ goto err_out;
+ }
strcpy(dev->name, "eth%d");
dev->netdev_ops = &ltq_eth_netdev_ops;
dev->ethtool_ops = &ltq_etop_ethtool_ops;
@@ -792,7 +803,7 @@ init_ltq_etop(void)
int ret = platform_driver_probe(&ltq_mii_driver, ltq_etop_probe);
if (ret)
- pr_err("ltq_etop: Error registering platfom driver!");
+ pr_err("ltq_etop: Error registering platform driver!");
return ret;
}
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 9edecfa1f0f4..75af1afe46c8 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -667,7 +667,7 @@ static int rxq_refill(struct rx_queue *rxq, int budget)
skb = __skb_dequeue(&mp->rx_recycle);
if (skb == NULL)
- skb = dev_alloc_skb(mp->skb_size);
+ skb = netdev_alloc_skb(mp->dev, mp->skb_size);
if (skb == NULL) {
mp->oom = 1;
@@ -1832,7 +1832,7 @@ static int mv643xx_eth_set_mac_address(struct net_device *dev, void *addr)
struct sockaddr *sa = addr;
if (!is_valid_ether_addr(sa->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 953ba5851f7b..3a7df0593c68 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -350,7 +350,7 @@ static void rxq_refill(struct net_device *dev)
while (pep->rx_desc_count < pep->rx_ring_size) {
int size;
- skb = dev_alloc_skb(pep->skb_size);
+ skb = netdev_alloc_skb(dev, pep->skb_size);
if (!skb)
break;
if (SKB_DMA_REALIGN)
@@ -627,8 +627,9 @@ static int pxa168_eth_set_mac_address(struct net_device *dev, void *addr)
unsigned char oldMac[ETH_ALEN];
if (!is_valid_ether_addr(sa->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
memcpy(oldMac, dev->dev_addr, ETH_ALEN);
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
netif_addr_lock_bh(dev);
update_hash_table_mac_address(pep, oldMac, dev->dev_addr);
@@ -1017,10 +1018,9 @@ static int rxq_init(struct net_device *dev)
/* Allocate RX skb rings */
pep->rx_skb = kmalloc(sizeof(*pep->rx_skb) * pep->rx_ring_size,
GFP_KERNEL);
- if (!pep->rx_skb) {
- printk(KERN_ERR "%s: Cannot alloc RX skb ring\n", dev->name);
+ if (!pep->rx_skb)
return -ENOMEM;
- }
+
/* Allocate RX ring */
pep->rx_desc_count = 0;
size = pep->rx_ring_size * sizeof(struct rx_desc);
@@ -1081,10 +1081,9 @@ static int txq_init(struct net_device *dev)
pep->tx_skb = kmalloc(sizeof(*pep->tx_skb) * pep->tx_ring_size,
GFP_KERNEL);
- if (!pep->tx_skb) {
- printk(KERN_ERR "%s: Cannot alloc TX skb ring\n", dev->name);
+ if (!pep->tx_skb)
return -ENOMEM;
- }
+
/* Allocate TX ring */
pep->tx_desc_count = 0;
size = pep->tx_ring_size * sizeof(struct tx_desc);
@@ -1522,7 +1521,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task);
printk(KERN_INFO "%s:Using random mac address\n", DRIVER_NAME);
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
pep->pd = pdev->dev.platform_data;
pep->rx_ring_size = NUM_RX_DESCS;
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index 33947ac595c0..5a30bf823099 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -3807,10 +3807,8 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
struct skge_port *skge;
struct net_device *dev = alloc_etherdev(sizeof(*skge));
- if (!dev) {
- dev_err(&hw->pdev->dev, "etherdev alloc failed\n");
+ if (!dev)
return NULL;
- }
SET_NETDEV_DEV(dev, &hw->pdev->dev);
dev->netdev_ops = &skge_netdev_ops;
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 760c2b17dfd3..82c2c86a1951 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4700,10 +4700,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
struct sky2_port *sky2;
struct net_device *dev = alloc_etherdev(sizeof(*sky2));
- if (!dev) {
- dev_err(&hw->pdev->dev, "etherdev alloc failed\n");
+ if (!dev)
return NULL;
- }
SET_NETDEV_DEV(dev, &hw->pdev->dev);
dev->irq = hw->pdev->irq;
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index eaf09d4f02d0..48d5c48d7ce8 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1314,7 +1314,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
down(&priv->cmd.slave_sem);
if (mlx4_master_process_vhcr(dev, slave, NULL)) {
mlx4_err(dev, "Failed processing vhcr for slave:%d,"
- " reseting slave.\n", slave);
+ " resetting slave.\n", slave);
up(&priv->cmd.slave_sem);
goto reset_slave;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 149e60da0a32..9fe4f94c6da7 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -1048,10 +1048,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv),
prof->tx_ring_num, prof->rx_ring_num);
- if (dev == NULL) {
- mlx4_err(mdev, "Net device allocation failed\n");
+ if (dev == NULL)
return -ENOMEM;
- }
SET_NETDEV_DEV(dev, &mdev->dev->pdev->dev);
dev->dev_id = port - 1;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index d4ad8c226b51..d703ef2c9c91 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -285,10 +285,9 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
tmp = size * roundup_pow_of_two(MLX4_EN_MAX_RX_FRAGS *
sizeof(struct skb_frag_struct));
ring->rx_info = vmalloc(tmp);
- if (!ring->rx_info) {
- en_err(priv, "Failed allocating rx_info ring\n");
+ if (!ring->rx_info)
return -ENOMEM;
- }
+
en_dbg(DRV, priv, "Allocated rx_info ring at addr:%p size:%d\n",
ring->rx_info, tmp);
@@ -468,12 +467,11 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
int used_frags;
dma_addr_t dma;
- skb = dev_alloc_skb(SMALL_PACKET_SIZE + NET_IP_ALIGN);
+ skb = netdev_alloc_skb(priv->dev, SMALL_PACKET_SIZE + NET_IP_ALIGN);
if (!skb) {
en_dbg(RX_ERR, priv, "Failed allocating skb\n");
return NULL;
}
- skb->dev = priv->dev;
skb_reserve(skb, NET_IP_ALIGN);
skb->len = length;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 9ef9038d0629..2fd51405a509 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -71,16 +71,14 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
tmp = size * sizeof(struct mlx4_en_tx_info);
ring->tx_info = vmalloc(tmp);
- if (!ring->tx_info) {
- en_err(priv, "Failed allocating tx_info ring\n");
+ if (!ring->tx_info)
return -ENOMEM;
- }
+
en_dbg(DRV, priv, "Allocated tx_info ring at addr:%p size:%d\n",
ring->tx_info, tmp);
ring->bounce_buf = kmalloc(MAX_DESC_SIZE, GFP_KERNEL);
if (!ring->bounce_buf) {
- en_err(priv, "Failed allocating bounce buffer\n");
err = -ENOMEM;
goto err_tx;
}
@@ -603,8 +601,6 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
struct skb_frag_struct *frag;
struct mlx4_en_tx_info *tx_info;
struct ethhdr *ethh;
- u64 mac;
- u32 mac_l, mac_h;
int tx_ind = 0;
int nr_txbb;
int desc_size;
@@ -689,16 +685,9 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
}
/* Copy dst mac address to wqe */
- skb_reset_mac_header(skb);
- ethh = eth_hdr(skb);
- if (ethh && ethh->h_dest) {
- mac = mlx4_en_mac_to_u64(ethh->h_dest);
- mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16);
- mac_l = (u32) (mac & 0xffffffff);
- tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h);
- tx_desc->ctrl.imm = cpu_to_be32(mac_l);
- }
-
+ ethh = (struct ethhdr *)skb->data;
+ tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((u16 *)ethh->h_dest);
+ tx_desc->ctrl.imm = get_unaligned((u32 *)(ethh->h_dest + 2));
/* Handle LSO (TSO) packets */
if (lso_header_size) {
/* Mark opcode as LSO */
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index d498f049c74e..5f15014713bc 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -1545,13 +1545,11 @@ static int mlx4_init_steering(struct mlx4_dev *dev)
if (!priv->steer)
return -ENOMEM;
- for (i = 0; i < num_entries; i++) {
+ for (i = 0; i < num_entries; i++)
for (j = 0; j < MLX4_NUM_STEERS; j++) {
INIT_LIST_HEAD(&priv->steer[i].promisc_qps[j]);
INIT_LIST_HEAD(&priv->steer[i].steer_entries[j]);
}
- INIT_LIST_HEAD(&priv->steer[i].high_prios);
- }
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c
index ca574d850b39..4799e824052f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mcg.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c
@@ -562,14 +562,14 @@ out_mutex:
*/
static int find_entry(struct mlx4_dev *dev, u8 port,
u8 *gid, enum mlx4_protocol prot,
- enum mlx4_steer_type steer,
struct mlx4_cmd_mailbox *mgm_mailbox,
- u16 *hash, int *prev, int *index)
+ int *prev, int *index)
{
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_mgm *mgm = mgm_mailbox->buf;
u8 *mgid;
int err;
+ u16 hash;
u8 op_mod = (prot == MLX4_PROT_ETH) ?
!!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) : 0;
@@ -580,15 +580,15 @@ static int find_entry(struct mlx4_dev *dev, u8 port,
memcpy(mgid, gid, 16);
- err = mlx4_GID_HASH(dev, mailbox, hash, op_mod);
+ err = mlx4_GID_HASH(dev, mailbox, &hash, op_mod);
mlx4_free_cmd_mailbox(dev, mailbox);
if (err)
return err;
if (0)
- mlx4_dbg(dev, "Hash for %pI6 is %04x\n", gid, *hash);
+ mlx4_dbg(dev, "Hash for %pI6 is %04x\n", gid, hash);
- *index = *hash;
+ *index = hash;
*prev = -1;
do {
@@ -597,7 +597,7 @@ static int find_entry(struct mlx4_dev *dev, u8 port,
return err;
if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
- if (*index != *hash) {
+ if (*index != hash) {
mlx4_err(dev, "Found zero MGID in AMGM.\n");
err = -EINVAL;
}
@@ -624,7 +624,6 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_mgm *mgm;
u32 members_count;
- u16 hash;
int index, prev;
int link = 0;
int i;
@@ -638,8 +637,8 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
mgm = mailbox->buf;
mutex_lock(&priv->mcg_table.mutex);
- err = find_entry(dev, port, gid, prot, steer,
- mailbox, &hash, &prev, &index);
+ err = find_entry(dev, port, gid, prot,
+ mailbox, &prev, &index);
if (err)
goto out;
@@ -733,7 +732,6 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_mgm *mgm;
u32 members_count;
- u16 hash;
int prev, index;
int i, loc;
int err;
@@ -747,8 +745,8 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
mutex_lock(&priv->mcg_table.mutex);
- err = find_entry(dev, port, gid, prot, steer,
- mailbox, &hash, &prev, &index);
+ err = find_entry(dev, port, gid, prot,
+ mailbox, &prev, &index);
if (err)
goto out;
@@ -872,44 +870,36 @@ static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp,
int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
int block_mcast_loopback, enum mlx4_protocol prot)
{
- enum mlx4_steer_type steer;
-
- steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
-
if (prot == MLX4_PROT_ETH &&
!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0;
if (prot == MLX4_PROT_ETH)
- gid[7] |= (steer << 1);
+ gid[7] |= (MLX4_MC_STEER << 1);
if (mlx4_is_mfunc(dev))
return mlx4_QP_ATTACH(dev, qp, gid, 1,
block_mcast_loopback, prot);
return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback,
- prot, steer);
+ prot, MLX4_MC_STEER);
}
EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
enum mlx4_protocol prot)
{
- enum mlx4_steer_type steer;
-
- steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
-
if (prot == MLX4_PROT_ETH &&
!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0;
if (prot == MLX4_PROT_ETH)
- gid[7] |= (steer << 1);
+ gid[7] |= (MLX4_MC_STEER << 1);
if (mlx4_is_mfunc(dev))
return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot);
- return mlx4_qp_detach_common(dev, qp, gid, prot, steer);
+ return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_MC_STEER);
}
EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 28f8251561f4..5da51b99dbb8 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -703,7 +703,6 @@ struct mlx4_msix_ctl {
struct mlx4_steer {
struct list_head promisc_qps[MLX4_NUM_STEERS];
struct list_head steer_entries[MLX4_NUM_STEERS];
- struct list_head high_prios;
};
struct mlx4_priv {
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index f44ae555bf43..575839dba8a2 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -87,7 +87,6 @@ static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
mac = cpu_to_be64(mac << 16);
memcpy(&gid[10], &mac, ETH_ALEN);
gid[5] = port;
- gid[7] = MLX4_UC_STEER << 1;
err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH);
if (err)
@@ -107,7 +106,6 @@ static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port,
mac = cpu_to_be64(mac << 16);
memcpy(&gid[10], &mac, ETH_ALEN);
gid[5] = port;
- gid[7] = MLX4_UC_STEER << 1;
mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH);
}
diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c
index ab81c0dc96e2..dccae1d1743a 100644
--- a/drivers/net/ethernet/micrel/ks8695net.c
+++ b/drivers/net/ethernet/micrel/ks8695net.c
@@ -278,7 +278,8 @@ ks8695_refill_rxbuffers(struct ks8695_priv *ksp)
for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
if (!ksp->rx_buffers[buff_n].skb) {
- struct sk_buff *skb = dev_alloc_skb(MAX_RXBUF_SIZE);
+ struct sk_buff *skb =
+ netdev_alloc_skb(ksp->ndev, MAX_RXBUF_SIZE);
dma_addr_t mapping;
ksp->rx_buffers[buff_n].skb = skb;
@@ -299,7 +300,6 @@ ks8695_refill_rxbuffers(struct ks8695_priv *ksp)
break;
}
ksp->rx_buffers[buff_n].dma_ptr = mapping;
- skb->dev = ksp->ndev;
ksp->rx_buffers[buff_n].length = MAX_RXBUF_SIZE;
/* Record this into the DMA ring */
@@ -1362,10 +1362,8 @@ ks8695_probe(struct platform_device *pdev)
/* Initialise a net_device */
ndev = alloc_etherdev(sizeof(struct ks8695_priv));
- if (!ndev) {
- dev_err(&pdev->dev, "could not allocate device.\n");
+ if (!ndev)
return -ENOMEM;
- }
SET_NETDEV_DEV(ndev, &pdev->dev);
diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
index 0a85690a1321..0686b93f1857 100644
--- a/drivers/net/ethernet/micrel/ks8842.c
+++ b/drivers/net/ethernet/micrel/ks8842.c
@@ -1080,6 +1080,7 @@ static int ks8842_set_mac(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
+ netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
memcpy(netdev->dev_addr, mac, netdev->addr_len);
ks8842_write_mac_addr(adapter, mac);
@@ -1211,7 +1212,7 @@ static int __devinit ks8842_probe(struct platform_device *pdev)
ks8842_read_mac_addr(adapter, netdev->dev_addr);
if (!is_valid_ether_addr(netdev->dev_addr))
- random_ether_addr(netdev->dev_addr);
+ eth_hw_addr_random(netdev);
}
id = ks8842_read16(adapter, 32, REG_SW_ID_AND_ENABLE);
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index 0c3e4005224d..c722aa607d07 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -1,4 +1,4 @@
-/* drivers/net/ks8851.c
+/* drivers/net/ethernet/micrel/ks8851.c
*
* Copyright 2009 Simtec Electronics
* http://www.simtec.co.uk/
@@ -439,13 +439,13 @@ static void ks8851_init_mac(struct ks8851_net *ks)
dev->dev_addr);
}
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
ks8851_write_mac_addr(dev);
}
/**
* ks8851_irq - device interrupt handler
- * @irq: Interrupt number passed from the IRQ hnalder.
+ * @irq: Interrupt number passed from the IRQ handler.
* @pw: The private word passed to register_irq(), our struct ks8851_net.
*
* Disable the interrupt from happening again until we've processed the
@@ -1050,6 +1050,7 @@ static int ks8851_set_mac_address(struct net_device *dev, void *addr)
if (!is_valid_ether_addr(sa->sa_data))
return -EADDRNOTAVAIL;
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
return ks8851_write_mac_addr(dev);
}
@@ -1419,10 +1420,8 @@ static int __devinit ks8851_probe(struct spi_device *spi)
int ret;
ndev = alloc_etherdev(sizeof(struct ks8851_net));
- if (!ndev) {
- dev_err(&spi->dev, "failed to alloc ethernet device\n");
+ if (!ndev)
return -ENOMEM;
- }
spi->bits_per_word = 8;
diff --git a/drivers/net/ethernet/micrel/ks8851.h b/drivers/net/ethernet/micrel/ks8851.h
index b0fae86aacad..852256ef1f22 100644
--- a/drivers/net/ethernet/micrel/ks8851.h
+++ b/drivers/net/ethernet/micrel/ks8851.h
@@ -1,4 +1,4 @@
-/* drivers/net/ks8851.h
+/* drivers/net/ethernet/micrel/ks8851.h
*
* Copyright 2009 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
index 2784bc706f1e..b8104d9f4081 100644
--- a/drivers/net/ethernet/micrel/ks8851_mll.c
+++ b/drivers/net/ethernet/micrel/ks8851_mll.c
@@ -1,5 +1,5 @@
/**
- * drivers/net/ks8851_mll.c
+ * drivers/net/ethernet/micrel/ks8851_mll.c
* Copyright (c) 2009 Micrel Inc.
*
* This program is free software; you can redistribute it and/or modify
@@ -794,7 +794,7 @@ static void ks_rcv(struct ks_net *ks, struct net_device *netdev)
frame_hdr = ks->frame_head_info;
while (ks->frame_cnt--) {
- skb = dev_alloc_skb(frame_hdr->len + 16);
+ skb = netdev_alloc_skb(netdev, frame_hdr->len + 16);
if (likely(skb && (frame_hdr->sts & RXFSHR_RXFV) &&
(frame_hdr->len < RX_BUF_SIZE) && frame_hdr->len)) {
skb_reserve(skb, 2);
@@ -837,7 +837,7 @@ static void ks_update_link_status(struct net_device *netdev, struct ks_net *ks)
/**
* ks_irq - device interrupt handler
- * @irq: Interrupt number passed from the IRQ hnalder.
+ * @irq: Interrupt number passed from the IRQ handler.
* @pw: The private word passed to register_irq(), our struct ks_net.
*
* This is the handler invoked to find out what happened
@@ -1239,6 +1239,7 @@ static int ks_set_mac_address(struct net_device *netdev, void *paddr)
struct sockaddr *addr = paddr;
u8 *da;
+ netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
da = (u8 *)netdev->dev_addr;
@@ -1499,10 +1500,8 @@ static int ks_hw_init(struct ks_net *ks)
ks->mcast_lst_size = 0;
ks->frame_head_info = kmalloc(MHEADER_SIZE, GFP_KERNEL);
- if (!ks->frame_head_info) {
- pr_err("Error: Fail to allocate frame memory\n");
+ if (!ks->frame_head_info)
return false;
- }
ks_set_mac(ks, KS_DEFAULT_MAC_ADDRESS);
return true;
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index e52cd310ae76..ef723b185d85 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -1,5 +1,5 @@
/**
- * drivers/net/ksx884x.c - Micrel KSZ8841/2 PCI Ethernet driver
+ * drivers/net/ethernet/micrel/ksx884x.c - Micrel KSZ8841/2 PCI Ethernet driver
*
* Copyright (c) 2009-2010 Micrel, Inc.
* Tristram Ha <Tristram.Ha@micrel.com>
@@ -4863,7 +4863,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev)
memset(&skb->data[skb->len], 0, 50 - skb->len);
skb->len = 50;
} else {
- skb = dev_alloc_skb(50);
+ skb = netdev_alloc_skb(dev, 50);
if (!skb)
return NETDEV_TX_BUSY;
memcpy(skb->data, org_skb->data, org_skb->len);
@@ -4885,7 +4885,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev)
(ETH_P_IPV6 == htons(skb->protocol)))) {
struct sk_buff *org_skb = skb;
- skb = dev_alloc_skb(org_skb->len);
+ skb = netdev_alloc_skb(dev, org_skb->len);
if (!skb) {
rc = NETDEV_TX_BUSY;
goto unlock;
@@ -5019,7 +5019,7 @@ static inline int rx_proc(struct net_device *dev, struct ksz_hw* hw,
do {
/* skb->data != skb->head */
- skb = dev_alloc_skb(packet_len + 2);
+ skb = netdev_alloc_skb(dev, packet_len + 2);
if (!skb) {
dev->stats.rx_dropped++;
return -ENOMEM;
diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
index 50055e0282ed..6118bdad244f 100644
--- a/drivers/net/ethernet/microchip/enc28j60.c
+++ b/drivers/net/ethernet/microchip/enc28j60.c
@@ -527,6 +527,7 @@ static int enc28j60_set_mac_address(struct net_device *dev, void *addr)
if (!is_valid_ether_addr(address->sa_data))
return -EADDRNOTAVAIL;
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
return enc28j60_set_hw_macaddr(dev);
}
@@ -954,14 +955,13 @@ static void enc28j60_hw_rx(struct net_device *ndev)
if (len > MAX_FRAMELEN)
ndev->stats.rx_over_errors++;
} else {
- skb = dev_alloc_skb(len + NET_IP_ALIGN);
+ skb = netdev_alloc_skb(ndev, len + NET_IP_ALIGN);
if (!skb) {
if (netif_msg_rx_err(priv))
dev_err(&ndev->dev,
"out of memory for Rx'd frame\n");
ndev->stats.rx_dropped++;
} else {
- skb->dev = ndev;
skb_reserve(skb, NET_IP_ALIGN);
/* copy the packet from the receive buffer */
enc28j60_mem_read(priv,
@@ -1553,9 +1553,6 @@ static int __devinit enc28j60_probe(struct spi_device *spi)
dev = alloc_etherdev(sizeof(struct enc28j60_net));
if (!dev) {
- if (netif_msg_drv(&debug))
- dev_err(&spi->dev, DRV_NAME
- ": unable to alloc new ethernet\n");
ret = -ENOMEM;
goto error_alloc;
}
@@ -1579,7 +1576,7 @@ static int __devinit enc28j60_probe(struct spi_device *spi)
ret = -EIO;
goto error_irq;
}
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
enc28j60_set_hw_macaddr(dev);
/* Board setup must set the relevant edge trigger type;
diff --git a/drivers/net/ethernet/mipsnet.c b/drivers/net/ethernet/mipsnet.c
index d05b0c9e1e9c..db5285befe2a 100644
--- a/drivers/net/ethernet/mipsnet.c
+++ b/drivers/net/ethernet/mipsnet.c
@@ -152,7 +152,7 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t len)
if (!len)
return len;
- skb = dev_alloc_skb(len + NET_IP_ALIGN);
+ skb = netdev_alloc_skb(dev, len + NET_IP_ALIGN);
if (!skb) {
dev->stats.rx_dropped++;
return -ENOMEM;
@@ -281,7 +281,7 @@ static int __devinit mipsnet_probe(struct platform_device *dev)
* Lacking any better mechanism to allocate a MAC address we use a
* random one ...
*/
- random_ether_addr(netdev->dev_addr);
+ eth_hw_addr_random(netdev);
err = register_netdev(netdev);
if (err) {
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 20b72ecb020a..27273ae1a6e6 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -3910,10 +3910,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
static int board_number;
netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES);
- if (netdev == NULL) {
- dev_err(dev, "Could not allocate ethernet device\n");
+ if (netdev == NULL)
return -ENOMEM;
- }
SET_NETDEV_DEV(netdev, &pdev->dev);
diff --git a/drivers/net/ethernet/natsemi/ibmlana.c b/drivers/net/ethernet/natsemi/ibmlana.c
index 999407f7ebdf..3f94ddbf4dc0 100644
--- a/drivers/net/ethernet/natsemi/ibmlana.c
+++ b/drivers/net/ethernet/natsemi/ibmlana.c
@@ -589,7 +589,7 @@ static void irqrx_handler(struct net_device *dev)
/* fetch buffer */
- skb = dev_alloc_skb(rda.length + 2);
+ skb = netdev_alloc_skb(dev, rda.length + 2);
if (skb == NULL)
dev->stats.rx_dropped++;
else {
diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
index f1b85561c650..e640e23460de 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -307,7 +307,7 @@ static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
printk(KERN_WARNING "macsonic: MAC address in CAM entry 15 "
"seems invalid, will use a random MAC\n");
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
}
static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
index ac7b16b6e7af..d38e48d4f430 100644
--- a/drivers/net/ethernet/natsemi/natsemi.c
+++ b/drivers/net/ethernet/natsemi/natsemi.c
@@ -1934,11 +1934,10 @@ static void refill_rx(struct net_device *dev)
int entry = np->dirty_rx % RX_RING_SIZE;
if (np->rx_skbuff[entry] == NULL) {
unsigned int buflen = np->rx_buf_sz+NATSEMI_PADDING;
- skb = dev_alloc_skb(buflen);
+ skb = netdev_alloc_skb(dev, buflen);
np->rx_skbuff[entry] = skb;
if (skb == NULL)
break; /* Better luck next round. */
- skb->dev = dev; /* Mark as being used by this device. */
np->rx_dma[entry] = pci_map_single(np->pci_dev,
skb->data, buflen, PCI_DMA_FROMDEVICE);
np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]);
@@ -2344,7 +2343,7 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do)
/* Check if the packet is long enough to accept
* without copying to a minimally-sized skbuff. */
if (pkt_len < rx_copybreak &&
- (skb = dev_alloc_skb(pkt_len + RX_OFFSET)) != NULL) {
+ (skb = netdev_alloc_skb(dev, pkt_len + RX_OFFSET)) != NULL) {
/* 16 byte align the IP header */
skb_reserve(skb, RX_OFFSET);
pci_dma_sync_single_for_cpu(np->pci_dev,
diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c
index 26e25d7f5829..46795e403467 100644
--- a/drivers/net/ethernet/natsemi/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
@@ -51,7 +51,7 @@ static int sonic_open(struct net_device *dev)
printk("sonic_open: initializing sonic driver.\n");
for (i = 0; i < SONIC_NUM_RRS; i++) {
- struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2);
+ struct sk_buff *skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2);
if (skb == NULL) {
while(i > 0) { /* free any that were allocated successfully */
i--;
@@ -422,7 +422,7 @@ static void sonic_rx(struct net_device *dev)
status = sonic_rda_get(dev, entry, SONIC_RD_STATUS);
if (status & SONIC_RCR_PRX) {
/* Malloc up new buffer. */
- new_skb = dev_alloc_skb(SONIC_RBSIZE + 2);
+ new_skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2);
if (new_skb == NULL) {
printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 97f63e12d86e..22a8de00bf02 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -2524,7 +2524,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, struct ring_info *ring,
size = ring->mtu + ALIGN_SIZE + BUF0_LEN + 4;
/* allocate skb */
- skb = dev_alloc_skb(size);
+ skb = netdev_alloc_skb(nic->dev, size);
if (!skb) {
DBG_PRINT(INFO_DBG, "%s: Could not allocate skb\n",
ring->dev->name);
@@ -5248,7 +5248,7 @@ static int s2io_set_mac_addr(struct net_device *dev, void *p)
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
@@ -6820,7 +6820,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
*/
rxdp1->Buffer0_ptr = *temp0;
} else {
- *skb = dev_alloc_skb(size);
+ *skb = netdev_alloc_skb(dev, size);
if (!(*skb)) {
DBG_PRINT(INFO_DBG,
"%s: Out of memory to allocate %s\n",
@@ -6849,7 +6849,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
rxdp3->Buffer0_ptr = *temp0;
rxdp3->Buffer1_ptr = *temp1;
} else {
- *skb = dev_alloc_skb(size);
+ *skb = netdev_alloc_skb(dev, size);
if (!(*skb)) {
DBG_PRINT(INFO_DBG,
"%s: Out of memory to allocate %s\n",
@@ -7760,7 +7760,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
else
dev = alloc_etherdev(sizeof(struct s2io_nic));
if (dev == NULL) {
- DBG_PRINT(ERR_DBG, "Device allocation failed\n");
pci_disable_device(pdev);
pci_release_regions(pdev);
return -ENODEV;
diff --git a/drivers/net/ethernet/netx-eth.c b/drivers/net/ethernet/netx-eth.c
index 8d288af16fc9..9d11ab7521bc 100644
--- a/drivers/net/ethernet/netx-eth.c
+++ b/drivers/net/ethernet/netx-eth.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/netx-eth.c
+ * drivers/net/ethernet/netx-eth.c
*
* Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
@@ -150,7 +150,7 @@ static void netx_eth_receive(struct net_device *ndev)
seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT;
len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT;
- skb = dev_alloc_skb(len);
+ skb = netdev_alloc_skb(ndev, len);
if (unlikely(skb == NULL)) {
printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
ndev->name);
@@ -383,7 +383,6 @@ static int netx_eth_drv_probe(struct platform_device *pdev)
ndev = alloc_etherdev(sizeof (struct netx_eth_priv));
if (!ndev) {
- printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM;
goto exit;
}
diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c
index b75a0497d58d..6893a65ae55f 100644
--- a/drivers/net/ethernet/nuvoton/w90p910_ether.c
+++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c
@@ -735,7 +735,7 @@ static void netdev_rx(struct net_device *dev)
if (status & RXDS_RXGD) {
data = ether->rdesc->recv_buf[ether->cur_rx];
- skb = dev_alloc_skb(length+2);
+ skb = netdev_alloc_skb(dev, length + 2);
if (!skb) {
dev_err(&pdev->dev, "get skb buffer error\n");
ether->stats.rx_dropped++;
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 4c4e7f458383..8561dd25db66 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -1815,7 +1815,7 @@ static int nv_alloc_rx(struct net_device *dev)
less_rx = np->last_rx.orig;
while (np->put_rx.orig != less_rx) {
- struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD);
+ struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz + NV_RX_ALLOC_PAD);
if (skb) {
np->put_rx_ctx->skb = skb;
np->put_rx_ctx->dma = pci_map_single(np->pci_dev,
@@ -1850,7 +1850,7 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
less_rx = np->last_rx.ex;
while (np->put_rx.ex != less_rx) {
- struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD);
+ struct sk_buff *skb = netdev_alloc_skb(dev, np->rx_buf_sz + NV_RX_ALLOC_PAD);
if (skb) {
np->put_rx_ctx->skb = skb;
np->put_rx_ctx->dma = pci_map_single(np->pci_dev,
@@ -3022,6 +3022,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
/* synchronized against open : rtnl_lock() held by caller */
memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
if (netif_running(dev)) {
netif_tx_lock_bh(dev);
@@ -4993,9 +4994,9 @@ static int nv_loopback_test(struct net_device *dev)
/* setup packet for tx */
pkt_len = ETH_DATA_LEN;
- tx_skb = dev_alloc_skb(pkt_len);
+ tx_skb = netdev_alloc_skb(dev, pkt_len);
if (!tx_skb) {
- netdev_err(dev, "dev_alloc_skb() failed during loopback test\n");
+ netdev_err(dev, "netdev_alloc_skb() failed during loopback test\n");
ret = 0;
goto out;
}
@@ -5741,7 +5742,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
dev_err(&pci_dev->dev,
"Invalid MAC address detected: %pM - Please complain to your hardware vendor.\n",
dev->dev_addr);
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
dev_err(&pci_dev->dev,
"Using random MAC address: %pM\n", dev->dev_addr);
}
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 3ead111111e1..69a66545c8ae 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
@@ -1224,7 +1224,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data)
/* When request status is Receive interruption */
if ((int_st & (PCH_GBE_INT_RX_DMA_CMPLT | PCH_GBE_INT_TX_CMPLT)) ||
- (adapter->rx_stop_flag == true)) {
+ (adapter->rx_stop_flag)) {
if (likely(napi_schedule_prep(&adapter->napi))) {
/* Enable only Rx Descriptor empty */
atomic_inc(&adapter->irq_sem);
@@ -1587,10 +1587,8 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
size = (int)sizeof(struct pch_gbe_buffer) * tx_ring->count;
tx_ring->buffer_info = vzalloc(size);
- if (!tx_ring->buffer_info) {
- pr_err("Unable to allocate memory for the buffer information\n");
+ if (!tx_ring->buffer_info)
return -ENOMEM;
- }
tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc);
@@ -1636,10 +1634,9 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
size = (int)sizeof(struct pch_gbe_buffer) * rx_ring->count;
rx_ring->buffer_info = vzalloc(size);
- if (!rx_ring->buffer_info) {
- pr_err("Unable to allocate memory for the receive descriptor ring\n");
+ if (!rx_ring->buffer_info)
return -ENOMEM;
- }
+
rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc);
rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
&rx_ring->dma, GFP_KERNEL);
@@ -2422,8 +2419,6 @@ static int pch_gbe_probe(struct pci_dev *pdev,
netdev = alloc_etherdev((int)sizeof(struct pch_gbe_adapter));
if (!netdev) {
ret = -ENOMEM;
- dev_err(&pdev->dev,
- "ERR: Can't allocate and set up an Ethernet device\n");
goto err_release_pci;
}
SET_NETDEV_DEV(netdev, &pdev->dev);
diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c
index 3458df3780b8..0d29f5f4b8e4 100644
--- a/drivers/net/ethernet/packetengines/hamachi.c
+++ b/drivers/net/ethernet/packetengines/hamachi.c
@@ -1188,11 +1188,10 @@ static void hamachi_init_ring(struct net_device *dev)
}
/* Fill in the Rx buffers. Handle allocation failure gracefully. */
for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz + 2);
+ struct sk_buff *skb = netdev_alloc_skb(dev, hmp->rx_buf_sz + 2);
hmp->rx_skbuff[i] = skb;
if (skb == NULL)
break;
- skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* 16 byte align the IP header. */
hmp->rx_ring[i].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev,
skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
@@ -1488,7 +1487,7 @@ static int hamachi_rx(struct net_device *dev)
/* Check if the packet is long enough to accept without copying
to a minimally-sized skbuff. */
if (pkt_len < rx_copybreak &&
- (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
#ifdef RX_CHECKSUM
printk(KERN_ERR "%s: rx_copybreak non-zero "
"not good with RX_CHECKSUM\n", dev->name);
@@ -1591,12 +1590,11 @@ static int hamachi_rx(struct net_device *dev)
entry = hmp->dirty_rx % RX_RING_SIZE;
desc = &(hmp->rx_ring[entry]);
if (hmp->rx_skbuff[entry] == NULL) {
- struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz + 2);
+ struct sk_buff *skb = netdev_alloc_skb(dev, hmp->rx_buf_sz + 2);
hmp->rx_skbuff[entry] = skb;
if (skb == NULL)
break; /* Better luck next round. */
- skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
desc->addr = cpu_to_leXX(pci_map_single(hmp->pci_dev,
skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c
index db44e9af03c3..7757b80ef924 100644
--- a/drivers/net/ethernet/packetengines/yellowfin.c
+++ b/drivers/net/ethernet/packetengines/yellowfin.c
@@ -397,10 +397,9 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
if (i) return i;
dev = alloc_etherdev(sizeof(*np));
- if (!dev) {
- pr_err("cannot allocate ethernet device\n");
+ if (!dev)
return -ENOMEM;
- }
+
SET_NETDEV_DEV(dev, &pdev->dev);
np = netdev_priv(dev);
@@ -744,11 +743,10 @@ static int yellowfin_init_ring(struct net_device *dev)
}
for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz + 2);
+ struct sk_buff *skb = netdev_alloc_skb(dev, yp->rx_buf_sz + 2);
yp->rx_skbuff[i] = skb;
if (skb == NULL)
break;
- skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* 16 byte align the IP header. */
yp->rx_ring[i].addr = cpu_to_le32(pci_map_single(yp->pci_dev,
skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE));
@@ -1134,7 +1132,7 @@ static int yellowfin_rx(struct net_device *dev)
PCI_DMA_FROMDEVICE);
yp->rx_skbuff[entry] = NULL;
} else {
- skb = dev_alloc_skb(pkt_len + 2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb == NULL)
break;
skb_reserve(skb, 2); /* 16 byte align the IP header */
@@ -1157,11 +1155,10 @@ static int yellowfin_rx(struct net_device *dev)
for (; yp->cur_rx - yp->dirty_rx > 0; yp->dirty_rx++) {
entry = yp->dirty_rx % RX_RING_SIZE;
if (yp->rx_skbuff[entry] == NULL) {
- struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz + 2);
+ struct sk_buff *skb = netdev_alloc_skb(dev, yp->rx_buf_sz + 2);
if (skb == NULL)
break; /* Better luck next round. */
yp->rx_skbuff[entry] = skb;
- skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
yp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(yp->pci_dev,
skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE));
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index 49b549ff2c78..ddc95b0ac78d 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -238,7 +238,7 @@ static int pasemi_mac_set_mac_addr(struct net_device *dev, void *p)
unsigned int adr0, adr1;
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
@@ -643,7 +643,7 @@ static void pasemi_mac_replenish_rx_ring(const struct net_device *dev,
/* Entry in use? */
WARN_ON(*buff);
- skb = dev_alloc_skb(mac->bufsz);
+ skb = netdev_alloc_skb(dev, mac->bufsz);
skb_reserve(skb, LOCAL_SKB_ALIGN);
if (unlikely(!skb))
@@ -1740,8 +1740,6 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev = alloc_etherdev(sizeof(struct pasemi_mac));
if (dev == NULL) {
- dev_err(&pdev->dev,
- "pasemi_mac: Could not allocate ethernet device.\n");
err = -ENOMEM;
goto out_disable_device;
}
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
index a876dffd7101..2eeac32f7fdd 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
@@ -53,8 +53,8 @@
#define _NETXEN_NIC_LINUX_MAJOR 4
#define _NETXEN_NIC_LINUX_MINOR 0
-#define _NETXEN_NIC_LINUX_SUBVERSION 77
-#define NETXEN_NIC_LINUX_VERSIONID "4.0.77"
+#define _NETXEN_NIC_LINUX_SUBVERSION 78
+#define NETXEN_NIC_LINUX_VERSIONID "4.0.78"
#define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c))
#define _major(v) (((v) >> 24) & 0xff)
@@ -686,6 +686,18 @@ struct netxen_recv_context {
dma_addr_t phys_addr;
};
+struct _cdrp_cmd {
+ u32 cmd;
+ u32 arg1;
+ u32 arg2;
+ u32 arg3;
+};
+
+struct netxen_cmd_args {
+ struct _cdrp_cmd req;
+ struct _cdrp_cmd rsp;
+};
+
/* New HW context creation */
#define NX_OS_CRB_RETRY_COUNT 4000
@@ -1142,6 +1154,7 @@ typedef struct {
#define NETXEN_NIC_LRO_DISABLED 0x00
#define NETXEN_NIC_BRIDGE_ENABLED 0X10
#define NETXEN_NIC_DIAG_ENABLED 0x20
+#define NETXEN_FW_RESET_OWNER 0x40
#define NETXEN_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED))
@@ -1159,6 +1172,419 @@ typedef struct {
#define __NX_DEV_UP 1
#define __NX_RESETTING 2
+/* Mini Coredump FW supported version */
+#define NX_MD_SUPPORT_MAJOR 4
+#define NX_MD_SUPPORT_MINOR 0
+#define NX_MD_SUPPORT_SUBVERSION 579
+
+#define LSW(x) ((uint16_t)(x))
+#define LSD(x) ((uint32_t)((uint64_t)(x)))
+#define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16))
+
+/* Mini Coredump mask level */
+#define NX_DUMP_MASK_MIN 0x03
+#define NX_DUMP_MASK_DEF 0x1f
+#define NX_DUMP_MASK_MAX 0xff
+
+/* Mini Coredump CDRP commands */
+#define NX_CDRP_CMD_TEMP_SIZE 0x0000002f
+#define NX_CDRP_CMD_GET_TEMP_HDR 0x00000030
+
+
+#define NX_DUMP_STATE_ARRAY_LEN 16
+#define NX_DUMP_CAP_SIZE_ARRAY_LEN 8
+
+/* Mini Coredump sysfs entries flags*/
+#define NX_FORCE_FW_DUMP_KEY 0xdeadfeed
+#define NX_ENABLE_FW_DUMP 0xaddfeed
+#define NX_DISABLE_FW_DUMP 0xbadfeed
+#define NX_FORCE_FW_RESET 0xdeaddead
+
+
+/* Flash read/write address */
+#define NX_FW_DUMP_REG1 0x00130060
+#define NX_FW_DUMP_REG2 0x001e0000
+#define NX_FLASH_SEM2_LK 0x0013C010
+#define NX_FLASH_SEM2_ULK 0x0013C014
+#define NX_FLASH_LOCK_ID 0x001B2100
+#define FLASH_ROM_WINDOW 0x42110030
+#define FLASH_ROM_DATA 0x42150000
+
+/* Mini Coredump register read/write routine */
+#define NX_RD_DUMP_REG(addr, bar0, data) do { \
+ writel((addr & 0xFFFF0000), (void __iomem *) (bar0 + \
+ NX_FW_DUMP_REG1)); \
+ readl((void __iomem *) (bar0 + NX_FW_DUMP_REG1)); \
+ *data = readl((void __iomem *) (bar0 + NX_FW_DUMP_REG2 + \
+ LSW(addr))); \
+} while (0)
+
+#define NX_WR_DUMP_REG(addr, bar0, data) do { \
+ writel((addr & 0xFFFF0000), (void __iomem *) (bar0 + \
+ NX_FW_DUMP_REG1)); \
+ readl((void __iomem *) (bar0 + NX_FW_DUMP_REG1)); \
+ writel(data, (void __iomem *) (bar0 + NX_FW_DUMP_REG2 + LSW(addr)));\
+ readl((void __iomem *) (bar0 + NX_FW_DUMP_REG2 + LSW(addr))); \
+} while (0)
+
+
+/*
+Entry Type Defines
+*/
+
+#define RDNOP 0
+#define RDCRB 1
+#define RDMUX 2
+#define QUEUE 3
+#define BOARD 4
+#define RDSRE 5
+#define RDOCM 6
+#define PREGS 7
+#define L1DTG 8
+#define L1ITG 9
+#define CACHE 10
+
+#define L1DAT 11
+#define L1INS 12
+#define RDSTK 13
+#define RDCON 14
+
+#define L2DTG 21
+#define L2ITG 22
+#define L2DAT 23
+#define L2INS 24
+#define RDOC3 25
+
+#define MEMBK 32
+
+#define RDROM 71
+#define RDMEM 72
+#define RDMN 73
+
+#define INFOR 81
+#define CNTRL 98
+
+#define TLHDR 99
+#define RDEND 255
+
+#define PRIMQ 103
+#define SQG2Q 104
+#define SQG3Q 105
+
+/*
+* Opcodes for Control Entries.
+* These Flags are bit fields.
+*/
+#define NX_DUMP_WCRB 0x01
+#define NX_DUMP_RWCRB 0x02
+#define NX_DUMP_ANDCRB 0x04
+#define NX_DUMP_ORCRB 0x08
+#define NX_DUMP_POLLCRB 0x10
+#define NX_DUMP_RD_SAVE 0x20
+#define NX_DUMP_WRT_SAVED 0x40
+#define NX_DUMP_MOD_SAVE_ST 0x80
+
+/* Driver Flags */
+#define NX_DUMP_SKIP 0x80 /* driver skipped this entry */
+#define NX_DUMP_SIZE_ERR 0x40 /*entry size vs capture size mismatch*/
+
+#define NX_PCI_READ_32(ADDR) readl((ADDR))
+#define NX_PCI_WRITE_32(DATA, ADDR) writel(DATA, (ADDR))
+
+
+
+struct netxen_minidump {
+ u32 pos; /* position in the dump buffer */
+ u8 fw_supports_md; /* FW supports Mini cordump */
+ u8 has_valid_dump; /* indicates valid dump */
+ u8 md_capture_mask; /* driver capture mask */
+ u8 md_enabled; /* Turn Mini Coredump on/off */
+ u32 md_dump_size; /* Total FW Mini Coredump size */
+ u32 md_capture_size; /* FW dump capture size */
+ u32 md_template_size; /* FW template size */
+ u32 md_template_ver; /* FW template version */
+ u64 md_timestamp; /* FW Mini dump timestamp */
+ void *md_template; /* FW template will be stored */
+ void *md_capture_buff; /* FW dump will be stored */
+};
+
+
+
+struct netxen_minidump_template_hdr {
+ u32 entry_type;
+ u32 first_entry_offset;
+ u32 size_of_template;
+ u32 capture_mask;
+ u32 num_of_entries;
+ u32 version;
+ u32 driver_timestamp;
+ u32 checksum;
+ u32 driver_capture_mask;
+ u32 driver_info_word2;
+ u32 driver_info_word3;
+ u32 driver_info_word4;
+ u32 saved_state_array[NX_DUMP_STATE_ARRAY_LEN];
+ u32 capture_size_array[NX_DUMP_CAP_SIZE_ARRAY_LEN];
+ u32 rsvd[0];
+};
+
+/* Common Entry Header: Common to All Entry Types */
+/*
+ * Driver Code is for driver to write some info about the entry.
+ * Currently not used.
+ */
+
+struct netxen_common_entry_hdr {
+ u32 entry_type;
+ u32 entry_size;
+ u32 entry_capture_size;
+ union {
+ struct {
+ u8 entry_capture_mask;
+ u8 entry_code;
+ u8 driver_code;
+ u8 driver_flags;
+ };
+ u32 entry_ctrl_word;
+ };
+};
+
+
+/* Generic Entry Including Header */
+struct netxen_minidump_entry {
+ struct netxen_common_entry_hdr hdr;
+ u32 entry_data00;
+ u32 entry_data01;
+ u32 entry_data02;
+ u32 entry_data03;
+ u32 entry_data04;
+ u32 entry_data05;
+ u32 entry_data06;
+ u32 entry_data07;
+};
+
+/* Read ROM Header */
+struct netxen_minidump_entry_rdrom {
+ struct netxen_common_entry_hdr h;
+ union {
+ struct {
+ u32 select_addr_reg;
+ };
+ u32 rsvd_0;
+ };
+ union {
+ struct {
+ u8 addr_stride;
+ u8 addr_cnt;
+ u16 data_size;
+ };
+ u32 rsvd_1;
+ };
+ union {
+ struct {
+ u32 op_count;
+ };
+ u32 rsvd_2;
+ };
+ union {
+ struct {
+ u32 read_addr_reg;
+ };
+ u32 rsvd_3;
+ };
+ union {
+ struct {
+ u32 write_mask;
+ };
+ u32 rsvd_4;
+ };
+ union {
+ struct {
+ u32 read_mask;
+ };
+ u32 rsvd_5;
+ };
+ u32 read_addr;
+ u32 read_data_size;
+};
+
+
+/* Read CRB and Control Entry Header */
+struct netxen_minidump_entry_crb {
+ struct netxen_common_entry_hdr h;
+ u32 addr;
+ union {
+ struct {
+ u8 addr_stride;
+ u8 state_index_a;
+ u16 poll_timeout;
+ };
+ u32 addr_cntrl;
+ };
+ u32 data_size;
+ u32 op_count;
+ union {
+ struct {
+ u8 opcode;
+ u8 state_index_v;
+ u8 shl;
+ u8 shr;
+ };
+ u32 control_value;
+ };
+ u32 value_1;
+ u32 value_2;
+ u32 value_3;
+};
+
+/* Read Memory and MN Header */
+struct netxen_minidump_entry_rdmem {
+ struct netxen_common_entry_hdr h;
+ union {
+ struct {
+ u32 select_addr_reg;
+ };
+ u32 rsvd_0;
+ };
+ union {
+ struct {
+ u8 addr_stride;
+ u8 addr_cnt;
+ u16 data_size;
+ };
+ u32 rsvd_1;
+ };
+ union {
+ struct {
+ u32 op_count;
+ };
+ u32 rsvd_2;
+ };
+ union {
+ struct {
+ u32 read_addr_reg;
+ };
+ u32 rsvd_3;
+ };
+ union {
+ struct {
+ u32 cntrl_addr_reg;
+ };
+ u32 rsvd_4;
+ };
+ union {
+ struct {
+ u8 wr_byte0;
+ u8 wr_byte1;
+ u8 poll_mask;
+ u8 poll_cnt;
+ };
+ u32 rsvd_5;
+ };
+ u32 read_addr;
+ u32 read_data_size;
+};
+
+/* Read Cache L1 and L2 Header */
+struct netxen_minidump_entry_cache {
+ struct netxen_common_entry_hdr h;
+ u32 tag_reg_addr;
+ union {
+ struct {
+ u16 tag_value_stride;
+ u16 init_tag_value;
+ };
+ u32 select_addr_cntrl;
+ };
+ u32 data_size;
+ u32 op_count;
+ u32 control_addr;
+ union {
+ struct {
+ u16 write_value;
+ u8 poll_mask;
+ u8 poll_wait;
+ };
+ u32 control_value;
+ };
+ u32 read_addr;
+ union {
+ struct {
+ u8 read_addr_stride;
+ u8 read_addr_cnt;
+ u16 rsvd_1;
+ };
+ u32 read_addr_cntrl;
+ };
+};
+
+/* Read OCM Header */
+struct netxen_minidump_entry_rdocm {
+ struct netxen_common_entry_hdr h;
+ u32 rsvd_0;
+ union {
+ struct {
+ u32 rsvd_1;
+ };
+ u32 select_addr_cntrl;
+ };
+ u32 data_size;
+ u32 op_count;
+ u32 rsvd_2;
+ u32 rsvd_3;
+ u32 read_addr;
+ union {
+ struct {
+ u32 read_addr_stride;
+ };
+ u32 read_addr_cntrl;
+ };
+};
+
+/* Read MUX Header */
+struct netxen_minidump_entry_mux {
+ struct netxen_common_entry_hdr h;
+ u32 select_addr;
+ union {
+ struct {
+ u32 rsvd_0;
+ };
+ u32 select_addr_cntrl;
+ };
+ u32 data_size;
+ u32 op_count;
+ u32 select_value;
+ u32 select_value_stride;
+ u32 read_addr;
+ u32 rsvd_1;
+};
+
+/* Read Queue Header */
+struct netxen_minidump_entry_queue {
+ struct netxen_common_entry_hdr h;
+ u32 select_addr;
+ union {
+ struct {
+ u16 queue_id_stride;
+ u16 rsvd_0;
+ };
+ u32 select_addr_cntrl;
+ };
+ u32 data_size;
+ u32 op_count;
+ u32 rsvd_1;
+ u32 rsvd_2;
+ u32 read_addr;
+ union {
+ struct {
+ u8 read_addr_stride;
+ u8 read_addr_cnt;
+ u16 rsvd_3;
+ };
+ u32 read_addr_cntrl;
+ };
+};
+
struct netxen_dummy_dma {
void *addr;
dma_addr_t phys_addr;
@@ -1263,6 +1689,8 @@ struct netxen_adapter {
__le32 file_prd_off; /*File fw product offset*/
u32 fw_version;
const struct firmware *fw;
+ struct netxen_minidump mdump; /* mdump ptr */
+ int fw_mdump_rdy; /* for mdump ready */
};
int nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val);
@@ -1365,13 +1793,16 @@ int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable);
int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable);
int netxen_send_lro_cleanup(struct netxen_adapter *adapter);
-
+int netxen_setup_minidump(struct netxen_adapter *adapter);
+void netxen_dump_fw(struct netxen_adapter *adapter);
void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
struct nx_host_tx_ring *tx_ring);
/* Functions from netxen_nic_main.c */
int netxen_nic_reset_context(struct netxen_adapter *);
+int nx_dev_request_reset(struct netxen_adapter *adapter);
+
/*
* NetXen Board information
*/
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
index a925392abd6f..f3c0057a802b 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
@@ -48,28 +48,27 @@ netxen_poll_rsp(struct netxen_adapter *adapter)
}
static u32
-netxen_issue_cmd(struct netxen_adapter *adapter,
- u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd)
+netxen_issue_cmd(struct netxen_adapter *adapter, struct netxen_cmd_args *cmd)
{
u32 rsp;
u32 signature = 0;
u32 rcode = NX_RCODE_SUCCESS;
- signature = NX_CDRP_SIGNATURE_MAKE(pci_fn, version);
-
+ signature = NX_CDRP_SIGNATURE_MAKE(adapter->ahw.pci_func,
+ NXHAL_VERSION);
/* Acquire semaphore before accessing CRB */
if (netxen_api_lock(adapter))
return NX_RCODE_TIMEOUT;
NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature);
- NXWR32(adapter, NX_ARG1_CRB_OFFSET, arg1);
+ NXWR32(adapter, NX_ARG1_CRB_OFFSET, cmd->req.arg1);
- NXWR32(adapter, NX_ARG2_CRB_OFFSET, arg2);
+ NXWR32(adapter, NX_ARG2_CRB_OFFSET, cmd->req.arg2);
- NXWR32(adapter, NX_ARG3_CRB_OFFSET, arg3);
+ NXWR32(adapter, NX_ARG3_CRB_OFFSET, cmd->req.arg3);
- NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd));
+ NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd->req.cmd));
rsp = netxen_poll_rsp(adapter);
@@ -83,28 +82,179 @@ netxen_issue_cmd(struct netxen_adapter *adapter,
printk(KERN_ERR "%s: failed card response code:0x%x\n",
netxen_nic_driver_name, rcode);
+ } else if (rsp == NX_CDRP_RSP_OK) {
+ cmd->rsp.cmd = NX_RCODE_SUCCESS;
+ if (cmd->rsp.arg2)
+ cmd->rsp.arg2 = NXRD32(adapter, NX_ARG2_CRB_OFFSET);
+ if (cmd->rsp.arg3)
+ cmd->rsp.arg3 = NXRD32(adapter, NX_ARG3_CRB_OFFSET);
}
+ if (cmd->rsp.arg1)
+ cmd->rsp.arg1 = NXRD32(adapter, NX_ARG1_CRB_OFFSET);
/* Release semaphore */
netxen_api_unlock(adapter);
return rcode;
}
+static int
+netxen_get_minidump_template_size(struct netxen_adapter *adapter)
+{
+ struct netxen_cmd_args cmd;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = NX_CDRP_CMD_TEMP_SIZE;
+ memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd));
+ netxen_issue_cmd(adapter, &cmd);
+ if (cmd.rsp.cmd != NX_RCODE_SUCCESS) {
+ dev_info(&adapter->pdev->dev,
+ "Can't get template size %d\n", cmd.rsp.cmd);
+ return -EIO;
+ }
+ adapter->mdump.md_template_size = cmd.rsp.arg2;
+ adapter->mdump.md_template_ver = cmd.rsp.arg3;
+ return 0;
+}
+
+static int
+netxen_get_minidump_template(struct netxen_adapter *adapter)
+{
+ dma_addr_t md_template_addr;
+ void *addr;
+ u32 size;
+ struct netxen_cmd_args cmd;
+ size = adapter->mdump.md_template_size;
+
+ if (size == 0) {
+ dev_err(&adapter->pdev->dev, "Can not capture Minidump "
+ "template. Invalid template size.\n");
+ return NX_RCODE_INVALID_ARGS;
+ }
+
+ addr = pci_alloc_consistent(adapter->pdev, size, &md_template_addr);
+
+ if (!addr) {
+ dev_err(&adapter->pdev->dev, "Unable to allocate dmable memory for template.\n");
+ return -ENOMEM;
+ }
+
+ memset(addr, 0, size);
+ memset(&cmd, 0, sizeof(cmd));
+ memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd));
+ cmd.req.cmd = NX_CDRP_CMD_GET_TEMP_HDR;
+ cmd.req.arg1 = LSD(md_template_addr);
+ cmd.req.arg2 = MSD(md_template_addr);
+ cmd.req.arg3 |= size;
+ netxen_issue_cmd(adapter, &cmd);
+
+ if ((cmd.rsp.cmd == NX_RCODE_SUCCESS) && (size == cmd.rsp.arg2)) {
+ memcpy(adapter->mdump.md_template, addr, size);
+ } else {
+ dev_err(&adapter->pdev->dev, "Failed to get minidump template, "
+ "err_code : %d, requested_size : %d, actual_size : %d\n ",
+ cmd.rsp.cmd, size, cmd.rsp.arg2);
+ }
+ pci_free_consistent(adapter->pdev, size, addr, md_template_addr);
+ return 0;
+}
+
+static u32
+netxen_check_template_checksum(struct netxen_adapter *adapter)
+{
+ u64 sum = 0 ;
+ u32 *buff = adapter->mdump.md_template;
+ int count = adapter->mdump.md_template_size/sizeof(uint32_t) ;
+
+ while (count-- > 0)
+ sum += *buff++ ;
+ while (sum >> 32)
+ sum = (sum & 0xFFFFFFFF) + (sum >> 32) ;
+
+ return ~sum;
+}
+
+int
+netxen_setup_minidump(struct netxen_adapter *adapter)
+{
+ int err = 0, i;
+ u32 *template, *tmp_buf;
+ struct netxen_minidump_template_hdr *hdr;
+ err = netxen_get_minidump_template_size(adapter);
+ if (err) {
+ adapter->mdump.fw_supports_md = 0;
+ if ((err == NX_RCODE_CMD_INVALID) ||
+ (err == NX_RCODE_CMD_NOT_IMPL)) {
+ dev_info(&adapter->pdev->dev,
+ "Flashed firmware version does not support minidump, "
+ "minimum version required is [ %u.%u.%u ].\n ",
+ NX_MD_SUPPORT_MAJOR, NX_MD_SUPPORT_MINOR,
+ NX_MD_SUPPORT_SUBVERSION);
+ }
+ return err;
+ }
+
+ if (!adapter->mdump.md_template_size) {
+ dev_err(&adapter->pdev->dev, "Error : Invalid template size "
+ ",should be non-zero.\n");
+ return -EIO;
+ }
+ adapter->mdump.md_template =
+ kmalloc(adapter->mdump.md_template_size, GFP_KERNEL);
+
+ if (!adapter->mdump.md_template) {
+ dev_err(&adapter->pdev->dev, "Unable to allocate memory "
+ "for minidump template.\n");
+ return -ENOMEM;
+ }
+
+ err = netxen_get_minidump_template(adapter);
+ if (err) {
+ if (err == NX_RCODE_CMD_NOT_IMPL)
+ adapter->mdump.fw_supports_md = 0;
+ goto free_template;
+ }
+
+ if (netxen_check_template_checksum(adapter)) {
+ dev_err(&adapter->pdev->dev, "Minidump template checksum Error\n");
+ err = -EIO;
+ goto free_template;
+ }
+
+ adapter->mdump.md_capture_mask = NX_DUMP_MASK_DEF;
+ tmp_buf = (u32 *) adapter->mdump.md_template;
+ template = (u32 *) adapter->mdump.md_template;
+ for (i = 0; i < adapter->mdump.md_template_size/sizeof(u32); i++)
+ *template++ = __le32_to_cpu(*tmp_buf++);
+ hdr = (struct netxen_minidump_template_hdr *)
+ adapter->mdump.md_template;
+ adapter->mdump.md_capture_buff = NULL;
+ adapter->mdump.fw_supports_md = 1;
+ adapter->mdump.md_enabled = 1;
+
+ return err;
+
+free_template:
+ kfree(adapter->mdump.md_template);
+ adapter->mdump.md_template = NULL;
+ return err;
+}
+
+
int
nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu)
{
u32 rcode = NX_RCODE_SUCCESS;
struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+ struct netxen_cmd_args cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = NX_CDRP_CMD_SET_MTU;
+ cmd.req.arg1 = recv_ctx->context_id;
+ cmd.req.arg2 = mtu;
+ cmd.req.arg3 = 0;
if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
- rcode = netxen_issue_cmd(adapter,
- adapter->ahw.pci_func,
- NXHAL_VERSION,
- recv_ctx->context_id,
- mtu,
- 0,
- NX_CDRP_CMD_SET_MTU);
+ netxen_issue_cmd(adapter, &cmd);
if (rcode != NX_RCODE_SUCCESS)
return -EIO;
@@ -116,15 +266,14 @@ int
nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter,
u32 speed, u32 duplex, u32 autoneg)
{
-
- return netxen_issue_cmd(adapter,
- adapter->ahw.pci_func,
- NXHAL_VERSION,
- speed,
- duplex,
- autoneg,
- NX_CDRP_CMD_CONFIG_GBE_PORT);
-
+ struct netxen_cmd_args cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = NX_CDRP_CMD_CONFIG_GBE_PORT;
+ cmd.req.arg1 = speed;
+ cmd.req.arg2 = duplex;
+ cmd.req.arg3 = autoneg;
+ return netxen_issue_cmd(adapter, &cmd);
}
static int
@@ -139,6 +288,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
nx_cardrsp_sds_ring_t *prsp_sds;
struct nx_host_rds_ring *rds_ring;
struct nx_host_sds_ring *sds_ring;
+ struct netxen_cmd_args cmd;
dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
u64 phys_addr;
@@ -218,13 +368,12 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
}
phys_addr = hostrq_phys_addr;
- err = netxen_issue_cmd(adapter,
- adapter->ahw.pci_func,
- NXHAL_VERSION,
- (u32)(phys_addr >> 32),
- (u32)(phys_addr & 0xffffffff),
- rq_size,
- NX_CDRP_CMD_CREATE_RX_CTX);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = (u32)(phys_addr >> 32);
+ cmd.req.arg2 = (u32)(phys_addr & 0xffffffff);
+ cmd.req.arg3 = rq_size;
+ cmd.req.cmd = NX_CDRP_CMD_CREATE_RX_CTX;
+ err = netxen_issue_cmd(adapter, &cmd);
if (err) {
printk(KERN_WARNING
"Failed to create rx ctx in firmware%d\n", err);
@@ -273,15 +422,15 @@ static void
nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter)
{
struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+ struct netxen_cmd_args cmd;
- if (netxen_issue_cmd(adapter,
- adapter->ahw.pci_func,
- NXHAL_VERSION,
- recv_ctx->context_id,
- NX_DESTROY_CTX_RESET,
- 0,
- NX_CDRP_CMD_DESTROY_RX_CTX)) {
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = recv_ctx->context_id;
+ cmd.req.arg2 = NX_DESTROY_CTX_RESET;
+ cmd.req.arg3 = 0;
+ cmd.req.cmd = NX_CDRP_CMD_DESTROY_RX_CTX;
+ if (netxen_issue_cmd(adapter, &cmd)) {
printk(KERN_WARNING
"%s: Failed to destroy rx ctx in firmware\n",
netxen_nic_driver_name);
@@ -302,6 +451,7 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
dma_addr_t rq_phys_addr, rsp_phys_addr;
struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+ struct netxen_cmd_args cmd;
rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t);
rq_addr = pci_alloc_consistent(adapter->pdev,
@@ -345,13 +495,12 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);
phys_addr = rq_phys_addr;
- err = netxen_issue_cmd(adapter,
- adapter->ahw.pci_func,
- NXHAL_VERSION,
- (u32)(phys_addr >> 32),
- ((u32)phys_addr & 0xffffffff),
- rq_size,
- NX_CDRP_CMD_CREATE_TX_CTX);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = (u32)(phys_addr >> 32);
+ cmd.req.arg2 = ((u32)phys_addr & 0xffffffff);
+ cmd.req.arg3 = rq_size;
+ cmd.req.cmd = NX_CDRP_CMD_CREATE_TX_CTX;
+ err = netxen_issue_cmd(adapter, &cmd);
if (err == NX_RCODE_SUCCESS) {
temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
@@ -380,14 +529,14 @@ out_free_rq:
static void
nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter)
{
- if (netxen_issue_cmd(adapter,
- adapter->ahw.pci_func,
- NXHAL_VERSION,
- adapter->tx_context_id,
- NX_DESTROY_CTX_RESET,
- 0,
- NX_CDRP_CMD_DESTROY_TX_CTX)) {
-
+ struct netxen_cmd_args cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = adapter->tx_context_id;
+ cmd.req.arg2 = NX_DESTROY_CTX_RESET;
+ cmd.req.arg3 = 0;
+ cmd.req.cmd = NX_CDRP_CMD_DESTROY_TX_CTX;
+ if (netxen_issue_cmd(adapter, &cmd)) {
printk(KERN_WARNING
"%s: Failed to destroy tx ctx in firmware\n",
netxen_nic_driver_name);
@@ -398,34 +547,37 @@ int
nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val)
{
u32 rcode;
-
- rcode = netxen_issue_cmd(adapter,
- adapter->ahw.pci_func,
- NXHAL_VERSION,
- reg,
- 0,
- 0,
- NX_CDRP_CMD_READ_PHY);
-
+ struct netxen_cmd_args cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = reg;
+ cmd.req.arg2 = 0;
+ cmd.req.arg3 = 0;
+ cmd.req.cmd = NX_CDRP_CMD_READ_PHY;
+ cmd.rsp.arg1 = 1;
+ rcode = netxen_issue_cmd(adapter, &cmd);
if (rcode != NX_RCODE_SUCCESS)
return -EIO;
- return NXRD32(adapter, NX_ARG1_CRB_OFFSET);
+ if (val == NULL)
+ return -EIO;
+
+ *val = cmd.rsp.arg1;
+ return 0;
}
int
nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val)
{
u32 rcode;
-
- rcode = netxen_issue_cmd(adapter,
- adapter->ahw.pci_func,
- NXHAL_VERSION,
- reg,
- val,
- 0,
- NX_CDRP_CMD_WRITE_PHY);
-
+ struct netxen_cmd_args cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.arg1 = reg;
+ cmd.req.arg2 = val;
+ cmd.req.arg3 = 0;
+ cmd.req.cmd = NX_CDRP_CMD_WRITE_PHY;
+ rcode = netxen_issue_cmd(adapter, &cmd);
if (rcode != NX_RCODE_SUCCESS)
return -EIO;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
index 8a371985319f..8c39299331a2 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
@@ -248,6 +248,11 @@ skip:
}
}
+ if (!netif_running(dev) || !adapter->ahw.linkup) {
+ ecmd->duplex = DUPLEX_UNKNOWN;
+ ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
+ }
+
return 0;
}
@@ -812,6 +817,107 @@ static int netxen_get_intr_coalesce(struct net_device *netdev,
return 0;
}
+static int
+netxen_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ struct netxen_minidump *mdump = &adapter->mdump;
+ if (adapter->fw_mdump_rdy)
+ dump->len = mdump->md_dump_size;
+ else
+ dump->len = 0;
+ dump->flag = mdump->md_capture_mask;
+ dump->version = adapter->fw_version;
+ return 0;
+}
+
+static int
+netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val)
+{
+ int ret = 0;
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ struct netxen_minidump *mdump = &adapter->mdump;
+
+ switch (val->flag) {
+ case NX_FORCE_FW_DUMP_KEY:
+ if (!mdump->md_enabled)
+ mdump->md_enabled = 1;
+ if (adapter->fw_mdump_rdy) {
+ netdev_info(netdev, "Previous dump not cleared, not forcing dump\n");
+ return ret;
+ }
+ netdev_info(netdev, "Forcing a fw dump\n");
+ nx_dev_request_reset(adapter);
+ break;
+ case NX_DISABLE_FW_DUMP:
+ if (mdump->md_enabled) {
+ netdev_info(netdev, "Disabling FW Dump\n");
+ mdump->md_enabled = 0;
+ }
+ break;
+ case NX_ENABLE_FW_DUMP:
+ if (!mdump->md_enabled) {
+ netdev_info(netdev, "Enabling FW dump\n");
+ mdump->md_enabled = 1;
+ }
+ break;
+ case NX_FORCE_FW_RESET:
+ netdev_info(netdev, "Forcing FW reset\n");
+ nx_dev_request_reset(adapter);
+ adapter->flags &= ~NETXEN_FW_RESET_OWNER;
+ break;
+ default:
+ if (val->flag <= NX_DUMP_MASK_MAX &&
+ val->flag >= NX_DUMP_MASK_MIN) {
+ mdump->md_capture_mask = val->flag & 0xff;
+ netdev_info(netdev, "Driver mask changed to: 0x%x\n",
+ mdump->md_capture_mask);
+ break;
+ }
+ netdev_info(netdev,
+ "Invalid dump level: 0x%x\n", val->flag);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int
+netxen_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
+ void *buffer)
+{
+ int i, copy_sz;
+ u32 *hdr_ptr, *data;
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ struct netxen_minidump *mdump = &adapter->mdump;
+
+
+ if (!adapter->fw_mdump_rdy) {
+ netdev_info(netdev, "Dump not available\n");
+ return -EINVAL;
+ }
+ /* Copy template header first */
+ copy_sz = mdump->md_template_size;
+ hdr_ptr = (u32 *) mdump->md_template;
+ data = buffer;
+ for (i = 0; i < copy_sz/sizeof(u32); i++)
+ *data++ = cpu_to_le32(*hdr_ptr++);
+
+ /* Copy captured dump data */
+ memcpy(buffer + copy_sz,
+ mdump->md_capture_buff + mdump->md_template_size,
+ mdump->md_capture_size);
+ dump->len = copy_sz + mdump->md_capture_size;
+ dump->flag = mdump->md_capture_mask;
+
+ /* Free dump area once data has been captured */
+ vfree(mdump->md_capture_buff);
+ mdump->md_capture_buff = NULL;
+ adapter->fw_mdump_rdy = 0;
+ netdev_info(netdev, "extracted the fw dump Successfully\n");
+ return 0;
+}
+
const struct ethtool_ops netxen_nic_ethtool_ops = {
.get_settings = netxen_nic_get_settings,
.set_settings = netxen_nic_set_settings,
@@ -833,4 +939,7 @@ const struct ethtool_ops netxen_nic_ethtool_ops = {
.get_sset_count = netxen_get_sset_count,
.get_coalesce = netxen_get_intr_coalesce,
.set_coalesce = netxen_set_intr_coalesce,
+ .get_dump_flag = netxen_get_dump_flag,
+ .get_dump_data = netxen_get_dump_data,
+ .set_dump = netxen_set_dump,
};
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h
index dc1967c1f312..b1a897cd9a8d 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h
@@ -969,6 +969,7 @@ enum {
#define NX_RCODE_FATAL_ERROR 0x80000000
#define NX_FWERROR_PEGNUM(code) ((code) & 0xff)
#define NX_FWERROR_CODE(code) ((code >> 8) & 0xfffff)
+#define NX_FWERROR_PEGSTAT1(code) ((code >> 8) & 0x1fffff)
#define FW_POLL_DELAY (2 * HZ)
#define FW_FAIL_THRESH 3
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
index 3f89e57cae50..6f37470750f3 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
@@ -46,7 +46,6 @@ static void netxen_nic_io_write_128M(struct netxen_adapter *adapter,
void __iomem *addr, u32 data);
static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter,
void __iomem *addr);
-
#ifndef readq
static inline u64 readq(void __iomem *addr)
{
@@ -1974,3 +1973,631 @@ netxen_nic_wol_supported(struct netxen_adapter *adapter)
return 0;
}
+
+static u32 netxen_md_cntrl(struct netxen_adapter *adapter,
+ struct netxen_minidump_template_hdr *template_hdr,
+ struct netxen_minidump_entry_crb *crtEntry)
+{
+ int loop_cnt, i, rv = 0, timeout_flag;
+ u32 op_count, stride;
+ u32 opcode, read_value, addr;
+ unsigned long timeout, timeout_jiffies;
+ addr = crtEntry->addr;
+ op_count = crtEntry->op_count;
+ stride = crtEntry->addr_stride;
+
+ for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
+ for (i = 0; i < sizeof(crtEntry->opcode) * 8; i++) {
+ opcode = (crtEntry->opcode & (0x1 << i));
+ if (opcode) {
+ switch (opcode) {
+ case NX_DUMP_WCRB:
+ NX_WR_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ crtEntry->value_1);
+ break;
+ case NX_DUMP_RWCRB:
+ NX_RD_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ &read_value);
+ NX_WR_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ read_value);
+ break;
+ case NX_DUMP_ANDCRB:
+ NX_RD_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ &read_value);
+ read_value &= crtEntry->value_2;
+ NX_WR_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ read_value);
+ break;
+ case NX_DUMP_ORCRB:
+ NX_RD_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ &read_value);
+ read_value |= crtEntry->value_3;
+ NX_WR_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ read_value);
+ break;
+ case NX_DUMP_POLLCRB:
+ timeout = crtEntry->poll_timeout;
+ NX_RD_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ &read_value);
+ timeout_jiffies =
+ msecs_to_jiffies(timeout) + jiffies;
+ for (timeout_flag = 0;
+ !timeout_flag
+ && ((read_value & crtEntry->value_2)
+ != crtEntry->value_1);) {
+ if (time_after(jiffies,
+ timeout_jiffies))
+ timeout_flag = 1;
+ NX_RD_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ &read_value);
+ }
+
+ if (timeout_flag) {
+ dev_err(&adapter->pdev->dev, "%s : "
+ "Timeout in poll_crb control operation.\n"
+ , __func__);
+ return -1;
+ }
+ break;
+ case NX_DUMP_RD_SAVE:
+ /* Decide which address to use */
+ if (crtEntry->state_index_a)
+ addr =
+ template_hdr->saved_state_array
+ [crtEntry->state_index_a];
+ NX_RD_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ &read_value);
+ template_hdr->saved_state_array
+ [crtEntry->state_index_v]
+ = read_value;
+ break;
+ case NX_DUMP_WRT_SAVED:
+ /* Decide which value to use */
+ if (crtEntry->state_index_v)
+ read_value =
+ template_hdr->saved_state_array
+ [crtEntry->state_index_v];
+ else
+ read_value = crtEntry->value_1;
+
+ /* Decide which address to use */
+ if (crtEntry->state_index_a)
+ addr =
+ template_hdr->saved_state_array
+ [crtEntry->state_index_a];
+
+ NX_WR_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ read_value);
+ break;
+ case NX_DUMP_MOD_SAVE_ST:
+ read_value =
+ template_hdr->saved_state_array
+ [crtEntry->state_index_v];
+ read_value <<= crtEntry->shl;
+ read_value >>= crtEntry->shr;
+ if (crtEntry->value_2)
+ read_value &=
+ crtEntry->value_2;
+ read_value |= crtEntry->value_3;
+ read_value += crtEntry->value_1;
+ /* Write value back to state area.*/
+ template_hdr->saved_state_array
+ [crtEntry->state_index_v]
+ = read_value;
+ break;
+ default:
+ rv = 1;
+ break;
+ }
+ }
+ }
+ addr = addr + stride;
+ }
+ return rv;
+}
+
+/* Read memory or MN */
+static u32
+netxen_md_rdmem(struct netxen_adapter *adapter,
+ struct netxen_minidump_entry_rdmem
+ *memEntry, u64 *data_buff)
+{
+ u64 addr, value = 0;
+ int i = 0, loop_cnt;
+
+ addr = (u64)memEntry->read_addr;
+ loop_cnt = memEntry->read_data_size; /* This is size in bytes */
+ loop_cnt /= sizeof(value);
+
+ for (i = 0; i < loop_cnt; i++) {
+ if (netxen_nic_pci_mem_read_2M(adapter, addr, &value))
+ goto out;
+ *data_buff++ = value;
+ addr += sizeof(value);
+ }
+out:
+ return i * sizeof(value);
+}
+
+/* Read CRB operation */
+static u32 netxen_md_rd_crb(struct netxen_adapter *adapter,
+ struct netxen_minidump_entry_crb
+ *crbEntry, u32 *data_buff)
+{
+ int loop_cnt;
+ u32 op_count, addr, stride, value;
+
+ addr = crbEntry->addr;
+ op_count = crbEntry->op_count;
+ stride = crbEntry->addr_stride;
+
+ for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
+ NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0, &value);
+ *data_buff++ = addr;
+ *data_buff++ = value;
+ addr = addr + stride;
+ }
+ return loop_cnt * (2 * sizeof(u32));
+}
+
+/* Read ROM */
+static u32
+netxen_md_rdrom(struct netxen_adapter *adapter,
+ struct netxen_minidump_entry_rdrom
+ *romEntry, u32 *data_buff)
+{
+ int i, count = 0;
+ u32 size, lck_val;
+ u32 val;
+ u32 fl_addr, waddr, raddr;
+ fl_addr = romEntry->read_addr;
+ size = romEntry->read_data_size/4;
+lock_try:
+ lck_val = readl((void __iomem *)(adapter->ahw.pci_base0 +
+ NX_FLASH_SEM2_LK));
+ if (!lck_val && count < MAX_CTL_CHECK) {
+ msleep(20);
+ count++;
+ goto lock_try;
+ }
+ writel(adapter->ahw.pci_func, (void __iomem *)(adapter->ahw.pci_base0 +
+ NX_FLASH_LOCK_ID));
+ for (i = 0; i < size; i++) {
+ waddr = fl_addr & 0xFFFF0000;
+ NX_WR_DUMP_REG(FLASH_ROM_WINDOW, adapter->ahw.pci_base0, waddr);
+ raddr = FLASH_ROM_DATA + (fl_addr & 0x0000FFFF);
+ NX_RD_DUMP_REG(raddr, adapter->ahw.pci_base0, &val);
+ *data_buff++ = cpu_to_le32(val);
+ fl_addr += sizeof(val);
+ }
+ readl((void __iomem *)(adapter->ahw.pci_base0 + NX_FLASH_SEM2_ULK));
+ return romEntry->read_data_size;
+}
+
+/* Handle L2 Cache */
+static u32
+netxen_md_L2Cache(struct netxen_adapter *adapter,
+ struct netxen_minidump_entry_cache
+ *cacheEntry, u32 *data_buff)
+{
+ int loop_cnt, i, k, timeout_flag = 0;
+ u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr;
+ u32 tag_value, read_cnt;
+ u8 cntl_value_w, cntl_value_r;
+ unsigned long timeout, timeout_jiffies;
+
+ loop_cnt = cacheEntry->op_count;
+ read_addr = cacheEntry->read_addr;
+ cntrl_addr = cacheEntry->control_addr;
+ cntl_value_w = (u32) cacheEntry->write_value;
+ tag_reg_addr = cacheEntry->tag_reg_addr;
+ tag_value = cacheEntry->init_tag_value;
+ read_cnt = cacheEntry->read_addr_cnt;
+
+ for (i = 0; i < loop_cnt; i++) {
+ NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value);
+ if (cntl_value_w)
+ NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0,
+ (u32)cntl_value_w);
+ if (cacheEntry->poll_mask) {
+ timeout = cacheEntry->poll_wait;
+ NX_RD_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0,
+ &cntl_value_r);
+ timeout_jiffies = msecs_to_jiffies(timeout) + jiffies;
+ for (timeout_flag = 0; !timeout_flag &&
+ ((cntl_value_r & cacheEntry->poll_mask) != 0);) {
+ if (time_after(jiffies, timeout_jiffies))
+ timeout_flag = 1;
+ NX_RD_DUMP_REG(cntrl_addr,
+ adapter->ahw.pci_base0,
+ &cntl_value_r);
+ }
+ if (timeout_flag) {
+ dev_err(&adapter->pdev->dev,
+ "Timeout in processing L2 Tag poll.\n");
+ return -1;
+ }
+ }
+ addr = read_addr;
+ for (k = 0; k < read_cnt; k++) {
+ NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0,
+ &read_value);
+ *data_buff++ = read_value;
+ addr += cacheEntry->read_addr_stride;
+ }
+ tag_value += cacheEntry->tag_value_stride;
+ }
+ return read_cnt * loop_cnt * sizeof(read_value);
+}
+
+
+/* Handle L1 Cache */
+static u32 netxen_md_L1Cache(struct netxen_adapter *adapter,
+ struct netxen_minidump_entry_cache
+ *cacheEntry, u32 *data_buff)
+{
+ int i, k, loop_cnt;
+ u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr;
+ u32 tag_value, read_cnt;
+ u8 cntl_value_w;
+
+ loop_cnt = cacheEntry->op_count;
+ read_addr = cacheEntry->read_addr;
+ cntrl_addr = cacheEntry->control_addr;
+ cntl_value_w = (u32) cacheEntry->write_value;
+ tag_reg_addr = cacheEntry->tag_reg_addr;
+ tag_value = cacheEntry->init_tag_value;
+ read_cnt = cacheEntry->read_addr_cnt;
+
+ for (i = 0; i < loop_cnt; i++) {
+ NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value);
+ NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0,
+ (u32) cntl_value_w);
+ addr = read_addr;
+ for (k = 0; k < read_cnt; k++) {
+ NX_RD_DUMP_REG(addr,
+ adapter->ahw.pci_base0,
+ &read_value);
+ *data_buff++ = read_value;
+ addr += cacheEntry->read_addr_stride;
+ }
+ tag_value += cacheEntry->tag_value_stride;
+ }
+ return read_cnt * loop_cnt * sizeof(read_value);
+}
+
+/* Reading OCM memory */
+static u32
+netxen_md_rdocm(struct netxen_adapter *adapter,
+ struct netxen_minidump_entry_rdocm
+ *ocmEntry, u32 *data_buff)
+{
+ int i, loop_cnt;
+ u32 value;
+ void __iomem *addr;
+ addr = (ocmEntry->read_addr + adapter->ahw.pci_base0);
+ loop_cnt = ocmEntry->op_count;
+
+ for (i = 0; i < loop_cnt; i++) {
+ value = readl(addr);
+ *data_buff++ = value;
+ addr += ocmEntry->read_addr_stride;
+ }
+ return i * sizeof(u32);
+}
+
+/* Read MUX data */
+static u32
+netxen_md_rdmux(struct netxen_adapter *adapter, struct netxen_minidump_entry_mux
+ *muxEntry, u32 *data_buff)
+{
+ int loop_cnt = 0;
+ u32 read_addr, read_value, select_addr, sel_value;
+
+ read_addr = muxEntry->read_addr;
+ sel_value = muxEntry->select_value;
+ select_addr = muxEntry->select_addr;
+
+ for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
+ NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, sel_value);
+ NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0, &read_value);
+ *data_buff++ = sel_value;
+ *data_buff++ = read_value;
+ sel_value += muxEntry->select_value_stride;
+ }
+ return loop_cnt * (2 * sizeof(u32));
+}
+
+/* Handling Queue State Reads */
+static u32
+netxen_md_rdqueue(struct netxen_adapter *adapter,
+ struct netxen_minidump_entry_queue
+ *queueEntry, u32 *data_buff)
+{
+ int loop_cnt, k;
+ u32 queue_id, read_addr, read_value, read_stride, select_addr, read_cnt;
+
+ read_cnt = queueEntry->read_addr_cnt;
+ read_stride = queueEntry->read_addr_stride;
+ select_addr = queueEntry->select_addr;
+
+ for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
+ loop_cnt++) {
+ NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, queue_id);
+ read_addr = queueEntry->read_addr;
+ for (k = 0; k < read_cnt; k--) {
+ NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0,
+ &read_value);
+ *data_buff++ = read_value;
+ read_addr += read_stride;
+ }
+ queue_id += queueEntry->queue_id_stride;
+ }
+ return loop_cnt * (read_cnt * sizeof(read_value));
+}
+
+
+/*
+* We catch an error where driver does not read
+* as much data as we expect from the entry.
+*/
+
+static int netxen_md_entry_err_chk(struct netxen_adapter *adapter,
+ struct netxen_minidump_entry *entry, int esize)
+{
+ if (esize < 0) {
+ entry->hdr.driver_flags |= NX_DUMP_SKIP;
+ return esize;
+ }
+ if (esize != entry->hdr.entry_capture_size) {
+ entry->hdr.entry_capture_size = esize;
+ entry->hdr.driver_flags |= NX_DUMP_SIZE_ERR;
+ dev_info(&adapter->pdev->dev,
+ "Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",
+ entry->hdr.entry_type, entry->hdr.entry_capture_mask,
+ esize, entry->hdr.entry_capture_size);
+ dev_info(&adapter->pdev->dev, "Aborting further dump capture\n");
+ }
+ return 0;
+}
+
+static int netxen_parse_md_template(struct netxen_adapter *adapter)
+{
+ int num_of_entries, buff_level, e_cnt, esize;
+ int end_cnt = 0, rv = 0, sane_start = 0, sane_end = 0;
+ char *dbuff;
+ void *template_buff = adapter->mdump.md_template;
+ char *dump_buff = adapter->mdump.md_capture_buff;
+ int capture_mask = adapter->mdump.md_capture_mask;
+ struct netxen_minidump_template_hdr *template_hdr;
+ struct netxen_minidump_entry *entry;
+
+ if ((capture_mask & 0x3) != 0x3) {
+ dev_err(&adapter->pdev->dev, "Capture mask %02x below minimum needed "
+ "for valid firmware dump\n", capture_mask);
+ return -EINVAL;
+ }
+ template_hdr = (struct netxen_minidump_template_hdr *) template_buff;
+ num_of_entries = template_hdr->num_of_entries;
+ entry = (struct netxen_minidump_entry *) ((char *) template_buff +
+ template_hdr->first_entry_offset);
+ memcpy(dump_buff, template_buff, adapter->mdump.md_template_size);
+ dump_buff = dump_buff + adapter->mdump.md_template_size;
+
+ if (template_hdr->entry_type == TLHDR)
+ sane_start = 1;
+
+ for (e_cnt = 0, buff_level = 0; e_cnt < num_of_entries; e_cnt++) {
+ if (!(entry->hdr.entry_capture_mask & capture_mask)) {
+ entry->hdr.driver_flags |= NX_DUMP_SKIP;
+ entry = (struct netxen_minidump_entry *)
+ ((char *) entry + entry->hdr.entry_size);
+ continue;
+ }
+ switch (entry->hdr.entry_type) {
+ case RDNOP:
+ entry->hdr.driver_flags |= NX_DUMP_SKIP;
+ break;
+ case RDEND:
+ entry->hdr.driver_flags |= NX_DUMP_SKIP;
+ if (!sane_end)
+ end_cnt = e_cnt;
+ sane_end += 1;
+ break;
+ case CNTRL:
+ rv = netxen_md_cntrl(adapter,
+ template_hdr, (void *)entry);
+ if (rv)
+ entry->hdr.driver_flags |= NX_DUMP_SKIP;
+ break;
+ case RDCRB:
+ dbuff = dump_buff + buff_level;
+ esize = netxen_md_rd_crb(adapter,
+ (void *) entry, (void *) dbuff);
+ rv = netxen_md_entry_err_chk
+ (adapter, entry, esize);
+ if (rv < 0)
+ break;
+ buff_level += esize;
+ break;
+ case RDMN:
+ case RDMEM:
+ dbuff = dump_buff + buff_level;
+ esize = netxen_md_rdmem(adapter,
+ (void *) entry, (void *) dbuff);
+ rv = netxen_md_entry_err_chk
+ (adapter, entry, esize);
+ if (rv < 0)
+ break;
+ buff_level += esize;
+ break;
+ case BOARD:
+ case RDROM:
+ dbuff = dump_buff + buff_level;
+ esize = netxen_md_rdrom(adapter,
+ (void *) entry, (void *) dbuff);
+ rv = netxen_md_entry_err_chk
+ (adapter, entry, esize);
+ if (rv < 0)
+ break;
+ buff_level += esize;
+ break;
+ case L2ITG:
+ case L2DTG:
+ case L2DAT:
+ case L2INS:
+ dbuff = dump_buff + buff_level;
+ esize = netxen_md_L2Cache(adapter,
+ (void *) entry, (void *) dbuff);
+ rv = netxen_md_entry_err_chk
+ (adapter, entry, esize);
+ if (rv < 0)
+ break;
+ buff_level += esize;
+ break;
+ case L1DAT:
+ case L1INS:
+ dbuff = dump_buff + buff_level;
+ esize = netxen_md_L1Cache(adapter,
+ (void *) entry, (void *) dbuff);
+ rv = netxen_md_entry_err_chk
+ (adapter, entry, esize);
+ if (rv < 0)
+ break;
+ buff_level += esize;
+ break;
+ case RDOCM:
+ dbuff = dump_buff + buff_level;
+ esize = netxen_md_rdocm(adapter,
+ (void *) entry, (void *) dbuff);
+ rv = netxen_md_entry_err_chk
+ (adapter, entry, esize);
+ if (rv < 0)
+ break;
+ buff_level += esize;
+ break;
+ case RDMUX:
+ dbuff = dump_buff + buff_level;
+ esize = netxen_md_rdmux(adapter,
+ (void *) entry, (void *) dbuff);
+ rv = netxen_md_entry_err_chk
+ (adapter, entry, esize);
+ if (rv < 0)
+ break;
+ buff_level += esize;
+ break;
+ case QUEUE:
+ dbuff = dump_buff + buff_level;
+ esize = netxen_md_rdqueue(adapter,
+ (void *) entry, (void *) dbuff);
+ rv = netxen_md_entry_err_chk
+ (adapter, entry, esize);
+ if (rv < 0)
+ break;
+ buff_level += esize;
+ break;
+ default:
+ entry->hdr.driver_flags |= NX_DUMP_SKIP;
+ break;
+ }
+ /* Next entry in the template */
+ entry = (struct netxen_minidump_entry *)
+ ((char *) entry + entry->hdr.entry_size);
+ }
+ if (!sane_start || sane_end > 1) {
+ dev_err(&adapter->pdev->dev,
+ "Firmware minidump template configuration error.\n");
+ }
+ return 0;
+}
+
+static int
+netxen_collect_minidump(struct netxen_adapter *adapter)
+{
+ int ret = 0;
+ struct netxen_minidump_template_hdr *hdr;
+ struct timespec val;
+ hdr = (struct netxen_minidump_template_hdr *)
+ adapter->mdump.md_template;
+ hdr->driver_capture_mask = adapter->mdump.md_capture_mask;
+ jiffies_to_timespec(jiffies, &val);
+ hdr->driver_timestamp = (u32) val.tv_sec;
+ hdr->driver_info_word2 = adapter->fw_version;
+ hdr->driver_info_word3 = NXRD32(adapter, CRB_DRIVER_VERSION);
+ ret = netxen_parse_md_template(adapter);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+
+void
+netxen_dump_fw(struct netxen_adapter *adapter)
+{
+ struct netxen_minidump_template_hdr *hdr;
+ int i, k, data_size = 0;
+ u32 capture_mask;
+ hdr = (struct netxen_minidump_template_hdr *)
+ adapter->mdump.md_template;
+ capture_mask = adapter->mdump.md_capture_mask;
+
+ for (i = 0x2, k = 1; (i & NX_DUMP_MASK_MAX); i <<= 1, k++) {
+ if (i & capture_mask)
+ data_size += hdr->capture_size_array[k];
+ }
+ if (!data_size) {
+ dev_err(&adapter->pdev->dev,
+ "Invalid cap sizes for capture_mask=0x%x\n",
+ adapter->mdump.md_capture_mask);
+ return;
+ }
+ adapter->mdump.md_capture_size = data_size;
+ adapter->mdump.md_dump_size = adapter->mdump.md_template_size +
+ adapter->mdump.md_capture_size;
+ if (!adapter->mdump.md_capture_buff) {
+ adapter->mdump.md_capture_buff =
+ vmalloc(adapter->mdump.md_dump_size);
+ if (!adapter->mdump.md_capture_buff) {
+ dev_info(&adapter->pdev->dev,
+ "Unable to allocate memory for minidump "
+ "capture_buffer(%d bytes).\n",
+ adapter->mdump.md_dump_size);
+ return;
+ }
+ memset(adapter->mdump.md_capture_buff, 0,
+ adapter->mdump.md_dump_size);
+ if (netxen_collect_minidump(adapter)) {
+ adapter->mdump.has_valid_dump = 0;
+ adapter->mdump.md_dump_size = 0;
+ vfree(adapter->mdump.md_capture_buff);
+ adapter->mdump.md_capture_buff = NULL;
+ dev_err(&adapter->pdev->dev,
+ "Error in collecting firmware minidump.\n");
+ } else {
+ adapter->mdump.md_timestamp = jiffies;
+ adapter->mdump.has_valid_dump = 1;
+ adapter->fw_mdump_rdy = 1;
+ dev_info(&adapter->pdev->dev, "%s Successfully "
+ "collected fw dump.\n", adapter->netdev->name);
+ }
+
+ } else {
+ dev_info(&adapter->pdev->dev,
+ "Cannot overwrite previously collected "
+ "firmware minidump.\n");
+ adapter->fw_mdump_rdy = 1;
+ return;
+ }
+}
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
index a8259cc19a63..718b27440351 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
@@ -280,13 +280,10 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
}
rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring));
- if (rds_ring->rx_buf_arr == NULL) {
- printk(KERN_ERR "%s: Failed to allocate "
- "rx buffer ring %d\n",
- netdev->name, ring);
+ if (rds_ring->rx_buf_arr == NULL)
/* free whatever was already allocated */
goto err_out;
- }
+
INIT_LIST_HEAD(&rds_ring->free_list);
/*
* Now go through all of them, set reference handles
@@ -449,7 +446,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter)
/* resetall */
netxen_rom_lock(adapter);
- NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff);
+ NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xfeffffff);
netxen_rom_unlock(adapter);
if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
@@ -480,11 +477,8 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter)
}
buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
- if (buf == NULL) {
- printk("%s: netxen_pinit_from_rom: Unable to calloc memory.\n",
- netxen_nic_driver_name);
+ if (buf == NULL)
return -ENOMEM;
- }
for (i = 0; i < n; i++) {
if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
@@ -1353,7 +1347,6 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
do {
val = NXRD32(adapter, CRB_CMDPEG_STATE);
-
switch (val) {
case PHAN_INITIALIZE_COMPLETE:
case PHAN_INITIALIZE_ACK:
@@ -1494,7 +1487,7 @@ netxen_alloc_rx_skb(struct netxen_adapter *adapter,
dma_addr_t dma;
struct pci_dev *pdev = adapter->pdev;
- buffer->skb = dev_alloc_skb(rds_ring->skb_size);
+ buffer->skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size);
if (!buffer->skb)
return 1;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 7dd9a4b107e6..7648995ea720 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -82,7 +82,6 @@ static void netxen_create_sysfs_entries(struct netxen_adapter *adapter);
static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter);
static void netxen_create_diag_entries(struct netxen_adapter *adapter);
static void netxen_remove_diag_entries(struct netxen_adapter *adapter);
-
static int nx_dev_request_aer(struct netxen_adapter *adapter);
static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter);
static int netxen_can_start_firmware(struct netxen_adapter *adapter);
@@ -519,7 +518,7 @@ static int netxen_nic_set_mac(struct net_device *netdev, void *p)
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
if (netif_running(netdev)) {
netif_device_detach(netdev);
@@ -802,10 +801,10 @@ err_out:
static void
netxen_check_options(struct netxen_adapter *adapter)
{
- u32 fw_major, fw_minor, fw_build;
+ u32 fw_major, fw_minor, fw_build, prev_fw_version;
char brd_name[NETXEN_MAX_SHORT_NAME];
char serial_num[32];
- int i, offset, val;
+ int i, offset, val, err;
int *ptr32;
struct pci_dev *pdev = adapter->pdev;
@@ -826,9 +825,22 @@ netxen_check_options(struct netxen_adapter *adapter)
fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
-
+ prev_fw_version = adapter->fw_version;
adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build);
+ /* Get FW Mini Coredump template and store it */
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ if (adapter->mdump.md_template == NULL ||
+ adapter->fw_version > prev_fw_version) {
+ kfree(adapter->mdump.md_template);
+ adapter->mdump.md_template = NULL;
+ err = netxen_setup_minidump(adapter);
+ if (err)
+ dev_err(&adapter->pdev->dev,
+ "Failed to setup minidump rcode = %d\n", err);
+ }
+ }
+
if (adapter->portnum == 0) {
get_brd_name_by_type(adapter->ahw.board_type, brd_name);
@@ -909,7 +921,12 @@ netxen_start_firmware(struct netxen_adapter *adapter)
if (err)
return err;
- if (!netxen_can_start_firmware(adapter))
+ err = netxen_can_start_firmware(adapter);
+
+ if (err < 0)
+ return err;
+
+ if (!err)
goto wait_init;
first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc));
@@ -1403,7 +1420,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev = alloc_etherdev(sizeof(struct netxen_adapter));
if(!netdev) {
- dev_err(&pdev->dev, "failed to allocate net_device\n");
err = -ENOMEM;
goto err_out_free_res;
}
@@ -1529,6 +1545,18 @@ err_out_disable_pdev:
return err;
}
+static
+void netxen_cleanup_minidump(struct netxen_adapter *adapter)
+{
+ kfree(adapter->mdump.md_template);
+ adapter->mdump.md_template = NULL;
+
+ if (adapter->mdump.md_capture_buff) {
+ vfree(adapter->mdump.md_capture_buff);
+ adapter->mdump.md_capture_buff = NULL;
+ }
+}
+
static void __devexit netxen_nic_remove(struct pci_dev *pdev)
{
struct netxen_adapter *adapter;
@@ -1564,8 +1592,10 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
netxen_release_firmware(adapter);
- if (NX_IS_REVISION_P3(pdev->revision))
+ if (NX_IS_REVISION_P3(pdev->revision)) {
+ netxen_cleanup_minidump(adapter);
pci_disable_pcie_error_reporting(pdev);
+ }
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -2317,7 +2347,7 @@ nx_incr_dev_ref_cnt(struct netxen_adapter *adapter)
static int
nx_decr_dev_ref_cnt(struct netxen_adapter *adapter)
{
- int count;
+ int count, state;
if (netxen_api_lock(adapter))
return -EIO;
@@ -2325,8 +2355,9 @@ nx_decr_dev_ref_cnt(struct netxen_adapter *adapter)
WARN_ON(count == 0);
NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count);
+ state = NXRD32(adapter, NX_CRB_DEV_STATE);
- if (count == 0)
+ if (count == 0 && state != NX_DEV_FAILED)
NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD);
netxen_api_unlock(adapter);
@@ -2355,7 +2386,7 @@ nx_dev_request_aer(struct netxen_adapter *adapter)
return ret;
}
-static int
+int
nx_dev_request_reset(struct netxen_adapter *adapter)
{
u32 state;
@@ -2366,10 +2397,11 @@ nx_dev_request_reset(struct netxen_adapter *adapter)
state = NXRD32(adapter, NX_CRB_DEV_STATE);
- if (state == NX_DEV_NEED_RESET)
+ if (state == NX_DEV_NEED_RESET || state == NX_DEV_FAILED)
ret = 0;
else if (state != NX_DEV_INITALIZING && state != NX_DEV_NEED_AER) {
NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET);
+ adapter->flags |= NETXEN_FW_RESET_OWNER;
ret = 0;
}
@@ -2384,8 +2416,10 @@ netxen_can_start_firmware(struct netxen_adapter *adapter)
int count;
int can_start = 0;
- if (netxen_api_lock(adapter))
- return 0;
+ if (netxen_api_lock(adapter)) {
+ nx_incr_dev_ref_cnt(adapter);
+ return -1;
+ }
count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
@@ -2457,8 +2491,31 @@ netxen_fwinit_work(struct work_struct *work)
struct netxen_adapter *adapter = container_of(work,
struct netxen_adapter, fw_work.work);
int dev_state;
-
+ int count;
dev_state = NXRD32(adapter, NX_CRB_DEV_STATE);
+ if (adapter->flags & NETXEN_FW_RESET_OWNER) {
+ count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
+ WARN_ON(count == 0);
+ if (count == 1) {
+ if (adapter->mdump.md_enabled) {
+ rtnl_lock();
+ netxen_dump_fw(adapter);
+ rtnl_unlock();
+ }
+ adapter->flags &= ~NETXEN_FW_RESET_OWNER;
+ if (netxen_api_lock(adapter)) {
+ clear_bit(__NX_RESETTING, &adapter->state);
+ NXWR32(adapter, NX_CRB_DEV_STATE,
+ NX_DEV_FAILED);
+ return;
+ }
+ count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
+ NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count);
+ NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD);
+ dev_state = NX_DEV_COLD;
+ netxen_api_unlock(adapter);
+ }
+ }
switch (dev_state) {
case NX_DEV_COLD:
@@ -2471,11 +2528,9 @@ netxen_fwinit_work(struct work_struct *work)
case NX_DEV_NEED_RESET:
case NX_DEV_INITALIZING:
- if (++adapter->fw_wait_cnt < FW_POLL_THRESH) {
netxen_schedule_work(adapter,
netxen_fwinit_work, 2 * FW_POLL_DELAY);
return;
- }
case NX_DEV_FAILED:
default:
@@ -2483,6 +2538,15 @@ netxen_fwinit_work(struct work_struct *work)
break;
}
+ if (netxen_api_lock(adapter)) {
+ clear_bit(__NX_RESETTING, &adapter->state);
+ return;
+ }
+ NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_FAILED);
+ netxen_api_unlock(adapter);
+ dev_err(&adapter->pdev->dev, "%s: Device initialization Failed\n",
+ adapter->netdev->name);
+
clear_bit(__NX_RESETTING, &adapter->state);
}
@@ -2492,7 +2556,7 @@ netxen_detach_work(struct work_struct *work)
struct netxen_adapter *adapter = container_of(work,
struct netxen_adapter, fw_work.work);
struct net_device *netdev = adapter->netdev;
- int ref_cnt, delay;
+ int ref_cnt = 0, delay;
u32 status;
netif_device_detach(netdev);
@@ -2511,7 +2575,8 @@ netxen_detach_work(struct work_struct *work)
if (adapter->temp == NX_TEMP_PANIC)
goto err_ret;
- ref_cnt = nx_decr_dev_ref_cnt(adapter);
+ if (!(adapter->flags & NETXEN_FW_RESET_OWNER))
+ ref_cnt = nx_decr_dev_ref_cnt(adapter);
if (ref_cnt == -EIO)
goto err_ret;
@@ -2531,6 +2596,7 @@ static int
netxen_check_health(struct netxen_adapter *adapter)
{
u32 state, heartbit;
+ u32 peg_status;
struct net_device *netdev = adapter->netdev;
state = NXRD32(adapter, NX_CRB_DEV_STATE);
@@ -2551,7 +2617,7 @@ netxen_check_health(struct netxen_adapter *adapter)
* Send request to destroy context in case of tx timeout only
* and doesn't required in case of Fw hang
*/
- if (state == NX_DEV_NEED_RESET) {
+ if (state == NX_DEV_NEED_RESET || state == NX_DEV_FAILED) {
adapter->need_fw_reset = 1;
if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
goto detach;
@@ -2577,8 +2643,24 @@ netxen_check_health(struct netxen_adapter *adapter)
clear_bit(__NX_FW_ATTACHED, &adapter->state);
- dev_info(&netdev->dev, "firmware hang detected\n");
-
+ dev_err(&netdev->dev, "firmware hang detected\n");
+ peg_status = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1);
+ dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n"
+ "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n"
+ "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n"
+ "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n"
+ "PEG_NET_4_PC: 0x%x\n",
+ peg_status,
+ NXRD32(adapter, NETXEN_PEG_HALT_STATUS2),
+ NXRD32(adapter, NETXEN_CRB_PEG_NET_0 + 0x3c),
+ NXRD32(adapter, NETXEN_CRB_PEG_NET_1 + 0x3c),
+ NXRD32(adapter, NETXEN_CRB_PEG_NET_2 + 0x3c),
+ NXRD32(adapter, NETXEN_CRB_PEG_NET_3 + 0x3c),
+ NXRD32(adapter, NETXEN_CRB_PEG_NET_4 + 0x3c));
+ if (NX_FWERROR_PEGSTAT1(peg_status) == 0x67)
+ dev_err(&adapter->pdev->dev,
+ "Firmware aborted with error code 0x00006700. "
+ "Device is being reset.\n");
detach:
if ((auto_fw_reset == AUTO_FW_RESET_ENABLED) &&
!test_and_set_bit(__NX_RESETTING, &adapter->state))
@@ -2848,13 +2930,12 @@ static struct bin_attribute bin_attr_mem = {
static void
netxen_create_sysfs_entries(struct netxen_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
- struct device *dev = &netdev->dev;
+ struct device *dev = &adapter->pdev->dev;
if (adapter->capabilities & NX_FW_CAPABILITY_BDG) {
/* bridged_mode control */
if (device_create_file(dev, &dev_attr_bridged_mode)) {
- dev_warn(&netdev->dev,
+ dev_warn(dev,
"failed to create bridged_mode sysfs entry\n");
}
}
@@ -2863,8 +2944,7 @@ netxen_create_sysfs_entries(struct netxen_adapter *adapter)
static void
netxen_remove_sysfs_entries(struct netxen_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
- struct device *dev = &netdev->dev;
+ struct device *dev = &adapter->pdev->dev;
if (adapter->capabilities & NX_FW_CAPABILITY_BDG)
device_remove_file(dev, &dev_attr_bridged_mode);
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 7931531c3a40..d49f6dac51fd 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -3805,7 +3805,6 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
ndev = alloc_etherdev(sizeof(struct ql3_adapter));
if (!ndev) {
- pr_err("%s could not alloc etherdev\n", pci_name(pdev));
err = -ENOMEM;
goto err_out_free_regions;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 60976fc4ccc6..2b5af22419a5 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -37,7 +37,7 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0
#define _QLCNIC_LINUX_SUBVERSION 25
-#define QLCNIC_LINUX_VERSIONID "5.0.25"
+#define QLCNIC_LINUX_VERSIONID "5.0.26"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index cc228cf3d84b..89ddf7f7d7df 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -155,7 +155,6 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
int check_sfp_module = 0;
- u16 pcifn = adapter->ahw->pci_func;
/* read which mode */
if (adapter->ahw->port_type == QLCNIC_GBE) {
@@ -194,10 +193,8 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
goto skip;
}
- val = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn));
- ethtool_cmd_speed_set(ecmd, P3P_LINK_SPEED_MHZ *
- P3P_LINK_SPEED_VAL(pcifn, val));
- ecmd->duplex = DUPLEX_FULL;
+ ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
+ ecmd->duplex = DUPLEX_UNKNOWN;
ecmd->autoneg = AUTONEG_DISABLE;
} else
return -EIO;
@@ -722,7 +719,7 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
int i, loop, cnt = 0;
for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
- skb = dev_alloc_skb(QLCNIC_ILB_PKT_SIZE);
+ skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
skb_put(skb, QLCNIC_ILB_PKT_SIZE);
@@ -1155,7 +1152,6 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
if (!fw_dump->clr) {
netdev_info(netdev, "Dump not available\n");
- qlcnic_api_unlock(adapter);
return -EINVAL;
}
/* Copy template header first */
@@ -1174,7 +1170,7 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
vfree(fw_dump->data);
fw_dump->data = NULL;
fw_dump->clr = 0;
-
+ netdev_info(netdev, "extracted the FW dump Successfully\n");
return 0;
}
@@ -1192,7 +1188,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
return ret;
}
if (fw_dump->clr) {
- dev_info(&adapter->pdev->dev,
+ netdev_info(netdev,
"Previous dump not cleared, not forcing dump\n");
return ret;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index 38669583840c..d32cf0ddf1b9 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -1369,7 +1369,13 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
adapter->module_type = module;
adapter->link_autoneg = autoneg;
- adapter->link_speed = link_speed;
+
+ if (link_status) {
+ adapter->link_speed = link_speed;
+ } else {
+ adapter->link_speed = SPEED_UNKNOWN;
+ adapter->link_duplex = DUPLEX_UNKNOWN;
+ }
}
static void
@@ -1434,7 +1440,7 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
dma_addr_t dma;
struct pci_dev *pdev = adapter->pdev;
- skb = dev_alloc_skb(rds_ring->skb_size);
+ skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size);
if (!skb) {
adapter->stats.skb_alloc_failure++;
return -ENOMEM;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 69b8e4ef14d9..81bb1a69e69f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -301,7 +301,7 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
return -EOPNOTSUPP;
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
netif_device_detach(netdev);
@@ -1576,7 +1576,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev = alloc_etherdev(sizeof(struct qlcnic_adapter));
if (!netdev) {
- dev_err(&pdev->dev, "failed to allocate net_device\n");
err = -ENOMEM;
goto err_out_free_res;
}
@@ -3000,8 +2999,18 @@ qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
void
qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
{
- u32 state;
-
+ u32 state, xg_val = 0, gb_val = 0;
+
+ qlcnic_xg_set_xg0_mask(xg_val);
+ qlcnic_xg_set_xg1_mask(xg_val);
+ QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, xg_val);
+ qlcnic_gb_set_gb0_mask(gb_val);
+ qlcnic_gb_set_gb1_mask(gb_val);
+ qlcnic_gb_set_gb2_mask(gb_val);
+ qlcnic_gb_set_gb3_mask(gb_val);
+ QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, gb_val);
+ dev_info(&adapter->pdev->dev, "Pause control frames disabled"
+ " on all ports\n");
adapter->need_fw_reset = 1;
if (qlcnic_api_lock(adapter))
return;
@@ -3150,7 +3159,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
QLCRD32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c),
QLCRD32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c));
peg_status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
- if (LSW(MSB(peg_status)) == 0x67)
+ if (QLCNIC_FWERROR_CODE(peg_status) == 0x67)
dev_err(&adapter->pdev->dev,
"Firmware aborted with error code 0x00006700. "
"Device is being reset.\n");
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h
index b8478aab050e..5a639df33f18 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge.h
+++ b/drivers/net/ethernet/qlogic/qlge/qlge.h
@@ -18,7 +18,7 @@
*/
#define DRV_NAME "qlge"
#define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver "
-#define DRV_VERSION "v1.00.00.29.00.00-01"
+#define DRV_VERSION "v1.00.00.30.00.00-01"
#define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
index fca804f36d61..58185b604b72 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
@@ -1824,10 +1824,8 @@ void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id)
pr_err("%s: Enter\n", __func__);
ptr = kmalloc(size, GFP_ATOMIC);
- if (ptr == NULL) {
- pr_err("%s: Couldn't allocate a buffer\n", __func__);
+ if (ptr == NULL)
return;
- }
if (ql_write_cfg(qdev, ptr, size, bit, q_id)) {
pr_err("%s: Failed to upload control block!\n", __func__);
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index b54898737284..49343ec21c82 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -375,13 +375,6 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
u32 lower =
(addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) |
(addr[5]);
-
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
- "Adding %s address %pM at index %d in the CAM.\n",
- type == MAC_ADDR_TYPE_MULTI_MAC ?
- "MULTICAST" : "UNICAST",
- addr, index);
-
status =
ql_wait_reg_rdy(qdev,
MAC_ADDR_IDX, MAC_ADDR_MW, 0);
@@ -430,12 +423,6 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
* addressing. It's either MAC_ADDR_E on or off.
* That's bit-27 we're talking about.
*/
- netif_info(qdev, ifup, qdev->ndev,
- "%s VLAN ID %d %s the CAM.\n",
- enable_bit ? "Adding" : "Removing",
- index,
- enable_bit ? "to" : "from");
-
status =
ql_wait_reg_rdy(qdev,
MAC_ADDR_IDX, MAC_ADDR_MW, 0);
@@ -535,28 +522,6 @@ static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask,
int status = -EINVAL; /* Return error if no mask match. */
u32 value = 0;
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
- "%s %s mask %s the routing reg.\n",
- enable ? "Adding" : "Removing",
- index == RT_IDX_ALL_ERR_SLOT ? "MAC ERROR/ALL ERROR" :
- index == RT_IDX_IP_CSUM_ERR_SLOT ? "IP CSUM ERROR" :
- index == RT_IDX_TCP_UDP_CSUM_ERR_SLOT ? "TCP/UDP CSUM ERROR" :
- index == RT_IDX_BCAST_SLOT ? "BROADCAST" :
- index == RT_IDX_MCAST_MATCH_SLOT ? "MULTICAST MATCH" :
- index == RT_IDX_ALLMULTI_SLOT ? "ALL MULTICAST MATCH" :
- index == RT_IDX_UNUSED6_SLOT ? "UNUSED6" :
- index == RT_IDX_UNUSED7_SLOT ? "UNUSED7" :
- index == RT_IDX_RSS_MATCH_SLOT ? "RSS ALL/IPV4 MATCH" :
- index == RT_IDX_RSS_IPV6_SLOT ? "RSS IPV6" :
- index == RT_IDX_RSS_TCP4_SLOT ? "RSS TCP4" :
- index == RT_IDX_RSS_TCP6_SLOT ? "RSS TCP6" :
- index == RT_IDX_CAM_HIT_SLOT ? "CAM HIT" :
- index == RT_IDX_UNUSED013 ? "UNUSED13" :
- index == RT_IDX_UNUSED014 ? "UNUSED14" :
- index == RT_IDX_PROMISCUOUS_SLOT ? "PROMISCUOUS" :
- "(Bad index != RT_IDX)",
- enable ? "to" : "from");
-
switch (mask) {
case RT_IDX_CAM_HIT:
{
@@ -1178,14 +1143,16 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
int i;
while (rx_ring->lbq_free_cnt > 32) {
- for (i = 0; i < 16; i++) {
+ for (i = (rx_ring->lbq_clean_idx % 16); i < 16; i++) {
netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
"lbq: try cleaning clean_idx = %d.\n",
clean_idx);
lbq_desc = &rx_ring->lbq[clean_idx];
if (ql_get_next_chunk(qdev, rx_ring, lbq_desc)) {
+ rx_ring->lbq_clean_idx = clean_idx;
netif_err(qdev, ifup, qdev->ndev,
- "Could not get a page chunk.\n");
+ "Could not get a page chunk, i=%d, clean_idx =%d .\n",
+ i, clean_idx);
return;
}
@@ -1230,7 +1197,7 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
int i;
while (rx_ring->sbq_free_cnt > 16) {
- for (i = 0; i < 16; i++) {
+ for (i = (rx_ring->sbq_clean_idx % 16); i < 16; i++) {
sbq_desc = &rx_ring->sbq[clean_idx];
netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
"sbq: try cleaning clean_idx = %d.\n",
@@ -1576,13 +1543,14 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,
} else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) &&
(ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) {
/* Unfragmented ipv4 UDP frame. */
- struct iphdr *iph = (struct iphdr *) skb->data;
+ struct iphdr *iph =
+ (struct iphdr *) ((u8 *)addr + ETH_HLEN);
if (!(iph->frag_off &
cpu_to_be16(IP_MF|IP_OFFSET))) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
netif_printk(qdev, rx_status, KERN_DEBUG,
qdev->ndev,
- "TCP checksum done!\n");
+ "UDP checksum done!\n");
}
}
}
@@ -1690,7 +1658,7 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev,
skb->ip_summed = CHECKSUM_UNNECESSARY;
netif_printk(qdev, rx_status, KERN_DEBUG,
qdev->ndev,
- "TCP checksum done!\n");
+ "UDP checksum done!\n");
}
}
}
@@ -2312,13 +2280,9 @@ static void qlge_vlan_mode(struct net_device *ndev, netdev_features_t features)
struct ql_adapter *qdev = netdev_priv(ndev);
if (features & NETIF_F_HW_VLAN_RX) {
- netif_printk(qdev, ifup, KERN_DEBUG, ndev,
- "Turning on VLAN in NIC_RCV_CFG.\n");
ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK |
NIC_RCV_CFG_VLAN_MATCH_AND_NON);
} else {
- netif_printk(qdev, ifup, KERN_DEBUG, ndev,
- "Turning off VLAN in NIC_RCV_CFG.\n");
ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK);
}
}
@@ -3183,8 +3147,6 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
"Invalid rx_ring->type = %d.\n", rx_ring->type);
}
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
- "Initializing rx work queue.\n");
err = ql_write_cfg(qdev, cqicb, sizeof(struct cqicb),
CFG_LCQ, rx_ring->cq_id);
if (err) {
@@ -3237,8 +3199,6 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring)
netif_err(qdev, ifup, qdev->ndev, "Failed to load tx_ring.\n");
return err;
}
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
- "Successfully loaded WQICB.\n");
return err;
}
@@ -3488,12 +3448,8 @@ static void ql_free_irq(struct ql_adapter *qdev)
if (test_bit(QL_MSIX_ENABLED, &qdev->flags)) {
free_irq(qdev->msi_x_entry[i].vector,
&qdev->rx_ring[i]);
- netif_printk(qdev, ifdown, KERN_DEBUG, qdev->ndev,
- "freeing msix interrupt %d.\n", i);
} else {
free_irq(qdev->pdev->irq, &qdev->rx_ring[0]);
- netif_printk(qdev, ifdown, KERN_DEBUG, qdev->ndev,
- "freeing msi interrupt %d.\n", i);
}
}
}
@@ -3522,17 +3478,6 @@ static int ql_request_irq(struct ql_adapter *qdev)
"Failed request for MSIX interrupt %d.\n",
i);
goto err_irq;
- } else {
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
- "Hooked intr %d, queue type %s, with name %s.\n",
- i,
- qdev->rx_ring[i].type == DEFAULT_Q ?
- "DEFAULT_Q" :
- qdev->rx_ring[i].type == TX_Q ?
- "TX_Q" :
- qdev->rx_ring[i].type == RX_Q ?
- "RX_Q" : "",
- intr_context->name);
}
} else {
netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
@@ -3602,15 +3547,11 @@ static int ql_start_rss(struct ql_adapter *qdev)
memcpy((void *)&ricb->ipv6_hash_key[0], init_hash_seed, 40);
memcpy((void *)&ricb->ipv4_hash_key[0], init_hash_seed, 16);
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, "Initializing RSS.\n");
-
status = ql_write_cfg(qdev, ricb, sizeof(*ricb), CFG_LR, 0);
if (status) {
netif_err(qdev, ifup, qdev->ndev, "Failed to load RICB.\n");
return status;
}
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
- "Successfully loaded RICB.\n");
return status;
}
@@ -3817,11 +3758,8 @@ static int ql_adapter_initialize(struct ql_adapter *qdev)
}
/* Start NAPI for the RSS queues. */
- for (i = 0; i < qdev->rss_ring_count; i++) {
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
- "Enabling NAPI for rx_ring[%d].\n", i);
+ for (i = 0; i < qdev->rss_ring_count; i++)
napi_enable(&qdev->rx_ring[i].napi);
- }
return status;
}
@@ -4121,10 +4059,6 @@ static int ql_configure_rings(struct ql_adapter *qdev)
rx_ring->lbq_size =
rx_ring->lbq_len * sizeof(__le64);
rx_ring->lbq_buf_size = (u16)lbq_buf_len;
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
- "lbq_buf_size %d, order = %d\n",
- rx_ring->lbq_buf_size,
- qdev->lbq_buf_order);
rx_ring->sbq_len = NUM_SMALL_BUFFERS;
rx_ring->sbq_size =
rx_ring->sbq_len * sizeof(__le64);
diff --git a/drivers/net/ethernet/racal/ni5010.c b/drivers/net/ethernet/racal/ni5010.c
index 072810da9a37..807982220050 100644
--- a/drivers/net/ethernet/racal/ni5010.c
+++ b/drivers/net/ethernet/racal/ni5010.c
@@ -552,7 +552,7 @@ static void ni5010_rx(struct net_device *dev)
}
/* Malloc up new buffer. */
- skb = dev_alloc_skb(i_pkt_size + 3);
+ skb = netdev_alloc_skb(dev, i_pkt_size + 3);
if (skb == NULL) {
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
dev->stats.rx_dropped++;
diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c
index cb0eca807852..b96e1920e045 100644
--- a/drivers/net/ethernet/rdc/r6040.c
+++ b/drivers/net/ethernet/rdc/r6040.c
@@ -1107,7 +1107,6 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(struct r6040_private));
if (!dev) {
- dev_err(&pdev->dev, "Failed to allocate etherdev\n");
err = -ENOMEM;
goto err_out;
}
@@ -1152,7 +1151,7 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
if (!(adrp[0] || adrp[1] || adrp[2])) {
netdev_warn(dev, "MAC address not initialized, "
"generating random\n");
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
}
/* Link new device into r6040_root_dev */
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index a8779bedb3d9..abd6aca70e9b 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -754,10 +754,9 @@ static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev)
/* dev and priv zeroed in alloc_etherdev */
dev = alloc_etherdev (sizeof (*tp));
- if (dev == NULL) {
- dev_err(&pdev->dev, "Unable to alloc new net device\n");
+ if (dev == NULL)
return ERR_PTR(-ENOMEM);
- }
+
SET_NETDEV_DEV(dev, &pdev->dev);
tp = netdev_priv(dev);
@@ -908,6 +907,33 @@ err_out:
return ERR_PTR(rc);
}
+static int rtl8139_set_features(struct net_device *dev, netdev_features_t features)
+{
+ struct rtl8139_private *tp = netdev_priv(dev);
+ unsigned long flags;
+ netdev_features_t changed = features ^ dev->features;
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ if (!(changed & (NETIF_F_RXALL)))
+ return 0;
+
+ spin_lock_irqsave(&tp->lock, flags);
+
+ if (changed & NETIF_F_RXALL) {
+ int rx_mode = tp->rx_config;
+ if (features & NETIF_F_RXALL)
+ rx_mode |= (AcceptErr | AcceptRunt);
+ else
+ rx_mode &= ~(AcceptErr | AcceptRunt);
+ tp->rx_config = rtl8139_rx_config | rx_mode;
+ RTL_W32_F(RxConfig, tp->rx_config);
+ }
+
+ spin_unlock_irqrestore(&tp->lock, flags);
+
+ return 0;
+}
+
static const struct net_device_ops rtl8139_netdev_ops = {
.ndo_open = rtl8139_open,
.ndo_stop = rtl8139_close,
@@ -922,6 +948,7 @@ static const struct net_device_ops rtl8139_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = rtl8139_poll_controller,
#endif
+ .ndo_set_features = rtl8139_set_features,
};
static int __devinit rtl8139_init_one (struct pci_dev *pdev,
@@ -995,6 +1022,9 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA;
dev->vlan_features = dev->features;
+ dev->hw_features |= NETIF_F_RXALL;
+ dev->hw_features |= NETIF_F_RXFCS;
+
dev->irq = pdev->irq;
/* tp zeroed and aligned in alloc_etherdev */
@@ -1941,7 +1971,10 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
/* read size+status of next frame from DMA ring buffer */
rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset));
rx_size = rx_status >> 16;
- pkt_size = rx_size - 4;
+ if (likely(!(dev->features & NETIF_F_RXFCS)))
+ pkt_size = rx_size - 4;
+ else
+ pkt_size = rx_size;
netif_dbg(tp, rx_status, dev, "%s() status %04x, size %04x, cur %04x\n",
__func__, rx_status, rx_size, cur_rx);
@@ -1979,11 +2012,30 @@ no_early_rx:
if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
(rx_size < 8) ||
(!(rx_status & RxStatusOK)))) {
+ if ((dev->features & NETIF_F_RXALL) &&
+ (rx_size <= (MAX_ETH_FRAME_SIZE + 4)) &&
+ (rx_size >= 8) &&
+ (!(rx_status & RxStatusOK))) {
+ /* Length is at least mostly OK, but pkt has
+ * error. I'm hoping we can handle some of these
+ * errors without resetting the chip. --Ben
+ */
+ dev->stats.rx_errors++;
+ if (rx_status & RxCRCErr) {
+ dev->stats.rx_crc_errors++;
+ goto keep_pkt;
+ }
+ if (rx_status & RxRunt) {
+ dev->stats.rx_length_errors++;
+ goto keep_pkt;
+ }
+ }
rtl8139_rx_err (rx_status, dev, tp, ioaddr);
received = -1;
goto out;
}
+keep_pkt:
/* Malloc up new buffer, compatible with net-2e. */
/* Omit the four octet CRC from the length. */
@@ -2516,6 +2568,9 @@ static void __set_rx_mode (struct net_device *dev)
}
}
+ if (dev->features & NETIF_F_RXALL)
+ rx_mode |= (AcceptErr | AcceptRunt);
+
/* We can safely update without stopping the chip. */
tmp = rtl8139_rx_config | rx_mode;
if (tp->rx_config != tmp) {
diff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig
index 0578859a3c73..5821966f9f28 100644
--- a/drivers/net/ethernet/realtek/Kconfig
+++ b/drivers/net/ethernet/realtek/Kconfig
@@ -24,11 +24,11 @@ config ATP
select CRC32
---help---
This is a network (Ethernet) device which attaches to your parallel
- port. Read <file:drivers/net/atp.c> as well as the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>, if you
- want to use this. If you intend to use this driver, you should have
- said N to the "Parallel printer support", because the two drivers
- don't like each other.
+ port. Read <file:drivers/net/ethernet/realtek/atp.c> as well as the
+ Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>,
+ if you want to use this. If you intend to use this driver, you
+ should have said N to the "Parallel printer support", because the two
+ drivers don't like each other.
To compile this driver as a module, choose M here: the module
will be called atp.
diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c
index e3f57fdbf0ea..46c1932048cb 100644
--- a/drivers/net/ethernet/realtek/atp.c
+++ b/drivers/net/ethernet/realtek/atp.c
@@ -783,7 +783,7 @@ static void net_rx(struct net_device *dev)
int pkt_len = (rx_head.rx_count & 0x7ff) - 4;
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_len + 2);
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
if (skb == NULL) {
printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n",
dev->name);
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 7a0c800b50ad..fbd855bcd9f0 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -667,12 +667,19 @@ struct rtl8169_counters {
__le16 tx_underun;
};
+enum rtl_flag {
+ RTL_FLAG_TASK_ENABLED,
+ RTL_FLAG_TASK_SLOW_PENDING,
+ RTL_FLAG_TASK_RESET_PENDING,
+ RTL_FLAG_TASK_PHY_PENDING,
+ RTL_FLAG_MAX
+};
+
struct rtl8169_private {
void __iomem *mmio_addr; /* memory map physical address */
struct pci_dev *pci_dev;
struct net_device *dev;
struct napi_struct napi;
- spinlock_t lock;
u32 msg_enable;
u16 txd_version;
u16 mac_version;
@@ -688,9 +695,8 @@ struct rtl8169_private {
struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
struct timer_list timer;
u16 cp_cmd;
- u16 intr_event;
- u16 napi_event;
- u16 intr_mask;
+
+ u16 event_slow;
struct mdio_ops {
void (*write)(void __iomem *, int, int);
@@ -714,7 +720,13 @@ struct rtl8169_private {
unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
unsigned int (*link_ok)(void __iomem *);
int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
- struct delayed_work task;
+
+ struct {
+ DECLARE_BITMAP(flags, RTL_FLAG_MAX);
+ struct mutex mutex;
+ struct work_struct work;
+ } wk;
+
unsigned features;
struct mii_if_info mii;
@@ -764,13 +776,20 @@ static int rtl8169_close(struct net_device *dev);
static void rtl_set_rx_mode(struct net_device *dev);
static void rtl8169_tx_timeout(struct net_device *dev);
static struct net_device_stats *rtl8169_get_stats(struct net_device *dev);
-static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
- void __iomem *, u32 budget);
static int rtl8169_change_mtu(struct net_device *dev, int new_mtu);
-static void rtl8169_down(struct net_device *dev);
static void rtl8169_rx_clear(struct rtl8169_private *tp);
static int rtl8169_poll(struct napi_struct *napi, int budget);
+static void rtl_lock_work(struct rtl8169_private *tp)
+{
+ mutex_lock(&tp->wk.mutex);
+}
+
+static void rtl_unlock_work(struct rtl8169_private *tp)
+{
+ mutex_unlock(&tp->wk.mutex);
+}
+
static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
{
int cap = pci_pcie_cap(pdev);
@@ -1180,12 +1199,51 @@ static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr)
return value;
}
+static u16 rtl_get_events(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ return RTL_R16(IntrStatus);
+}
+
+static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W16(IntrStatus, bits);
+ mmiowb();
+}
+
+static void rtl_irq_disable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W16(IntrMask, 0);
+ mmiowb();
+}
+
+static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W16(IntrMask, bits);
+}
+
+#define RTL_EVENT_NAPI_RX (RxOK | RxErr)
+#define RTL_EVENT_NAPI_TX (TxOK | TxErr)
+#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX)
+
+static void rtl_irq_enable_all(struct rtl8169_private *tp)
+{
+ rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow);
+}
+
static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- RTL_W16(IntrMask, 0x0000);
- RTL_W16(IntrStatus, tp->intr_event);
+ rtl_irq_disable(tp);
+ rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow);
RTL_R8(ChipCmd);
}
@@ -1276,9 +1334,6 @@ static void __rtl8169_check_link_status(struct net_device *dev,
struct rtl8169_private *tp,
void __iomem *ioaddr, bool pm)
{
- unsigned long flags;
-
- spin_lock_irqsave(&tp->lock, flags);
if (tp->link_ok(ioaddr)) {
rtl_link_chg_patch(tp);
/* This is to cancel a scheduled suspend if there's one. */
@@ -1293,7 +1348,6 @@ static void __rtl8169_check_link_status(struct net_device *dev,
if (pm)
pm_schedule_suspend(&tp->pci_dev->dev, 5000);
}
- spin_unlock_irqrestore(&tp->lock, flags);
}
static void rtl8169_check_link_status(struct net_device *dev,
@@ -1336,12 +1390,12 @@ static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
- spin_lock_irq(&tp->lock);
+ rtl_lock_work(tp);
wol->supported = WAKE_ANY;
wol->wolopts = __rtl8169_get_wol(tp);
- spin_unlock_irq(&tp->lock);
+ rtl_unlock_work(tp);
}
static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
@@ -1378,14 +1432,15 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
- spin_lock_irq(&tp->lock);
+ rtl_lock_work(tp);
if (wol->wolopts)
tp->features |= RTL_FEATURE_WOL;
else
tp->features &= ~RTL_FEATURE_WOL;
__rtl8169_set_wol(tp, wol->wolopts);
- spin_unlock_irq(&tp->lock);
+
+ rtl_unlock_work(tp);
device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
@@ -1540,15 +1595,14 @@ out:
static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct rtl8169_private *tp = netdev_priv(dev);
- unsigned long flags;
int ret;
del_timer_sync(&tp->timer);
- spin_lock_irqsave(&tp->lock, flags);
+ rtl_lock_work(tp);
ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd),
cmd->duplex, cmd->advertising);
- spin_unlock_irqrestore(&tp->lock, flags);
+ rtl_unlock_work(tp);
return ret;
}
@@ -1568,33 +1622,51 @@ static netdev_features_t rtl8169_fix_features(struct net_device *dev,
return features;
}
-static int rtl8169_set_features(struct net_device *dev,
- netdev_features_t features)
+static void __rtl8169_set_features(struct net_device *dev,
+ netdev_features_t features)
{
struct rtl8169_private *tp = netdev_priv(dev);
+ netdev_features_t changed = features ^ dev->features;
void __iomem *ioaddr = tp->mmio_addr;
- unsigned long flags;
- spin_lock_irqsave(&tp->lock, flags);
+ if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)))
+ return;
- if (features & NETIF_F_RXCSUM)
- tp->cp_cmd |= RxChkSum;
- else
- tp->cp_cmd &= ~RxChkSum;
+ if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)) {
+ if (features & NETIF_F_RXCSUM)
+ tp->cp_cmd |= RxChkSum;
+ else
+ tp->cp_cmd &= ~RxChkSum;
- if (dev->features & NETIF_F_HW_VLAN_RX)
- tp->cp_cmd |= RxVlan;
- else
- tp->cp_cmd &= ~RxVlan;
+ if (dev->features & NETIF_F_HW_VLAN_RX)
+ tp->cp_cmd |= RxVlan;
+ else
+ tp->cp_cmd &= ~RxVlan;
- RTL_W16(CPlusCmd, tp->cp_cmd);
- RTL_R16(CPlusCmd);
+ RTL_W16(CPlusCmd, tp->cp_cmd);
+ RTL_R16(CPlusCmd);
+ }
+ if (changed & NETIF_F_RXALL) {
+ int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
+ if (features & NETIF_F_RXALL)
+ tmp |= (AcceptErr | AcceptRunt);
+ RTL_W32(RxConfig, tmp);
+ }
+}
- spin_unlock_irqrestore(&tp->lock, flags);
+static int rtl8169_set_features(struct net_device *dev,
+ netdev_features_t features)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ rtl_lock_work(tp);
+ __rtl8169_set_features(dev, features);
+ rtl_unlock_work(tp);
return 0;
}
+
static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
struct sk_buff *skb)
{
@@ -1643,14 +1715,12 @@ static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct rtl8169_private *tp = netdev_priv(dev);
- unsigned long flags;
int rc;
- spin_lock_irqsave(&tp->lock, flags);
-
+ rtl_lock_work(tp);
rc = tp->get_settings(dev, cmd);
+ rtl_unlock_work(tp);
- spin_unlock_irqrestore(&tp->lock, flags);
return rc;
}
@@ -1658,14 +1728,13 @@ static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *p)
{
struct rtl8169_private *tp = netdev_priv(dev);
- unsigned long flags;
if (regs->len > R8169_REGS_SIZE)
regs->len = R8169_REGS_SIZE;
- spin_lock_irqsave(&tp->lock, flags);
+ rtl_lock_work(tp);
memcpy_fromio(p, tp->mmio_addr, regs->len);
- spin_unlock_irqrestore(&tp->lock, flags);
+ rtl_unlock_work(tp);
}
static u32 rtl8169_get_msglevel(struct net_device *dev)
@@ -3182,18 +3251,14 @@ static void rtl_hw_phy_config(struct net_device *dev)
}
}
-static void rtl8169_phy_timer(unsigned long __opaque)
+static void rtl_phy_work(struct rtl8169_private *tp)
{
- struct net_device *dev = (struct net_device *)__opaque;
- struct rtl8169_private *tp = netdev_priv(dev);
struct timer_list *timer = &tp->timer;
void __iomem *ioaddr = tp->mmio_addr;
unsigned long timeout = RTL8169_PHY_TIMEOUT;
assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
- spin_lock_irq(&tp->lock);
-
if (tp->phy_reset_pending(tp)) {
/*
* A busy loop could burn quite a few cycles on nowadays CPU.
@@ -3204,32 +3269,36 @@ static void rtl8169_phy_timer(unsigned long __opaque)
}
if (tp->link_ok(ioaddr))
- goto out_unlock;
+ return;
- netif_warn(tp, link, dev, "PHY reset until link up\n");
+ netif_warn(tp, link, tp->dev, "PHY reset until link up\n");
tp->phy_reset_enable(tp);
out_mod_timer:
mod_timer(timer, jiffies + timeout);
-out_unlock:
- spin_unlock_irq(&tp->lock);
+}
+
+static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
+{
+ if (!test_and_set_bit(flag, tp->wk.flags))
+ schedule_work(&tp->wk.work);
+}
+
+static void rtl8169_phy_timer(unsigned long __opaque)
+{
+ struct net_device *dev = (struct net_device *)__opaque;
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
static void rtl8169_netpoll(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
- struct pci_dev *pdev = tp->pci_dev;
- disable_irq(pdev->irq);
- rtl8169_interrupt(pdev->irq, dev);
- enable_irq(pdev->irq);
+ rtl8169_interrupt(tp->pci_dev->irq, dev);
}
#endif
@@ -3310,7 +3379,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
high = addr[4] | (addr[5] << 8);
- spin_lock_irq(&tp->lock);
+ rtl_lock_work(tp);
RTL_W8(Cfg9346, Cfg9346_Unlock);
@@ -3334,7 +3403,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
RTL_W8(Cfg9346, Cfg9346_Lock);
- spin_unlock_irq(&tp->lock);
+ rtl_unlock_work(tp);
}
static int rtl_set_mac_address(struct net_device *dev, void *p)
@@ -3388,8 +3457,7 @@ static const struct rtl_cfg_info {
void (*hw_start)(struct net_device *);
unsigned int region;
unsigned int align;
- u16 intr_event;
- u16 napi_event;
+ u16 event_slow;
unsigned features;
u8 default_ver;
} rtl_cfg_infos [] = {
@@ -3397,9 +3465,7 @@ static const struct rtl_cfg_info {
.hw_start = rtl_hw_start_8169,
.region = 1,
.align = 0,
- .intr_event = SYSErr | LinkChg | RxOverflow |
- RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
- .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
+ .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver,
.features = RTL_FEATURE_GMII,
.default_ver = RTL_GIGA_MAC_VER_01,
},
@@ -3407,9 +3473,7 @@ static const struct rtl_cfg_info {
.hw_start = rtl_hw_start_8168,
.region = 2,
.align = 8,
- .intr_event = SYSErr | LinkChg | RxOverflow |
- TxErr | TxOK | RxOK | RxErr,
- .napi_event = TxErr | TxOK | RxOK | RxOverflow,
+ .event_slow = SYSErr | LinkChg | RxOverflow,
.features = RTL_FEATURE_GMII | RTL_FEATURE_MSI,
.default_ver = RTL_GIGA_MAC_VER_11,
},
@@ -3417,9 +3481,8 @@ static const struct rtl_cfg_info {
.hw_start = rtl_hw_start_8101,
.region = 2,
.align = 8,
- .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
- RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
- .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
+ .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver |
+ PCSTimeout,
.features = RTL_FEATURE_MSI,
.default_ver = RTL_GIGA_MAC_VER_13,
}
@@ -3824,23 +3887,21 @@ static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- struct pci_dev *pdev = tp->pci_dev;
RTL_W8(MaxTxPacketSize, 0x3f);
RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
RTL_W8(Config4, RTL_R8(Config4) | 0x01);
- pci_write_config_byte(pdev, 0x79, 0x20);
+ rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
}
static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- struct pci_dev *pdev = tp->pci_dev;
RTL_W8(MaxTxPacketSize, 0x0c);
RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
- pci_write_config_byte(pdev, 0x79, 0x50);
+ rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
}
static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
@@ -3958,8 +4019,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev = alloc_etherdev(sizeof (*tp));
if (!dev) {
- if (netif_msg_drv(&debug))
- dev_err(&pdev->dev, "unable to alloc new ethernet\n");
rc = -ENOMEM;
goto out;
}
@@ -4048,11 +4107,11 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rtl_init_rxcfg(tp);
- RTL_W16(IntrMask, 0x0000);
+ rtl_irq_disable(tp);
rtl_hw_reset(tp);
- RTL_W16(IntrStatus, 0xffff);
+ rtl_ack_events(tp, 0xffff);
pci_set_master(pdev);
@@ -4098,7 +4157,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->do_ioctl = rtl_xmii_ioctl;
}
- spin_lock_init(&tp->lock);
+ mutex_init(&tp->wk.mutex);
/* Get MAC address */
for (i = 0; i < ETH_ALEN; i++)
@@ -4126,10 +4185,11 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* 8110SCd requires hardware Rx VLAN - disallow toggling */
dev->hw_features &= ~NETIF_F_HW_VLAN_RX;
- tp->intr_mask = 0xffff;
+ dev->hw_features |= NETIF_F_RXALL;
+ dev->hw_features |= NETIF_F_RXFCS;
+
tp->hw_start = cfg->hw_start;
- tp->intr_event = cfg->intr_event;
- tp->napi_event = cfg->napi_event;
+ tp->event_slow = cfg->event_slow;
tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ?
~(RxBOVF | RxFOVF) : ~0;
@@ -4196,7 +4256,7 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
rtl8168_driver_stop(tp);
}
- cancel_delayed_work_sync(&tp->task);
+ cancel_work_sync(&tp->wk.work);
unregister_netdev(dev);
@@ -4257,6 +4317,8 @@ static void rtl_request_firmware(struct rtl8169_private *tp)
rtl_request_uncached_firmware(tp);
}
+static void rtl_task(struct work_struct *);
+
static int rtl8169_open(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -4284,7 +4346,7 @@ static int rtl8169_open(struct net_device *dev)
if (retval < 0)
goto err_free_rx_1;
- INIT_DELAYED_WORK(&tp->task, NULL);
+ INIT_WORK(&tp->wk.work, rtl_task);
smp_mb();
@@ -4296,16 +4358,24 @@ static int rtl8169_open(struct net_device *dev)
if (retval < 0)
goto err_release_fw_2;
+ rtl_lock_work(tp);
+
+ set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
+
napi_enable(&tp->napi);
rtl8169_init_phy(dev, tp);
- rtl8169_set_features(dev, dev->features);
+ __rtl8169_set_features(dev, dev->features);
rtl_pll_power_up(tp);
rtl_hw_start(dev);
+ netif_start_queue(dev);
+
+ rtl_unlock_work(tp);
+
tp->saved_wolopts = 0;
pm_runtime_put_noidle(&pdev->dev);
@@ -4379,7 +4449,7 @@ static void rtl_hw_start(struct net_device *dev)
tp->hw_start(dev);
- netif_start_queue(dev);
+ rtl_irq_enable_all(tp);
}
static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
@@ -4506,9 +4576,6 @@ static void rtl_hw_start_8169(struct net_device *dev)
/* no early-rx interrupts */
RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
-
- /* Enable all known interrupts by setting the interrupt mask. */
- RTL_W16(IntrMask, tp->intr_event);
}
static void rtl_csi_access_enable(void __iomem *ioaddr, u32 bits)
@@ -4888,8 +4955,8 @@ static void rtl_hw_start_8168(struct net_device *dev)
/* Work around for RxFIFO overflow. */
if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
- tp->intr_event |= RxFIFOOver | PCSTimeout;
- tp->intr_event &= ~RxOverflow;
+ tp->event_slow |= RxFIFOOver | PCSTimeout;
+ tp->event_slow &= ~RxOverflow;
}
rtl_set_rx_tx_desc_registers(tp, ioaddr);
@@ -4977,8 +5044,6 @@ static void rtl_hw_start_8168(struct net_device *dev)
RTL_W8(Cfg9346, Cfg9346_Lock);
RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
-
- RTL_W16(IntrMask, tp->intr_event);
}
#define R810X_CPCMD_QUIRK_MASK (\
@@ -5077,10 +5142,8 @@ static void rtl_hw_start_8101(struct net_device *dev)
void __iomem *ioaddr = tp->mmio_addr;
struct pci_dev *pdev = tp->pci_dev;
- if (tp->mac_version >= RTL_GIGA_MAC_VER_30) {
- tp->intr_event &= ~RxFIFOOver;
- tp->napi_event &= ~RxFIFOOver;
- }
+ if (tp->mac_version >= RTL_GIGA_MAC_VER_30)
+ tp->event_slow &= ~RxFIFOOver;
if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
tp->mac_version == RTL_GIGA_MAC_VER_16) {
@@ -5136,8 +5199,6 @@ static void rtl_hw_start_8101(struct net_device *dev)
rtl_set_rx_mode(dev);
RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
-
- RTL_W16(IntrMask, tp->intr_event);
}
static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
@@ -5330,92 +5391,34 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp)
tp->cur_tx = tp->dirty_tx = 0;
}
-static void rtl8169_schedule_work(struct net_device *dev, work_func_t task)
-{
- struct rtl8169_private *tp = netdev_priv(dev);
-
- PREPARE_DELAYED_WORK(&tp->task, task);
- schedule_delayed_work(&tp->task, 4);
-}
-
-static void rtl8169_wait_for_quiescence(struct net_device *dev)
+static void rtl_reset_work(struct rtl8169_private *tp)
{
- struct rtl8169_private *tp = netdev_priv(dev);
- void __iomem *ioaddr = tp->mmio_addr;
-
- synchronize_irq(dev->irq);
-
- /* Wait for any pending NAPI task to complete */
- napi_disable(&tp->napi);
-
- rtl8169_irq_mask_and_ack(tp);
-
- tp->intr_mask = 0xffff;
- RTL_W16(IntrMask, tp->intr_event);
- napi_enable(&tp->napi);
-}
-
-static void rtl8169_reinit_task(struct work_struct *work)
-{
- struct rtl8169_private *tp =
- container_of(work, struct rtl8169_private, task.work);
- struct net_device *dev = tp->dev;
- int ret;
-
- rtnl_lock();
-
- if (!netif_running(dev))
- goto out_unlock;
-
- rtl8169_wait_for_quiescence(dev);
- rtl8169_close(dev);
-
- ret = rtl8169_open(dev);
- if (unlikely(ret < 0)) {
- if (net_ratelimit())
- netif_err(tp, drv, dev,
- "reinit failure (status = %d). Rescheduling\n",
- ret);
- rtl8169_schedule_work(dev, rtl8169_reinit_task);
- }
-
-out_unlock:
- rtnl_unlock();
-}
-
-static void rtl8169_reset_task(struct work_struct *work)
-{
- struct rtl8169_private *tp =
- container_of(work, struct rtl8169_private, task.work);
struct net_device *dev = tp->dev;
int i;
- rtnl_lock();
-
- if (!netif_running(dev))
- goto out_unlock;
+ napi_disable(&tp->napi);
+ netif_stop_queue(dev);
+ synchronize_sched();
rtl8169_hw_reset(tp);
- rtl8169_wait_for_quiescence(dev);
-
for (i = 0; i < NUM_RX_DESC; i++)
rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz);
rtl8169_tx_clear(tp);
rtl8169_init_ring_indexes(tp);
+ napi_enable(&tp->napi);
rtl_hw_start(dev);
netif_wake_queue(dev);
rtl8169_check_link_status(dev, tp, tp->mmio_addr);
-
-out_unlock:
- rtnl_unlock();
}
static void rtl8169_tx_timeout(struct net_device *dev)
{
- rtl8169_schedule_work(dev, rtl8169_reset_task);
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
}
static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
@@ -5552,9 +5555,22 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
RTL_W8(TxPoll, NPQ);
+ mmiowb();
+
if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) {
+ /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
+ * not miss a ring update when it notices a stopped queue.
+ */
+ smp_wmb();
netif_stop_queue(dev);
- smp_rmb();
+ /* Sync with rtl_tx:
+ * - publish queue status and cur_tx ring index (write barrier)
+ * - refresh dirty_tx ring index (read barrier).
+ * May the current thread have a pessimistic view of the ring
+ * status and forget to wake up queue, a racing rtl_tx thread
+ * can't.
+ */
+ smp_mb();
if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)
netif_wake_queue(dev);
}
@@ -5618,12 +5634,10 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
rtl8169_hw_reset(tp);
- rtl8169_schedule_work(dev, rtl8169_reinit_task);
+ rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
}
-static void rtl8169_tx_interrupt(struct net_device *dev,
- struct rtl8169_private *tp,
- void __iomem *ioaddr)
+static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
{
unsigned int dirty_tx, tx_left;
@@ -5655,7 +5669,14 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
if (tp->dirty_tx != dirty_tx) {
tp->dirty_tx = dirty_tx;
- smp_wmb();
+ /* Sync with rtl8169_start_xmit:
+ * - publish dirty_tx ring index (write barrier)
+ * - refresh cur_tx ring index and queue status (read barrier)
+ * May the current thread miss the stopped queue condition,
+ * a racing xmit thread can only have a right view of the
+ * ring status.
+ */
+ smp_mb();
if (netif_queue_stopped(dev) &&
(TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) {
netif_wake_queue(dev);
@@ -5666,9 +5687,11 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
* of start_xmit activity is detected (if it is not detected,
* it is slow enough). -- FR
*/
- smp_rmb();
- if (tp->cur_tx != dirty_tx)
+ if (tp->cur_tx != dirty_tx) {
+ void __iomem *ioaddr = tp->mmio_addr;
+
RTL_W8(TxPoll, NPQ);
+ }
}
}
@@ -5707,9 +5730,7 @@ static struct sk_buff *rtl8169_try_rx_copy(void *data,
return skb;
}
-static int rtl8169_rx_interrupt(struct net_device *dev,
- struct rtl8169_private *tp,
- void __iomem *ioaddr, u32 budget)
+static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget)
{
unsigned int cur_rx, rx_left;
unsigned int count;
@@ -5737,14 +5758,26 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
if (status & RxCRC)
dev->stats.rx_crc_errors++;
if (status & RxFOVF) {
- rtl8169_schedule_work(dev, rtl8169_reset_task);
+ rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
dev->stats.rx_fifo_errors++;
}
+ if ((status & (RxRUNT | RxCRC)) &&
+ !(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 = le64_to_cpu(desc->addr);
- int pkt_size = (status & 0x00003fff) - 4;
+ dma_addr_t addr;
+ int pkt_size;
+
+process_pkt:
+ addr = le64_to_cpu(desc->addr);
+ if (likely(!(dev->features & NETIF_F_RXFCS)))
+ pkt_size = (status & 0x00003fff) - 4;
+ else
+ pkt_size = status & 0x00003fff;
/*
* The driver does not support incoming fragmented
@@ -5798,101 +5831,120 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
struct rtl8169_private *tp = netdev_priv(dev);
- void __iomem *ioaddr = tp->mmio_addr;
int handled = 0;
- int status;
+ u16 status;
- /* loop handling interrupts until we have no new ones or
- * we hit a invalid/hotplug case.
- */
- status = RTL_R16(IntrStatus);
- while (status && status != 0xffff) {
- status &= tp->intr_event;
- if (!status)
- break;
+ status = rtl_get_events(tp);
+ if (status && status != 0xffff) {
+ status &= RTL_EVENT_NAPI | tp->event_slow;
+ if (status) {
+ handled = 1;
- handled = 1;
+ rtl_irq_disable(tp);
+ napi_schedule(&tp->napi);
+ }
+ }
+ return IRQ_RETVAL(handled);
+}
- /* Handle all of the error cases first. These will reset
- * the chip, so just exit the loop.
- */
- if (unlikely(!netif_running(dev))) {
- rtl8169_hw_reset(tp);
+/*
+ * Workqueue context.
+ */
+static void rtl_slow_event_work(struct rtl8169_private *tp)
+{
+ struct net_device *dev = tp->dev;
+ u16 status;
+
+ status = rtl_get_events(tp) & tp->event_slow;
+ rtl_ack_events(tp, status);
+
+ if (unlikely(status & RxFIFOOver)) {
+ switch (tp->mac_version) {
+ /* Work around for rx fifo overflow */
+ case RTL_GIGA_MAC_VER_11:
+ netif_stop_queue(dev);
+ /* XXX - Hack alert. See rtl_task(). */
+ set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags);
+ default:
break;
}
+ }
- if (unlikely(status & RxFIFOOver)) {
- switch (tp->mac_version) {
- /* Work around for rx fifo overflow */
- case RTL_GIGA_MAC_VER_11:
- netif_stop_queue(dev);
- rtl8169_tx_timeout(dev);
- goto done;
- default:
- break;
- }
- }
+ if (unlikely(status & SYSErr))
+ rtl8169_pcierr_interrupt(dev);
- if (unlikely(status & SYSErr)) {
- rtl8169_pcierr_interrupt(dev);
- break;
- }
+ if (status & LinkChg)
+ __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true);
- if (status & LinkChg)
- __rtl8169_check_link_status(dev, tp, ioaddr, true);
+ napi_disable(&tp->napi);
+ rtl_irq_disable(tp);
- /* We need to see the lastest version of tp->intr_mask to
- * avoid ignoring an MSI interrupt and having to wait for
- * another event which may never come.
- */
- smp_rmb();
- if (status & tp->intr_mask & tp->napi_event) {
- RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event);
- tp->intr_mask = ~tp->napi_event;
+ napi_enable(&tp->napi);
+ napi_schedule(&tp->napi);
+}
- if (likely(napi_schedule_prep(&tp->napi)))
- __napi_schedule(&tp->napi);
- else
- netif_info(tp, intr, dev,
- "interrupt %04x in poll\n", status);
- }
+static void rtl_task(struct work_struct *work)
+{
+ static const struct {
+ int bitnr;
+ void (*action)(struct rtl8169_private *);
+ } rtl_work[] = {
+ /* XXX - keep rtl_slow_event_work() as first element. */
+ { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work },
+ { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work },
+ { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work }
+ };
+ struct rtl8169_private *tp =
+ container_of(work, struct rtl8169_private, wk.work);
+ struct net_device *dev = tp->dev;
+ int i;
- /* We only get a new MSI interrupt when all active irq
- * sources on the chip have been acknowledged. So, ack
- * everything we've seen and check if new sources have become
- * active to avoid blocking all interrupts from the chip.
- */
- RTL_W16(IntrStatus,
- (status & RxFIFOOver) ? (status | RxOverflow) : status);
- status = RTL_R16(IntrStatus);
+ rtl_lock_work(tp);
+
+ if (!netif_running(dev) ||
+ !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
+ goto out_unlock;
+
+ for (i = 0; i < ARRAY_SIZE(rtl_work); i++) {
+ bool pending;
+
+ pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags);
+ if (pending)
+ rtl_work[i].action(tp);
}
-done:
- return IRQ_RETVAL(handled);
+
+out_unlock:
+ rtl_unlock_work(tp);
}
static int rtl8169_poll(struct napi_struct *napi, int budget)
{
struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
struct net_device *dev = tp->dev;
- void __iomem *ioaddr = tp->mmio_addr;
- int work_done;
+ u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow;
+ int work_done= 0;
+ u16 status;
+
+ status = rtl_get_events(tp);
+ rtl_ack_events(tp, status & ~tp->event_slow);
+
+ if (status & RTL_EVENT_NAPI_RX)
+ work_done = rtl_rx(dev, tp, (u32) budget);
+
+ if (status & RTL_EVENT_NAPI_TX)
+ rtl_tx(dev, tp);
- work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget);
- rtl8169_tx_interrupt(dev, tp, ioaddr);
+ if (status & tp->event_slow) {
+ enable_mask &= ~tp->event_slow;
+
+ rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING);
+ }
if (work_done < budget) {
napi_complete(napi);
- /* We need for force the visibility of tp->intr_mask
- * for other CPUs, as we can loose an MSI interrupt
- * and potentially wait for a retransmit timeout if we don't.
- * The posted write to IntrMask is safe, as it will
- * eventually make it to the chip and we won't loose anything
- * until it does.
- */
- tp->intr_mask = 0xffff;
- wmb();
- RTL_W16(IntrMask, tp->intr_event);
+ rtl_irq_enable(tp, enable_mask);
+ mmiowb();
}
return work_done;
@@ -5916,26 +5968,19 @@ static void rtl8169_down(struct net_device *dev)
del_timer_sync(&tp->timer);
- netif_stop_queue(dev);
-
napi_disable(&tp->napi);
-
- spin_lock_irq(&tp->lock);
+ netif_stop_queue(dev);
rtl8169_hw_reset(tp);
/*
* At this point device interrupts can not be enabled in any function,
- * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task,
- * rtl8169_reinit_task) and napi is disabled (rtl8169_poll).
+ * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task)
+ * and napi is disabled (rtl8169_poll).
*/
rtl8169_rx_missed(dev, ioaddr);
- spin_unlock_irq(&tp->lock);
-
- synchronize_irq(dev->irq);
-
/* Give a racing hard_start_xmit a few cycles to complete. */
- synchronize_sched(); /* FIXME: should this be synchronize_irq()? */
+ synchronize_sched();
rtl8169_tx_clear(tp);
@@ -5954,7 +5999,11 @@ static int rtl8169_close(struct net_device *dev)
/* Update counters before going down */
rtl8169_update_counters(dev);
+ rtl_lock_work(tp);
+ clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
+
rtl8169_down(dev);
+ rtl_unlock_work(tp);
free_irq(dev->irq, dev);
@@ -5974,7 +6023,6 @@ static void rtl_set_rx_mode(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- unsigned long flags;
u32 mc_filter[2]; /* Multicast hash filter */
int rx_mode;
u32 tmp = 0;
@@ -6003,7 +6051,8 @@ static void rtl_set_rx_mode(struct net_device *dev)
}
}
- spin_lock_irqsave(&tp->lock, flags);
+ if (dev->features & NETIF_F_RXALL)
+ rx_mode |= (AcceptErr | AcceptRunt);
tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
@@ -6018,8 +6067,6 @@ static void rtl_set_rx_mode(struct net_device *dev)
RTL_W32(MAR0 + 0, mc_filter[0]);
RTL_W32(RxConfig, tmp);
-
- spin_unlock_irqrestore(&tp->lock, flags);
}
/**
@@ -6032,13 +6079,9 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- unsigned long flags;
- if (netif_running(dev)) {
- spin_lock_irqsave(&tp->lock, flags);
+ if (netif_running(dev))
rtl8169_rx_missed(dev, ioaddr);
- spin_unlock_irqrestore(&tp->lock, flags);
- }
return &dev->stats;
}
@@ -6050,10 +6093,15 @@ static void rtl8169_net_suspend(struct net_device *dev)
if (!netif_running(dev))
return;
- rtl_pll_power_down(tp);
-
netif_device_detach(dev);
netif_stop_queue(dev);
+
+ rtl_lock_work(tp);
+ napi_disable(&tp->napi);
+ clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
+ rtl_unlock_work(tp);
+
+ rtl_pll_power_down(tp);
}
#ifdef CONFIG_PM
@@ -6076,7 +6124,9 @@ static void __rtl8169_resume(struct net_device *dev)
rtl_pll_power_up(tp);
- rtl8169_schedule_work(dev, rtl8169_reset_task);
+ set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
+
+ rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
}
static int rtl8169_resume(struct device *device)
@@ -6102,10 +6152,10 @@ static int rtl8169_runtime_suspend(struct device *device)
if (!tp->TxDescArray)
return 0;
- spin_lock_irq(&tp->lock);
+ rtl_lock_work(tp);
tp->saved_wolopts = __rtl8169_get_wol(tp);
__rtl8169_set_wol(tp, WAKE_ANY);
- spin_unlock_irq(&tp->lock);
+ rtl_unlock_work(tp);
rtl8169_net_suspend(dev);
@@ -6121,10 +6171,10 @@ static int rtl8169_runtime_resume(struct device *device)
if (!tp->TxDescArray)
return 0;
- spin_lock_irq(&tp->lock);
+ rtl_lock_work(tp);
__rtl8169_set_wol(tp, tp->saved_wolopts);
tp->saved_wolopts = 0;
- spin_unlock_irq(&tp->lock);
+ rtl_unlock_work(tp);
rtl8169_init_phy(dev, tp);
@@ -6192,12 +6242,8 @@ static void rtl_shutdown(struct pci_dev *pdev)
/* Restore original MAC address */
rtl_rar_set(tp, dev->perm_addr);
- spin_lock_irq(&tp->lock);
-
rtl8169_hw_reset(tp);
- spin_unlock_irq(&tp->lock);
-
if (system_state == SYSTEM_POWER_OFF) {
if (__rtl8169_get_wol(tp) & WAKE_ANY) {
rtl_wol_suspend_quirk(tp);
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 87b650131774..8615961c1287 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -34,7 +34,6 @@
#include <linux/phy.h>
#include <linux/cache.h>
#include <linux/io.h>
-#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/ethtool.h>
@@ -269,6 +268,7 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = {
.rpadir_value = 2 << 16,
.no_trimd = 1,
.no_ade = 1,
+ .tsu = 1,
};
static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
@@ -654,13 +654,12 @@ static void sh_eth_ring_format(struct net_device *ndev)
for (i = 0; i < RX_RING_SIZE; i++) {
/* skb */
mdp->rx_skbuff[i] = NULL;
- skb = dev_alloc_skb(mdp->rx_buf_sz);
+ skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
mdp->rx_skbuff[i] = skb;
if (skb == NULL)
break;
- dma_map_single(&ndev->dev, skb->tail, mdp->rx_buf_sz,
+ dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
DMA_FROM_DEVICE);
- skb->dev = ndev; /* Mark as being used by this device. */
sh_eth_set_receive_align(skb);
/* RX descriptor */
@@ -883,8 +882,8 @@ static int sh_eth_txfree(struct net_device *ndev)
if (entry >= TX_RING_SIZE - 1)
txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
- mdp->stats.tx_packets++;
- mdp->stats.tx_bytes += txdesc->buffer_length;
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += txdesc->buffer_length;
}
return freeNum;
}
@@ -910,23 +909,23 @@ static int sh_eth_rx(struct net_device *ndev)
break;
if (!(desc_status & RDFEND))
- mdp->stats.rx_length_errors++;
+ ndev->stats.rx_length_errors++;
if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
RD_RFS5 | RD_RFS6 | RD_RFS10)) {
- mdp->stats.rx_errors++;
+ ndev->stats.rx_errors++;
if (desc_status & RD_RFS1)
- mdp->stats.rx_crc_errors++;
+ ndev->stats.rx_crc_errors++;
if (desc_status & RD_RFS2)
- mdp->stats.rx_frame_errors++;
+ ndev->stats.rx_frame_errors++;
if (desc_status & RD_RFS3)
- mdp->stats.rx_length_errors++;
+ ndev->stats.rx_length_errors++;
if (desc_status & RD_RFS4)
- mdp->stats.rx_length_errors++;
+ ndev->stats.rx_length_errors++;
if (desc_status & RD_RFS6)
- mdp->stats.rx_missed_errors++;
+ ndev->stats.rx_missed_errors++;
if (desc_status & RD_RFS10)
- mdp->stats.rx_over_errors++;
+ ndev->stats.rx_over_errors++;
} else {
if (!mdp->cd->hw_swap)
sh_eth_soft_swap(
@@ -939,8 +938,8 @@ static int sh_eth_rx(struct net_device *ndev)
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, ndev);
netif_rx(skb);
- mdp->stats.rx_packets++;
- mdp->stats.rx_bytes += pkt_len;
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += pkt_len;
}
rxdesc->status |= cpu_to_edmac(mdp, RD_RACT);
entry = (++mdp->cur_rx) % RX_RING_SIZE;
@@ -955,13 +954,12 @@ static int sh_eth_rx(struct net_device *ndev)
rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
if (mdp->rx_skbuff[entry] == NULL) {
- skb = dev_alloc_skb(mdp->rx_buf_sz);
+ skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
mdp->rx_skbuff[entry] = skb;
if (skb == NULL)
break; /* Better luck next round. */
- dma_map_single(&ndev->dev, skb->tail, mdp->rx_buf_sz,
+ dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
DMA_FROM_DEVICE);
- skb->dev = ndev;
sh_eth_set_receive_align(skb);
skb_checksum_none_assert(skb);
@@ -1009,7 +1007,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
felic_stat = sh_eth_read(ndev, ECSR);
sh_eth_write(ndev, felic_stat, ECSR); /* clear int */
if (felic_stat & ECSR_ICD)
- mdp->stats.tx_carrier_errors++;
+ ndev->stats.tx_carrier_errors++;
if (felic_stat & ECSR_LCHNG) {
/* Link Changed */
if (mdp->cd->no_psr || mdp->no_ether_link) {
@@ -1042,7 +1040,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
if (intr_status & EESR_TWB) {
/* Write buck end. unused write back interrupt */
if (intr_status & EESR_TABT) /* Transmit Abort int */
- mdp->stats.tx_aborted_errors++;
+ ndev->stats.tx_aborted_errors++;
if (netif_msg_tx_err(mdp))
dev_err(&ndev->dev, "Transmit Abort\n");
}
@@ -1051,7 +1049,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
/* Receive Abort int */
if (intr_status & EESR_RFRMER) {
/* Receive Frame Overflow int */
- mdp->stats.rx_frame_errors++;
+ ndev->stats.rx_frame_errors++;
if (netif_msg_rx_err(mdp))
dev_err(&ndev->dev, "Receive Abort\n");
}
@@ -1059,21 +1057,21 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
if (intr_status & EESR_TDE) {
/* Transmit Descriptor Empty int */
- mdp->stats.tx_fifo_errors++;
+ ndev->stats.tx_fifo_errors++;
if (netif_msg_tx_err(mdp))
dev_err(&ndev->dev, "Transmit Descriptor Empty\n");
}
if (intr_status & EESR_TFE) {
/* FIFO under flow */
- mdp->stats.tx_fifo_errors++;
+ ndev->stats.tx_fifo_errors++;
if (netif_msg_tx_err(mdp))
dev_err(&ndev->dev, "Transmit FIFO Under flow\n");
}
if (intr_status & EESR_RDE) {
/* Receive Descriptor Empty int */
- mdp->stats.rx_over_errors++;
+ ndev->stats.rx_over_errors++;
if (sh_eth_read(ndev, EDRRR) ^ EDRRR_R)
sh_eth_write(ndev, EDRRR_R, EDRRR);
@@ -1083,14 +1081,14 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
if (intr_status & EESR_RFE) {
/* Receive FIFO Overflow int */
- mdp->stats.rx_fifo_errors++;
+ ndev->stats.rx_fifo_errors++;
if (netif_msg_rx_err(mdp))
dev_err(&ndev->dev, "Receive FIFO Overflow\n");
}
if (!mdp->cd->no_ade && (intr_status & EESR_ADE)) {
/* Address Error */
- mdp->stats.tx_fifo_errors++;
+ ndev->stats.tx_fifo_errors++;
if (netif_msg_tx_err(mdp))
dev_err(&ndev->dev, "Address Error\n");
}
@@ -1447,7 +1445,7 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
" resetting...\n", ndev->name, (int)sh_eth_read(ndev, EESR));
/* tx_errors count up */
- mdp->stats.tx_errors++;
+ ndev->stats.tx_errors++;
/* timer off */
del_timer_sync(&mdp->timer);
@@ -1569,27 +1567,27 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
pm_runtime_get_sync(&mdp->pdev->dev);
- mdp->stats.tx_dropped += sh_eth_read(ndev, TROCR);
+ ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR);
sh_eth_write(ndev, 0, TROCR); /* (write clear) */
- mdp->stats.collisions += sh_eth_read(ndev, CDCR);
+ ndev->stats.collisions += sh_eth_read(ndev, CDCR);
sh_eth_write(ndev, 0, CDCR); /* (write clear) */
- mdp->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
+ ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
sh_eth_write(ndev, 0, LCCR); /* (write clear) */
if (sh_eth_is_gether(mdp)) {
- mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
+ ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
sh_eth_write(ndev, 0, CERCR); /* (write clear) */
- mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
+ ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
sh_eth_write(ndev, 0, CEECR); /* (write clear) */
} else {
- mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
+ ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
sh_eth_write(ndev, 0, CNDCR); /* (write clear) */
}
pm_runtime_put_sync(&mdp->pdev->dev);
- return &mdp->stats;
+ return &ndev->stats;
}
-/* ioctl to device funciotn*/
+/* ioctl to device function */
static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq,
int cmd)
{
@@ -1606,18 +1604,345 @@ static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq,
}
#if defined(SH_ETH_HAS_TSU)
+/* For TSU_POSTn. Please refer to the manual about this (strange) bitfields */
+static void *sh_eth_tsu_get_post_reg_offset(struct sh_eth_private *mdp,
+ int entry)
+{
+ return sh_eth_tsu_get_offset(mdp, TSU_POST1) + (entry / 8 * 4);
+}
+
+static u32 sh_eth_tsu_get_post_mask(int entry)
+{
+ return 0x0f << (28 - ((entry % 8) * 4));
+}
+
+static u32 sh_eth_tsu_get_post_bit(struct sh_eth_private *mdp, int entry)
+{
+ return (0x08 >> (mdp->port << 1)) << (28 - ((entry % 8) * 4));
+}
+
+static void sh_eth_tsu_enable_cam_entry_post(struct net_device *ndev,
+ int entry)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ u32 tmp;
+ void *reg_offset;
+
+ reg_offset = sh_eth_tsu_get_post_reg_offset(mdp, entry);
+ tmp = ioread32(reg_offset);
+ iowrite32(tmp | sh_eth_tsu_get_post_bit(mdp, entry), reg_offset);
+}
+
+static bool sh_eth_tsu_disable_cam_entry_post(struct net_device *ndev,
+ int entry)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ u32 post_mask, ref_mask, tmp;
+ void *reg_offset;
+
+ reg_offset = sh_eth_tsu_get_post_reg_offset(mdp, entry);
+ post_mask = sh_eth_tsu_get_post_mask(entry);
+ ref_mask = sh_eth_tsu_get_post_bit(mdp, entry) & ~post_mask;
+
+ tmp = ioread32(reg_offset);
+ iowrite32(tmp & ~post_mask, reg_offset);
+
+ /* If other port enables, the function returns "true" */
+ return tmp & ref_mask;
+}
+
+static int sh_eth_tsu_busy(struct net_device *ndev)
+{
+ int timeout = SH_ETH_TSU_TIMEOUT_MS * 100;
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+
+ while ((sh_eth_tsu_read(mdp, TSU_ADSBSY) & TSU_ADSBSY_0)) {
+ udelay(10);
+ timeout--;
+ if (timeout <= 0) {
+ dev_err(&ndev->dev, "%s: timeout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static int sh_eth_tsu_write_entry(struct net_device *ndev, void *reg,
+ const u8 *addr)
+{
+ u32 val;
+
+ val = addr[0] << 24 | addr[1] << 16 | addr[2] << 8 | addr[3];
+ iowrite32(val, reg);
+ if (sh_eth_tsu_busy(ndev) < 0)
+ return -EBUSY;
+
+ val = addr[4] << 8 | addr[5];
+ iowrite32(val, reg + 4);
+ if (sh_eth_tsu_busy(ndev) < 0)
+ return -EBUSY;
+
+ return 0;
+}
+
+static void sh_eth_tsu_read_entry(void *reg, u8 *addr)
+{
+ u32 val;
+
+ val = ioread32(reg);
+ addr[0] = (val >> 24) & 0xff;
+ addr[1] = (val >> 16) & 0xff;
+ addr[2] = (val >> 8) & 0xff;
+ addr[3] = val & 0xff;
+ val = ioread32(reg + 4);
+ addr[4] = (val >> 8) & 0xff;
+ addr[5] = val & 0xff;
+}
+
+
+static int sh_eth_tsu_find_entry(struct net_device *ndev, const u8 *addr)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
+ int i;
+ u8 c_addr[ETH_ALEN];
+
+ for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
+ sh_eth_tsu_read_entry(reg_offset, c_addr);
+ if (memcmp(addr, c_addr, ETH_ALEN) == 0)
+ return i;
+ }
+
+ return -ENOENT;
+}
+
+static int sh_eth_tsu_find_empty(struct net_device *ndev)
+{
+ u8 blank[ETH_ALEN];
+ int entry;
+
+ memset(blank, 0, sizeof(blank));
+ entry = sh_eth_tsu_find_entry(ndev, blank);
+ return (entry < 0) ? -ENOMEM : entry;
+}
+
+static int sh_eth_tsu_disable_cam_entry_table(struct net_device *ndev,
+ int entry)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
+ int ret;
+ u8 blank[ETH_ALEN];
+
+ sh_eth_tsu_write(mdp, sh_eth_tsu_read(mdp, TSU_TEN) &
+ ~(1 << (31 - entry)), TSU_TEN);
+
+ memset(blank, 0, sizeof(blank));
+ ret = sh_eth_tsu_write_entry(ndev, reg_offset + entry * 8, blank);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static int sh_eth_tsu_add_entry(struct net_device *ndev, const u8 *addr)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
+ int i, ret;
+
+ if (!mdp->cd->tsu)
+ return 0;
+
+ i = sh_eth_tsu_find_entry(ndev, addr);
+ if (i < 0) {
+ /* No entry found, create one */
+ i = sh_eth_tsu_find_empty(ndev);
+ if (i < 0)
+ return -ENOMEM;
+ ret = sh_eth_tsu_write_entry(ndev, reg_offset + i * 8, addr);
+ if (ret < 0)
+ return ret;
+
+ /* Enable the entry */
+ sh_eth_tsu_write(mdp, sh_eth_tsu_read(mdp, TSU_TEN) |
+ (1 << (31 - i)), TSU_TEN);
+ }
+
+ /* Entry found or created, enable POST */
+ sh_eth_tsu_enable_cam_entry_post(ndev, i);
+
+ return 0;
+}
+
+static int sh_eth_tsu_del_entry(struct net_device *ndev, const u8 *addr)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ int i, ret;
+
+ if (!mdp->cd->tsu)
+ return 0;
+
+ i = sh_eth_tsu_find_entry(ndev, addr);
+ if (i) {
+ /* Entry found */
+ if (sh_eth_tsu_disable_cam_entry_post(ndev, i))
+ goto done;
+
+ /* Disable the entry if both ports was disabled */
+ ret = sh_eth_tsu_disable_cam_entry_table(ndev, i);
+ if (ret < 0)
+ return ret;
+ }
+done:
+ return 0;
+}
+
+static int sh_eth_tsu_purge_all(struct net_device *ndev)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ int i, ret;
+
+ if (unlikely(!mdp->cd->tsu))
+ return 0;
+
+ for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++) {
+ if (sh_eth_tsu_disable_cam_entry_post(ndev, i))
+ continue;
+
+ /* Disable the entry if both ports was disabled */
+ ret = sh_eth_tsu_disable_cam_entry_table(ndev, i);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void sh_eth_tsu_purge_mcast(struct net_device *ndev)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ u8 addr[ETH_ALEN];
+ void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
+ int i;
+
+ if (unlikely(!mdp->cd->tsu))
+ return;
+
+ for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
+ sh_eth_tsu_read_entry(reg_offset, addr);
+ if (is_multicast_ether_addr(addr))
+ sh_eth_tsu_del_entry(ndev, addr);
+ }
+}
+
/* Multicast reception directions set */
static void sh_eth_set_multicast_list(struct net_device *ndev)
{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ u32 ecmr_bits;
+ int mcast_all = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mdp->lock, flags);
+ /*
+ * Initial condition is MCT = 1, PRM = 0.
+ * Depending on ndev->flags, set PRM or clear MCT
+ */
+ ecmr_bits = (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) | ECMR_MCT;
+
+ if (!(ndev->flags & IFF_MULTICAST)) {
+ sh_eth_tsu_purge_mcast(ndev);
+ mcast_all = 1;
+ }
+ if (ndev->flags & IFF_ALLMULTI) {
+ sh_eth_tsu_purge_mcast(ndev);
+ ecmr_bits &= ~ECMR_MCT;
+ mcast_all = 1;
+ }
+
if (ndev->flags & IFF_PROMISC) {
- /* Set promiscuous. */
- sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_MCT) |
- ECMR_PRM, ECMR);
+ sh_eth_tsu_purge_all(ndev);
+ ecmr_bits = (ecmr_bits & ~ECMR_MCT) | ECMR_PRM;
+ } else if (mdp->cd->tsu) {
+ struct netdev_hw_addr *ha;
+ netdev_for_each_mc_addr(ha, ndev) {
+ if (mcast_all && is_multicast_ether_addr(ha->addr))
+ continue;
+
+ if (sh_eth_tsu_add_entry(ndev, ha->addr) < 0) {
+ if (!mcast_all) {
+ sh_eth_tsu_purge_mcast(ndev);
+ ecmr_bits &= ~ECMR_MCT;
+ mcast_all = 1;
+ }
+ }
+ }
} else {
/* Normal, unicast/broadcast-only mode. */
- sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) |
- ECMR_MCT, ECMR);
+ ecmr_bits = (ecmr_bits & ~ECMR_PRM) | ECMR_MCT;
}
+
+ /* update the ethernet mode */
+ sh_eth_write(ndev, ecmr_bits, ECMR);
+
+ spin_unlock_irqrestore(&mdp->lock, flags);
+}
+
+static int sh_eth_get_vtag_index(struct sh_eth_private *mdp)
+{
+ if (!mdp->port)
+ return TSU_VTAG0;
+ else
+ return TSU_VTAG1;
+}
+
+static int sh_eth_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ int vtag_reg_index = sh_eth_get_vtag_index(mdp);
+
+ if (unlikely(!mdp->cd->tsu))
+ return -EPERM;
+
+ /* No filtering if vid = 0 */
+ if (!vid)
+ return 0;
+
+ mdp->vlan_num_ids++;
+
+ /*
+ * The controller has one VLAN tag HW filter. So, if the filter is
+ * already enabled, the driver disables it and the filte
+ */
+ if (mdp->vlan_num_ids > 1) {
+ /* disable VLAN filter */
+ sh_eth_tsu_write(mdp, 0, vtag_reg_index);
+ return 0;
+ }
+
+ sh_eth_tsu_write(mdp, TSU_VTAG_ENABLE | (vid & TSU_VTAG_VID_MASK),
+ vtag_reg_index);
+
+ return 0;
+}
+
+static int sh_eth_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ int vtag_reg_index = sh_eth_get_vtag_index(mdp);
+
+ if (unlikely(!mdp->cd->tsu))
+ return -EPERM;
+
+ /* No filtering if vid = 0 */
+ if (!vid)
+ return 0;
+
+ mdp->vlan_num_ids--;
+ sh_eth_tsu_write(mdp, 0, vtag_reg_index);
+
+ return 0;
}
#endif /* SH_ETH_HAS_TSU */
@@ -1768,6 +2093,8 @@ static const struct net_device_ops sh_eth_netdev_ops = {
.ndo_get_stats = sh_eth_get_stats,
#if defined(SH_ETH_HAS_TSU)
.ndo_set_rx_mode = sh_eth_set_multicast_list,
+ .ndo_vlan_rx_add_vid = sh_eth_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = sh_eth_vlan_rx_kill_vid,
#endif
.ndo_tx_timeout = sh_eth_tx_timeout,
.ndo_do_ioctl = sh_eth_do_ioctl,
@@ -1794,7 +2121,6 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
ndev = alloc_etherdev(sizeof(struct sh_eth_private));
if (!ndev) {
- dev_err(&pdev->dev, "Could not allocate device.\n");
ret = -ENOMEM;
goto out;
}
@@ -1862,18 +2188,22 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
/* read and set MAC address */
read_mac_address(ndev, pd->mac_addr);
- /* First device only init */
- if (!devno) {
- if (mdp->cd->tsu) {
- struct resource *rtsu;
- rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!rtsu) {
- dev_err(&pdev->dev, "Not found TSU resource\n");
- goto out_release;
- }
- mdp->tsu_addr = ioremap(rtsu->start,
- resource_size(rtsu));
+ /* ioremap the TSU registers */
+ if (mdp->cd->tsu) {
+ struct resource *rtsu;
+ rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!rtsu) {
+ dev_err(&pdev->dev, "Not found TSU resource\n");
+ goto out_release;
}
+ mdp->tsu_addr = ioremap(rtsu->start,
+ resource_size(rtsu));
+ mdp->port = devno % 2;
+ ndev->features = NETIF_F_HW_VLAN_FILTER;
+ }
+
+ /* initialize first or needed device */
+ if (!devno || pd->needs_init) {
if (mdp->cd->chip_reset)
mdp->cd->chip_reset(ndev);
@@ -1922,7 +2252,8 @@ static int sh_eth_drv_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct sh_eth_private *mdp = netdev_priv(ndev);
- iounmap(mdp->tsu_addr);
+ if (mdp->cd->tsu)
+ iounmap(mdp->tsu_addr);
sh_mdio_release(ndev);
unregister_netdev(ndev);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index cdbd844662a7..57dc26261116 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -29,6 +29,8 @@
#define RX_RING_SIZE 64 /* Rx ring size */
#define ETHERSMALL 60
#define PKT_BUF_SZ 1538
+#define SH_ETH_TSU_TIMEOUT_MS 500
+#define SH_ETH_TSU_CAM_ENTRIES 32
enum {
/* E-DMAC registers */
@@ -677,6 +679,10 @@ enum TSU_FWSLC_BIT {
TSU_FWSLC_CAMSEL11 = 0x0002, TSU_FWSLC_CAMSEL10 = 0x0001,
};
+/* TSU_VTAGn */
+#define TSU_VTAG_ENABLE 0x80000000
+#define TSU_VTAG_VID_MASK 0x00000fff
+
/*
* The sh ether Tx buffer descriptors.
* This structure should be 20 bytes.
@@ -759,7 +765,6 @@ struct sh_eth_private {
struct sh_eth_txdesc *tx_ring;
struct sk_buff **rx_skbuff;
struct sk_buff **tx_skbuff;
- struct net_device_stats stats;
struct timer_list timer;
spinlock_t lock;
u32 cur_rx, dirty_rx; /* Producer/consumer ring indices */
@@ -779,6 +784,8 @@ struct sh_eth_private {
char post_rx; /* POST receive */
char post_fw; /* POST forward */
struct net_device_stats tsu_stats; /* TSU forward status */
+ int port; /* for TSU */
+ int vlan_num_ids; /* for VLAN tag filter */
unsigned no_ether_link:1;
unsigned ether_link_active_low:1;
@@ -812,6 +819,12 @@ static inline unsigned long sh_eth_read(struct net_device *ndev,
return ioread32(mdp->addr + mdp->reg_offset[enum_index]);
}
+static inline void *sh_eth_tsu_get_offset(struct sh_eth_private *mdp,
+ int enum_index)
+{
+ return mdp->tsu_addr + mdp->reg_offset[enum_index];
+}
+
static inline void sh_eth_tsu_write(struct sh_eth_private *mdp,
unsigned long data, int enum_index)
{
diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c
index 22e9c0181ce8..1895605abb35 100644
--- a/drivers/net/ethernet/s6gmac.c
+++ b/drivers/net/ethernet/s6gmac.c
@@ -370,12 +370,13 @@ struct s6gmac {
} link;
};
-static void s6gmac_rx_fillfifo(struct s6gmac *pd)
+static void s6gmac_rx_fillfifo(struct net_device *dev)
{
+ struct s6gmac *pd = netdev_priv(dev);
struct sk_buff *skb;
while ((((u8)(pd->rx_skb_i - pd->rx_skb_o)) < S6_NUM_RX_SKB) &&
(!s6dmac_fifo_full(pd->rx_dma, pd->rx_chan)) &&
- (skb = dev_alloc_skb(S6_MAX_FRLEN + 2))) {
+ (skb = netdev_alloc_skb(dev, S6_MAX_FRLEN + 2))) {
pd->rx_skb[(pd->rx_skb_i++) % S6_NUM_RX_SKB] = skb;
s6dmac_put_fifo_cache(pd->rx_dma, pd->rx_chan,
pd->io, (u32)skb->data, S6_MAX_FRLEN);
@@ -514,7 +515,7 @@ static irqreturn_t s6gmac_interrupt(int irq, void *dev_id)
spin_lock(&pd->lock);
if (s6dmac_termcnt_irq(pd->rx_dma, pd->rx_chan))
s6gmac_rx_interrupt(dev);
- s6gmac_rx_fillfifo(pd);
+ s6gmac_rx_fillfifo(dev);
if (s6dmac_termcnt_irq(pd->tx_dma, pd->tx_chan))
s6gmac_tx_interrupt(dev);
s6gmac_stats_interrupt(pd, 0);
@@ -894,7 +895,7 @@ static int s6gmac_open(struct net_device *dev)
s6gmac_init_device(dev);
s6gmac_init_stats(dev);
s6gmac_init_dmac(dev);
- s6gmac_rx_fillfifo(pd);
+ s6gmac_rx_fillfifo(dev);
s6dmac_enable_chan(pd->rx_dma, pd->rx_chan,
2, 1, 0, 1, 0, 0, 0, 7, -1, 2, 0, 1);
s6dmac_enable_chan(pd->tx_dma, pd->tx_chan,
@@ -960,11 +961,11 @@ static int __devinit s6gmac_probe(struct platform_device *pdev)
int res;
unsigned long i;
struct mii_bus *mb;
+
dev = alloc_etherdev(sizeof(*pd));
- if (!dev) {
- printk(KERN_ERR DRV_PRMT "etherdev alloc failed, aborting.\n");
+ if (!dev)
return -ENOMEM;
- }
+
dev->open = s6gmac_open;
dev->stop = s6gmac_stop;
dev->hard_start_xmit = s6gmac_tx;
diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c
index 893c880dadf0..7b819bd8c416 100644
--- a/drivers/net/ethernet/seeq/ether3.c
+++ b/drivers/net/ethernet/seeq/ether3.c
@@ -643,7 +643,7 @@ if (next_ptr < RX_START || next_ptr >= RX_END) {
if (next_ptr <= this_ptr)
length += RX_END - RX_START;
- skb = dev_alloc_skb(length + 2);
+ skb = netdev_alloc_skb(dev, length + 2);
if (skb) {
unsigned char *buf;
diff --git a/drivers/net/ethernet/seeq/seeq8005.c b/drivers/net/ethernet/seeq/seeq8005.c
index 60561451789b..798990774446 100644
--- a/drivers/net/ethernet/seeq/seeq8005.c
+++ b/drivers/net/ethernet/seeq/seeq8005.c
@@ -548,7 +548,7 @@ static void seeq8005_rx(struct net_device *dev)
struct sk_buff *skb;
unsigned char *buf;
- skb = dev_alloc_skb(pkt_len);
+ skb = netdev_alloc_skb(dev, pkt_len);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
dev->stats.rx_dropped++;
diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c
index f955a19eb22f..bb8c8222122b 100644
--- a/drivers/net/ethernet/seeq/sgiseeq.c
+++ b/drivers/net/ethernet/seeq/sgiseeq.c
@@ -733,7 +733,6 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev)
dev = alloc_etherdev(sizeof (struct sgiseeq_private));
if (!dev) {
- printk(KERN_ERR "Sgiseeq: Etherdev alloc failed, aborting.\n");
err = -ENOMEM;
goto err_out;
}
diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index 5d18841f0f3d..fb3cbc27063c 100644
--- a/drivers/net/ethernet/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -16,6 +16,21 @@ config SFC_MTD
depends on SFC && MTD && !(SFC=y && MTD=m)
default y
---help---
- This exposes the on-board flash memory as MTD devices (e.g.
- /dev/mtd1). This makes it possible to upload new firmware
- to the NIC.
+ This exposes the on-board flash and/or EEPROM as MTD devices
+ (e.g. /dev/mtd1). This is required to update the firmware or
+ the boot configuration under Linux.
+config SFC_MCDI_MON
+ bool "Solarflare SFC9000-family hwmon support"
+ depends on SFC && HWMON && !(SFC=y && HWMON=m)
+ default y
+ ----help---
+ This exposes the on-board firmware-managed sensors as a
+ hardware monitor device.
+config SFC_SRIOV
+ bool "Solarflare SFC9000-family SR-IOV support"
+ depends on SFC && PCI_IOV
+ default y
+ ---help---
+ This enables support for the SFC9000 I/O Virtualization
+ features, allowing accelerated network performance in
+ virtualized environments.
diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index ab31c7124db1..ea1f8db57318 100644
--- a/drivers/net/ethernet/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
@@ -2,7 +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.o mcdi_phy.o mcdi_mon.o
sfc-$(CONFIG_SFC_MTD) += mtd.o
+sfc-$(CONFIG_SFC_SRIOV) += siena_sriov.o
obj-$(CONFIG_SFC) += sfc.o
diff --git a/drivers/net/ethernet/sfc/bitfield.h b/drivers/net/ethernet/sfc/bitfield.h
index 098ac2ad757d..b26a954c27fc 100644
--- a/drivers/net/ethernet/sfc/bitfield.h
+++ b/drivers/net/ethernet/sfc/bitfield.h
@@ -448,40 +448,40 @@ typedef union efx_oword {
EFX_INSERT32(min, max, low, high, EFX_MASK32(high + 1 - low))
#define EFX_SET_OWORD64(oword, low, high, value) do { \
- (oword).u64[0] = (((oword).u64[0] \
+ (oword).u64[0] = (((oword).u64[0] \
& ~EFX_INPLACE_MASK64(0, 63, low, high)) \
| EFX_INSERT64(0, 63, low, high, value)); \
- (oword).u64[1] = (((oword).u64[1] \
+ (oword).u64[1] = (((oword).u64[1] \
& ~EFX_INPLACE_MASK64(64, 127, low, high)) \
| EFX_INSERT64(64, 127, low, high, value)); \
} while (0)
#define EFX_SET_QWORD64(qword, low, high, value) do { \
- (qword).u64[0] = (((qword).u64[0] \
+ (qword).u64[0] = (((qword).u64[0] \
& ~EFX_INPLACE_MASK64(0, 63, low, high)) \
| EFX_INSERT64(0, 63, low, high, value)); \
} while (0)
#define EFX_SET_OWORD32(oword, low, high, value) do { \
- (oword).u32[0] = (((oword).u32[0] \
+ (oword).u32[0] = (((oword).u32[0] \
& ~EFX_INPLACE_MASK32(0, 31, low, high)) \
| EFX_INSERT32(0, 31, low, high, value)); \
- (oword).u32[1] = (((oword).u32[1] \
+ (oword).u32[1] = (((oword).u32[1] \
& ~EFX_INPLACE_MASK32(32, 63, low, high)) \
| EFX_INSERT32(32, 63, low, high, value)); \
- (oword).u32[2] = (((oword).u32[2] \
+ (oword).u32[2] = (((oword).u32[2] \
& ~EFX_INPLACE_MASK32(64, 95, low, high)) \
| EFX_INSERT32(64, 95, low, high, value)); \
- (oword).u32[3] = (((oword).u32[3] \
+ (oword).u32[3] = (((oword).u32[3] \
& ~EFX_INPLACE_MASK32(96, 127, low, high)) \
| EFX_INSERT32(96, 127, low, high, value)); \
} while (0)
#define EFX_SET_QWORD32(qword, low, high, value) do { \
- (qword).u32[0] = (((qword).u32[0] \
+ (qword).u32[0] = (((qword).u32[0] \
& ~EFX_INPLACE_MASK32(0, 31, low, high)) \
| EFX_INSERT32(0, 31, low, high, value)); \
- (qword).u32[1] = (((qword).u32[1] \
+ (qword).u32[1] = (((qword).u32[1] \
& ~EFX_INPLACE_MASK32(32, 63, low, high)) \
| EFX_INSERT32(32, 63, low, high, value)); \
} while (0)
@@ -531,8 +531,8 @@ typedef union efx_oword {
/* Static initialiser */
-#define EFX_OWORD32(a, b, c, d) \
- { .u32 = { cpu_to_le32(a), cpu_to_le32(b), \
+#define EFX_OWORD32(a, b, c, d) \
+ { .u32 = { cpu_to_le32(a), cpu_to_le32(b), \
cpu_to_le32(c), cpu_to_le32(d) } }
#endif /* EFX_BITFIELD_H */
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index e43702f33b62..1908ba7ca7e6 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -38,15 +38,15 @@
/* Loopback mode names (see LOOPBACK_MODE()) */
const unsigned int efx_loopback_mode_max = LOOPBACK_MAX;
-const char *efx_loopback_mode_names[] = {
+const char *const efx_loopback_mode_names[] = {
[LOOPBACK_NONE] = "NONE",
[LOOPBACK_DATA] = "DATAPATH",
[LOOPBACK_GMAC] = "GMAC",
[LOOPBACK_XGMII] = "XGMII",
[LOOPBACK_XGXS] = "XGXS",
- [LOOPBACK_XAUI] = "XAUI",
- [LOOPBACK_GMII] = "GMII",
- [LOOPBACK_SGMII] = "SGMII",
+ [LOOPBACK_XAUI] = "XAUI",
+ [LOOPBACK_GMII] = "GMII",
+ [LOOPBACK_SGMII] = "SGMII",
[LOOPBACK_XGBR] = "XGBR",
[LOOPBACK_XFI] = "XFI",
[LOOPBACK_XAUI_FAR] = "XAUI_FAR",
@@ -55,21 +55,21 @@ const char *efx_loopback_mode_names[] = {
[LOOPBACK_XFI_FAR] = "XFI_FAR",
[LOOPBACK_GPHY] = "GPHY",
[LOOPBACK_PHYXS] = "PHYXS",
- [LOOPBACK_PCS] = "PCS",
- [LOOPBACK_PMAPMD] = "PMA/PMD",
+ [LOOPBACK_PCS] = "PCS",
+ [LOOPBACK_PMAPMD] = "PMA/PMD",
[LOOPBACK_XPORT] = "XPORT",
[LOOPBACK_XGMII_WS] = "XGMII_WS",
- [LOOPBACK_XAUI_WS] = "XAUI_WS",
+ [LOOPBACK_XAUI_WS] = "XAUI_WS",
[LOOPBACK_XAUI_WS_FAR] = "XAUI_WS_FAR",
[LOOPBACK_XAUI_WS_NEAR] = "XAUI_WS_NEAR",
- [LOOPBACK_GMII_WS] = "GMII_WS",
+ [LOOPBACK_GMII_WS] = "GMII_WS",
[LOOPBACK_XFI_WS] = "XFI_WS",
[LOOPBACK_XFI_WS_FAR] = "XFI_WS_FAR",
- [LOOPBACK_PHYXS_WS] = "PHYXS_WS",
+ [LOOPBACK_PHYXS_WS] = "PHYXS_WS",
};
const unsigned int efx_reset_type_max = RESET_TYPE_MAX;
-const char *efx_reset_type_names[] = {
+const char *const efx_reset_type_names[] = {
[RESET_TYPE_INVISIBLE] = "INVISIBLE",
[RESET_TYPE_ALL] = "ALL",
[RESET_TYPE_WORLD] = "WORLD",
@@ -122,15 +122,6 @@ static int napi_weight = 64;
*/
static unsigned int efx_monitor_interval = 1 * HZ;
-/* This controls whether or not the driver will initialise devices
- * with invalid MAC addresses stored in the EEPROM or flash. If true,
- * such devices will be initialised with a random locally-generated
- * MAC address. This allows for loading the sfc_mtd driver to
- * reprogram the flash, even if the flash contents (including the MAC
- * address) have previously been erased.
- */
-static unsigned int allow_bad_hwaddr;
-
/* Initial interrupt moderation settings. They can be modified after
* module load with ethtool.
*
@@ -162,7 +153,7 @@ static unsigned int interrupt_mode;
* interrupt handling.
*
* Cards without MSI-X will only target one CPU via legacy or MSI interrupt.
- * The default (0) means to assign an interrupt to each package (level II cache)
+ * The default (0) means to assign an interrupt to each core.
*/
static unsigned int rss_cpus;
module_param(rss_cpus, uint, 0444);
@@ -195,9 +186,13 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
*
*************************************************************************/
+static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq);
+static void efx_stop_interrupts(struct efx_nic *efx, bool may_keep_eventq);
+static void efx_remove_channel(struct efx_channel *channel);
static void efx_remove_channels(struct efx_nic *efx);
+static const struct efx_channel_type efx_default_channel_type;
static void efx_remove_port(struct efx_nic *efx);
-static void efx_init_napi(struct efx_nic *efx);
+static void efx_init_napi_channel(struct efx_channel *channel);
static void efx_fini_napi(struct efx_nic *efx);
static void efx_fini_napi_channel(struct efx_channel *channel);
static void efx_fini_struct(struct efx_nic *efx);
@@ -226,27 +221,27 @@ static void efx_stop_all(struct efx_nic *efx);
*/
static int efx_process_channel(struct efx_channel *channel, int budget)
{
- struct efx_nic *efx = channel->efx;
int spent;
- if (unlikely(efx->reset_pending || !channel->enabled))
+ if (unlikely(!channel->enabled))
return 0;
spent = efx_nic_process_eventq(channel, budget);
- if (spent == 0)
- return 0;
-
- /* Deliver last RX packet. */
- if (channel->rx_pkt) {
- __efx_rx_packet(channel, channel->rx_pkt,
- channel->rx_pkt_csummed);
- channel->rx_pkt = NULL;
+ if (spent && efx_channel_has_rx_queue(channel)) {
+ struct efx_rx_queue *rx_queue =
+ efx_channel_get_rx_queue(channel);
+
+ /* Deliver last RX packet. */
+ if (channel->rx_pkt) {
+ __efx_rx_packet(channel, channel->rx_pkt);
+ channel->rx_pkt = NULL;
+ }
+ if (rx_queue->enabled) {
+ efx_rx_strategy(channel);
+ efx_fast_push_rx_descriptors(rx_queue);
+ }
}
- efx_rx_strategy(channel);
-
- efx_fast_push_rx_descriptors(efx_channel_get_rx_queue(channel));
-
return spent;
}
@@ -286,7 +281,7 @@ static int efx_poll(struct napi_struct *napi, int budget)
spent = efx_process_channel(channel, budget);
if (spent < budget) {
- if (channel->channel < efx->n_rx_channels &&
+ if (efx_channel_has_rx_queue(channel) &&
efx->irq_rx_adaptive &&
unlikely(++channel->irq_count == 1000)) {
if (unlikely(channel->irq_mod_score <
@@ -373,7 +368,7 @@ static int efx_probe_eventq(struct efx_channel *channel)
struct efx_nic *efx = channel->efx;
unsigned long entries;
- netif_dbg(channel->efx, probe, channel->efx->net_dev,
+ netif_dbg(efx, probe, efx->net_dev,
"chan %d create event queue\n", channel->channel);
/* Build an event queue with room for one event per tx and rx buffer,
@@ -396,6 +391,34 @@ static void efx_init_eventq(struct efx_channel *channel)
efx_nic_init_eventq(channel);
}
+/* Enable event queue processing and NAPI */
+static void efx_start_eventq(struct efx_channel *channel)
+{
+ netif_dbg(channel->efx, ifup, channel->efx->net_dev,
+ "chan %d start event queue\n", channel->channel);
+
+ /* The interrupt handler for this channel may set work_pending
+ * as soon as we enable it. Make sure it's cleared before
+ * then. Similarly, make sure it sees the enabled flag set.
+ */
+ channel->work_pending = false;
+ channel->enabled = true;
+ smp_wmb();
+
+ napi_enable(&channel->napi_str);
+ efx_nic_eventq_read_ack(channel);
+}
+
+/* Disable event queue processing and NAPI */
+static void efx_stop_eventq(struct efx_channel *channel)
+{
+ if (!channel->enabled)
+ return;
+
+ napi_disable(&channel->napi_str);
+ channel->enabled = false;
+}
+
static void efx_fini_eventq(struct efx_channel *channel)
{
netif_dbg(channel->efx, drv, channel->efx->net_dev,
@@ -418,8 +441,7 @@ static void efx_remove_eventq(struct efx_channel *channel)
*
*************************************************************************/
-/* Allocate and initialise a channel structure, optionally copying
- * parameters (but not resources) from an old channel structure. */
+/* Allocate and initialise a channel structure. */
static struct efx_channel *
efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
{
@@ -428,45 +450,60 @@ efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
struct efx_tx_queue *tx_queue;
int j;
- if (old_channel) {
- channel = kmalloc(sizeof(*channel), GFP_KERNEL);
- if (!channel)
- return NULL;
+ channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+ if (!channel)
+ return NULL;
- *channel = *old_channel;
+ channel->efx = efx;
+ channel->channel = i;
+ channel->type = &efx_default_channel_type;
- channel->napi_dev = NULL;
- memset(&channel->eventq, 0, sizeof(channel->eventq));
+ for (j = 0; j < EFX_TXQ_TYPES; j++) {
+ tx_queue = &channel->tx_queue[j];
+ tx_queue->efx = efx;
+ tx_queue->queue = i * EFX_TXQ_TYPES + j;
+ tx_queue->channel = channel;
+ }
- rx_queue = &channel->rx_queue;
- rx_queue->buffer = NULL;
- memset(&rx_queue->rxd, 0, sizeof(rx_queue->rxd));
+ rx_queue = &channel->rx_queue;
+ rx_queue->efx = efx;
+ setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
+ (unsigned long)rx_queue);
- for (j = 0; j < EFX_TXQ_TYPES; j++) {
- tx_queue = &channel->tx_queue[j];
- if (tx_queue->channel)
- tx_queue->channel = channel;
- tx_queue->buffer = NULL;
- memset(&tx_queue->txd, 0, sizeof(tx_queue->txd));
- }
- } else {
- channel = kzalloc(sizeof(*channel), GFP_KERNEL);
- if (!channel)
- return NULL;
+ return channel;
+}
+
+/* Allocate and initialise a channel structure, copying parameters
+ * (but not resources) from an old channel structure.
+ */
+static struct efx_channel *
+efx_copy_channel(const struct efx_channel *old_channel)
+{
+ struct efx_channel *channel;
+ struct efx_rx_queue *rx_queue;
+ struct efx_tx_queue *tx_queue;
+ int j;
+
+ channel = kmalloc(sizeof(*channel), GFP_KERNEL);
+ if (!channel)
+ return NULL;
- channel->efx = efx;
- channel->channel = i;
+ *channel = *old_channel;
- for (j = 0; j < EFX_TXQ_TYPES; j++) {
- tx_queue = &channel->tx_queue[j];
- tx_queue->efx = efx;
- tx_queue->queue = i * EFX_TXQ_TYPES + j;
+ channel->napi_dev = NULL;
+ memset(&channel->eventq, 0, sizeof(channel->eventq));
+
+ for (j = 0; j < EFX_TXQ_TYPES; j++) {
+ tx_queue = &channel->tx_queue[j];
+ if (tx_queue->channel)
tx_queue->channel = channel;
- }
+ tx_queue->buffer = NULL;
+ memset(&tx_queue->txd, 0, sizeof(tx_queue->txd));
}
rx_queue = &channel->rx_queue;
- rx_queue->efx = efx;
+ rx_queue->buffer = NULL;
+ memset(&rx_queue->rxd, 0, sizeof(rx_queue->rxd));
setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
(unsigned long)rx_queue);
@@ -482,57 +519,62 @@ static int efx_probe_channel(struct efx_channel *channel)
netif_dbg(channel->efx, probe, channel->efx->net_dev,
"creating channel %d\n", channel->channel);
+ rc = channel->type->pre_probe(channel);
+ if (rc)
+ goto fail;
+
rc = efx_probe_eventq(channel);
if (rc)
- goto fail1;
+ goto fail;
efx_for_each_channel_tx_queue(tx_queue, channel) {
rc = efx_probe_tx_queue(tx_queue);
if (rc)
- goto fail2;
+ goto fail;
}
efx_for_each_channel_rx_queue(rx_queue, channel) {
rc = efx_probe_rx_queue(rx_queue);
if (rc)
- goto fail3;
+ goto fail;
}
channel->n_rx_frm_trunc = 0;
return 0;
- fail3:
- efx_for_each_channel_rx_queue(rx_queue, channel)
- efx_remove_rx_queue(rx_queue);
- fail2:
- efx_for_each_channel_tx_queue(tx_queue, channel)
- efx_remove_tx_queue(tx_queue);
- fail1:
+fail:
+ efx_remove_channel(channel);
return rc;
}
+static void
+efx_get_channel_name(struct efx_channel *channel, char *buf, size_t len)
+{
+ struct efx_nic *efx = channel->efx;
+ const char *type;
+ int number;
+
+ number = channel->channel;
+ if (efx->tx_channel_offset == 0) {
+ type = "";
+ } else if (channel->channel < efx->tx_channel_offset) {
+ type = "-rx";
+ } else {
+ type = "-tx";
+ number -= efx->tx_channel_offset;
+ }
+ snprintf(buf, len, "%s%s-%d", efx->name, type, number);
+}
static void efx_set_channel_names(struct efx_nic *efx)
{
struct efx_channel *channel;
- const char *type = "";
- int number;
- efx_for_each_channel(channel, efx) {
- number = channel->channel;
- if (efx->n_channels > efx->n_rx_channels) {
- if (channel->channel < efx->n_rx_channels) {
- type = "-rx";
- } else {
- type = "-tx";
- number -= efx->n_rx_channels;
- }
- }
- snprintf(efx->channel_name[channel->channel],
- sizeof(efx->channel_name[0]),
- "%s%s-%d", efx->name, type, number);
- }
+ efx_for_each_channel(channel, efx)
+ channel->type->get_name(channel,
+ efx->channel_name[channel->channel],
+ sizeof(efx->channel_name[0]));
}
static int efx_probe_channels(struct efx_nic *efx)
@@ -543,7 +585,12 @@ static int efx_probe_channels(struct efx_nic *efx)
/* Restart special buffer allocation */
efx->next_buffer_table = 0;
- efx_for_each_channel(channel, efx) {
+ /* Probe channels in reverse, so that any 'extra' channels
+ * use the start of the buffer table. This allows the traffic
+ * channels to be resized without moving them or wasting the
+ * entries before them.
+ */
+ efx_for_each_channel_rev(channel, efx) {
rc = efx_probe_channel(channel);
if (rc) {
netif_err(efx, probe, efx->net_dev,
@@ -565,7 +612,7 @@ fail:
* to propagate configuration changes (mtu, checksum offload), or
* to clear hardware error conditions
*/
-static void efx_init_channels(struct efx_nic *efx)
+static void efx_start_datapath(struct efx_nic *efx)
{
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
@@ -584,68 +631,26 @@ static void efx_init_channels(struct efx_nic *efx)
/* Initialise the channels */
efx_for_each_channel(channel, efx) {
- netif_dbg(channel->efx, drv, channel->efx->net_dev,
- "init chan %d\n", channel->channel);
-
- efx_init_eventq(channel);
-
efx_for_each_channel_tx_queue(tx_queue, channel)
efx_init_tx_queue(tx_queue);
/* The rx buffer allocation strategy is MTU dependent */
efx_rx_strategy(channel);
- efx_for_each_channel_rx_queue(rx_queue, channel)
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
efx_init_rx_queue(rx_queue);
+ efx_nic_generate_fill_event(rx_queue);
+ }
WARN_ON(channel->rx_pkt != NULL);
efx_rx_strategy(channel);
}
-}
-
-/* This enables event queue processing and packet transmission.
- *
- * Note that this function is not allowed to fail, since that would
- * introduce too much complexity into the suspend/resume path.
- */
-static void efx_start_channel(struct efx_channel *channel)
-{
- struct efx_rx_queue *rx_queue;
- netif_dbg(channel->efx, ifup, channel->efx->net_dev,
- "starting chan %d\n", channel->channel);
-
- /* The interrupt handler for this channel may set work_pending
- * as soon as we enable it. Make sure it's cleared before
- * then. Similarly, make sure it sees the enabled flag set. */
- channel->work_pending = false;
- channel->enabled = true;
- smp_wmb();
-
- /* Fill the queues before enabling NAPI */
- efx_for_each_channel_rx_queue(rx_queue, channel)
- efx_fast_push_rx_descriptors(rx_queue);
-
- napi_enable(&channel->napi_str);
-}
-
-/* This disables event queue processing and packet transmission.
- * This function does not guarantee that all queue processing
- * (e.g. RX refill) is complete.
- */
-static void efx_stop_channel(struct efx_channel *channel)
-{
- if (!channel->enabled)
- return;
-
- netif_dbg(channel->efx, ifdown, channel->efx->net_dev,
- "stop chan %d\n", channel->channel);
-
- channel->enabled = false;
- napi_disable(&channel->napi_str);
+ if (netif_device_present(efx->net_dev))
+ netif_tx_wake_all_queues(efx->net_dev);
}
-static void efx_fini_channels(struct efx_nic *efx)
+static void efx_stop_datapath(struct efx_nic *efx)
{
struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
@@ -672,14 +677,21 @@ static void efx_fini_channels(struct efx_nic *efx)
}
efx_for_each_channel(channel, efx) {
- netif_dbg(channel->efx, drv, channel->efx->net_dev,
- "shut down chan %d\n", channel->channel);
+ /* RX packet processing is pipelined, so wait for the
+ * NAPI handler to complete. At least event queue 0
+ * might be kept active by non-data events, so don't
+ * use napi_synchronize() but actually disable NAPI
+ * temporarily.
+ */
+ if (efx_channel_has_rx_queue(channel)) {
+ efx_stop_eventq(channel);
+ efx_start_eventq(channel);
+ }
efx_for_each_channel_rx_queue(rx_queue, channel)
efx_fini_rx_queue(rx_queue);
efx_for_each_possible_channel_tx_queue(tx_queue, channel)
efx_fini_tx_queue(tx_queue);
- efx_fini_eventq(channel);
}
}
@@ -711,16 +723,40 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
{
struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel;
u32 old_rxq_entries, old_txq_entries;
- unsigned i;
- int rc;
+ unsigned i, next_buffer_table = 0;
+ int rc = 0;
+
+ /* Not all channels should be reallocated. We must avoid
+ * reallocating their buffer table entries.
+ */
+ efx_for_each_channel(channel, efx) {
+ struct efx_rx_queue *rx_queue;
+ struct efx_tx_queue *tx_queue;
+
+ if (channel->type->copy)
+ continue;
+ next_buffer_table = max(next_buffer_table,
+ channel->eventq.index +
+ channel->eventq.entries);
+ efx_for_each_channel_rx_queue(rx_queue, channel)
+ next_buffer_table = max(next_buffer_table,
+ rx_queue->rxd.index +
+ rx_queue->rxd.entries);
+ efx_for_each_channel_tx_queue(tx_queue, channel)
+ next_buffer_table = max(next_buffer_table,
+ tx_queue->txd.index +
+ tx_queue->txd.entries);
+ }
efx_stop_all(efx);
- efx_fini_channels(efx);
+ efx_stop_interrupts(efx, true);
- /* Clone channels */
+ /* Clone channels (where possible) */
memset(other_channel, 0, sizeof(other_channel));
for (i = 0; i < efx->n_channels; i++) {
- channel = efx_alloc_channel(efx, i, efx->channel[i]);
+ channel = efx->channel[i];
+ if (channel->type->copy)
+ channel = channel->type->copy(channel);
if (!channel) {
rc = -ENOMEM;
goto out;
@@ -739,23 +775,31 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
other_channel[i] = channel;
}
- rc = efx_probe_channels(efx);
- if (rc)
- goto rollback;
+ /* Restart buffer table allocation */
+ efx->next_buffer_table = next_buffer_table;
- efx_init_napi(efx);
-
- /* Destroy old channels */
for (i = 0; i < efx->n_channels; i++) {
- efx_fini_napi_channel(other_channel[i]);
- efx_remove_channel(other_channel[i]);
+ channel = efx->channel[i];
+ if (!channel->type->copy)
+ continue;
+ rc = efx_probe_channel(channel);
+ if (rc)
+ goto rollback;
+ efx_init_napi_channel(efx->channel[i]);
}
+
out:
- /* Free unused channel structures */
- for (i = 0; i < efx->n_channels; i++)
- kfree(other_channel[i]);
+ /* Destroy unused channel structures */
+ for (i = 0; i < efx->n_channels; i++) {
+ channel = other_channel[i];
+ if (channel && channel->type->copy) {
+ efx_fini_napi_channel(channel);
+ efx_remove_channel(channel);
+ kfree(channel);
+ }
+ }
- efx_init_channels(efx);
+ efx_start_interrupts(efx, true);
efx_start_all(efx);
return rc;
@@ -776,6 +820,18 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100));
}
+static const struct efx_channel_type efx_default_channel_type = {
+ .pre_probe = efx_channel_dummy_op_int,
+ .get_name = efx_get_channel_name,
+ .copy = efx_copy_channel,
+ .keep_eventq = false,
+};
+
+int efx_channel_dummy_op_int(struct efx_channel *channel)
+{
+ return 0;
+}
+
/**************************************************************************
*
* Port handling
@@ -807,16 +863,14 @@ void efx_link_status_changed(struct efx_nic *efx)
}
/* Status message for kernel log */
- if (link_state->up) {
+ if (link_state->up)
netif_info(efx, link, efx->net_dev,
"link up at %uMbps %s-duplex (MTU %d)%s\n",
link_state->speed, link_state->fd ? "full" : "half",
efx->net_dev->mtu,
(efx->promiscuous ? " [PROMISC]" : ""));
- } else {
+ else
netif_info(efx, link, efx->net_dev, "link down\n");
- }
-
}
void efx_link_set_advertising(struct efx_nic *efx, u32 advertising)
@@ -863,11 +917,9 @@ int __efx_reconfigure_port(struct efx_nic *efx)
WARN_ON(!mutex_is_locked(&efx->mac_lock));
- /* Serialise the promiscuous flag with efx_set_multicast_list. */
- if (efx_dev_registered(efx)) {
- netif_addr_lock_bh(efx->net_dev);
- netif_addr_unlock_bh(efx->net_dev);
- }
+ /* Serialise the promiscuous flag with efx_set_rx_mode. */
+ netif_addr_lock_bh(efx->net_dev);
+ netif_addr_unlock_bh(efx->net_dev);
/* Disable PHY transmit in mac level loopbacks */
phy_mode = efx->phy_mode;
@@ -907,16 +959,13 @@ static void efx_mac_work(struct work_struct *data)
struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
mutex_lock(&efx->mac_lock);
- if (efx->port_enabled) {
- efx->type->push_multicast_hash(efx);
- efx->mac_op->reconfigure(efx);
- }
+ if (efx->port_enabled)
+ efx->type->reconfigure_mac(efx);
mutex_unlock(&efx->mac_lock);
}
static int efx_probe_port(struct efx_nic *efx)
{
- unsigned char *perm_addr;
int rc;
netif_dbg(efx, probe, efx->net_dev, "create port\n");
@@ -929,28 +978,10 @@ static int efx_probe_port(struct efx_nic *efx)
if (rc)
return rc;
- /* Sanity check MAC address */
- perm_addr = efx->net_dev->perm_addr;
- if (is_valid_ether_addr(perm_addr)) {
- memcpy(efx->net_dev->dev_addr, perm_addr, ETH_ALEN);
- } else {
- netif_err(efx, probe, efx->net_dev, "invalid MAC address %pM\n",
- perm_addr);
- if (!allow_bad_hwaddr) {
- rc = -EINVAL;
- goto err;
- }
- random_ether_addr(efx->net_dev->dev_addr);
- netif_info(efx, probe, efx->net_dev,
- "using locally-generated MAC %pM\n",
- efx->net_dev->dev_addr);
- }
+ /* Initialise MAC address to permanent address */
+ memcpy(efx->net_dev->dev_addr, efx->net_dev->perm_addr, ETH_ALEN);
return 0;
-
- err:
- efx->type->remove_port(efx);
- return rc;
}
static int efx_init_port(struct efx_nic *efx)
@@ -969,7 +1000,7 @@ static int efx_init_port(struct efx_nic *efx)
/* Reconfigure the MAC before creating dma queues (required for
* Falcon/A1 where RX_INGR_EN/TX_DRAIN_EN isn't supported) */
- efx->mac_op->reconfigure(efx);
+ efx->type->reconfigure_mac(efx);
/* Ensure the PHY advertises the correct flow control settings */
rc = efx->phy_op->reconfigure(efx);
@@ -996,8 +1027,7 @@ static void efx_start_port(struct efx_nic *efx)
/* efx_mac_work() might have been scheduled after efx_stop_port(),
* and then cancelled by efx_flush_all() */
- efx->type->push_multicast_hash(efx);
- efx->mac_op->reconfigure(efx);
+ efx->type->reconfigure_mac(efx);
mutex_unlock(&efx->mac_lock);
}
@@ -1012,10 +1042,8 @@ static void efx_stop_port(struct efx_nic *efx)
mutex_unlock(&efx->mac_lock);
/* Serialise against efx_set_multicast_list() */
- if (efx_dev_registered(efx)) {
- netif_addr_lock_bh(efx->net_dev);
- netif_addr_unlock_bh(efx->net_dev);
- }
+ netif_addr_lock_bh(efx->net_dev);
+ netif_addr_unlock_bh(efx->net_dev);
}
static void efx_fini_port(struct efx_nic *efx)
@@ -1069,9 +1097,11 @@ static int efx_init_io(struct efx_nic *efx)
* masks event though they reject 46 bit masks.
*/
while (dma_mask > 0x7fffffffUL) {
- if (pci_dma_supported(pci_dev, dma_mask) &&
- ((rc = pci_set_dma_mask(pci_dev, dma_mask)) == 0))
- break;
+ if (pci_dma_supported(pci_dev, dma_mask)) {
+ rc = pci_set_dma_mask(pci_dev, dma_mask);
+ if (rc == 0)
+ break;
+ }
dma_mask >>= 1;
}
if (rc) {
@@ -1144,33 +1174,46 @@ static void efx_fini_io(struct efx_nic *efx)
pci_disable_device(efx->pci_dev);
}
-/* Get number of channels wanted. Each channel will have its own IRQ,
- * 1 RX queue and/or 2 TX queues. */
-static int efx_wanted_channels(void)
+static unsigned int efx_wanted_parallelism(struct efx_nic *efx)
{
- cpumask_var_t core_mask;
- int count;
+ cpumask_var_t thread_mask;
+ unsigned int count;
int cpu;
- if (rss_cpus)
- return rss_cpus;
+ if (rss_cpus) {
+ count = rss_cpus;
+ } else {
+ if (unlikely(!zalloc_cpumask_var(&thread_mask, GFP_KERNEL))) {
+ netif_warn(efx, probe, efx->net_dev,
+ "RSS disabled due to allocation failure\n");
+ return 1;
+ }
+
+ count = 0;
+ for_each_online_cpu(cpu) {
+ if (!cpumask_test_cpu(cpu, thread_mask)) {
+ ++count;
+ cpumask_or(thread_mask, thread_mask,
+ topology_thread_cpumask(cpu));
+ }
+ }
- if (unlikely(!zalloc_cpumask_var(&core_mask, GFP_KERNEL))) {
- printk(KERN_WARNING
- "sfc: RSS disabled due to allocation failure\n");
- return 1;
+ free_cpumask_var(thread_mask);
}
- count = 0;
- for_each_online_cpu(cpu) {
- if (!cpumask_test_cpu(cpu, core_mask)) {
- ++count;
- cpumask_or(core_mask, core_mask,
- topology_core_cpumask(cpu));
- }
+ /* If RSS is requested for the PF *and* VFs then we can't write RSS
+ * table entries that are inaccessible to VFs
+ */
+ if (efx_sriov_wanted(efx) && efx_vf_size(efx) > 1 &&
+ count > efx_vf_size(efx)) {
+ netif_warn(efx, probe, efx->net_dev,
+ "Reducing number of RSS channels from %u to %u for "
+ "VF support. Increase vf-msix-limit to use more "
+ "channels on the PF.\n",
+ count, efx_vf_size(efx));
+ count = efx_vf_size(efx);
}
- free_cpumask_var(core_mask);
return count;
}
@@ -1178,7 +1221,8 @@ static int
efx_init_rx_cpu_rmap(struct efx_nic *efx, struct msix_entry *xentries)
{
#ifdef CONFIG_RFS_ACCEL
- int i, rc;
+ unsigned int i;
+ int rc;
efx->net_dev->rx_cpu_rmap = alloc_irq_cpu_rmap(efx->n_rx_channels);
if (!efx->net_dev->rx_cpu_rmap)
@@ -1201,17 +1245,24 @@ efx_init_rx_cpu_rmap(struct efx_nic *efx, struct msix_entry *xentries)
*/
static int efx_probe_interrupts(struct efx_nic *efx)
{
- int max_channels =
- min_t(int, efx->type->phys_addr_channels, EFX_MAX_CHANNELS);
- int rc, i;
+ unsigned int max_channels =
+ min(efx->type->phys_addr_channels, EFX_MAX_CHANNELS);
+ unsigned int extra_channels = 0;
+ unsigned int i, j;
+ int rc;
+
+ for (i = 0; i < EFX_MAX_EXTRA_CHANNELS; i++)
+ if (efx->extra_channel_type[i])
+ ++extra_channels;
if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
struct msix_entry xentries[EFX_MAX_CHANNELS];
- int n_channels;
+ unsigned int n_channels;
- n_channels = efx_wanted_channels();
+ n_channels = efx_wanted_parallelism(efx);
if (separate_tx_channels)
n_channels *= 2;
+ n_channels += extra_channels;
n_channels = min(n_channels, max_channels);
for (i = 0; i < n_channels; i++)
@@ -1220,7 +1271,7 @@ static int efx_probe_interrupts(struct efx_nic *efx)
if (rc > 0) {
netif_err(efx, drv, efx->net_dev,
"WARNING: Insufficient MSI-X vectors"
- " available (%d < %d).\n", rc, n_channels);
+ " available (%d < %u).\n", rc, n_channels);
netif_err(efx, drv, efx->net_dev,
"WARNING: Performance may be reduced.\n");
EFX_BUG_ON_PARANOID(rc >= n_channels);
@@ -1231,22 +1282,23 @@ static int efx_probe_interrupts(struct efx_nic *efx)
if (rc == 0) {
efx->n_channels = n_channels;
+ if (n_channels > extra_channels)
+ n_channels -= extra_channels;
if (separate_tx_channels) {
- efx->n_tx_channels =
- max(efx->n_channels / 2, 1U);
- efx->n_rx_channels =
- max(efx->n_channels -
- efx->n_tx_channels, 1U);
+ efx->n_tx_channels = max(n_channels / 2, 1U);
+ efx->n_rx_channels = max(n_channels -
+ efx->n_tx_channels,
+ 1U);
} else {
- efx->n_tx_channels = efx->n_channels;
- efx->n_rx_channels = efx->n_channels;
+ efx->n_tx_channels = n_channels;
+ efx->n_rx_channels = n_channels;
}
rc = efx_init_rx_cpu_rmap(efx, xentries);
if (rc) {
pci_disable_msix(efx->pci_dev);
return rc;
}
- for (i = 0; i < n_channels; i++)
+ for (i = 0; i < efx->n_channels; i++)
efx_get_channel(efx, i)->irq =
xentries[i].vector;
} else {
@@ -1280,9 +1332,68 @@ static int efx_probe_interrupts(struct efx_nic *efx)
efx->legacy_irq = efx->pci_dev->irq;
}
+ /* Assign extra channels if possible */
+ j = efx->n_channels;
+ for (i = 0; i < EFX_MAX_EXTRA_CHANNELS; i++) {
+ if (!efx->extra_channel_type[i])
+ continue;
+ if (efx->interrupt_mode != EFX_INT_MODE_MSIX ||
+ efx->n_channels <= extra_channels) {
+ efx->extra_channel_type[i]->handle_no_channel(efx);
+ } else {
+ --j;
+ efx_get_channel(efx, j)->type =
+ efx->extra_channel_type[i];
+ }
+ }
+
+ /* RSS might be usable on VFs even if it is disabled on the PF */
+ efx->rss_spread = (efx->n_rx_channels > 1 ?
+ efx->n_rx_channels : efx_vf_size(efx));
+
return 0;
}
+/* Enable interrupts, then probe and start the event queues */
+static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq)
+{
+ struct efx_channel *channel;
+
+ if (efx->legacy_irq)
+ efx->legacy_irq_enabled = true;
+ efx_nic_enable_interrupts(efx);
+
+ efx_for_each_channel(channel, efx) {
+ if (!channel->type->keep_eventq || !may_keep_eventq)
+ efx_init_eventq(channel);
+ efx_start_eventq(channel);
+ }
+
+ efx_mcdi_mode_event(efx);
+}
+
+static void efx_stop_interrupts(struct efx_nic *efx, bool may_keep_eventq)
+{
+ struct efx_channel *channel;
+
+ efx_mcdi_mode_poll(efx);
+
+ efx_nic_disable_interrupts(efx);
+ if (efx->legacy_irq) {
+ synchronize_irq(efx->legacy_irq);
+ efx->legacy_irq_enabled = false;
+ }
+
+ efx_for_each_channel(channel, efx) {
+ if (channel->irq)
+ synchronize_irq(channel->irq);
+
+ efx_stop_eventq(channel);
+ if (!channel->type->keep_eventq || !may_keep_eventq)
+ efx_fini_eventq(channel);
+ }
+}
+
static void efx_remove_interrupts(struct efx_nic *efx)
{
struct efx_channel *channel;
@@ -1333,11 +1444,13 @@ static int efx_probe_nic(struct efx_nic *efx)
if (rc)
goto fail;
+ efx->type->dimension_resources(efx);
+
if (efx->n_channels > 1)
get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key));
for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
efx->rx_indir_table[i] =
- ethtool_rxfh_indir_default(i, efx->n_rx_channels);
+ ethtool_rxfh_indir_default(i, efx->rss_spread);
efx_set_channels(efx);
netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
@@ -1385,21 +1498,22 @@ static int efx_probe_all(struct efx_nic *efx)
}
efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE;
- rc = efx_probe_channels(efx);
- if (rc)
- goto fail3;
rc = efx_probe_filters(efx);
if (rc) {
netif_err(efx, probe, efx->net_dev,
"failed to create filter tables\n");
- goto fail4;
+ goto fail3;
}
+ rc = efx_probe_channels(efx);
+ if (rc)
+ goto fail4;
+
return 0;
fail4:
- efx_remove_channels(efx);
+ efx_remove_filters(efx);
fail3:
efx_remove_port(efx);
fail2:
@@ -1408,15 +1522,13 @@ static int efx_probe_all(struct efx_nic *efx)
return rc;
}
-/* Called after previous invocation(s) of efx_stop_all, restarts the
- * port, kernel transmit queue, NAPI processing and hardware interrupts,
- * and ensures that the port is scheduled to be reconfigured.
- * This function is safe to call multiple times when the NIC is in any
- * state. */
+/* Called after previous invocation(s) of efx_stop_all, restarts the port,
+ * kernel transmit queues and NAPI processing, and ensures that the port is
+ * scheduled to be reconfigured. This function is safe to call multiple
+ * times when the NIC is in any state.
+ */
static void efx_start_all(struct efx_nic *efx)
{
- struct efx_channel *channel;
-
EFX_ASSERT_RESET_SERIALISED(efx);
/* Check that it is appropriate to restart the interface. All
@@ -1425,31 +1537,11 @@ static void efx_start_all(struct efx_nic *efx)
return;
if ((efx->state != STATE_RUNNING) && (efx->state != STATE_INIT))
return;
- if (efx_dev_registered(efx) && !netif_running(efx->net_dev))
+ if (!netif_running(efx->net_dev))
return;
- /* Mark the port as enabled so port reconfigurations can start, then
- * restart the transmit interface early so the watchdog timer stops */
efx_start_port(efx);
-
- if (efx_dev_registered(efx) && netif_device_present(efx->net_dev))
- netif_tx_wake_all_queues(efx->net_dev);
-
- efx_for_each_channel(channel, efx)
- efx_start_channel(channel);
-
- if (efx->legacy_irq)
- efx->legacy_irq_enabled = true;
- efx_nic_enable_interrupts(efx);
-
- /* Switch to event based MCDI completions after enabling interrupts.
- * If a reset has been scheduled, then we need to stay in polled mode.
- * Rather than serialising efx_mcdi_mode_event() [which sleeps] and
- * reset_pending [modified from an atomic context], we instead guarantee
- * that efx_mcdi_mode_poll() isn't reverted erroneously */
- efx_mcdi_mode_event(efx);
- if (efx->reset_pending)
- efx_mcdi_mode_poll(efx);
+ efx_start_datapath(efx);
/* Start the hardware monitor if there is one. Otherwise (we're link
* event driven), we have to poll the PHY because after an event queue
@@ -1485,8 +1577,6 @@ static void efx_flush_all(struct efx_nic *efx)
* taking locks. */
static void efx_stop_all(struct efx_nic *efx)
{
- struct efx_channel *channel;
-
EFX_ASSERT_RESET_SERIALISED(efx);
/* port_enabled can be read safely under the rtnl lock */
@@ -1494,28 +1584,6 @@ static void efx_stop_all(struct efx_nic *efx)
return;
efx->type->stop_stats(efx);
-
- /* Switch to MCDI polling on Siena before disabling interrupts */
- efx_mcdi_mode_poll(efx);
-
- /* Disable interrupts and wait for ISR to complete */
- efx_nic_disable_interrupts(efx);
- if (efx->legacy_irq) {
- synchronize_irq(efx->legacy_irq);
- efx->legacy_irq_enabled = false;
- }
- efx_for_each_channel(channel, efx) {
- if (channel->irq)
- synchronize_irq(channel->irq);
- }
-
- /* Stop all NAPI processing and synchronous rx refills */
- efx_for_each_channel(channel, efx)
- efx_stop_channel(channel);
-
- /* Stop all asynchronous port reconfigurations. Since all
- * event processing has already been stopped, there is no
- * window to loose phy events */
efx_stop_port(efx);
/* Flush efx_mac_work(), refill_workqueue, monitor_work */
@@ -1523,17 +1591,15 @@ static void efx_stop_all(struct efx_nic *efx)
/* Stop the kernel transmit interface late, so the watchdog
* timer isn't ticking over the flush */
- if (efx_dev_registered(efx)) {
- netif_tx_stop_all_queues(efx->net_dev);
- netif_tx_lock_bh(efx->net_dev);
- netif_tx_unlock_bh(efx->net_dev);
- }
+ netif_tx_disable(efx->net_dev);
+
+ efx_stop_datapath(efx);
}
static void efx_remove_all(struct efx_nic *efx)
{
- efx_remove_filters(efx);
efx_remove_channels(efx);
+ efx_remove_filters(efx);
efx_remove_port(efx);
efx_remove_nic(efx);
}
@@ -1544,13 +1610,13 @@ static void efx_remove_all(struct efx_nic *efx)
*
**************************************************************************/
-static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int resolution)
+static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int quantum_ns)
{
if (usecs == 0)
return 0;
- if (usecs < resolution)
+ if (usecs * 1000 < quantum_ns)
return 1; /* never round down to 0 */
- return usecs / resolution;
+ return usecs * 1000 / quantum_ns;
}
/* Set interrupt moderation parameters */
@@ -1559,14 +1625,20 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
bool rx_may_override_tx)
{
struct efx_channel *channel;
- unsigned tx_ticks = irq_mod_ticks(tx_usecs, EFX_IRQ_MOD_RESOLUTION);
- unsigned rx_ticks = irq_mod_ticks(rx_usecs, EFX_IRQ_MOD_RESOLUTION);
+ unsigned int irq_mod_max = DIV_ROUND_UP(efx->type->timer_period_max *
+ efx->timer_quantum_ns,
+ 1000);
+ unsigned int tx_ticks;
+ unsigned int rx_ticks;
EFX_ASSERT_RESET_SERIALISED(efx);
- if (tx_ticks > EFX_IRQ_MOD_MAX || rx_ticks > EFX_IRQ_MOD_MAX)
+ if (tx_usecs > irq_mod_max || rx_usecs > irq_mod_max)
return -EINVAL;
+ tx_ticks = irq_mod_ticks(tx_usecs, efx->timer_quantum_ns);
+ rx_ticks = irq_mod_ticks(rx_usecs, efx->timer_quantum_ns);
+
if (tx_ticks != rx_ticks && efx->tx_channel_offset == 0 &&
!rx_may_override_tx) {
netif_err(efx, drv, efx->net_dev, "Channels are shared. "
@@ -1589,8 +1661,14 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
unsigned int *rx_usecs, bool *rx_adaptive)
{
+ /* We must round up when converting ticks to microseconds
+ * because we round down when converting the other way.
+ */
+
*rx_adaptive = efx->irq_rx_adaptive;
- *rx_usecs = efx->irq_rx_moderation * EFX_IRQ_MOD_RESOLUTION;
+ *rx_usecs = DIV_ROUND_UP(efx->irq_rx_moderation *
+ efx->timer_quantum_ns,
+ 1000);
/* If channels are shared between RX and TX, so is IRQ
* moderation. Otherwise, IRQ moderation is the same for all
@@ -1599,9 +1677,10 @@ void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
if (efx->tx_channel_offset == 0)
*tx_usecs = *rx_usecs;
else
- *tx_usecs =
+ *tx_usecs = DIV_ROUND_UP(
efx->channel[efx->tx_channel_offset]->irq_moderation *
- EFX_IRQ_MOD_RESOLUTION;
+ efx->timer_quantum_ns,
+ 1000);
}
/**************************************************************************
@@ -1664,15 +1743,21 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
*
**************************************************************************/
+static void efx_init_napi_channel(struct efx_channel *channel)
+{
+ struct efx_nic *efx = channel->efx;
+
+ channel->napi_dev = efx->net_dev;
+ netif_napi_add(channel->napi_dev, &channel->napi_str,
+ efx_poll, napi_weight);
+}
+
static void efx_init_napi(struct efx_nic *efx)
{
struct efx_channel *channel;
- efx_for_each_channel(channel, efx) {
- channel->napi_dev = efx->net_dev;
- netif_napi_add(channel->napi_dev, &channel->napi_str,
- efx_poll, napi_weight);
- }
+ efx_for_each_channel(channel, efx)
+ efx_init_napi_channel(channel);
}
static void efx_fini_napi_channel(struct efx_channel *channel)
@@ -1757,22 +1842,21 @@ static int efx_net_stop(struct net_device *net_dev)
if (efx->state != STATE_DISABLED) {
/* Stop the device and flush all the channels */
efx_stop_all(efx);
- efx_fini_channels(efx);
- efx_init_channels(efx);
}
return 0;
}
/* Context: process, dev_base_lock or RTNL held, non-blocking. */
-static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, struct rtnl_link_stats64 *stats)
+static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev,
+ struct rtnl_link_stats64 *stats)
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_mac_stats *mac_stats = &efx->mac_stats;
spin_lock_bh(&efx->stats_lock);
+
efx->type->update_stats(efx);
- spin_unlock_bh(&efx->stats_lock);
stats->rx_packets = mac_stats->rx_packets;
stats->tx_packets = mac_stats->tx_packets;
@@ -1796,6 +1880,8 @@ static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev, struc
stats->tx_errors = (stats->tx_window_errors +
mac_stats->tx_bad);
+ spin_unlock_bh(&efx->stats_lock);
+
return stats;
}
@@ -1816,7 +1902,6 @@ static void efx_watchdog(struct net_device *net_dev)
static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
{
struct efx_nic *efx = netdev_priv(net_dev);
- int rc = 0;
EFX_ASSERT_RESET_SERIALISED(efx);
@@ -1827,19 +1912,15 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
- efx_fini_channels(efx);
-
mutex_lock(&efx->mac_lock);
/* Reconfigure the MAC before enabling the dma queues so that
* the RX buffers don't overflow */
net_dev->mtu = new_mtu;
- efx->mac_op->reconfigure(efx);
+ efx->type->reconfigure_mac(efx);
mutex_unlock(&efx->mac_lock);
- efx_init_channels(efx);
-
efx_start_all(efx);
- return rc;
+ return 0;
}
static int efx_set_mac_address(struct net_device *net_dev, void *data)
@@ -1854,21 +1935,22 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
netif_err(efx, drv, efx->net_dev,
"invalid ethernet MAC address requested: %pM\n",
new_addr);
- return -EINVAL;
+ return -EADDRNOTAVAIL;
}
memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len);
+ efx_sriov_mac_address_changed(efx);
/* Reconfigure the MAC */
mutex_lock(&efx->mac_lock);
- efx->mac_op->reconfigure(efx);
+ efx->type->reconfigure_mac(efx);
mutex_unlock(&efx->mac_lock);
return 0;
}
/* Context: netif_addr_lock held, BHs disabled. */
-static void efx_set_multicast_list(struct net_device *net_dev)
+static void efx_set_rx_mode(struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
struct netdev_hw_addr *ha;
@@ -1922,8 +2004,14 @@ static const struct net_device_ops efx_netdev_ops = {
.ndo_do_ioctl = efx_ioctl,
.ndo_change_mtu = efx_change_mtu,
.ndo_set_mac_address = efx_set_mac_address,
- .ndo_set_rx_mode = efx_set_multicast_list,
+ .ndo_set_rx_mode = efx_set_rx_mode,
.ndo_set_features = efx_set_features,
+#ifdef CONFIG_SFC_SRIOV
+ .ndo_set_vf_mac = efx_sriov_set_vf_mac,
+ .ndo_set_vf_vlan = efx_sriov_set_vf_vlan,
+ .ndo_set_vf_spoofchk = efx_sriov_set_vf_spoofchk,
+ .ndo_get_vf_config = efx_sriov_get_vf_config,
+#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = efx_netpoll,
#endif
@@ -1975,10 +2063,6 @@ static int efx_register_netdev(struct efx_nic *efx)
net_dev->netdev_ops = &efx_netdev_ops;
SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
- /* Clear MAC statistics */
- efx->mac_op->update_stats(efx);
- memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
-
rtnl_lock();
rc = dev_alloc_name(net_dev, net_dev->name);
@@ -1997,7 +2081,7 @@ static int efx_register_netdev(struct efx_nic *efx)
}
/* Always start with carrier off; PHY events will detect the link */
- netif_carrier_off(efx->net_dev);
+ netif_carrier_off(net_dev);
rtnl_unlock();
@@ -2038,11 +2122,9 @@ static void efx_unregister_netdev(struct efx_nic *efx)
efx_release_tx_buffers(tx_queue);
}
- if (efx_dev_registered(efx)) {
- strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
- device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
- unregister_netdev(efx->net_dev);
- }
+ strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
+ device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
+ unregister_netdev(efx->net_dev);
}
/**************************************************************************
@@ -2060,7 +2142,7 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method)
efx_stop_all(efx);
mutex_lock(&efx->mac_lock);
- efx_fini_channels(efx);
+ efx_stop_interrupts(efx, false);
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
efx->phy_op->fini(efx);
efx->type->fini(efx);
@@ -2095,10 +2177,11 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
"could not restore PHY settings\n");
}
- efx->mac_op->reconfigure(efx);
+ efx->type->reconfigure_mac(efx);
- efx_init_channels(efx);
+ efx_start_interrupts(efx, false);
efx_restore_filters(efx);
+ efx_sriov_reset(efx);
mutex_unlock(&efx->mac_lock);
@@ -2300,10 +2383,10 @@ static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type,
efx->net_dev = net_dev;
spin_lock_init(&efx->stats_lock);
mutex_init(&efx->mac_lock);
- efx->mac_op = type->default_mac_ops;
efx->phy_op = &efx_dummy_phy_operations;
efx->mdio.dev = net_dev;
INIT_WORK(&efx->mac_work, efx_mac_work);
+ init_waitqueue_head(&efx->flush_wq);
for (i = 0; i < EFX_MAX_CHANNELS; i++) {
efx->channel[i] = efx_alloc_channel(efx, i, NULL);
@@ -2361,8 +2444,8 @@ static void efx_pci_remove_main(struct efx_nic *efx)
free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap);
efx->net_dev->rx_cpu_rmap = NULL;
#endif
+ efx_stop_interrupts(efx, false);
efx_nic_fini_interrupt(efx);
- efx_fini_channels(efx);
efx_fini_port(efx);
efx->type->fini(efx);
efx_fini_napi(efx);
@@ -2388,6 +2471,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
/* Allow any queued efx_resets() to complete */
rtnl_unlock();
+ efx_stop_interrupts(efx, false);
+ efx_sriov_fini(efx);
efx_unregister_netdev(efx);
efx_mtd_remove(efx);
@@ -2436,16 +2521,14 @@ static int efx_pci_probe_main(struct efx_nic *efx)
goto fail4;
}
- efx_init_channels(efx);
-
rc = efx_nic_init_interrupt(efx);
if (rc)
goto fail5;
+ efx_start_interrupts(efx, false);
return 0;
fail5:
- efx_fini_channels(efx);
efx_fini_port(efx);
fail4:
efx->type->fini(efx);
@@ -2459,7 +2542,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)
/* NIC initialisation
*
* This is called at module load (or hotplug insertion,
- * theoretically). It sets up PCI mappings, tests and resets the NIC,
+ * theoretically). It sets up PCI mappings, resets the NIC,
* sets up and registers the network devices with the kernel and hooks
* the interrupt service routine. It does not prepare the device for
* transmission; this is left to the first time one of the network
@@ -2471,7 +2554,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
const struct efx_nic_type *type = (const struct efx_nic_type *) entry->driver_data;
struct net_device *net_dev;
struct efx_nic *efx;
- int i, rc;
+ int rc;
/* Allocate and initialise a struct net_device and struct efx_nic */
net_dev = alloc_etherdev_mqs(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES,
@@ -2504,39 +2587,22 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
if (rc)
goto fail2;
- /* No serialisation is required with the reset path because
- * we're in STATE_INIT. */
- for (i = 0; i < 5; i++) {
- rc = efx_pci_probe_main(efx);
-
- /* Serialise against efx_reset(). No more resets will be
- * scheduled since efx_stop_all() has been called, and we
- * have not and never have been registered with either
- * the rtnetlink or driverlink layers. */
- cancel_work_sync(&efx->reset_work);
+ rc = efx_pci_probe_main(efx);
- if (rc == 0) {
- if (efx->reset_pending) {
- /* If there was a scheduled reset during
- * probe, the NIC is probably hosed anyway */
- efx_pci_remove_main(efx);
- rc = -EIO;
- } else {
- break;
- }
- }
-
- /* Retry if a recoverably reset event has been scheduled */
- if (efx->reset_pending &
- ~(1 << RESET_TYPE_INVISIBLE | 1 << RESET_TYPE_ALL) ||
- !efx->reset_pending)
- goto fail3;
+ /* Serialise against efx_reset(). No more resets will be
+ * scheduled since efx_stop_all() has been called, and we have
+ * not and never have been registered.
+ */
+ cancel_work_sync(&efx->reset_work);
- efx->reset_pending = 0;
- }
+ if (rc)
+ goto fail3;
- if (rc) {
- netif_err(efx, probe, efx->net_dev, "Could not reset NIC\n");
+ /* If there was a scheduled reset during probe, the NIC is
+ * probably hosed anyway.
+ */
+ if (efx->reset_pending) {
+ rc = -EIO;
goto fail4;
}
@@ -2546,18 +2612,27 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
rc = efx_register_netdev(efx);
if (rc)
- goto fail5;
+ goto fail4;
+
+ rc = efx_sriov_init(efx);
+ if (rc)
+ netif_err(efx, probe, efx->net_dev,
+ "SR-IOV can't be enabled rc %d\n", rc);
netif_dbg(efx, probe, efx->net_dev, "initialisation successful\n");
+ /* Try to create MTDs, but allow this to fail */
rtnl_lock();
- efx_mtd_probe(efx); /* allowed to fail */
+ rc = efx_mtd_probe(efx);
rtnl_unlock();
+ if (rc)
+ netif_warn(efx, probe, efx->net_dev,
+ "failed to create MTDs (%d)\n", rc);
+
return 0;
- fail5:
- efx_pci_remove_main(efx);
fail4:
+ efx_pci_remove_main(efx);
fail3:
efx_fini_io(efx);
fail2:
@@ -2578,7 +2653,7 @@ static int efx_pm_freeze(struct device *dev)
netif_device_detach(efx->net_dev);
efx_stop_all(efx);
- efx_fini_channels(efx);
+ efx_stop_interrupts(efx, false);
return 0;
}
@@ -2589,7 +2664,7 @@ static int efx_pm_thaw(struct device *dev)
efx->state = STATE_INIT;
- efx_init_channels(efx);
+ efx_start_interrupts(efx, false);
mutex_lock(&efx->mac_lock);
efx->phy_op->reconfigure(efx);
@@ -2658,7 +2733,7 @@ static int efx_pm_suspend(struct device *dev)
return rc;
}
-static struct dev_pm_ops efx_pm_ops = {
+static const struct dev_pm_ops efx_pm_ops = {
.suspend = efx_pm_suspend,
.resume = efx_pm_resume,
.freeze = efx_pm_freeze,
@@ -2695,6 +2770,10 @@ static int __init efx_init_module(void)
if (rc)
goto err_notifier;
+ rc = efx_init_sriov();
+ if (rc)
+ goto err_sriov;
+
reset_workqueue = create_singlethread_workqueue("sfc_reset");
if (!reset_workqueue) {
rc = -ENOMEM;
@@ -2710,6 +2789,8 @@ static int __init efx_init_module(void)
err_pci:
destroy_workqueue(reset_workqueue);
err_reset:
+ efx_fini_sriov();
+ err_sriov:
unregister_netdevice_notifier(&efx_netdev_notifier);
err_notifier:
return rc;
@@ -2721,6 +2802,7 @@ static void __exit efx_exit_module(void)
pci_unregister_driver(&efx_pci_driver);
destroy_workqueue(reset_workqueue);
+ efx_fini_sriov();
unregister_netdevice_notifier(&efx_netdev_notifier);
}
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index a3541ac6ea01..4debfe07fb88 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -40,9 +40,9 @@ extern void efx_rx_strategy(struct efx_channel *channel);
extern void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
extern void efx_rx_slow_fill(unsigned long context);
extern void __efx_rx_packet(struct efx_channel *channel,
- struct efx_rx_buffer *rx_buf, bool checksummed);
+ struct efx_rx_buffer *rx_buf);
extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
- unsigned int len, bool checksummed, bool discard);
+ unsigned int len, u16 flags);
extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
#define EFX_MAX_DMAQ_SIZE 4096UL
@@ -95,6 +95,7 @@ static inline void efx_filter_rfs_expire(struct efx_channel *channel) {}
#endif
/* Channels */
+extern int efx_channel_dummy_op_int(struct efx_channel *channel);
extern void efx_process_channel_now(struct efx_channel *channel);
extern int
efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries);
@@ -145,6 +146,12 @@ static inline void efx_schedule_channel(struct efx_channel *channel)
napi_schedule(&channel->napi_str);
}
+static inline void efx_schedule_channel_irq(struct efx_channel *channel)
+{
+ channel->last_irq_cpu = raw_smp_processor_id();
+ efx_schedule_channel(channel);
+}
+
extern void efx_link_status_changed(struct efx_nic *efx);
extern void efx_link_set_advertising(struct efx_nic *efx, u32);
extern void efx_link_set_wanted_fc(struct efx_nic *efx, u8);
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index 29b2ebfef19f..f22f45f515a8 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -52,11 +52,6 @@ static u64 efx_get_uint_stat(void *field)
return *(unsigned int *)field;
}
-static u64 efx_get_ulong_stat(void *field)
-{
- return *(unsigned long *)field;
-}
-
static u64 efx_get_u64_stat(void *field)
{
return *(u64 *) field;
@@ -67,12 +62,8 @@ static u64 efx_get_atomic_stat(void *field)
return atomic_read((atomic_t *) field);
}
-#define EFX_ETHTOOL_ULONG_MAC_STAT(field) \
- EFX_ETHTOOL_STAT(field, mac_stats, field, \
- unsigned long, efx_get_ulong_stat)
-
#define EFX_ETHTOOL_U64_MAC_STAT(field) \
- EFX_ETHTOOL_STAT(field, mac_stats, field, \
+ EFX_ETHTOOL_STAT(field, mac_stats, field, \
u64, efx_get_u64_stat)
#define EFX_ETHTOOL_UINT_NIC_STAT(name) \
@@ -91,36 +82,36 @@ static u64 efx_get_atomic_stat(void *field)
EFX_ETHTOOL_STAT(tx_##field, tx_queue, field, \
unsigned int, efx_get_uint_stat)
-static struct efx_ethtool_stat efx_ethtool_stats[] = {
+static const struct efx_ethtool_stat efx_ethtool_stats[] = {
EFX_ETHTOOL_U64_MAC_STAT(tx_bytes),
EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes),
EFX_ETHTOOL_U64_MAC_STAT(tx_bad_bytes),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_packets),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_bad),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_pause),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_control),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_unicast),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_multicast),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_broadcast),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_lt64),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_64),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_65_to_127),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_128_to_255),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_256_to_511),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_512_to_1023),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_1024_to_15xx),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_15xx_to_jumbo),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_gtjumbo),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_collision),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_single_collision),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_multiple_collision),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_collision),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_deferred),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_late_collision),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_deferred),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_non_tcpudp),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_mac_src_error),
- EFX_ETHTOOL_ULONG_MAC_STAT(tx_ip_src_error),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_packets),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_bad),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_pause),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_control),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_unicast),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_multicast),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_broadcast),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_lt64),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_64),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_65_to_127),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_128_to_255),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_256_to_511),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_512_to_1023),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_1024_to_15xx),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_15xx_to_jumbo),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_gtjumbo),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_collision),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_single_collision),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_multiple_collision),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_excessive_collision),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_deferred),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_late_collision),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_excessive_deferred),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_non_tcpudp),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_mac_src_error),
+ EFX_ETHTOOL_U64_MAC_STAT(tx_ip_src_error),
EFX_ETHTOOL_UINT_TXQ_STAT(tso_bursts),
EFX_ETHTOOL_UINT_TXQ_STAT(tso_long_headers),
EFX_ETHTOOL_UINT_TXQ_STAT(tso_packets),
@@ -128,34 +119,34 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = {
EFX_ETHTOOL_U64_MAC_STAT(rx_bytes),
EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes),
EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_packets),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_good),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_pause),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_control),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_unicast),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_multicast),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_broadcast),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_lt64),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_64),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_65_to_127),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_128_to_255),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_256_to_511),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_512_to_1023),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_1024_to_15xx),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_15xx_to_jumbo),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_gtjumbo),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_lt64),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_64_to_15xx),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_15xx_to_jumbo),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_gtjumbo),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_overflow),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_missed),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_false_carrier),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_symbol_error),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_align_error),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_length_error),
- EFX_ETHTOOL_ULONG_MAC_STAT(rx_internal_error),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_packets),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_good),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_bad),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_pause),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_control),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_unicast),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_multicast),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_broadcast),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_lt64),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_64),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_65_to_127),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_128_to_255),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_256_to_511),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_512_to_1023),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_1024_to_15xx),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_15xx_to_jumbo),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_gtjumbo),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_bad_lt64),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_bad_64_to_15xx),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_bad_15xx_to_jumbo),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_bad_gtjumbo),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_overflow),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_missed),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_false_carrier),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_symbol_error),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_align_error),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_length_error),
+ EFX_ETHTOOL_U64_MAC_STAT(rx_internal_error),
EFX_ETHTOOL_UINT_NIC_STAT(rx_nodesc_drop_cnt),
EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc),
@@ -404,10 +395,6 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
&tests->eventq_int[channel->channel],
EFX_CHANNEL_NAME(channel),
"eventq.int", NULL);
- efx_fill_test(n++, strings, data,
- &tests->eventq_poll[channel->channel],
- EFX_CHANNEL_NAME(channel),
- "eventq.poll", NULL);
}
efx_fill_test(n++, strings, data, &tests->registers,
@@ -486,16 +473,17 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_mac_stats *mac_stats = &efx->mac_stats;
- struct efx_ethtool_stat *stat;
+ const struct efx_ethtool_stat *stat;
struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
- struct rtnl_link_stats64 temp;
int i;
EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS);
+ spin_lock_bh(&efx->stats_lock);
+
/* Update MAC and NIC statistics */
- dev_get_stats(net_dev, &temp);
+ efx->type->update_stats(efx);
/* Fill detailed statistics buffer */
for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) {
@@ -525,6 +513,8 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
break;
}
}
+
+ spin_unlock_bh(&efx->stats_lock);
}
static void efx_ethtool_self_test(struct net_device *net_dev,
@@ -747,7 +737,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
/* Recover by resetting the EM block */
falcon_stop_nic_stats(efx);
falcon_drain_tx_fifo(efx);
- efx->mac_op->reconfigure(efx);
+ falcon_reconfigure_xmac(efx);
falcon_start_nic_stats(efx);
} else {
/* Schedule a reset to recover */
@@ -772,7 +762,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
/* Reconfigure the MAC. The PHY *may* generate a link state change event
* if the user just changed the advertised capabilities, but there's no
* harm doing this twice */
- efx->mac_op->reconfigure(efx);
+ efx->type->reconfigure_mac(efx);
out:
mutex_unlock(&efx->mac_lock);
@@ -818,11 +808,16 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
return efx_reset(efx, rc);
}
+/* MAC address mask including only MC flag */
+static const u8 mac_addr_mc_mask[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
+
static int efx_ethtool_get_class_rule(struct efx_nic *efx,
struct ethtool_rx_flow_spec *rule)
{
struct ethtool_tcpip4_spec *ip_entry = &rule->h_u.tcp_ip4_spec;
struct ethtool_tcpip4_spec *ip_mask = &rule->m_u.tcp_ip4_spec;
+ struct ethhdr *mac_entry = &rule->h_u.ether_spec;
+ struct ethhdr *mac_mask = &rule->m_u.ether_spec;
struct efx_filter_spec spec;
u16 vid;
u8 proto;
@@ -838,11 +833,18 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx,
else
rule->ring_cookie = spec.dmaq_id;
- rc = efx_filter_get_eth_local(&spec, &vid,
- rule->h_u.ether_spec.h_dest);
+ if (spec.type == EFX_FILTER_MC_DEF || spec.type == EFX_FILTER_UC_DEF) {
+ rule->flow_type = ETHER_FLOW;
+ memcpy(mac_mask->h_dest, mac_addr_mc_mask, ETH_ALEN);
+ if (spec.type == EFX_FILTER_MC_DEF)
+ memcpy(mac_entry->h_dest, mac_addr_mc_mask, ETH_ALEN);
+ return 0;
+ }
+
+ rc = efx_filter_get_eth_local(&spec, &vid, mac_entry->h_dest);
if (rc == 0) {
rule->flow_type = ETHER_FLOW;
- memset(rule->m_u.ether_spec.h_dest, ~0, ETH_ALEN);
+ memset(mac_mask->h_dest, ~0, ETH_ALEN);
if (vid != EFX_FILTER_VID_UNSPEC) {
rule->flow_type |= FLOW_EXT;
rule->h_ext.vlan_tci = htons(vid);
@@ -1011,27 +1013,40 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
}
case ETHER_FLOW | FLOW_EXT:
- /* Must match all or none of VID */
- if (rule->m_ext.vlan_tci != htons(0xfff) &&
- rule->m_ext.vlan_tci != 0)
- return -EINVAL;
- case ETHER_FLOW:
- /* Must match all of destination */
- if (!is_broadcast_ether_addr(mac_mask->h_dest))
- return -EINVAL;
- /* and nothing else */
+ case ETHER_FLOW: {
+ u16 vlan_tag_mask = (rule->flow_type & FLOW_EXT ?
+ ntohs(rule->m_ext.vlan_tci) : 0);
+
+ /* Must not match on source address or Ethertype */
if (!is_zero_ether_addr(mac_mask->h_source) ||
mac_mask->h_proto)
return -EINVAL;
- rc = efx_filter_set_eth_local(
- &spec,
- (rule->flow_type & FLOW_EXT && rule->m_ext.vlan_tci) ?
- ntohs(rule->h_ext.vlan_tci) : EFX_FILTER_VID_UNSPEC,
- mac_entry->h_dest);
+ /* Is it a default UC or MC filter? */
+ if (!compare_ether_addr(mac_mask->h_dest, mac_addr_mc_mask) &&
+ vlan_tag_mask == 0) {
+ if (is_multicast_ether_addr(mac_entry->h_dest))
+ rc = efx_filter_set_mc_def(&spec);
+ else
+ rc = efx_filter_set_uc_def(&spec);
+ }
+ /* Otherwise, it must match all of destination and all
+ * or none of VID.
+ */
+ else if (is_broadcast_ether_addr(mac_mask->h_dest) &&
+ (vlan_tag_mask == 0xfff || vlan_tag_mask == 0)) {
+ rc = efx_filter_set_eth_local(
+ &spec,
+ vlan_tag_mask ?
+ ntohs(rule->h_ext.vlan_tci) : EFX_FILTER_VID_UNSPEC,
+ mac_entry->h_dest);
+ } else {
+ rc = -EINVAL;
+ }
if (rc)
return rc;
break;
+ }
default:
return -EINVAL;
@@ -1070,7 +1085,8 @@ static u32 efx_ethtool_get_rxfh_indir_size(struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
- return (efx_nic_rev(efx) < EFX_REV_FALCON_B0 ?
+ return ((efx_nic_rev(efx) < EFX_REV_FALCON_B0 ||
+ efx->n_rx_channels == 1) ?
0 : ARRAY_SIZE(efx->rx_indir_table));
}
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 8ae1ebd35397..3a1ca2bd1548 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -19,7 +19,6 @@
#include "net_driver.h"
#include "bitfield.h"
#include "efx.h"
-#include "mac.h"
#include "spi.h"
#include "nic.h"
#include "regs.h"
@@ -89,7 +88,7 @@ static int falcon_getscl(void *data)
return EFX_OWORD_FIELD(reg, FRF_AB_GPIO0_IN);
}
-static struct i2c_algo_bit_data falcon_i2c_bit_operations = {
+static const struct i2c_algo_bit_data falcon_i2c_bit_operations = {
.setsda = falcon_setsda,
.setscl = falcon_setscl,
.getsda = falcon_getsda,
@@ -104,8 +103,6 @@ static void falcon_push_irq_moderation(struct efx_channel *channel)
efx_dword_t timer_cmd;
struct efx_nic *efx = channel->efx;
- BUILD_BUG_ON(EFX_IRQ_MOD_MAX > (1 << FRF_AB_TC_TIMER_VAL_WIDTH));
-
/* Set timer register */
if (channel->irq_moderation) {
EFX_POPULATE_DWORD_2(timer_cmd,
@@ -177,27 +174,24 @@ irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
"IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
+ /* Check to see if we have a serious error condition */
+ syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
+ if (unlikely(syserr))
+ return efx_nic_fatal_interrupt(efx);
+
/* Determine interrupting queues, clear interrupt status
* register and acknowledge the device interrupt.
*/
BUILD_BUG_ON(FSF_AZ_NET_IVEC_INT_Q_WIDTH > EFX_MAX_CHANNELS);
queues = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_INT_Q);
-
- /* Check to see if we have a serious error condition */
- if (queues & (1U << efx->fatal_irq_level)) {
- syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
- if (unlikely(syserr))
- return efx_nic_fatal_interrupt(efx);
- }
-
EFX_ZERO_OWORD(*int_ker);
wmb(); /* Ensure the vector is cleared before interrupt ack */
falcon_irq_ack_a1(efx);
if (queues & 1)
- efx_schedule_channel(efx_get_channel(efx, 0));
+ efx_schedule_channel_irq(efx_get_channel(efx, 0));
if (queues & 2)
- efx_schedule_channel(efx_get_channel(efx, 1));
+ efx_schedule_channel_irq(efx_get_channel(efx, 1));
return IRQ_HANDLED;
}
/**************************************************************************
@@ -613,7 +607,7 @@ static void falcon_stats_complete(struct efx_nic *efx)
nic_data->stats_pending = false;
if (*nic_data->stats_dma_done == FALCON_STATS_DONE) {
rmb(); /* read the done flag before the stats */
- efx->mac_op->update_stats(efx);
+ falcon_update_stats_xmac(efx);
} else {
netif_err(efx, hw, efx->net_dev,
"timed out waiting for statistics\n");
@@ -670,7 +664,7 @@ static int falcon_reconfigure_port(struct efx_nic *efx)
falcon_reset_macs(efx);
efx->phy_op->reconfigure(efx);
- rc = efx->mac_op->reconfigure(efx);
+ rc = falcon_reconfigure_xmac(efx);
BUG_ON(rc);
falcon_start_nic_stats(efx);
@@ -1218,7 +1212,7 @@ static void falcon_monitor(struct efx_nic *efx)
falcon_deconfigure_mac_wrapper(efx);
falcon_reset_macs(efx);
- rc = efx->mac_op->reconfigure(efx);
+ rc = falcon_reconfigure_xmac(efx);
BUG_ON(rc);
falcon_start_nic_stats(efx);
@@ -1339,6 +1333,12 @@ out:
return rc;
}
+static void falcon_dimension_resources(struct efx_nic *efx)
+{
+ efx->rx_dc_base = 0x20000;
+ efx->tx_dc_base = 0x26000;
+}
+
/* Probe all SPI devices on the NIC */
static void falcon_probe_spi_devices(struct efx_nic *efx)
{
@@ -1472,6 +1472,8 @@ static int falcon_probe_nic(struct efx_nic *efx)
goto fail5;
}
+ efx->timer_quantum_ns = 4968; /* 621 cycles */
+
/* Initialise I2C adapter */
board = falcon_board(efx);
board->i2c_adap.owner = THIS_MODULE;
@@ -1676,7 +1678,7 @@ static void falcon_update_nic_stats(struct efx_nic *efx)
*nic_data->stats_dma_done == FALCON_STATS_DONE) {
nic_data->stats_pending = false;
rmb(); /* read the done flag before the stats */
- efx->mac_op->update_stats(efx);
+ falcon_update_stats_xmac(efx);
}
}
@@ -1753,6 +1755,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
.probe = falcon_probe_nic,
.remove = falcon_remove_nic,
.init = falcon_init_nic,
+ .dimension_resources = falcon_dimension_resources,
.fini = efx_port_dummy_op_void,
.monitor = falcon_monitor,
.map_reset_reason = falcon_map_reset_reason,
@@ -1767,13 +1770,13 @@ const struct efx_nic_type falcon_a1_nic_type = {
.stop_stats = falcon_stop_nic_stats,
.set_id_led = falcon_set_id_led,
.push_irq_moderation = falcon_push_irq_moderation,
- .push_multicast_hash = falcon_push_multicast_hash,
.reconfigure_port = falcon_reconfigure_port,
+ .reconfigure_mac = falcon_reconfigure_xmac,
+ .check_mac_fault = falcon_xmac_check_fault,
.get_wol = falcon_get_wol,
.set_wol = falcon_set_wol,
.resume_wol = efx_port_dummy_op_void,
.test_nvram = falcon_test_nvram,
- .default_mac_ops = &falcon_xmac_operations,
.revision = EFX_REV_FALCON_A1,
.mem_map_size = 0x20000,
@@ -1786,8 +1789,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
.rx_buffer_padding = 0x24,
.max_interrupt_mode = EFX_INT_MODE_MSI,
.phys_addr_channels = 4,
- .tx_dc_base = 0x130000,
- .rx_dc_base = 0x100000,
+ .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH,
.offload_features = NETIF_F_IP_CSUM,
};
@@ -1795,6 +1797,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
.probe = falcon_probe_nic,
.remove = falcon_remove_nic,
.init = falcon_init_nic,
+ .dimension_resources = falcon_dimension_resources,
.fini = efx_port_dummy_op_void,
.monitor = falcon_monitor,
.map_reset_reason = falcon_map_reset_reason,
@@ -1809,14 +1812,14 @@ const struct efx_nic_type falcon_b0_nic_type = {
.stop_stats = falcon_stop_nic_stats,
.set_id_led = falcon_set_id_led,
.push_irq_moderation = falcon_push_irq_moderation,
- .push_multicast_hash = falcon_push_multicast_hash,
.reconfigure_port = falcon_reconfigure_port,
+ .reconfigure_mac = falcon_reconfigure_xmac,
+ .check_mac_fault = falcon_xmac_check_fault,
.get_wol = falcon_get_wol,
.set_wol = falcon_set_wol,
.resume_wol = efx_port_dummy_op_void,
.test_registers = falcon_b0_test_registers,
.test_nvram = falcon_test_nvram,
- .default_mac_ops = &falcon_xmac_operations,
.revision = EFX_REV_FALCON_B0,
/* Map everything up to and including the RSS indirection
@@ -1837,8 +1840,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
.phys_addr_channels = 32, /* Hardware limit is 64, but the legacy
* interrupt handler only supports 32
* channels */
- .tx_dc_base = 0x130000,
- .rx_dc_base = 0x100000,
+ .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH,
.offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE,
};
diff --git a/drivers/net/ethernet/sfc/falcon_boards.c b/drivers/net/ethernet/sfc/falcon_boards.c
index 6cc16b8cc6f4..2084cc6ede52 100644
--- a/drivers/net/ethernet/sfc/falcon_boards.c
+++ b/drivers/net/ethernet/sfc/falcon_boards.c
@@ -87,7 +87,7 @@ static const u8 falcon_lm87_common_regs[] = {
0
};
-static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
+static int efx_init_lm87(struct efx_nic *efx, const struct i2c_board_info *info,
const u8 *reg_values)
{
struct falcon_board *board = falcon_board(efx);
@@ -179,7 +179,7 @@ static int efx_check_lm87(struct efx_nic *efx, unsigned mask)
#else /* !CONFIG_SENSORS_LM87 */
static inline int
-efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
+efx_init_lm87(struct efx_nic *efx, const struct i2c_board_info *info,
const u8 *reg_values)
{
return 0;
@@ -442,7 +442,7 @@ static int sfe4001_check_hw(struct efx_nic *efx)
return (status < 0) ? -EIO : -ERANGE;
}
-static struct i2c_board_info sfe4001_hwmon_info = {
+static const struct i2c_board_info sfe4001_hwmon_info = {
I2C_BOARD_INFO("max6647", 0x4e),
};
@@ -522,7 +522,7 @@ static const u8 sfe4002_lm87_regs[] = {
0
};
-static struct i2c_board_info sfe4002_hwmon_info = {
+static const struct i2c_board_info sfe4002_hwmon_info = {
I2C_BOARD_INFO("lm87", 0x2e),
.platform_data = &sfe4002_lm87_channel,
};
@@ -591,7 +591,7 @@ static const u8 sfn4112f_lm87_regs[] = {
0
};
-static struct i2c_board_info sfn4112f_hwmon_info = {
+static const struct i2c_board_info sfn4112f_hwmon_info = {
I2C_BOARD_INFO("lm87", 0x2e),
.platform_data = &sfn4112f_lm87_channel,
};
@@ -653,7 +653,7 @@ static const u8 sfe4003_lm87_regs[] = {
0
};
-static struct i2c_board_info sfe4003_hwmon_info = {
+static const struct i2c_board_info sfe4003_hwmon_info = {
I2C_BOARD_INFO("lm87", 0x2e),
.platform_data = &sfe4003_lm87_channel,
};
diff --git a/drivers/net/ethernet/sfc/falcon_xmac.c b/drivers/net/ethernet/sfc/falcon_xmac.c
index 9516452c079c..6106ef15dee3 100644
--- a/drivers/net/ethernet/sfc/falcon_xmac.c
+++ b/drivers/net/ethernet/sfc/falcon_xmac.c
@@ -14,7 +14,6 @@
#include "nic.h"
#include "regs.h"
#include "io.h"
-#include "mac.h"
#include "mdio_10g.h"
#include "workarounds.h"
@@ -139,7 +138,7 @@ static bool falcon_xmac_link_ok(struct efx_nic *efx)
return (efx->loopback_mode == LOOPBACK_XGMII ||
falcon_xgxs_link_ok(efx)) &&
(!(efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) ||
- LOOPBACK_INTERNAL(efx) ||
+ LOOPBACK_INTERNAL(efx) ||
efx_mdio_phyxgxs_lane_sync(efx));
}
@@ -270,12 +269,12 @@ static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries)
return mac_up;
}
-static bool falcon_xmac_check_fault(struct efx_nic *efx)
+bool falcon_xmac_check_fault(struct efx_nic *efx)
{
return !falcon_xmac_link_ok_retry(efx, 5);
}
-static int falcon_reconfigure_xmac(struct efx_nic *efx)
+int falcon_reconfigure_xmac(struct efx_nic *efx)
{
struct falcon_nic_data *nic_data = efx->nic_data;
@@ -290,7 +289,7 @@ static int falcon_reconfigure_xmac(struct efx_nic *efx)
return 0;
}
-static void falcon_update_stats_xmac(struct efx_nic *efx)
+void falcon_update_stats_xmac(struct efx_nic *efx)
{
struct efx_mac_stats *mac_stats = &efx->mac_stats;
@@ -361,9 +360,3 @@ void falcon_poll_xmac(struct efx_nic *efx)
nic_data->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1);
falcon_ack_status_intr(efx);
}
-
-const struct efx_mac_operations falcon_xmac_operations = {
- .reconfigure = falcon_reconfigure_xmac,
- .update_stats = falcon_update_stats_xmac,
- .check_fault = falcon_xmac_check_fault,
-};
diff --git a/drivers/net/ethernet/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c
index 1fbbbee7b1ae..fea7f7300675 100644
--- a/drivers/net/ethernet/sfc/filter.c
+++ b/drivers/net/ethernet/sfc/filter.c
@@ -35,9 +35,17 @@
enum efx_filter_table_id {
EFX_FILTER_TABLE_RX_IP = 0,
EFX_FILTER_TABLE_RX_MAC,
+ EFX_FILTER_TABLE_RX_DEF,
+ EFX_FILTER_TABLE_TX_MAC,
EFX_FILTER_TABLE_COUNT,
};
+enum efx_filter_index {
+ EFX_FILTER_INDEX_UC_DEF,
+ EFX_FILTER_INDEX_MC_DEF,
+ EFX_FILTER_SIZE_RX_DEF,
+};
+
struct efx_filter_table {
enum efx_filter_table_id id;
u32 offset; /* address of table relative to BAR */
@@ -90,8 +98,9 @@ efx_filter_spec_table_id(const struct efx_filter_spec *spec)
BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_UDP_WILD >> 2));
BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_MAC_FULL >> 2));
BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_MAC_WILD >> 2));
+ BUILD_BUG_ON(EFX_FILTER_TABLE_TX_MAC != EFX_FILTER_TABLE_RX_MAC + 2);
EFX_BUG_ON_PARANOID(spec->type == EFX_FILTER_UNSPEC);
- return spec->type >> 2;
+ return (spec->type >> 2) + ((spec->flags & EFX_FILTER_FLAG_TX) ? 2 : 0);
}
static struct efx_filter_table *
@@ -109,7 +118,7 @@ static void efx_filter_table_reset_search_depth(struct efx_filter_table *table)
memset(table->search_depth, 0, sizeof(table->search_depth));
}
-static void efx_filter_push_rx_limits(struct efx_nic *efx)
+static void efx_filter_push_rx_config(struct efx_nic *efx)
{
struct efx_filter_state *state = efx->filter_state;
struct efx_filter_table *table;
@@ -143,9 +152,58 @@ static void efx_filter_push_rx_limits(struct efx_nic *efx)
FILTER_CTL_SRCH_FUDGE_WILD);
}
+ table = &state->table[EFX_FILTER_TABLE_RX_DEF];
+ if (table->size) {
+ EFX_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_UNICAST_NOMATCH_Q_ID,
+ table->spec[EFX_FILTER_INDEX_UC_DEF].dmaq_id);
+ EFX_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED,
+ !!(table->spec[EFX_FILTER_INDEX_UC_DEF].flags &
+ EFX_FILTER_FLAG_RX_RSS));
+ EFX_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE,
+ !!(table->spec[EFX_FILTER_INDEX_UC_DEF].flags &
+ EFX_FILTER_FLAG_RX_OVERRIDE_IP));
+ EFX_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_MULTICAST_NOMATCH_Q_ID,
+ table->spec[EFX_FILTER_INDEX_MC_DEF].dmaq_id);
+ EFX_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED,
+ !!(table->spec[EFX_FILTER_INDEX_MC_DEF].flags &
+ EFX_FILTER_FLAG_RX_RSS));
+ EFX_SET_OWORD_FIELD(
+ filter_ctl, FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE,
+ !!(table->spec[EFX_FILTER_INDEX_MC_DEF].flags &
+ EFX_FILTER_FLAG_RX_OVERRIDE_IP));
+ }
+
efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
}
+static void efx_filter_push_tx_limits(struct efx_nic *efx)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ struct efx_filter_table *table;
+ efx_oword_t tx_cfg;
+
+ efx_reado(efx, &tx_cfg, FR_AZ_TX_CFG);
+
+ table = &state->table[EFX_FILTER_TABLE_TX_MAC];
+ if (table->size) {
+ EFX_SET_OWORD_FIELD(
+ tx_cfg, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
+ table->search_depth[EFX_FILTER_MAC_FULL] +
+ FILTER_CTL_SRCH_FUDGE_FULL);
+ EFX_SET_OWORD_FIELD(
+ tx_cfg, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
+ table->search_depth[EFX_FILTER_MAC_WILD] +
+ FILTER_CTL_SRCH_FUDGE_WILD);
+ }
+
+ efx_writeo(efx, &tx_cfg, FR_AZ_TX_CFG);
+}
+
static inline void __efx_filter_set_ipv4(struct efx_filter_spec *spec,
__be32 host1, __be16 port1,
__be32 host2, __be16 port2)
@@ -300,7 +358,8 @@ int efx_filter_get_ipv4_full(const struct efx_filter_spec *spec,
int efx_filter_set_eth_local(struct efx_filter_spec *spec,
u16 vid, const u8 *addr)
{
- EFX_BUG_ON_PARANOID(!(spec->flags & EFX_FILTER_FLAG_RX));
+ EFX_BUG_ON_PARANOID(!(spec->flags &
+ (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)));
/* This cannot currently be combined with other filtering */
if (spec->type != EFX_FILTER_UNSPEC)
@@ -319,6 +378,52 @@ int efx_filter_set_eth_local(struct efx_filter_spec *spec,
return 0;
}
+/**
+ * efx_filter_set_uc_def - specify matching otherwise-unmatched unicast
+ * @spec: Specification to initialise
+ */
+int efx_filter_set_uc_def(struct efx_filter_spec *spec)
+{
+ EFX_BUG_ON_PARANOID(!(spec->flags &
+ (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)));
+
+ if (spec->type != EFX_FILTER_UNSPEC)
+ return -EINVAL;
+
+ spec->type = EFX_FILTER_UC_DEF;
+ memset(spec->data, 0, sizeof(spec->data)); /* ensure equality */
+ return 0;
+}
+
+/**
+ * efx_filter_set_mc_def - specify matching otherwise-unmatched multicast
+ * @spec: Specification to initialise
+ */
+int efx_filter_set_mc_def(struct efx_filter_spec *spec)
+{
+ EFX_BUG_ON_PARANOID(!(spec->flags &
+ (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)));
+
+ if (spec->type != EFX_FILTER_UNSPEC)
+ return -EINVAL;
+
+ spec->type = EFX_FILTER_MC_DEF;
+ memset(spec->data, 0, sizeof(spec->data)); /* ensure equality */
+ return 0;
+}
+
+static void efx_filter_reset_rx_def(struct efx_nic *efx, unsigned filter_idx)
+{
+ struct efx_filter_state *state = efx->filter_state;
+ struct efx_filter_table *table = &state->table[EFX_FILTER_TABLE_RX_DEF];
+ struct efx_filter_spec *spec = &table->spec[filter_idx];
+
+ efx_filter_init_rx(spec, EFX_FILTER_PRI_MANUAL,
+ EFX_FILTER_FLAG_RX_RSS, 0);
+ spec->type = EFX_FILTER_UC_DEF + filter_idx;
+ table->used_bitmap[0] |= 1 << filter_idx;
+}
+
int efx_filter_get_eth_local(const struct efx_filter_spec *spec,
u16 *vid, u8 *addr)
{
@@ -366,6 +471,13 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
break;
}
+ case EFX_FILTER_TABLE_RX_DEF:
+ /* One filter spec per type */
+ BUILD_BUG_ON(EFX_FILTER_INDEX_UC_DEF != 0);
+ BUILD_BUG_ON(EFX_FILTER_INDEX_MC_DEF !=
+ EFX_FILTER_MC_DEF - EFX_FILTER_UC_DEF);
+ return spec->type - EFX_FILTER_UC_DEF;
+
case EFX_FILTER_TABLE_RX_MAC: {
bool is_wild = spec->type == EFX_FILTER_MAC_WILD;
EFX_POPULATE_OWORD_8(
@@ -385,6 +497,18 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
break;
}
+ case EFX_FILTER_TABLE_TX_MAC: {
+ bool is_wild = spec->type == EFX_FILTER_MAC_WILD;
+ EFX_POPULATE_OWORD_5(*filter,
+ FRF_CZ_TMFT_TXQ_ID, spec->dmaq_id,
+ FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
+ FRF_CZ_TMFT_SRC_MAC_HI, spec->data[2],
+ FRF_CZ_TMFT_SRC_MAC_LO, spec->data[1],
+ FRF_CZ_TMFT_VLAN_ID, spec->data[0]);
+ data3 = is_wild | spec->dmaq_id << 1;
+ break;
+ }
+
default:
BUG();
}
@@ -399,6 +523,10 @@ static bool efx_filter_equal(const struct efx_filter_spec *left,
memcmp(left->data, right->data, sizeof(left->data)))
return false;
+ if (left->flags & EFX_FILTER_FLAG_TX &&
+ left->dmaq_id != right->dmaq_id)
+ return false;
+
return true;
}
@@ -448,23 +576,40 @@ static int efx_filter_search(struct efx_filter_table *table,
* MAC filters without overriding behaviour.
*/
+#define EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP 0
+#define EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP 1
+#define EFX_FILTER_MATCH_PRI_NORMAL_BASE 2
+
#define EFX_FILTER_INDEX_WIDTH 13
#define EFX_FILTER_INDEX_MASK ((1 << EFX_FILTER_INDEX_WIDTH) - 1)
static inline u32 efx_filter_make_id(enum efx_filter_table_id table_id,
unsigned int index, u8 flags)
{
- return (table_id == EFX_FILTER_TABLE_RX_MAC &&
- flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP) ?
- index :
- (table_id + 1) << EFX_FILTER_INDEX_WIDTH | index;
+ unsigned int match_pri = EFX_FILTER_MATCH_PRI_NORMAL_BASE + table_id;
+
+ if (flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP) {
+ if (table_id == EFX_FILTER_TABLE_RX_MAC)
+ match_pri = EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP;
+ else if (table_id == EFX_FILTER_TABLE_RX_DEF)
+ match_pri = EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP;
+ }
+
+ return match_pri << EFX_FILTER_INDEX_WIDTH | index;
}
static inline enum efx_filter_table_id efx_filter_id_table_id(u32 id)
{
- return (id <= EFX_FILTER_INDEX_MASK) ?
- EFX_FILTER_TABLE_RX_MAC :
- (id >> EFX_FILTER_INDEX_WIDTH) - 1;
+ unsigned int match_pri = id >> EFX_FILTER_INDEX_WIDTH;
+
+ switch (match_pri) {
+ case EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP:
+ return EFX_FILTER_TABLE_RX_MAC;
+ case EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP:
+ return EFX_FILTER_TABLE_RX_DEF;
+ default:
+ return match_pri - EFX_FILTER_MATCH_PRI_NORMAL_BASE;
+ }
}
static inline unsigned int efx_filter_id_index(u32 id)
@@ -474,23 +619,30 @@ static inline unsigned int efx_filter_id_index(u32 id)
static inline u8 efx_filter_id_flags(u32 id)
{
- return (id <= EFX_FILTER_INDEX_MASK) ?
- EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_OVERRIDE_IP :
- EFX_FILTER_FLAG_RX;
+ unsigned int match_pri = id >> EFX_FILTER_INDEX_WIDTH;
+
+ if (match_pri < EFX_FILTER_MATCH_PRI_NORMAL_BASE)
+ return EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_OVERRIDE_IP;
+ else if (match_pri <=
+ EFX_FILTER_MATCH_PRI_NORMAL_BASE + EFX_FILTER_TABLE_RX_DEF)
+ return EFX_FILTER_FLAG_RX;
+ else
+ return EFX_FILTER_FLAG_TX;
}
u32 efx_filter_get_rx_id_limit(struct efx_nic *efx)
{
struct efx_filter_state *state = efx->filter_state;
+ unsigned int table_id = EFX_FILTER_TABLE_RX_DEF;
- if (state->table[EFX_FILTER_TABLE_RX_MAC].size != 0)
- return ((EFX_FILTER_TABLE_RX_MAC + 1) << EFX_FILTER_INDEX_WIDTH)
- + state->table[EFX_FILTER_TABLE_RX_MAC].size;
- else if (state->table[EFX_FILTER_TABLE_RX_IP].size != 0)
- return ((EFX_FILTER_TABLE_RX_IP + 1) << EFX_FILTER_INDEX_WIDTH)
- + state->table[EFX_FILTER_TABLE_RX_IP].size;
- else
- return 0;
+ do {
+ if (state->table[table_id].size != 0)
+ return ((EFX_FILTER_MATCH_PRI_NORMAL_BASE + table_id)
+ << EFX_FILTER_INDEX_WIDTH) +
+ state->table[table_id].size;
+ } while (table_id--);
+
+ return 0;
}
/**
@@ -548,12 +700,20 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
}
*saved_spec = *spec;
- if (table->search_depth[spec->type] < depth) {
- table->search_depth[spec->type] = depth;
- efx_filter_push_rx_limits(efx);
- }
+ if (table->id == EFX_FILTER_TABLE_RX_DEF) {
+ efx_filter_push_rx_config(efx);
+ } else {
+ if (table->search_depth[spec->type] < depth) {
+ table->search_depth[spec->type] = depth;
+ if (spec->flags & EFX_FILTER_FLAG_TX)
+ efx_filter_push_tx_limits(efx);
+ else
+ efx_filter_push_rx_config(efx);
+ }
- efx_writeo(efx, &filter, table->offset + table->step * filter_idx);
+ efx_writeo(efx, &filter,
+ table->offset + table->step * filter_idx);
+ }
netif_vdbg(efx, hw, efx->net_dev,
"%s: filter type %d index %d rxq %u set",
@@ -571,7 +731,11 @@ static void efx_filter_table_clear_entry(struct efx_nic *efx,
{
static efx_oword_t filter;
- if (test_bit(filter_idx, table->used_bitmap)) {
+ if (table->id == EFX_FILTER_TABLE_RX_DEF) {
+ /* RX default filters must always exist */
+ efx_filter_reset_rx_def(efx, filter_idx);
+ efx_filter_push_rx_config(efx);
+ } else if (test_bit(filter_idx, table->used_bitmap)) {
__clear_bit(filter_idx, table->used_bitmap);
--table->used;
memset(&table->spec[filter_idx], 0, sizeof(table->spec[0]));
@@ -617,7 +781,8 @@ int efx_filter_remove_id_safe(struct efx_nic *efx,
spin_lock_bh(&state->lock);
if (test_bit(filter_idx, table->used_bitmap) &&
- spec->priority == priority && spec->flags == filter_flags) {
+ spec->priority == priority &&
+ !((spec->flags ^ filter_flags) & EFX_FILTER_FLAG_RX_OVERRIDE_IP)) {
efx_filter_table_clear_entry(efx, table, filter_idx);
if (table->used == 0)
efx_filter_table_reset_search_depth(table);
@@ -668,7 +833,8 @@ int efx_filter_get_filter_safe(struct efx_nic *efx,
spin_lock_bh(&state->lock);
if (test_bit(filter_idx, table->used_bitmap) &&
- spec->priority == priority && spec->flags == filter_flags) {
+ spec->priority == priority &&
+ !((spec->flags ^ filter_flags) & EFX_FILTER_FLAG_RX_OVERRIDE_IP)) {
*spec_buf = *spec;
rc = 0;
} else {
@@ -722,7 +888,7 @@ u32 efx_filter_count_rx_used(struct efx_nic *efx,
spin_lock_bh(&state->lock);
for (table_id = EFX_FILTER_TABLE_RX_IP;
- table_id <= EFX_FILTER_TABLE_RX_MAC;
+ table_id <= EFX_FILTER_TABLE_RX_DEF;
table_id++) {
table = &state->table[table_id];
for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
@@ -750,7 +916,7 @@ s32 efx_filter_get_rx_ids(struct efx_nic *efx,
spin_lock_bh(&state->lock);
for (table_id = EFX_FILTER_TABLE_RX_IP;
- table_id <= EFX_FILTER_TABLE_RX_MAC;
+ table_id <= EFX_FILTER_TABLE_RX_DEF;
table_id++) {
table = &state->table[table_id];
for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
@@ -785,6 +951,11 @@ void efx_restore_filters(struct efx_nic *efx)
for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
table = &state->table[table_id];
+
+ /* Check whether this is a regular register table */
+ if (table->step == 0)
+ continue;
+
for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
if (!test_bit(filter_idx, table->used_bitmap))
continue;
@@ -794,7 +965,8 @@ void efx_restore_filters(struct efx_nic *efx)
}
}
- efx_filter_push_rx_limits(efx);
+ efx_filter_push_rx_config(efx);
+ efx_filter_push_tx_limits(efx);
spin_unlock_bh(&state->lock);
}
@@ -833,6 +1005,16 @@ int efx_probe_filters(struct efx_nic *efx)
table->offset = FR_CZ_RX_MAC_FILTER_TBL0;
table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP;
+
+ table = &state->table[EFX_FILTER_TABLE_RX_DEF];
+ table->id = EFX_FILTER_TABLE_RX_DEF;
+ table->size = EFX_FILTER_SIZE_RX_DEF;
+
+ table = &state->table[EFX_FILTER_TABLE_TX_MAC];
+ table->id = EFX_FILTER_TABLE_TX_MAC;
+ table->offset = FR_CZ_TX_MAC_FILTER_TBL0;
+ table->size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
+ table->step = FR_CZ_TX_MAC_FILTER_TBL0_STEP;
}
for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
@@ -849,6 +1031,15 @@ int efx_probe_filters(struct efx_nic *efx)
goto fail;
}
+ if (state->table[EFX_FILTER_TABLE_RX_DEF].size) {
+ /* RX default filters must always exist */
+ unsigned i;
+ for (i = 0; i < EFX_FILTER_SIZE_RX_DEF; i++)
+ efx_filter_reset_rx_def(efx, i);
+ }
+
+ efx_filter_push_rx_config(efx);
+
return 0;
fail:
diff --git a/drivers/net/ethernet/sfc/filter.h b/drivers/net/ethernet/sfc/filter.h
index 3d4108cd90ca..3c77802aed6c 100644
--- a/drivers/net/ethernet/sfc/filter.h
+++ b/drivers/net/ethernet/sfc/filter.h
@@ -20,6 +20,8 @@
* @EFX_FILTER_UDP_WILD: Matching UDP/IPv4 destination (host, port)
* @EFX_FILTER_MAC_FULL: Matching Ethernet destination MAC address, VID
* @EFX_FILTER_MAC_WILD: Matching Ethernet destination MAC address
+ * @EFX_FILTER_UC_DEF: Matching all otherwise unmatched unicast
+ * @EFX_FILTER_MC_DEF: Matching all otherwise unmatched multicast
* @EFX_FILTER_UNSPEC: Match type is unspecified
*
* Falcon NICs only support the TCP/IPv4 and UDP/IPv4 filter types.
@@ -31,6 +33,8 @@ enum efx_filter_type {
EFX_FILTER_UDP_WILD,
EFX_FILTER_MAC_FULL = 4,
EFX_FILTER_MAC_WILD,
+ EFX_FILTER_UC_DEF = 8,
+ EFX_FILTER_MC_DEF,
EFX_FILTER_TYPE_COUNT, /* number of specific types */
EFX_FILTER_UNSPEC = 0xf,
};
@@ -39,7 +43,8 @@ enum efx_filter_type {
* enum efx_filter_priority - priority of a hardware filter specification
* @EFX_FILTER_PRI_HINT: Performance hint
* @EFX_FILTER_PRI_MANUAL: Manually configured filter
- * @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour
+ * @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour (user-level
+ * networking and SR-IOV)
*/
enum efx_filter_priority {
EFX_FILTER_PRI_HINT = 0,
@@ -60,12 +65,14 @@ enum efx_filter_priority {
* any IP filter that matches the same packet. By default, IP
* filters take precedence.
* @EFX_FILTER_FLAG_RX: Filter is for RX
+ * @EFX_FILTER_FLAG_TX: Filter is for TX
*/
enum efx_filter_flags {
EFX_FILTER_FLAG_RX_RSS = 0x01,
EFX_FILTER_FLAG_RX_SCATTER = 0x02,
EFX_FILTER_FLAG_RX_OVERRIDE_IP = 0x04,
EFX_FILTER_FLAG_RX = 0x08,
+ EFX_FILTER_FLAG_TX = 0x10,
};
/**
@@ -103,6 +110,15 @@ static inline void efx_filter_init_rx(struct efx_filter_spec *spec,
spec->dmaq_id = rxq_id;
}
+static inline void efx_filter_init_tx(struct efx_filter_spec *spec,
+ unsigned txq_id)
+{
+ spec->type = EFX_FILTER_UNSPEC;
+ spec->priority = EFX_FILTER_PRI_REQUIRED;
+ spec->flags = EFX_FILTER_FLAG_TX;
+ spec->dmaq_id = txq_id;
+}
+
extern int efx_filter_set_ipv4_local(struct efx_filter_spec *spec, u8 proto,
__be32 host, __be16 port);
extern int efx_filter_get_ipv4_local(const struct efx_filter_spec *spec,
@@ -117,6 +133,8 @@ extern int efx_filter_set_eth_local(struct efx_filter_spec *spec,
u16 vid, const u8 *addr);
extern int efx_filter_get_eth_local(const struct efx_filter_spec *spec,
u16 *vid, u8 *addr);
+extern int efx_filter_set_uc_def(struct efx_filter_spec *spec);
+extern int efx_filter_set_mc_def(struct efx_filter_spec *spec);
enum {
EFX_FILTER_VID_UNSPEC = 0xffff,
};
diff --git a/drivers/net/ethernet/sfc/mac.h b/drivers/net/ethernet/sfc/mac.h
deleted file mode 100644
index d6a255d0856b..000000000000
--- a/drivers/net/ethernet/sfc/mac.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/****************************************************************************
- * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation, incorporated herein by reference.
- */
-
-#ifndef EFX_MAC_H
-#define EFX_MAC_H
-
-#include "net_driver.h"
-
-extern const struct efx_mac_operations falcon_xmac_operations;
-extern const struct efx_mac_operations efx_mcdi_mac_operations;
-extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
- u32 dma_len, int enable, int clear);
-
-#endif
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 81a425397468..17b6463e459c 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -22,22 +22,22 @@
**************************************************************************
*/
-/* Software-defined structure to the shared-memory */
-#define CMD_NOTIFY_PORT0 0
-#define CMD_NOTIFY_PORT1 4
-#define CMD_PDU_PORT0 0x008
-#define CMD_PDU_PORT1 0x108
-#define REBOOT_FLAG_PORT0 0x3f8
-#define REBOOT_FLAG_PORT1 0x3fc
-
#define MCDI_RPC_TIMEOUT 10 /*seconds */
#define MCDI_PDU(efx) \
- (efx_port_num(efx) ? CMD_PDU_PORT1 : CMD_PDU_PORT0)
+ (efx_port_num(efx) ? MC_SMEM_P1_PDU_OFST : MC_SMEM_P0_PDU_OFST)
#define MCDI_DOORBELL(efx) \
- (efx_port_num(efx) ? CMD_NOTIFY_PORT1 : CMD_NOTIFY_PORT0)
-#define MCDI_REBOOT_FLAG(efx) \
- (efx_port_num(efx) ? REBOOT_FLAG_PORT1 : REBOOT_FLAG_PORT0)
+ (efx_port_num(efx) ? MC_SMEM_P1_DOORBELL_OFST : MC_SMEM_P0_DOORBELL_OFST)
+#define MCDI_STATUS(efx) \
+ (efx_port_num(efx) ? MC_SMEM_P1_STATUS_OFST : MC_SMEM_P0_STATUS_OFST)
+
+/* A reboot/assertion causes the MCDI status word to be set after the
+ * command word is set or a REBOOT event is sent. If we notice a reboot
+ * via these mechanisms then wait 10ms for the status word to be set. */
+#define MCDI_STATUS_DELAY_US 100
+#define MCDI_STATUS_DELAY_COUNT 100
+#define MCDI_STATUS_SLEEP_MS \
+ (MCDI_STATUS_DELAY_US * MCDI_STATUS_DELAY_COUNT / 1000)
#define SEQ_MASK \
EFX_MASK32(EFX_WIDTH(MCDI_HEADER_SEQ))
@@ -77,7 +77,7 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
u32 xflags, seqno;
BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
- BUG_ON(inlen & 3 || inlen >= 0x100);
+ BUG_ON(inlen & 3 || inlen >= MC_SMEM_PDU_LEN);
seqno = mcdi->seqno & SEQ_MASK;
xflags = 0;
@@ -111,7 +111,7 @@ static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen)
int i;
BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
- BUG_ON(outlen & 3 || outlen >= 0x100);
+ BUG_ON(outlen & 3 || outlen >= MC_SMEM_PDU_LEN);
for (i = 0; i < outlen; i += 4)
*((__le32 *)(outbuf + i)) = _efx_readd(efx, pdu + 4 + i);
@@ -210,7 +210,7 @@ out:
/* Test and clear MC-rebooted flag for this port/function */
int efx_mcdi_poll_reboot(struct efx_nic *efx)
{
- unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_REBOOT_FLAG(efx);
+ unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx);
efx_dword_t reg;
uint32_t value;
@@ -384,6 +384,11 @@ int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
netif_dbg(efx, hw, efx->net_dev,
"MC command 0x%x inlen %d failed rc=%d\n",
cmd, (int)inlen, -rc);
+
+ if (rc == -EIO || rc == -EINTR) {
+ msleep(MCDI_STATUS_SLEEP_MS);
+ efx_mcdi_poll_reboot(efx);
+ }
}
efx_mcdi_release(mcdi);
@@ -465,10 +470,20 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
mcdi->resplen = 0;
++mcdi->credits;
}
- } else
+ } else {
+ int count;
+
/* Nobody was waiting for an MCDI request, so trigger a reset */
efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
+ /* Consume the status word since efx_mcdi_rpc_finish() won't */
+ for (count = 0; count < MCDI_STATUS_DELAY_COUNT; ++count) {
+ if (efx_mcdi_poll_reboot(efx))
+ break;
+ udelay(MCDI_STATUS_DELAY_US);
+ }
+ }
+
spin_unlock(&mcdi->iface_lock);
}
@@ -502,49 +517,6 @@ static void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev)
efx_link_status_changed(efx);
}
-static const char *sensor_names[] = {
- [MC_CMD_SENSOR_CONTROLLER_TEMP] = "Controller temp. sensor",
- [MC_CMD_SENSOR_PHY_COMMON_TEMP] = "PHY shared temp. sensor",
- [MC_CMD_SENSOR_CONTROLLER_COOLING] = "Controller cooling",
- [MC_CMD_SENSOR_PHY0_TEMP] = "PHY 0 temp. sensor",
- [MC_CMD_SENSOR_PHY0_COOLING] = "PHY 0 cooling",
- [MC_CMD_SENSOR_PHY1_TEMP] = "PHY 1 temp. sensor",
- [MC_CMD_SENSOR_PHY1_COOLING] = "PHY 1 cooling",
- [MC_CMD_SENSOR_IN_1V0] = "1.0V supply sensor",
- [MC_CMD_SENSOR_IN_1V2] = "1.2V supply sensor",
- [MC_CMD_SENSOR_IN_1V8] = "1.8V supply sensor",
- [MC_CMD_SENSOR_IN_2V5] = "2.5V supply sensor",
- [MC_CMD_SENSOR_IN_3V3] = "3.3V supply sensor",
- [MC_CMD_SENSOR_IN_12V0] = "12V supply sensor"
-};
-
-static const char *sensor_status_names[] = {
- [MC_CMD_SENSOR_STATE_OK] = "OK",
- [MC_CMD_SENSOR_STATE_WARNING] = "Warning",
- [MC_CMD_SENSOR_STATE_FATAL] = "Fatal",
- [MC_CMD_SENSOR_STATE_BROKEN] = "Device failure",
-};
-
-static void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev)
-{
- unsigned int monitor, state, value;
- const char *name, *state_txt;
- monitor = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR);
- state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE);
- value = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_VALUE);
- /* Deal gracefully with the board having more drivers than we
- * know about, but do not expect new sensor states. */
- name = (monitor >= ARRAY_SIZE(sensor_names))
- ? "No sensor name available" :
- sensor_names[monitor];
- EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names));
- state_txt = sensor_status_names[state];
-
- netif_err(efx, hw, efx->net_dev,
- "Sensor %d (%s) reports condition '%s' for raw value %d\n",
- monitor, name, state_txt, value);
-}
-
/* Called from falcon_process_eventq for MCDI events */
void efx_mcdi_process_event(struct efx_channel *channel,
efx_qword_t *event)
@@ -588,6 +560,9 @@ void efx_mcdi_process_event(struct efx_channel *channel,
case MCDI_EVENT_CODE_MAC_STATS_DMA:
/* MAC stats are gather lazily. We can ignore this. */
break;
+ case MCDI_EVENT_CODE_FLR:
+ efx_sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF));
+ break;
default:
netif_err(efx, hw, efx->net_dev, "Unknown MCDI event 0x%x\n",
@@ -604,7 +579,7 @@ void efx_mcdi_process_event(struct efx_channel *channel,
void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
{
- u8 outbuf[ALIGN(MC_CMD_GET_VERSION_V1_OUT_LEN, 4)];
+ u8 outbuf[ALIGN(MC_CMD_GET_VERSION_OUT_LEN, 4)];
size_t outlength;
const __le16 *ver_words;
int rc;
@@ -616,7 +591,7 @@ void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
if (rc)
goto fail;
- if (outlength < MC_CMD_GET_VERSION_V1_OUT_LEN) {
+ if (outlength < MC_CMD_GET_VERSION_OUT_LEN) {
rc = -EIO;
goto fail;
}
@@ -663,9 +638,9 @@ fail:
}
int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
- u16 *fw_subtype_list)
+ u16 *fw_subtype_list, u32 *capabilities)
{
- uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LEN];
+ uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LENMIN];
size_t outlen;
int port_num = efx_port_num(efx);
int offset;
@@ -678,7 +653,7 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
if (rc)
goto fail;
- if (outlen < MC_CMD_GET_BOARD_CFG_OUT_LEN) {
+ if (outlen < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) {
rc = -EIO;
goto fail;
}
@@ -691,7 +666,16 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
if (fw_subtype_list)
memcpy(fw_subtype_list,
outbuf + MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST,
- MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN);
+ MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM *
+ sizeof(fw_subtype_list[0]));
+ if (capabilities) {
+ if (port_num)
+ *capabilities = MCDI_DWORD(outbuf,
+ GET_BOARD_CFG_OUT_CAPABILITIES_PORT1);
+ else
+ *capabilities = MCDI_DWORD(outbuf,
+ GET_BOARD_CFG_OUT_CAPABILITIES_PORT0);
+ }
return 0;
@@ -779,7 +763,7 @@ int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
*size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_SIZE);
*erase_size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_ERASESIZE);
*protected_out = !!(MCDI_DWORD(outbuf, NVRAM_INFO_OUT_FLAGS) &
- (1 << MC_CMD_NVRAM_PROTECTED_LBN));
+ (1 << MC_CMD_NVRAM_INFO_OUT_PROTECTED_LBN));
return 0;
fail:
@@ -1060,7 +1044,7 @@ void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
int efx_mcdi_reset_port(struct efx_nic *efx)
{
- int rc = efx_mcdi_rpc(efx, MC_CMD_PORT_RESET, NULL, 0, NULL, 0, NULL);
+ int rc = efx_mcdi_rpc(efx, MC_CMD_ENTITY_RESET, NULL, 0, NULL, 0, NULL);
if (rc)
netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
__func__, rc);
@@ -1173,6 +1157,37 @@ fail:
return rc;
}
+int efx_mcdi_flush_rxqs(struct efx_nic *efx)
+{
+ struct efx_channel *channel;
+ struct efx_rx_queue *rx_queue;
+ __le32 *qid;
+ int rc, count;
+
+ qid = kmalloc(EFX_MAX_CHANNELS * sizeof(*qid), GFP_KERNEL);
+ if (qid == NULL)
+ return -ENOMEM;
+
+ count = 0;
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
+ if (rx_queue->flush_pending) {
+ rx_queue->flush_pending = false;
+ atomic_dec(&efx->rxq_flush_pending);
+ qid[count++] = cpu_to_le32(
+ efx_rx_queue_index(rx_queue));
+ }
+ }
+ }
+
+ rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, (u8 *)qid,
+ count * sizeof(*qid), NULL, 0, NULL);
+ WARN_ON(rc > 0);
+
+ kfree(qid);
+
+ return rc;
+}
int efx_mcdi_wol_filter_reset(struct efx_nic *efx)
{
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index aced2a7856fc..0bdf3e331832 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -56,6 +56,15 @@ struct efx_mcdi_iface {
size_t resplen;
};
+struct efx_mcdi_mon {
+ struct efx_buffer dma_buf;
+ struct mutex update_lock;
+ unsigned long last_update;
+ struct device *device;
+ struct efx_mcdi_mon_attribute *attrs;
+ unsigned int n_attrs;
+};
+
extern void efx_mcdi_init(struct efx_nic *efx);
extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, const u8 *inbuf,
@@ -68,6 +77,7 @@ extern void efx_mcdi_mode_event(struct efx_nic *efx);
extern void efx_mcdi_process_event(struct efx_channel *channel,
efx_qword_t *event);
+extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
#define MCDI_PTR2(_buf, _ofst) \
(((u8 *)_buf) + _ofst)
@@ -83,6 +93,10 @@ extern void efx_mcdi_process_event(struct efx_channel *channel,
#define MCDI_PTR(_buf, _ofst) \
MCDI_PTR2(_buf, MC_CMD_ ## _ofst ## _OFST)
+#define MCDI_ARRAY_PTR(_buf, _field, _type, _index) \
+ MCDI_PTR2(_buf, \
+ MC_CMD_ ## _field ## _OFST + \
+ (_index) * MC_CMD_ ## _type ## _TYPEDEF_LEN)
#define MCDI_SET_DWORD(_buf, _ofst, _value) \
MCDI_SET_DWORD2(_buf, MC_CMD_ ## _ofst ## _OFST, _value)
#define MCDI_DWORD(_buf, _ofst) \
@@ -92,12 +106,18 @@ extern void efx_mcdi_process_event(struct efx_channel *channel,
#define MCDI_EVENT_FIELD(_ev, _field) \
EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field)
+#define MCDI_ARRAY_FIELD(_buf, _field1, _type, _index, _field2) \
+ EFX_DWORD_FIELD( \
+ *((efx_dword_t *) \
+ (MCDI_ARRAY_PTR(_buf, _field1, _type, _index) + \
+ (MC_CMD_ ## _type ## _TYPEDEF_ ## _field2 ## _OFST & ~3))), \
+ MC_CMD_ ## _type ## _TYPEDEF_ ## _field2)
extern void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len);
extern int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
bool *was_attached_out);
extern int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
- u16 *fw_subtype_list);
+ u16 *fw_subtype_list, u32 *capabilities);
extern int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart,
u32 dest_evq);
extern int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out);
@@ -126,5 +146,19 @@ extern int efx_mcdi_wol_filter_set_magic(struct efx_nic *efx,
extern int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out);
extern int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id);
extern int efx_mcdi_wol_filter_reset(struct efx_nic *efx);
+extern int efx_mcdi_flush_rxqs(struct efx_nic *efx);
+extern int efx_mcdi_set_mac(struct efx_nic *efx);
+extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
+ u32 dma_len, int enable, int clear);
+extern int efx_mcdi_mac_reconfigure(struct efx_nic *efx);
+extern bool efx_mcdi_mac_check_fault(struct efx_nic *efx);
+
+#ifdef CONFIG_SFC_MCDI_MON
+extern int efx_mcdi_mon_probe(struct efx_nic *efx);
+extern void efx_mcdi_mon_remove(struct efx_nic *efx);
+#else
+static inline int efx_mcdi_mon_probe(struct efx_nic *efx) { return 0; }
+static inline void efx_mcdi_mon_remove(struct efx_nic *efx) {}
+#endif
#endif /* EFX_MCDI_H */
diff --git a/drivers/net/ethernet/sfc/mcdi_mac.c b/drivers/net/ethernet/sfc/mcdi_mac.c
index 50c20777a564..1003f309cba7 100644
--- a/drivers/net/ethernet/sfc/mcdi_mac.c
+++ b/drivers/net/ethernet/sfc/mcdi_mac.c
@@ -9,11 +9,10 @@
#include "net_driver.h"
#include "efx.h"
-#include "mac.h"
#include "mcdi.h"
#include "mcdi_pcol.h"
-static int efx_mcdi_set_mac(struct efx_nic *efx)
+int efx_mcdi_set_mac(struct efx_nic *efx)
{
u32 reject, fcntl;
u8 cmdbytes[MC_CMD_SET_MAC_IN_LEN];
@@ -45,6 +44,8 @@ static int efx_mcdi_set_mac(struct efx_nic *efx)
}
if (efx->wanted_fc & EFX_FC_AUTO)
fcntl = MC_CMD_FCNTL_AUTO;
+ if (efx->fc_disable)
+ fcntl = MC_CMD_FCNTL_OFF;
MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl);
@@ -52,7 +53,7 @@ static int efx_mcdi_set_mac(struct efx_nic *efx)
NULL, 0, NULL);
}
-static int efx_mcdi_get_mac_faults(struct efx_nic *efx, u32 *faults)
+bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
{
u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
size_t outlength;
@@ -62,16 +63,13 @@ static int efx_mcdi_get_mac_faults(struct efx_nic *efx, u32 *faults)
rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
outbuf, sizeof(outbuf), &outlength);
- if (rc)
- goto fail;
-
- *faults = MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT);
- return 0;
+ if (rc) {
+ netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
+ __func__, rc);
+ return true;
+ }
-fail:
- netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
- __func__, rc);
- return rc;
+ return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
}
int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
@@ -84,7 +82,7 @@ int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
u32 addr_hi;
u32 addr_lo;
- BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_LEN != 0);
+ BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0);
addr_lo = ((u64)dma_addr) >> 0;
addr_hi = ((u64)dma_addr) >> 32;
@@ -93,13 +91,13 @@ int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_ADDR_HI, addr_hi);
cmd_ptr = (efx_dword_t *)MCDI_PTR(inbuf, MAC_STATS_IN_CMD);
EFX_POPULATE_DWORD_7(*cmd_ptr,
- MC_CMD_MAC_STATS_CMD_DMA, !!enable,
- MC_CMD_MAC_STATS_CMD_CLEAR, clear,
- MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE, 1,
- MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE, !!enable,
- MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR, 0,
- MC_CMD_MAC_STATS_CMD_PERIODIC_NOEVENT, 1,
- MC_CMD_MAC_STATS_CMD_PERIOD_MS, period);
+ MC_CMD_MAC_STATS_IN_DMA, !!enable,
+ MC_CMD_MAC_STATS_IN_CLEAR, clear,
+ MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE, 1,
+ MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE, !!enable,
+ MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR, 0,
+ MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT, 1,
+ MC_CMD_MAC_STATS_IN_PERIOD_MS, period);
MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len);
rc = efx_mcdi_rpc(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
@@ -115,31 +113,18 @@ fail:
return rc;
}
-static int efx_mcdi_mac_reconfigure(struct efx_nic *efx)
+int efx_mcdi_mac_reconfigure(struct efx_nic *efx)
{
int rc;
+ WARN_ON(!mutex_is_locked(&efx->mac_lock));
+
rc = efx_mcdi_set_mac(efx);
if (rc != 0)
return rc;
- /* Restore the multicast hash registers. */
- efx->type->push_multicast_hash(efx);
-
- return 0;
-}
-
-
-static bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
-{
- u32 faults;
- int rc = efx_mcdi_get_mac_faults(efx, &faults);
- return (rc != 0) || (faults != 0);
+ return efx_mcdi_rpc(efx, MC_CMD_SET_MCAST_HASH,
+ efx->multicast_hash.byte,
+ sizeof(efx->multicast_hash),
+ NULL, 0, NULL);
}
-
-
-const struct efx_mac_operations efx_mcdi_mac_operations = {
- .reconfigure = efx_mcdi_mac_reconfigure,
- .update_stats = efx_port_dummy_op_void,
- .check_fault = efx_mcdi_mac_check_fault,
-};
diff --git a/drivers/net/ethernet/sfc/mcdi_mon.c b/drivers/net/ethernet/sfc/mcdi_mon.c
new file mode 100644
index 000000000000..fb7f65b59eb8
--- /dev/null
+++ b/drivers/net/ethernet/sfc/mcdi_mon.c
@@ -0,0 +1,415 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2011 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/hwmon.h>
+#include <linux/stat.h>
+
+#include "net_driver.h"
+#include "mcdi.h"
+#include "mcdi_pcol.h"
+#include "nic.h"
+
+enum efx_hwmon_type {
+ EFX_HWMON_UNKNOWN,
+ EFX_HWMON_TEMP, /* temperature */
+ EFX_HWMON_COOL, /* cooling device, probably a heatsink */
+ EFX_HWMON_IN /* input voltage */
+};
+
+static const struct {
+ const char *label;
+ enum efx_hwmon_type hwmon_type;
+ int port;
+} efx_mcdi_sensor_type[MC_CMD_SENSOR_ENTRY_MAXNUM] = {
+#define SENSOR(name, label, hwmon_type, port) \
+ [MC_CMD_SENSOR_##name] = { label, hwmon_type, port }
+ SENSOR(CONTROLLER_TEMP, "Controller temp.", EFX_HWMON_TEMP, -1),
+ SENSOR(PHY_COMMON_TEMP, "PHY temp.", EFX_HWMON_TEMP, -1),
+ SENSOR(CONTROLLER_COOLING, "Controller cooling", EFX_HWMON_COOL, -1),
+ SENSOR(PHY0_TEMP, "PHY temp.", EFX_HWMON_TEMP, 0),
+ SENSOR(PHY0_COOLING, "PHY cooling", EFX_HWMON_COOL, 0),
+ SENSOR(PHY1_TEMP, "PHY temp.", EFX_HWMON_TEMP, 1),
+ SENSOR(PHY1_COOLING, "PHY cooling", EFX_HWMON_COOL, 1),
+ SENSOR(IN_1V0, "1.0V supply", EFX_HWMON_IN, -1),
+ SENSOR(IN_1V2, "1.2V supply", EFX_HWMON_IN, -1),
+ SENSOR(IN_1V8, "1.8V supply", EFX_HWMON_IN, -1),
+ SENSOR(IN_2V5, "2.5V supply", EFX_HWMON_IN, -1),
+ SENSOR(IN_3V3, "3.3V supply", EFX_HWMON_IN, -1),
+ SENSOR(IN_12V0, "12.0V supply", EFX_HWMON_IN, -1),
+ SENSOR(IN_1V2A, "1.2V analogue supply", EFX_HWMON_IN, -1),
+ SENSOR(IN_VREF, "ref. voltage", EFX_HWMON_IN, -1),
+#undef SENSOR
+};
+
+static const char *const sensor_status_names[] = {
+ [MC_CMD_SENSOR_STATE_OK] = "OK",
+ [MC_CMD_SENSOR_STATE_WARNING] = "Warning",
+ [MC_CMD_SENSOR_STATE_FATAL] = "Fatal",
+ [MC_CMD_SENSOR_STATE_BROKEN] = "Device failure",
+};
+
+void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev)
+{
+ unsigned int type, state, value;
+ const char *name = NULL, *state_txt;
+
+ type = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR);
+ state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE);
+ value = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_VALUE);
+
+ /* Deal gracefully with the board having more drivers than we
+ * know about, but do not expect new sensor states. */
+ if (type < ARRAY_SIZE(efx_mcdi_sensor_type))
+ name = efx_mcdi_sensor_type[type].label;
+ if (!name)
+ name = "No sensor name available";
+ EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names));
+ state_txt = sensor_status_names[state];
+
+ netif_err(efx, hw, efx->net_dev,
+ "Sensor %d (%s) reports condition '%s' for raw value %d\n",
+ type, name, state_txt, value);
+}
+
+#ifdef CONFIG_SFC_MCDI_MON
+
+struct efx_mcdi_mon_attribute {
+ struct device_attribute dev_attr;
+ unsigned int index;
+ unsigned int type;
+ unsigned int limit_value;
+ char name[12];
+};
+
+static int efx_mcdi_mon_update(struct efx_nic *efx)
+{
+ struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
+ u8 inbuf[MC_CMD_READ_SENSORS_IN_LEN];
+ int rc;
+
+ MCDI_SET_DWORD(inbuf, READ_SENSORS_IN_DMA_ADDR_LO,
+ hwmon->dma_buf.dma_addr & 0xffffffff);
+ MCDI_SET_DWORD(inbuf, READ_SENSORS_IN_DMA_ADDR_HI,
+ (u64)hwmon->dma_buf.dma_addr >> 32);
+
+ rc = efx_mcdi_rpc(efx, MC_CMD_READ_SENSORS,
+ inbuf, sizeof(inbuf), NULL, 0, NULL);
+ if (rc == 0)
+ hwmon->last_update = jiffies;
+ return rc;
+}
+
+static ssize_t efx_mcdi_mon_show_name(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", KBUILD_MODNAME);
+}
+
+static int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index,
+ efx_dword_t *entry)
+{
+ struct efx_nic *efx = dev_get_drvdata(dev);
+ struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
+ int rc;
+
+ BUILD_BUG_ON(MC_CMD_READ_SENSORS_OUT_LEN != 0);
+
+ mutex_lock(&hwmon->update_lock);
+
+ /* Use cached value if last update was < 1 s ago */
+ if (time_before(jiffies, hwmon->last_update + HZ))
+ rc = 0;
+ else
+ rc = efx_mcdi_mon_update(efx);
+
+ /* Copy out the requested entry */
+ *entry = ((efx_dword_t *)hwmon->dma_buf.addr)[index];
+
+ mutex_unlock(&hwmon->update_lock);
+
+ return rc;
+}
+
+static ssize_t efx_mcdi_mon_show_value(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct efx_mcdi_mon_attribute *mon_attr =
+ container_of(attr, struct efx_mcdi_mon_attribute, dev_attr);
+ efx_dword_t entry;
+ unsigned int value;
+ int rc;
+
+ rc = efx_mcdi_mon_get_entry(dev, mon_attr->index, &entry);
+ if (rc)
+ return rc;
+
+ value = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
+
+ /* Convert temperature from degrees to milli-degrees Celsius */
+ if (efx_mcdi_sensor_type[mon_attr->type].hwmon_type == EFX_HWMON_TEMP)
+ value *= 1000;
+
+ return sprintf(buf, "%u\n", value);
+}
+
+static ssize_t efx_mcdi_mon_show_limit(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct efx_mcdi_mon_attribute *mon_attr =
+ container_of(attr, struct efx_mcdi_mon_attribute, dev_attr);
+ unsigned int value;
+
+ value = mon_attr->limit_value;
+
+ /* Convert temperature from degrees to milli-degrees Celsius */
+ if (efx_mcdi_sensor_type[mon_attr->type].hwmon_type == EFX_HWMON_TEMP)
+ value *= 1000;
+
+ return sprintf(buf, "%u\n", value);
+}
+
+static ssize_t efx_mcdi_mon_show_alarm(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct efx_mcdi_mon_attribute *mon_attr =
+ container_of(attr, struct efx_mcdi_mon_attribute, dev_attr);
+ efx_dword_t entry;
+ int state;
+ int rc;
+
+ rc = efx_mcdi_mon_get_entry(dev, mon_attr->index, &entry);
+ if (rc)
+ return rc;
+
+ state = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE);
+ return sprintf(buf, "%d\n", state != MC_CMD_SENSOR_STATE_OK);
+}
+
+static ssize_t efx_mcdi_mon_show_label(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct efx_mcdi_mon_attribute *mon_attr =
+ container_of(attr, struct efx_mcdi_mon_attribute, dev_attr);
+ return sprintf(buf, "%s\n",
+ efx_mcdi_sensor_type[mon_attr->type].label);
+}
+
+static int
+efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
+ ssize_t (*reader)(struct device *,
+ struct device_attribute *, char *),
+ unsigned int index, unsigned int type,
+ unsigned int limit_value)
+{
+ struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
+ struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs];
+ int rc;
+
+ strlcpy(attr->name, name, sizeof(attr->name));
+ attr->index = index;
+ attr->type = type;
+ attr->limit_value = limit_value;
+ attr->dev_attr.attr.name = attr->name;
+ attr->dev_attr.attr.mode = S_IRUGO;
+ attr->dev_attr.show = reader;
+ rc = device_create_file(&efx->pci_dev->dev, &attr->dev_attr);
+ if (rc == 0)
+ ++hwmon->n_attrs;
+ return rc;
+}
+
+int efx_mcdi_mon_probe(struct efx_nic *efx)
+{
+ struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
+ unsigned int n_attrs, n_temp = 0, n_cool = 0, n_in = 0;
+ u8 outbuf[MC_CMD_SENSOR_INFO_OUT_LENMAX];
+ size_t outlen;
+ char name[12];
+ u32 mask;
+ int rc, i, type;
+
+ BUILD_BUG_ON(MC_CMD_SENSOR_INFO_IN_LEN != 0);
+
+ rc = efx_mcdi_rpc(efx, MC_CMD_SENSOR_INFO, NULL, 0,
+ outbuf, sizeof(outbuf), &outlen);
+ if (rc)
+ return rc;
+ if (outlen < MC_CMD_SENSOR_INFO_OUT_LENMIN)
+ return -EIO;
+
+ /* Find out which sensors are present. Don't create a device
+ * if there are none.
+ */
+ mask = MCDI_DWORD(outbuf, SENSOR_INFO_OUT_MASK);
+ if (mask == 0)
+ return 0;
+
+ /* Check again for short response */
+ if (outlen < MC_CMD_SENSOR_INFO_OUT_LEN(hweight32(mask)))
+ return -EIO;
+
+ rc = efx_nic_alloc_buffer(efx, &hwmon->dma_buf,
+ 4 * MC_CMD_SENSOR_ENTRY_MAXNUM);
+ if (rc)
+ return rc;
+
+ mutex_init(&hwmon->update_lock);
+ efx_mcdi_mon_update(efx);
+
+ /* Allocate space for the maximum possible number of
+ * attributes for this set of sensors: name of the driver plus
+ * value, min, max, crit, alarm and label for each sensor.
+ */
+ n_attrs = 1 + 6 * hweight32(mask);
+ hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL);
+ if (!hwmon->attrs) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ hwmon->device = hwmon_device_register(&efx->pci_dev->dev);
+ if (IS_ERR(hwmon->device)) {
+ rc = PTR_ERR(hwmon->device);
+ goto fail;
+ }
+
+ rc = efx_mcdi_mon_add_attr(efx, "name", efx_mcdi_mon_show_name, 0, 0, 0);
+ if (rc)
+ goto fail;
+
+ for (i = 0, type = -1; ; i++) {
+ const char *hwmon_prefix;
+ unsigned hwmon_index;
+ u16 min1, max1, min2, max2;
+
+ /* Find next sensor type or exit if there is none */
+ type++;
+ while (!(mask & (1 << type))) {
+ type++;
+ if (type == 32)
+ return 0;
+ }
+
+ /* Skip sensors specific to a different port */
+ if (efx_mcdi_sensor_type[type].hwmon_type != EFX_HWMON_UNKNOWN &&
+ efx_mcdi_sensor_type[type].port >= 0 &&
+ efx_mcdi_sensor_type[type].port != efx_port_num(efx))
+ continue;
+
+ switch (efx_mcdi_sensor_type[type].hwmon_type) {
+ case EFX_HWMON_TEMP:
+ hwmon_prefix = "temp";
+ hwmon_index = ++n_temp; /* 1-based */
+ break;
+ case EFX_HWMON_COOL:
+ /* This is likely to be a heatsink, but there
+ * is no convention for representing cooling
+ * devices other than fans.
+ */
+ hwmon_prefix = "fan";
+ hwmon_index = ++n_cool; /* 1-based */
+ break;
+ default:
+ hwmon_prefix = "in";
+ hwmon_index = n_in++; /* 0-based */
+ break;
+ }
+
+ min1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY,
+ SENSOR_INFO_ENTRY, i, MIN1);
+ max1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY,
+ SENSOR_INFO_ENTRY, i, MAX1);
+ min2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY,
+ SENSOR_INFO_ENTRY, i, MIN2);
+ max2 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY,
+ SENSOR_INFO_ENTRY, i, MAX2);
+
+ if (min1 != max1) {
+ snprintf(name, sizeof(name), "%s%u_input",
+ hwmon_prefix, hwmon_index);
+ rc = efx_mcdi_mon_add_attr(
+ efx, name, efx_mcdi_mon_show_value, i, type, 0);
+ if (rc)
+ goto fail;
+
+ snprintf(name, sizeof(name), "%s%u_min",
+ hwmon_prefix, hwmon_index);
+ rc = efx_mcdi_mon_add_attr(
+ efx, name, efx_mcdi_mon_show_limit,
+ i, type, min1);
+ if (rc)
+ goto fail;
+
+ snprintf(name, sizeof(name), "%s%u_max",
+ hwmon_prefix, hwmon_index);
+ rc = efx_mcdi_mon_add_attr(
+ efx, name, efx_mcdi_mon_show_limit,
+ i, type, max1);
+ if (rc)
+ goto fail;
+
+ if (min2 != max2) {
+ /* Assume max2 is critical value.
+ * But we have no good way to expose min2.
+ */
+ snprintf(name, sizeof(name), "%s%u_crit",
+ hwmon_prefix, hwmon_index);
+ rc = efx_mcdi_mon_add_attr(
+ efx, name, efx_mcdi_mon_show_limit,
+ i, type, max2);
+ if (rc)
+ goto fail;
+ }
+ }
+
+ snprintf(name, sizeof(name), "%s%u_alarm",
+ hwmon_prefix, hwmon_index);
+ rc = efx_mcdi_mon_add_attr(
+ efx, name, efx_mcdi_mon_show_alarm, i, type, 0);
+ if (rc)
+ goto fail;
+
+ if (efx_mcdi_sensor_type[type].label) {
+ snprintf(name, sizeof(name), "%s%u_label",
+ hwmon_prefix, hwmon_index);
+ rc = efx_mcdi_mon_add_attr(
+ efx, name, efx_mcdi_mon_show_label, i, type, 0);
+ if (rc)
+ goto fail;
+ }
+ }
+
+fail:
+ efx_mcdi_mon_remove(efx);
+ return rc;
+}
+
+void efx_mcdi_mon_remove(struct efx_nic *efx)
+{
+ struct siena_nic_data *nic_data = efx->nic_data;
+ struct efx_mcdi_mon *hwmon = &nic_data->hwmon;
+ unsigned int i;
+
+ for (i = 0; i < hwmon->n_attrs; i++)
+ device_remove_file(&efx->pci_dev->dev,
+ &hwmon->attrs[i].dev_attr);
+ kfree(hwmon->attrs);
+ if (hwmon->device)
+ hwmon_device_unregister(hwmon->device);
+ efx_nic_free_buffer(efx, &hwmon->dma_buf);
+}
+
+#endif /* CONFIG_SFC_MCDI_MON */
diff --git a/drivers/net/ethernet/sfc/mcdi_pcol.h b/drivers/net/ethernet/sfc/mcdi_pcol.h
index 41fe06fa0600..0310b9f08c9b 100644
--- a/drivers/net/ethernet/sfc/mcdi_pcol.h
+++ b/drivers/net/ethernet/sfc/mcdi_pcol.h
@@ -22,6 +22,18 @@
/* The Scheduler has started. */
#define MC_FW_STATE_SCHED (8)
+/* Siena MC shared memmory offsets */
+/* The 'doorbell' addresses are hard-wired to alert the MC when written */
+#define MC_SMEM_P0_DOORBELL_OFST 0x000
+#define MC_SMEM_P1_DOORBELL_OFST 0x004
+/* The rest of these are firmware-defined */
+#define MC_SMEM_P0_PDU_OFST 0x008
+#define MC_SMEM_P1_PDU_OFST 0x108
+#define MC_SMEM_PDU_LEN 0x100
+#define MC_SMEM_P0_PTP_TIME_OFST 0x7f0
+#define MC_SMEM_P0_STATUS_OFST 0x7f8
+#define MC_SMEM_P1_STATUS_OFST 0x7fc
+
/* Values to be written to the per-port status dword in shared
* memory on reboot and assert */
#define MC_STATUS_DWORD_REBOOT (0xb007b007)
@@ -34,6 +46,8 @@
*/
#define MCDI_PCOL_VERSION 1
+/* Unused commands: 0x23, 0x27, 0x30, 0x31 */
+
/**
* MCDI version 1
*
@@ -131,53 +145,6 @@
*/
#define FSE_AZ_EV_CODE_MCDI_EVRESPONSE 0xc
-#define MCDI_EVENT_DATA_LBN 0
-#define MCDI_EVENT_DATA_WIDTH 32
-#define MCDI_EVENT_CONT_LBN 32
-#define MCDI_EVENT_CONT_WIDTH 1
-#define MCDI_EVENT_LEVEL_LBN 33
-#define MCDI_EVENT_LEVEL_WIDTH 3
-#define MCDI_EVENT_LEVEL_INFO (0)
-#define MCDI_EVENT_LEVEL_WARN (1)
-#define MCDI_EVENT_LEVEL_ERR (2)
-#define MCDI_EVENT_LEVEL_FATAL (3)
-#define MCDI_EVENT_SRC_LBN 36
-#define MCDI_EVENT_SRC_WIDTH 8
-#define MCDI_EVENT_CODE_LBN 44
-#define MCDI_EVENT_CODE_WIDTH 8
-#define MCDI_EVENT_CODE_BADSSERT (1)
-#define MCDI_EVENT_CODE_PMNOTICE (2)
-#define MCDI_EVENT_CODE_CMDDONE (3)
-#define MCDI_EVENT_CMDDONE_SEQ_LBN 0
-#define MCDI_EVENT_CMDDONE_SEQ_WIDTH 8
-#define MCDI_EVENT_CMDDONE_DATALEN_LBN 8
-#define MCDI_EVENT_CMDDONE_DATALEN_WIDTH 8
-#define MCDI_EVENT_CMDDONE_ERRNO_LBN 16
-#define MCDI_EVENT_CMDDONE_ERRNO_WIDTH 8
-#define MCDI_EVENT_CODE_LINKCHANGE (4)
-#define MCDI_EVENT_LINKCHANGE_LP_CAP_LBN 0
-#define MCDI_EVENT_LINKCHANGE_LP_CAP_WIDTH 16
-#define MCDI_EVENT_LINKCHANGE_SPEED_LBN 16
-#define MCDI_EVENT_LINKCHANGE_SPEED_WIDTH 4
-#define MCDI_EVENT_LINKCHANGE_SPEED_100M 1
-#define MCDI_EVENT_LINKCHANGE_SPEED_1G 2
-#define MCDI_EVENT_LINKCHANGE_SPEED_10G 3
-#define MCDI_EVENT_LINKCHANGE_FCNTL_LBN 20
-#define MCDI_EVENT_LINKCHANGE_FCNTL_WIDTH 4
-#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_LBN 24
-#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_WIDTH 8
-#define MCDI_EVENT_CODE_SENSOREVT (5)
-#define MCDI_EVENT_SENSOREVT_MONITOR_LBN 0
-#define MCDI_EVENT_SENSOREVT_MONITOR_WIDTH 8
-#define MCDI_EVENT_SENSOREVT_STATE_LBN 8
-#define MCDI_EVENT_SENSOREVT_STATE_WIDTH 8
-#define MCDI_EVENT_SENSOREVT_VALUE_LBN 16
-#define MCDI_EVENT_SENSOREVT_VALUE_WIDTH 16
-#define MCDI_EVENT_CODE_SCHEDERR (6)
-#define MCDI_EVENT_CODE_REBOOT (7)
-#define MCDI_EVENT_CODE_MAC_STATS_DMA (8)
-#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_LBN 0
-#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_WIDTH 32
/* Non-existent command target */
#define MC_CMD_ERR_ENOENT 2
@@ -198,121 +165,24 @@
#define MC_CMD_ERR_CODE_OFST 0
+/* We define 8 "escape" commands to allow
+ for command number space extension */
+
+#define MC_CMD_CMD_SPACE_ESCAPE_0 0x78
+#define MC_CMD_CMD_SPACE_ESCAPE_1 0x79
+#define MC_CMD_CMD_SPACE_ESCAPE_2 0x7A
+#define MC_CMD_CMD_SPACE_ESCAPE_3 0x7B
+#define MC_CMD_CMD_SPACE_ESCAPE_4 0x7C
+#define MC_CMD_CMD_SPACE_ESCAPE_5 0x7D
+#define MC_CMD_CMD_SPACE_ESCAPE_6 0x7E
+#define MC_CMD_CMD_SPACE_ESCAPE_7 0x7F
+
+/* Vectors in the boot ROM */
+/* Point to the copycode entry point. */
+#define MC_BOOTROM_COPYCODE_VEC (0x7f4)
+/* Points to the recovery mode entry point. */
+#define MC_BOOTROM_NOFLASH_VEC (0x7f8)
-/* MC_CMD_READ32: (debug, variadic out)
- * Read multiple 32byte words from MC memory
- */
-#define MC_CMD_READ32 0x01
-#define MC_CMD_READ32_IN_LEN 8
-#define MC_CMD_READ32_IN_ADDR_OFST 0
-#define MC_CMD_READ32_IN_NUMWORDS_OFST 4
-#define MC_CMD_READ32_OUT_LEN(_numwords) \
- (4 * (_numwords))
-#define MC_CMD_READ32_OUT_BUFFER_OFST 0
-
-/* MC_CMD_WRITE32: (debug, variadic in)
- * Write multiple 32byte words to MC memory
- */
-#define MC_CMD_WRITE32 0x02
-#define MC_CMD_WRITE32_IN_LEN(_numwords) (((_numwords) * 4) + 4)
-#define MC_CMD_WRITE32_IN_ADDR_OFST 0
-#define MC_CMD_WRITE32_IN_BUFFER_OFST 4
-#define MC_CMD_WRITE32_OUT_LEN 0
-
-/* MC_CMD_COPYCODE: (debug)
- * Copy MC code between two locations and jump
- */
-#define MC_CMD_COPYCODE 0x03
-#define MC_CMD_COPYCODE_IN_LEN 16
-#define MC_CMD_COPYCODE_IN_SRC_ADDR_OFST 0
-#define MC_CMD_COPYCODE_IN_DEST_ADDR_OFST 4
-#define MC_CMD_COPYCODE_IN_NUMWORDS_OFST 8
-#define MC_CMD_COPYCODE_IN_JUMP_OFST 12
-/* Control should return to the caller rather than jumping */
-#define MC_CMD_COPYCODE_JUMP_NONE 1
-#define MC_CMD_COPYCODE_OUT_LEN 0
-
-/* MC_CMD_SET_FUNC: (debug)
- * Select function for function-specific commands.
- */
-#define MC_CMD_SET_FUNC 0x04
-#define MC_CMD_SET_FUNC_IN_LEN 4
-#define MC_CMD_SET_FUNC_IN_FUNC_OFST 0
-#define MC_CMD_SET_FUNC_OUT_LEN 0
-
-/* MC_CMD_GET_BOOT_STATUS:
- * Get the instruction address from which the MC booted.
- */
-#define MC_CMD_GET_BOOT_STATUS 0x05
-#define MC_CMD_GET_BOOT_STATUS_IN_LEN 0
-#define MC_CMD_GET_BOOT_STATUS_OUT_LEN 8
-#define MC_CMD_GET_BOOT_STATUS_OUT_BOOT_OFFSET_OFST 0
-#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_OFST 4
-/* Reboot caused by watchdog */
-#define MC_CMD_GET_BOOT_STATUS_FLAGS_WATCHDOG_LBN (0)
-#define MC_CMD_GET_BOOT_STATUS_FLAGS_WATCHDOG_WIDTH (1)
-/* MC booted from primary flash partition */
-#define MC_CMD_GET_BOOT_STATUS_FLAGS_PRIMARY_LBN (1)
-#define MC_CMD_GET_BOOT_STATUS_FLAGS_PRIMARY_WIDTH (1)
-/* MC booted from backup flash partition */
-#define MC_CMD_GET_BOOT_STATUS_FLAGS_BACKUP_LBN (2)
-#define MC_CMD_GET_BOOT_STATUS_FLAGS_BACKUP_WIDTH (1)
-
-/* MC_CMD_GET_ASSERTS: (debug, variadic out)
- * Get (and optionally clear) the current assertion status.
- *
- * Only OUT.GLOBAL_FLAGS is guaranteed to exist in the completion
- * payload. The other fields will only be present if
- * OUT.GLOBAL_FLAGS != NO_FAILS
- */
-#define MC_CMD_GET_ASSERTS 0x06
-#define MC_CMD_GET_ASSERTS_IN_LEN 4
-#define MC_CMD_GET_ASSERTS_IN_CLEAR_OFST 0
-#define MC_CMD_GET_ASSERTS_OUT_LEN 140
-/* Assertion status flag */
-#define MC_CMD_GET_ASSERTS_OUT_GLOBAL_FLAGS_OFST 0
-/*! No assertions have failed. */
-#define MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS 1
-/*! A system-level assertion has failed. */
-#define MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL 2
-/*! A thread-level assertion has failed. */
-#define MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL 3
-/*! The system was reset by the watchdog. */
-#define MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED 4
-/* Failing PC value */
-#define MC_CMD_GET_ASSERTS_OUT_SAVED_PC_OFFS_OFST 4
-/* Saved GP regs */
-#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST 8
-#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_LEN 124
-/* Failing thread address */
-#define MC_CMD_GET_ASSERTS_OUT_THREAD_OFFS_OFST 132
-
-/* MC_CMD_LOG_CTRL:
- * Determine the output stream for various events and messages
- */
-#define MC_CMD_LOG_CTRL 0x07
-#define MC_CMD_LOG_CTRL_IN_LEN 8
-#define MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0
-#define MC_CMD_LOG_CTRL_IN_LOG_DEST_UART (1)
-#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ (2)
-#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ_OFST 4
-#define MC_CMD_LOG_CTRL_OUT_LEN 0
-
-/* MC_CMD_GET_VERSION:
- * Get version information about the MC firmware
- */
-#define MC_CMD_GET_VERSION 0x08
-#define MC_CMD_GET_VERSION_IN_LEN 0
-#define MC_CMD_GET_VERSION_V0_OUT_LEN 4
-#define MC_CMD_GET_VERSION_V1_OUT_LEN 32
-#define MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0
-/* Reserved version number to indicate "any" version. */
-#define MC_CMD_GET_VERSION_OUT_FIRMWARE_ANY 0xffffffff
-/* The version response of a boot ROM awaiting rescue */
-#define MC_CMD_GET_VERSION_OUT_FIRMWARE_BOOTROM 0xb0070000
-#define MC_CMD_GET_VERSION_V1_OUT_PCOL_OFST 4
-/* 128bit mask of functions supported by the current firmware */
-#define MC_CMD_GET_VERSION_V1_OUT_SUPPORTED_FUNCS_OFST 8
/* The command set exported by the boot ROM (MCDI v0) */
#define MC_CMD_GET_VERSION_V0_SUPPORTED_FUNCS { \
(1 << MC_CMD_READ32) | \
@@ -320,1456 +190,2214 @@
(1 << MC_CMD_COPYCODE) | \
(1 << MC_CMD_GET_VERSION), \
0, 0, 0 }
-#define MC_CMD_GET_VERSION_OUT_VERSION_OFST 24
-/* Vectors in the boot ROM */
-/* Point to the copycode entry point. */
-#define MC_BOOTROM_COPYCODE_VEC (0x7f4)
-/* Points to the recovery mode entry point. */
-#define MC_BOOTROM_NOFLASH_VEC (0x7f8)
+#define MC_CMD_SENSOR_INFO_OUT_OFFSET_OFST(_x) \
+ (MC_CMD_SENSOR_ENTRY_OFST + (_x))
+
+#define MC_CMD_DBI_WRITE_IN_ADDRESS_OFST(n) \
+ (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST + \
+ MC_CMD_DBIWROP_TYPEDEF_ADDRESS_OFST + \
+ (n) * MC_CMD_DBIWROP_TYPEDEF_LEN)
+
+#define MC_CMD_DBI_WRITE_IN_BYTE_MASK_OFST(n) \
+ (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST + \
+ MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_OFST + \
+ (n) * MC_CMD_DBIWROP_TYPEDEF_LEN)
+
+#define MC_CMD_DBI_WRITE_IN_VALUE_OFST(n) \
+ (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST + \
+ MC_CMD_DBIWROP_TYPEDEF_VALUE_OFST + \
+ (n) * MC_CMD_DBIWROP_TYPEDEF_LEN)
+
+
+/* MCDI_EVENT structuredef */
+#define MCDI_EVENT_LEN 8
+#define MCDI_EVENT_CONT_LBN 32
+#define MCDI_EVENT_CONT_WIDTH 1
+#define MCDI_EVENT_LEVEL_LBN 33
+#define MCDI_EVENT_LEVEL_WIDTH 3
+#define MCDI_EVENT_LEVEL_INFO 0x0 /* enum */
+#define MCDI_EVENT_LEVEL_WARN 0x1 /* enum */
+#define MCDI_EVENT_LEVEL_ERR 0x2 /* enum */
+#define MCDI_EVENT_LEVEL_FATAL 0x3 /* enum */
+#define MCDI_EVENT_DATA_OFST 0
+#define MCDI_EVENT_CMDDONE_SEQ_LBN 0
+#define MCDI_EVENT_CMDDONE_SEQ_WIDTH 8
+#define MCDI_EVENT_CMDDONE_DATALEN_LBN 8
+#define MCDI_EVENT_CMDDONE_DATALEN_WIDTH 8
+#define MCDI_EVENT_CMDDONE_ERRNO_LBN 16
+#define MCDI_EVENT_CMDDONE_ERRNO_WIDTH 8
+#define MCDI_EVENT_LINKCHANGE_LP_CAP_LBN 0
+#define MCDI_EVENT_LINKCHANGE_LP_CAP_WIDTH 16
+#define MCDI_EVENT_LINKCHANGE_SPEED_LBN 16
+#define MCDI_EVENT_LINKCHANGE_SPEED_WIDTH 4
+#define MCDI_EVENT_LINKCHANGE_SPEED_100M 0x1 /* enum */
+#define MCDI_EVENT_LINKCHANGE_SPEED_1G 0x2 /* enum */
+#define MCDI_EVENT_LINKCHANGE_SPEED_10G 0x3 /* enum */
+#define MCDI_EVENT_LINKCHANGE_FCNTL_LBN 20
+#define MCDI_EVENT_LINKCHANGE_FCNTL_WIDTH 4
+#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_LBN 24
+#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_WIDTH 8
+#define MCDI_EVENT_SENSOREVT_MONITOR_LBN 0
+#define MCDI_EVENT_SENSOREVT_MONITOR_WIDTH 8
+#define MCDI_EVENT_SENSOREVT_STATE_LBN 8
+#define MCDI_EVENT_SENSOREVT_STATE_WIDTH 8
+#define MCDI_EVENT_SENSOREVT_VALUE_LBN 16
+#define MCDI_EVENT_SENSOREVT_VALUE_WIDTH 16
+#define MCDI_EVENT_FWALERT_DATA_LBN 8
+#define MCDI_EVENT_FWALERT_DATA_WIDTH 24
+#define MCDI_EVENT_FWALERT_REASON_LBN 0
+#define MCDI_EVENT_FWALERT_REASON_WIDTH 8
+#define MCDI_EVENT_FWALERT_REASON_SRAM_ACCESS 0x1 /* enum */
+#define MCDI_EVENT_FLR_VF_LBN 0
+#define MCDI_EVENT_FLR_VF_WIDTH 8
+#define MCDI_EVENT_TX_ERR_TXQ_LBN 0
+#define MCDI_EVENT_TX_ERR_TXQ_WIDTH 12
+#define MCDI_EVENT_TX_ERR_TYPE_LBN 12
+#define MCDI_EVENT_TX_ERR_TYPE_WIDTH 4
+#define MCDI_EVENT_TX_ERR_DL_FAIL 0x1 /* enum */
+#define MCDI_EVENT_TX_ERR_NO_EOP 0x2 /* enum */
+#define MCDI_EVENT_TX_ERR_2BIG 0x3 /* enum */
+#define MCDI_EVENT_TX_ERR_INFO_LBN 16
+#define MCDI_EVENT_TX_ERR_INFO_WIDTH 16
+#define MCDI_EVENT_TX_FLUSH_TXQ_LBN 0
+#define MCDI_EVENT_TX_FLUSH_TXQ_WIDTH 12
+#define MCDI_EVENT_PTP_ERR_TYPE_LBN 0
+#define MCDI_EVENT_PTP_ERR_TYPE_WIDTH 8
+#define MCDI_EVENT_PTP_ERR_PLL_LOST 0x1 /* enum */
+#define MCDI_EVENT_PTP_ERR_FILTER 0x2 /* enum */
+#define MCDI_EVENT_PTP_ERR_FIFO 0x3 /* enum */
+#define MCDI_EVENT_PTP_ERR_QUEUE 0x4 /* enum */
+#define MCDI_EVENT_DATA_LBN 0
+#define MCDI_EVENT_DATA_WIDTH 32
+#define MCDI_EVENT_SRC_LBN 36
+#define MCDI_EVENT_SRC_WIDTH 8
+#define MCDI_EVENT_EV_CODE_LBN 60
+#define MCDI_EVENT_EV_CODE_WIDTH 4
+#define MCDI_EVENT_CODE_LBN 44
+#define MCDI_EVENT_CODE_WIDTH 8
+#define MCDI_EVENT_CODE_BADSSERT 0x1 /* enum */
+#define MCDI_EVENT_CODE_PMNOTICE 0x2 /* enum */
+#define MCDI_EVENT_CODE_CMDDONE 0x3 /* enum */
+#define MCDI_EVENT_CODE_LINKCHANGE 0x4 /* enum */
+#define MCDI_EVENT_CODE_SENSOREVT 0x5 /* enum */
+#define MCDI_EVENT_CODE_SCHEDERR 0x6 /* enum */
+#define MCDI_EVENT_CODE_REBOOT 0x7 /* enum */
+#define MCDI_EVENT_CODE_MAC_STATS_DMA 0x8 /* enum */
+#define MCDI_EVENT_CODE_FWALERT 0x9 /* enum */
+#define MCDI_EVENT_CODE_FLR 0xa /* enum */
+#define MCDI_EVENT_CODE_TX_ERR 0xb /* enum */
+#define MCDI_EVENT_CODE_TX_FLUSH 0xc /* enum */
+#define MCDI_EVENT_CODE_PTP_RX 0xd /* enum */
+#define MCDI_EVENT_CODE_PTP_FAULT 0xe /* enum */
+#define MCDI_EVENT_CMDDONE_DATA_OFST 0
+#define MCDI_EVENT_CMDDONE_DATA_LBN 0
+#define MCDI_EVENT_CMDDONE_DATA_WIDTH 32
+#define MCDI_EVENT_LINKCHANGE_DATA_OFST 0
+#define MCDI_EVENT_LINKCHANGE_DATA_LBN 0
+#define MCDI_EVENT_LINKCHANGE_DATA_WIDTH 32
+#define MCDI_EVENT_SENSOREVT_DATA_OFST 0
+#define MCDI_EVENT_SENSOREVT_DATA_LBN 0
+#define MCDI_EVENT_SENSOREVT_DATA_WIDTH 32
+#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_OFST 0
+#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_LBN 0
+#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_WIDTH 32
+#define MCDI_EVENT_TX_ERR_DATA_OFST 0
+#define MCDI_EVENT_TX_ERR_DATA_LBN 0
+#define MCDI_EVENT_TX_ERR_DATA_WIDTH 32
+#define MCDI_EVENT_PTP_SECONDS_OFST 0
+#define MCDI_EVENT_PTP_SECONDS_LBN 0
+#define MCDI_EVENT_PTP_SECONDS_WIDTH 32
+#define MCDI_EVENT_PTP_NANOSECONDS_OFST 0
+#define MCDI_EVENT_PTP_NANOSECONDS_LBN 0
+#define MCDI_EVENT_PTP_NANOSECONDS_WIDTH 32
+#define MCDI_EVENT_PTP_UUID_OFST 0
+#define MCDI_EVENT_PTP_UUID_LBN 0
+#define MCDI_EVENT_PTP_UUID_WIDTH 32
+
+
+/***********************************/
+/* MC_CMD_READ32
+ * Read multiple 32byte words from MC memory.
+ */
+#define MC_CMD_READ32 0x1
+
+/* MC_CMD_READ32_IN msgrequest */
+#define MC_CMD_READ32_IN_LEN 8
+#define MC_CMD_READ32_IN_ADDR_OFST 0
+#define MC_CMD_READ32_IN_NUMWORDS_OFST 4
+
+/* MC_CMD_READ32_OUT msgresponse */
+#define MC_CMD_READ32_OUT_LENMIN 4
+#define MC_CMD_READ32_OUT_LENMAX 252
+#define MC_CMD_READ32_OUT_LEN(num) (0+4*(num))
+#define MC_CMD_READ32_OUT_BUFFER_OFST 0
+#define MC_CMD_READ32_OUT_BUFFER_LEN 4
+#define MC_CMD_READ32_OUT_BUFFER_MINNUM 1
+#define MC_CMD_READ32_OUT_BUFFER_MAXNUM 63
+
+
+/***********************************/
+/* MC_CMD_WRITE32
+ * Write multiple 32byte words to MC memory.
+ */
+#define MC_CMD_WRITE32 0x2
+
+/* MC_CMD_WRITE32_IN msgrequest */
+#define MC_CMD_WRITE32_IN_LENMIN 8
+#define MC_CMD_WRITE32_IN_LENMAX 252
+#define MC_CMD_WRITE32_IN_LEN(num) (4+4*(num))
+#define MC_CMD_WRITE32_IN_ADDR_OFST 0
+#define MC_CMD_WRITE32_IN_BUFFER_OFST 4
+#define MC_CMD_WRITE32_IN_BUFFER_LEN 4
+#define MC_CMD_WRITE32_IN_BUFFER_MINNUM 1
+#define MC_CMD_WRITE32_IN_BUFFER_MAXNUM 62
+
+/* MC_CMD_WRITE32_OUT msgresponse */
+#define MC_CMD_WRITE32_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_COPYCODE
+ * Copy MC code between two locations and jump.
+ */
+#define MC_CMD_COPYCODE 0x3
+
+/* MC_CMD_COPYCODE_IN msgrequest */
+#define MC_CMD_COPYCODE_IN_LEN 16
+#define MC_CMD_COPYCODE_IN_SRC_ADDR_OFST 0
+#define MC_CMD_COPYCODE_IN_DEST_ADDR_OFST 4
+#define MC_CMD_COPYCODE_IN_NUMWORDS_OFST 8
+#define MC_CMD_COPYCODE_IN_JUMP_OFST 12
+#define MC_CMD_COPYCODE_JUMP_NONE 0x1 /* enum */
+
+/* MC_CMD_COPYCODE_OUT msgresponse */
+#define MC_CMD_COPYCODE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SET_FUNC
+ */
+#define MC_CMD_SET_FUNC 0x4
+
+/* MC_CMD_SET_FUNC_IN msgrequest */
+#define MC_CMD_SET_FUNC_IN_LEN 4
+#define MC_CMD_SET_FUNC_IN_FUNC_OFST 0
+
+/* MC_CMD_SET_FUNC_OUT msgresponse */
+#define MC_CMD_SET_FUNC_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_BOOT_STATUS
+ */
+#define MC_CMD_GET_BOOT_STATUS 0x5
+
+/* MC_CMD_GET_BOOT_STATUS_IN msgrequest */
+#define MC_CMD_GET_BOOT_STATUS_IN_LEN 0
+
+/* MC_CMD_GET_BOOT_STATUS_OUT msgresponse */
+#define MC_CMD_GET_BOOT_STATUS_OUT_LEN 8
+#define MC_CMD_GET_BOOT_STATUS_OUT_BOOT_OFFSET_OFST 0
+#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_OFST 4
+#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_WATCHDOG_LBN 0
+#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_WATCHDOG_WIDTH 1
+#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_PRIMARY_LBN 1
+#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_PRIMARY_WIDTH 1
+#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_BACKUP_LBN 2
+#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_BACKUP_WIDTH 1
-/* Test execution limits */
-#define MC_TESTEXEC_VARIANT_COUNT 16
-#define MC_TESTEXEC_RESULT_COUNT 7
-/* MC_CMD_SET_TESTVARS: (debug, variadic in)
- * Write variant words for test.
- *
- * The user supplies a bitmap of the variants they wish to set.
- * They must ensure that IN.LEN >= 4 + 4 * ffs(BITMAP)
- */
-#define MC_CMD_SET_TESTVARS 0x09
-#define MC_CMD_SET_TESTVARS_IN_LEN(_numwords) \
- (4 + 4*(_numwords))
-#define MC_CMD_SET_TESTVARS_IN_ARGS_BITMAP_OFST 0
-/* Up to MC_TESTEXEC_VARIANT_COUNT of 32byte words start here */
-#define MC_CMD_SET_TESTVARS_IN_ARGS_BUFFER_OFST 4
-#define MC_CMD_SET_TESTVARS_OUT_LEN 0
-
-/* MC_CMD_GET_TESTRCS: (debug, variadic out)
- * Return result words from test.
- */
-#define MC_CMD_GET_TESTRCS 0x0a
-#define MC_CMD_GET_TESTRCS_IN_LEN 4
-#define MC_CMD_GET_TESTRCS_IN_NUMWORDS_OFST 0
-#define MC_CMD_GET_TESTRCS_OUT_LEN(_numwords) \
- (4 * (_numwords))
-#define MC_CMD_GET_TESTRCS_OUT_BUFFER_OFST 0
-
-/* MC_CMD_RUN_TEST: (debug)
- * Run the test exported by this firmware image
- */
-#define MC_CMD_RUN_TEST 0x0b
-#define MC_CMD_RUN_TEST_IN_LEN 0
-#define MC_CMD_RUN_TEST_OUT_LEN 0
-
-/* MC_CMD_CSR_READ32: (debug, variadic out)
- * Read 32bit words from the indirect memory map
- */
-#define MC_CMD_CSR_READ32 0x0c
-#define MC_CMD_CSR_READ32_IN_LEN 12
-#define MC_CMD_CSR_READ32_IN_ADDR_OFST 0
-#define MC_CMD_CSR_READ32_IN_STEP_OFST 4
-#define MC_CMD_CSR_READ32_IN_NUMWORDS_OFST 8
-#define MC_CMD_CSR_READ32_OUT_LEN(_numwords) \
- (((_numwords) * 4) + 4)
-/* IN.NUMWORDS of 32bit words start here */
-#define MC_CMD_CSR_READ32_OUT_BUFFER_OFST 0
-#define MC_CMD_CSR_READ32_OUT_IREG_STATUS_OFST(_numwords) \
- ((_numwords) * 4)
-
-/* MC_CMD_CSR_WRITE32: (debug, variadic in)
- * Write 32bit dwords to the indirect memory map
- */
-#define MC_CMD_CSR_WRITE32 0x0d
-#define MC_CMD_CSR_WRITE32_IN_LEN(_numwords) \
- (((_numwords) * 4) + 8)
-#define MC_CMD_CSR_WRITE32_IN_ADDR_OFST 0
-#define MC_CMD_CSR_WRITE32_IN_STEP_OFST 4
-/* Multiple 32bit words of data to write start here */
-#define MC_CMD_CSR_WRITE32_IN_BUFFER_OFST 8
-#define MC_CMD_CSR_WRITE32_OUT_LEN 4
-#define MC_CMD_CSR_WRITE32_OUT_STATUS_OFST 0
-
-/* MC_CMD_JTAG_WORK: (debug, fpga only)
- * Process JTAG work buffer for RBF acceleration.
- *
- * Host: bit count, (up to) 32 words of data to clock out to JTAG
- * (bits 1,0=TMS,TDO for first bit; bits 3,2=TMS,TDO for second bit, etc.)
- * MC: bit count, (up to) 32 words of data clocked in from JTAG
- * (bit 0=TDI for first bit, bit 1=TDI for second bit, etc.; [31:16] unused)
+/***********************************/
+/* MC_CMD_GET_ASSERTS
+ * Get and clear any assertion status.
*/
-#define MC_CMD_JTAG_WORK 0x0e
+#define MC_CMD_GET_ASSERTS 0x6
-/* MC_CMD_STACKINFO: (debug, variadic out)
- * Get stack information
- *
- * Host: nothing
- * MC: (thread ptr, stack size, free space) for each thread in system
- */
-#define MC_CMD_STACKINFO 0x0f
+/* MC_CMD_GET_ASSERTS_IN msgrequest */
+#define MC_CMD_GET_ASSERTS_IN_LEN 4
+#define MC_CMD_GET_ASSERTS_IN_CLEAR_OFST 0
+
+/* MC_CMD_GET_ASSERTS_OUT msgresponse */
+#define MC_CMD_GET_ASSERTS_OUT_LEN 140
+#define MC_CMD_GET_ASSERTS_OUT_GLOBAL_FLAGS_OFST 0
+#define MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS 0x1 /* enum */
+#define MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL 0x2 /* enum */
+#define MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL 0x3 /* enum */
+#define MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED 0x4 /* enum */
+#define MC_CMD_GET_ASSERTS_OUT_SAVED_PC_OFFS_OFST 4
+#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST 8
+#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_LEN 4
+#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_NUM 31
+#define MC_CMD_GET_ASSERTS_OUT_THREAD_OFFS_OFST 132
+#define MC_CMD_GET_ASSERTS_OUT_RESERVED_OFST 136
-/* MC_CMD_MDIO_READ:
- * MDIO register read
+
+/***********************************/
+/* MC_CMD_LOG_CTRL
+ * Configure the output stream for various events and messages.
+ */
+#define MC_CMD_LOG_CTRL 0x7
+
+/* MC_CMD_LOG_CTRL_IN msgrequest */
+#define MC_CMD_LOG_CTRL_IN_LEN 8
+#define MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0
+#define MC_CMD_LOG_CTRL_IN_LOG_DEST_UART 0x1 /* enum */
+#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ 0x2 /* enum */
+#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ_OFST 4
+
+/* MC_CMD_LOG_CTRL_OUT msgresponse */
+#define MC_CMD_LOG_CTRL_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_VERSION
+ * Get version information about the MC firmware.
+ */
+#define MC_CMD_GET_VERSION 0x8
+
+/* MC_CMD_GET_VERSION_IN msgrequest */
+#define MC_CMD_GET_VERSION_IN_LEN 0
+
+/* MC_CMD_GET_VERSION_V0_OUT msgresponse */
+#define MC_CMD_GET_VERSION_V0_OUT_LEN 4
+#define MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0
+#define MC_CMD_GET_VERSION_OUT_FIRMWARE_ANY 0xffffffff /* enum */
+#define MC_CMD_GET_VERSION_OUT_FIRMWARE_BOOTROM 0xb0070000 /* enum */
+
+/* MC_CMD_GET_VERSION_OUT msgresponse */
+#define MC_CMD_GET_VERSION_OUT_LEN 32
+/* MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
+/* Enum values, see field(s): */
+/* MC_CMD_GET_VERSION_V0_OUT/MC_CMD_GET_VERSION_OUT_FIRMWARE */
+#define MC_CMD_GET_VERSION_OUT_PCOL_OFST 4
+#define MC_CMD_GET_VERSION_OUT_SUPPORTED_FUNCS_OFST 8
+#define MC_CMD_GET_VERSION_OUT_SUPPORTED_FUNCS_LEN 16
+#define MC_CMD_GET_VERSION_OUT_VERSION_OFST 24
+#define MC_CMD_GET_VERSION_OUT_VERSION_LEN 8
+#define MC_CMD_GET_VERSION_OUT_VERSION_LO_OFST 24
+#define MC_CMD_GET_VERSION_OUT_VERSION_HI_OFST 28
+
+
+/***********************************/
+/* MC_CMD_GET_FPGAREG
+ * Read multiple bytes from PTP FPGA.
+ */
+#define MC_CMD_GET_FPGAREG 0x9
+
+/* MC_CMD_GET_FPGAREG_IN msgrequest */
+#define MC_CMD_GET_FPGAREG_IN_LEN 8
+#define MC_CMD_GET_FPGAREG_IN_ADDR_OFST 0
+#define MC_CMD_GET_FPGAREG_IN_NUMBYTES_OFST 4
+
+/* MC_CMD_GET_FPGAREG_OUT msgresponse */
+#define MC_CMD_GET_FPGAREG_OUT_LENMIN 1
+#define MC_CMD_GET_FPGAREG_OUT_LENMAX 255
+#define MC_CMD_GET_FPGAREG_OUT_LEN(num) (0+1*(num))
+#define MC_CMD_GET_FPGAREG_OUT_BUFFER_OFST 0
+#define MC_CMD_GET_FPGAREG_OUT_BUFFER_LEN 1
+#define MC_CMD_GET_FPGAREG_OUT_BUFFER_MINNUM 1
+#define MC_CMD_GET_FPGAREG_OUT_BUFFER_MAXNUM 255
+
+
+/***********************************/
+/* MC_CMD_PUT_FPGAREG
+ * Write multiple bytes to PTP FPGA.
+ */
+#define MC_CMD_PUT_FPGAREG 0xa
+
+/* MC_CMD_PUT_FPGAREG_IN msgrequest */
+#define MC_CMD_PUT_FPGAREG_IN_LENMIN 5
+#define MC_CMD_PUT_FPGAREG_IN_LENMAX 255
+#define MC_CMD_PUT_FPGAREG_IN_LEN(num) (4+1*(num))
+#define MC_CMD_PUT_FPGAREG_IN_ADDR_OFST 0
+#define MC_CMD_PUT_FPGAREG_IN_BUFFER_OFST 4
+#define MC_CMD_PUT_FPGAREG_IN_BUFFER_LEN 1
+#define MC_CMD_PUT_FPGAREG_IN_BUFFER_MINNUM 1
+#define MC_CMD_PUT_FPGAREG_IN_BUFFER_MAXNUM 251
+
+/* MC_CMD_PUT_FPGAREG_OUT msgresponse */
+#define MC_CMD_PUT_FPGAREG_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_PTP
+ * Perform PTP operation
+ */
+#define MC_CMD_PTP 0xb
+
+/* MC_CMD_PTP_IN msgrequest */
+#define MC_CMD_PTP_IN_LEN 1
+#define MC_CMD_PTP_IN_OP_OFST 0
+#define MC_CMD_PTP_IN_OP_LEN 1
+#define MC_CMD_PTP_OP_ENABLE 0x1 /* enum */
+#define MC_CMD_PTP_OP_DISABLE 0x2 /* enum */
+#define MC_CMD_PTP_OP_TRANSMIT 0x3 /* enum */
+#define MC_CMD_PTP_OP_READ_NIC_TIME 0x4 /* enum */
+#define MC_CMD_PTP_OP_STATUS 0x5 /* enum */
+#define MC_CMD_PTP_OP_ADJUST 0x6 /* enum */
+#define MC_CMD_PTP_OP_SYNCHRONIZE 0x7 /* enum */
+#define MC_CMD_PTP_OP_MANFTEST_BASIC 0x8 /* enum */
+#define MC_CMD_PTP_OP_MANFTEST_PACKET 0x9 /* enum */
+#define MC_CMD_PTP_OP_RESET_STATS 0xa /* enum */
+#define MC_CMD_PTP_OP_DEBUG 0xb /* enum */
+#define MC_CMD_PTP_OP_MAX 0xc /* enum */
+
+/* MC_CMD_PTP_IN_ENABLE msgrequest */
+#define MC_CMD_PTP_IN_ENABLE_LEN 16
+#define MC_CMD_PTP_IN_CMD_OFST 0
+#define MC_CMD_PTP_IN_PERIPH_ID_OFST 4
+#define MC_CMD_PTP_IN_ENABLE_QUEUE_OFST 8
+#define MC_CMD_PTP_IN_ENABLE_MODE_OFST 12
+#define MC_CMD_PTP_MODE_V1 0x0 /* enum */
+#define MC_CMD_PTP_MODE_V1_VLAN 0x1 /* enum */
+#define MC_CMD_PTP_MODE_V2 0x2 /* enum */
+#define MC_CMD_PTP_MODE_V2_VLAN 0x3 /* enum */
+
+/* MC_CMD_PTP_IN_DISABLE msgrequest */
+#define MC_CMD_PTP_IN_DISABLE_LEN 8
+/* MC_CMD_PTP_IN_CMD_OFST 0 */
+/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+
+/* MC_CMD_PTP_IN_TRANSMIT msgrequest */
+#define MC_CMD_PTP_IN_TRANSMIT_LENMIN 13
+#define MC_CMD_PTP_IN_TRANSMIT_LENMAX 255
+#define MC_CMD_PTP_IN_TRANSMIT_LEN(num) (12+1*(num))
+/* MC_CMD_PTP_IN_CMD_OFST 0 */
+/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+#define MC_CMD_PTP_IN_TRANSMIT_LENGTH_OFST 8
+#define MC_CMD_PTP_IN_TRANSMIT_PACKET_OFST 12
+#define MC_CMD_PTP_IN_TRANSMIT_PACKET_LEN 1
+#define MC_CMD_PTP_IN_TRANSMIT_PACKET_MINNUM 1
+#define MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM 243
+
+/* MC_CMD_PTP_IN_READ_NIC_TIME msgrequest */
+#define MC_CMD_PTP_IN_READ_NIC_TIME_LEN 8
+/* MC_CMD_PTP_IN_CMD_OFST 0 */
+/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+
+/* MC_CMD_PTP_IN_STATUS msgrequest */
+#define MC_CMD_PTP_IN_STATUS_LEN 8
+/* MC_CMD_PTP_IN_CMD_OFST 0 */
+/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+
+/* MC_CMD_PTP_IN_ADJUST msgrequest */
+#define MC_CMD_PTP_IN_ADJUST_LEN 24
+/* MC_CMD_PTP_IN_CMD_OFST 0 */
+/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+#define MC_CMD_PTP_IN_ADJUST_FREQ_OFST 8
+#define MC_CMD_PTP_IN_ADJUST_FREQ_LEN 8
+#define MC_CMD_PTP_IN_ADJUST_FREQ_LO_OFST 8
+#define MC_CMD_PTP_IN_ADJUST_FREQ_HI_OFST 12
+#define MC_CMD_PTP_IN_ADJUST_BITS 0x28 /* enum */
+#define MC_CMD_PTP_IN_ADJUST_SECONDS_OFST 16
+#define MC_CMD_PTP_IN_ADJUST_NANOSECONDS_OFST 20
+
+/* MC_CMD_PTP_IN_SYNCHRONIZE msgrequest */
+#define MC_CMD_PTP_IN_SYNCHRONIZE_LEN 20
+/* MC_CMD_PTP_IN_CMD_OFST 0 */
+/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+#define MC_CMD_PTP_IN_SYNCHRONIZE_NUMTIMESETS_OFST 8
+#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_OFST 12
+#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_LEN 8
+#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_LO_OFST 12
+#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_HI_OFST 16
+
+/* MC_CMD_PTP_IN_MANFTEST_BASIC msgrequest */
+#define MC_CMD_PTP_IN_MANFTEST_BASIC_LEN 8
+/* MC_CMD_PTP_IN_CMD_OFST 0 */
+/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+
+/* MC_CMD_PTP_IN_MANFTEST_PACKET msgrequest */
+#define MC_CMD_PTP_IN_MANFTEST_PACKET_LEN 12
+/* MC_CMD_PTP_IN_CMD_OFST 0 */
+/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+#define MC_CMD_PTP_IN_MANFTEST_PACKET_TEST_ENABLE_OFST 8
+
+/* MC_CMD_PTP_IN_RESET_STATS msgrequest */
+#define MC_CMD_PTP_IN_RESET_STATS_LEN 8
+/* MC_CMD_PTP_IN_CMD_OFST 0 */
+/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+
+/* MC_CMD_PTP_IN_DEBUG msgrequest */
+#define MC_CMD_PTP_IN_DEBUG_LEN 12
+/* MC_CMD_PTP_IN_CMD_OFST 0 */
+/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
+#define MC_CMD_PTP_IN_DEBUG_DEBUG_PARAM_OFST 8
+
+/* MC_CMD_PTP_OUT msgresponse */
+#define MC_CMD_PTP_OUT_LEN 0
+
+/* MC_CMD_PTP_OUT_TRANSMIT msgresponse */
+#define MC_CMD_PTP_OUT_TRANSMIT_LEN 8
+#define MC_CMD_PTP_OUT_TRANSMIT_SECONDS_OFST 0
+#define MC_CMD_PTP_OUT_TRANSMIT_NANOSECONDS_OFST 4
+
+/* MC_CMD_PTP_OUT_READ_NIC_TIME msgresponse */
+#define MC_CMD_PTP_OUT_READ_NIC_TIME_LEN 8
+#define MC_CMD_PTP_OUT_READ_NIC_TIME_SECONDS_OFST 0
+#define MC_CMD_PTP_OUT_READ_NIC_TIME_NANOSECONDS_OFST 4
+
+/* MC_CMD_PTP_OUT_STATUS msgresponse */
+#define MC_CMD_PTP_OUT_STATUS_LEN 64
+#define MC_CMD_PTP_OUT_STATUS_CLOCK_FREQ_OFST 0
+#define MC_CMD_PTP_OUT_STATUS_STATS_TX_OFST 4
+#define MC_CMD_PTP_OUT_STATUS_STATS_RX_OFST 8
+#define MC_CMD_PTP_OUT_STATUS_STATS_TS_OFST 12
+#define MC_CMD_PTP_OUT_STATUS_STATS_FM_OFST 16
+#define MC_CMD_PTP_OUT_STATUS_STATS_NFM_OFST 20
+#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFLOW_OFST 24
+#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_BAD_OFST 28
+#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MIN_OFST 32
+#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MAX_OFST 36
+#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_LAST_OFST 40
+#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MEAN_OFST 44
+#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MIN_OFST 48
+#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MAX_OFST 52
+#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_LAST_OFST 56
+#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MEAN_OFST 60
+
+/* MC_CMD_PTP_OUT_SYNCHRONIZE msgresponse */
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_LENMIN 20
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_LENMAX 240
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_LEN(num) (0+20*(num))
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_OFST 0
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_LEN 20
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_MINNUM 1
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_MAXNUM 12
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_HOSTSTART_OFST 0
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_SECONDS_OFST 4
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_NANOSECONDS_OFST 8
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_HOSTEND_OFST 12
+#define MC_CMD_PTP_OUT_SYNCHRONIZE_WAITNS_OFST 16
+
+/* MC_CMD_PTP_OUT_MANFTEST_BASIC msgresponse */
+#define MC_CMD_PTP_OUT_MANFTEST_BASIC_LEN 8
+#define MC_CMD_PTP_OUT_MANFTEST_BASIC_TEST_RESULT_OFST 0
+#define MC_CMD_PTP_MANF_SUCCESS 0x0 /* enum */
+#define MC_CMD_PTP_MANF_FPGA_LOAD 0x1 /* enum */
+#define MC_CMD_PTP_MANF_FPGA_VERSION 0x2 /* enum */
+#define MC_CMD_PTP_MANF_FPGA_REGISTERS 0x3 /* enum */
+#define MC_CMD_PTP_MANF_OSCILLATOR 0x4 /* enum */
+#define MC_CMD_PTP_MANF_TIMESTAMPS 0x5 /* enum */
+#define MC_CMD_PTP_MANF_PACKET_COUNT 0x6 /* enum */
+#define MC_CMD_PTP_MANF_FILTER_COUNT 0x7 /* enum */
+#define MC_CMD_PTP_MANF_PACKET_ENOUGH 0x8 /* enum */
+#define MC_CMD_PTP_MANF_GPIO_TRIGGER 0x9 /* enum */
+#define MC_CMD_PTP_OUT_MANFTEST_BASIC_TEST_EXTOSC_OFST 4
+
+/* MC_CMD_PTP_OUT_MANFTEST_PACKET msgresponse */
+#define MC_CMD_PTP_OUT_MANFTEST_PACKET_LEN 12
+#define MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_RESULT_OFST 0
+#define MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_FPGACOUNT_OFST 4
+#define MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_FILTERCOUNT_OFST 8
+
+
+/***********************************/
+/* MC_CMD_CSR_READ32
+ * Read 32bit words from the indirect memory map.
+ */
+#define MC_CMD_CSR_READ32 0xc
+
+/* MC_CMD_CSR_READ32_IN msgrequest */
+#define MC_CMD_CSR_READ32_IN_LEN 12
+#define MC_CMD_CSR_READ32_IN_ADDR_OFST 0
+#define MC_CMD_CSR_READ32_IN_STEP_OFST 4
+#define MC_CMD_CSR_READ32_IN_NUMWORDS_OFST 8
+
+/* MC_CMD_CSR_READ32_OUT msgresponse */
+#define MC_CMD_CSR_READ32_OUT_LENMIN 4
+#define MC_CMD_CSR_READ32_OUT_LENMAX 252
+#define MC_CMD_CSR_READ32_OUT_LEN(num) (0+4*(num))
+#define MC_CMD_CSR_READ32_OUT_BUFFER_OFST 0
+#define MC_CMD_CSR_READ32_OUT_BUFFER_LEN 4
+#define MC_CMD_CSR_READ32_OUT_BUFFER_MINNUM 1
+#define MC_CMD_CSR_READ32_OUT_BUFFER_MAXNUM 63
+
+
+/***********************************/
+/* MC_CMD_CSR_WRITE32
+ * Write 32bit dwords to the indirect memory map.
+ */
+#define MC_CMD_CSR_WRITE32 0xd
+
+/* MC_CMD_CSR_WRITE32_IN msgrequest */
+#define MC_CMD_CSR_WRITE32_IN_LENMIN 12
+#define MC_CMD_CSR_WRITE32_IN_LENMAX 252
+#define MC_CMD_CSR_WRITE32_IN_LEN(num) (8+4*(num))
+#define MC_CMD_CSR_WRITE32_IN_ADDR_OFST 0
+#define MC_CMD_CSR_WRITE32_IN_STEP_OFST 4
+#define MC_CMD_CSR_WRITE32_IN_BUFFER_OFST 8
+#define MC_CMD_CSR_WRITE32_IN_BUFFER_LEN 4
+#define MC_CMD_CSR_WRITE32_IN_BUFFER_MINNUM 1
+#define MC_CMD_CSR_WRITE32_IN_BUFFER_MAXNUM 61
+
+/* MC_CMD_CSR_WRITE32_OUT msgresponse */
+#define MC_CMD_CSR_WRITE32_OUT_LEN 4
+#define MC_CMD_CSR_WRITE32_OUT_STATUS_OFST 0
+
+
+/***********************************/
+/* MC_CMD_STACKINFO
+ * Get stack information.
+ */
+#define MC_CMD_STACKINFO 0xf
+
+/* MC_CMD_STACKINFO_IN msgrequest */
+#define MC_CMD_STACKINFO_IN_LEN 0
+
+/* MC_CMD_STACKINFO_OUT msgresponse */
+#define MC_CMD_STACKINFO_OUT_LENMIN 12
+#define MC_CMD_STACKINFO_OUT_LENMAX 252
+#define MC_CMD_STACKINFO_OUT_LEN(num) (0+12*(num))
+#define MC_CMD_STACKINFO_OUT_THREAD_INFO_OFST 0
+#define MC_CMD_STACKINFO_OUT_THREAD_INFO_LEN 12
+#define MC_CMD_STACKINFO_OUT_THREAD_INFO_MINNUM 1
+#define MC_CMD_STACKINFO_OUT_THREAD_INFO_MAXNUM 21
+
+
+/***********************************/
+/* MC_CMD_MDIO_READ
+ * MDIO register read.
*/
#define MC_CMD_MDIO_READ 0x10
-#define MC_CMD_MDIO_READ_IN_LEN 16
-#define MC_CMD_MDIO_READ_IN_BUS_OFST 0
-#define MC_CMD_MDIO_READ_IN_PRTAD_OFST 4
-#define MC_CMD_MDIO_READ_IN_DEVAD_OFST 8
-#define MC_CMD_MDIO_READ_IN_ADDR_OFST 12
-#define MC_CMD_MDIO_READ_OUT_LEN 8
-#define MC_CMD_MDIO_READ_OUT_VALUE_OFST 0
-#define MC_CMD_MDIO_READ_OUT_STATUS_OFST 4
-
-/* MC_CMD_MDIO_WRITE:
- * MDIO register write
- */
-#define MC_CMD_MDIO_WRITE 0x11
-#define MC_CMD_MDIO_WRITE_IN_LEN 20
-#define MC_CMD_MDIO_WRITE_IN_BUS_OFST 0
-#define MC_CMD_MDIO_WRITE_IN_PRTAD_OFST 4
-#define MC_CMD_MDIO_WRITE_IN_DEVAD_OFST 8
-#define MC_CMD_MDIO_WRITE_IN_ADDR_OFST 12
-#define MC_CMD_MDIO_WRITE_IN_VALUE_OFST 16
-#define MC_CMD_MDIO_WRITE_OUT_LEN 4
-#define MC_CMD_MDIO_WRITE_OUT_STATUS_OFST 0
-/* By default all the MCDI MDIO operations perform clause45 mode.
- * If you want to use clause22 then set DEVAD = MC_CMD_MDIO_CLAUSE22.
- */
-#define MC_CMD_MDIO_CLAUSE22 32
+/* MC_CMD_MDIO_READ_IN msgrequest */
+#define MC_CMD_MDIO_READ_IN_LEN 16
+#define MC_CMD_MDIO_READ_IN_BUS_OFST 0
+#define MC_CMD_MDIO_BUS_INTERNAL 0x0 /* enum */
+#define MC_CMD_MDIO_BUS_EXTERNAL 0x1 /* enum */
+#define MC_CMD_MDIO_READ_IN_PRTAD_OFST 4
+#define MC_CMD_MDIO_READ_IN_DEVAD_OFST 8
+#define MC_CMD_MDIO_CLAUSE22 0x20 /* enum */
+#define MC_CMD_MDIO_READ_IN_ADDR_OFST 12
-/* There are two MDIO buses: one for the internal PHY, and one for external
- * devices.
- */
-#define MC_CMD_MDIO_BUS_INTERNAL 0
-#define MC_CMD_MDIO_BUS_EXTERNAL 1
+/* MC_CMD_MDIO_READ_OUT msgresponse */
+#define MC_CMD_MDIO_READ_OUT_LEN 8
+#define MC_CMD_MDIO_READ_OUT_VALUE_OFST 0
+#define MC_CMD_MDIO_READ_OUT_STATUS_OFST 4
+#define MC_CMD_MDIO_STATUS_GOOD 0x8 /* enum */
-/* The MDIO commands return the raw status bits from the MDIO block. A "good"
- * transaction should have the DONE bit set and all other bits clear.
+
+/***********************************/
+/* MC_CMD_MDIO_WRITE
+ * MDIO register write.
*/
-#define MC_CMD_MDIO_STATUS_GOOD 0x08
+#define MC_CMD_MDIO_WRITE 0x11
+/* MC_CMD_MDIO_WRITE_IN msgrequest */
+#define MC_CMD_MDIO_WRITE_IN_LEN 20
+#define MC_CMD_MDIO_WRITE_IN_BUS_OFST 0
+/* MC_CMD_MDIO_BUS_INTERNAL 0x0 */
+/* MC_CMD_MDIO_BUS_EXTERNAL 0x1 */
+#define MC_CMD_MDIO_WRITE_IN_PRTAD_OFST 4
+#define MC_CMD_MDIO_WRITE_IN_DEVAD_OFST 8
+/* MC_CMD_MDIO_CLAUSE22 0x20 */
+#define MC_CMD_MDIO_WRITE_IN_ADDR_OFST 12
+#define MC_CMD_MDIO_WRITE_IN_VALUE_OFST 16
-/* MC_CMD_DBI_WRITE: (debug)
- * Write DBI register(s)
- *
- * Host: address, byte-enables (and VF selection, and cs2 flag),
- * value [,address ...]
- * MC: nothing
+/* MC_CMD_MDIO_WRITE_OUT msgresponse */
+#define MC_CMD_MDIO_WRITE_OUT_LEN 4
+#define MC_CMD_MDIO_WRITE_OUT_STATUS_OFST 0
+/* MC_CMD_MDIO_STATUS_GOOD 0x8 */
+
+
+/***********************************/
+/* MC_CMD_DBI_WRITE
+ * Write DBI register(s).
*/
#define MC_CMD_DBI_WRITE 0x12
-#define MC_CMD_DBI_WRITE_IN_LEN(_numwords) \
- (12 * (_numwords))
-#define MC_CMD_DBI_WRITE_IN_ADDRESS_OFST(_word) \
- (((_word) * 12) + 0)
-#define MC_CMD_DBI_WRITE_IN_BYTE_MASK_OFST(_word) \
- (((_word) * 12) + 4)
-#define MC_CMD_DBI_WRITE_IN_VALUE_OFST(_word) \
- (((_word) * 12) + 8)
-#define MC_CMD_DBI_WRITE_OUT_LEN 0
-
-/* MC_CMD_DBI_READ: (debug)
- * Read DBI register(s)
- *
- * Host: address, [,address ...]
- * MC: value [,value ...]
- * (note: this does not support reading from VFs, but is retained for backwards
- * compatibility; see MC_CMD_DBI_READX below)
- */
-#define MC_CMD_DBI_READ 0x13
-#define MC_CMD_DBI_READ_IN_LEN(_numwords) \
- (4 * (_numwords))
-#define MC_CMD_DBI_READ_OUT_LEN(_numwords) \
- (4 * (_numwords))
-
-/* MC_CMD_PORT_READ32: (debug)
+
+/* MC_CMD_DBI_WRITE_IN msgrequest */
+#define MC_CMD_DBI_WRITE_IN_LENMIN 12
+#define MC_CMD_DBI_WRITE_IN_LENMAX 252
+#define MC_CMD_DBI_WRITE_IN_LEN(num) (0+12*(num))
+#define MC_CMD_DBI_WRITE_IN_DBIWROP_OFST 0
+#define MC_CMD_DBI_WRITE_IN_DBIWROP_LEN 12
+#define MC_CMD_DBI_WRITE_IN_DBIWROP_MINNUM 1
+#define MC_CMD_DBI_WRITE_IN_DBIWROP_MAXNUM 21
+
+/* MC_CMD_DBI_WRITE_OUT msgresponse */
+#define MC_CMD_DBI_WRITE_OUT_LEN 0
+
+/* MC_CMD_DBIWROP_TYPEDEF structuredef */
+#define MC_CMD_DBIWROP_TYPEDEF_LEN 12
+#define MC_CMD_DBIWROP_TYPEDEF_ADDRESS_OFST 0
+#define MC_CMD_DBIWROP_TYPEDEF_ADDRESS_LBN 0
+#define MC_CMD_DBIWROP_TYPEDEF_ADDRESS_WIDTH 32
+#define MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_OFST 4
+#define MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_LBN 32
+#define MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_WIDTH 32
+#define MC_CMD_DBIWROP_TYPEDEF_VALUE_OFST 8
+#define MC_CMD_DBIWROP_TYPEDEF_VALUE_LBN 64
+#define MC_CMD_DBIWROP_TYPEDEF_VALUE_WIDTH 32
+
+
+/***********************************/
+/* MC_CMD_PORT_READ32
* Read a 32-bit register from the indirect port register map.
- *
- * The port to access is implied by the Shared memory channel used.
*/
#define MC_CMD_PORT_READ32 0x14
-#define MC_CMD_PORT_READ32_IN_LEN 4
-#define MC_CMD_PORT_READ32_IN_ADDR_OFST 0
-#define MC_CMD_PORT_READ32_OUT_LEN 8
-#define MC_CMD_PORT_READ32_OUT_VALUE_OFST 0
-#define MC_CMD_PORT_READ32_OUT_STATUS_OFST 4
-/* MC_CMD_PORT_WRITE32: (debug)
+/* MC_CMD_PORT_READ32_IN msgrequest */
+#define MC_CMD_PORT_READ32_IN_LEN 4
+#define MC_CMD_PORT_READ32_IN_ADDR_OFST 0
+
+/* MC_CMD_PORT_READ32_OUT msgresponse */
+#define MC_CMD_PORT_READ32_OUT_LEN 8
+#define MC_CMD_PORT_READ32_OUT_VALUE_OFST 0
+#define MC_CMD_PORT_READ32_OUT_STATUS_OFST 4
+
+
+/***********************************/
+/* MC_CMD_PORT_WRITE32
* Write a 32-bit register to the indirect port register map.
- *
- * The port to access is implied by the Shared memory channel used.
*/
#define MC_CMD_PORT_WRITE32 0x15
-#define MC_CMD_PORT_WRITE32_IN_LEN 8
-#define MC_CMD_PORT_WRITE32_IN_ADDR_OFST 0
-#define MC_CMD_PORT_WRITE32_IN_VALUE_OFST 4
-#define MC_CMD_PORT_WRITE32_OUT_LEN 4
-#define MC_CMD_PORT_WRITE32_OUT_STATUS_OFST 0
-
-/* MC_CMD_PORT_READ128: (debug)
- * Read a 128-bit register from indirect port register map
- *
- * The port to access is implied by the Shared memory channel used.
+
+/* MC_CMD_PORT_WRITE32_IN msgrequest */
+#define MC_CMD_PORT_WRITE32_IN_LEN 8
+#define MC_CMD_PORT_WRITE32_IN_ADDR_OFST 0
+#define MC_CMD_PORT_WRITE32_IN_VALUE_OFST 4
+
+/* MC_CMD_PORT_WRITE32_OUT msgresponse */
+#define MC_CMD_PORT_WRITE32_OUT_LEN 4
+#define MC_CMD_PORT_WRITE32_OUT_STATUS_OFST 0
+
+
+/***********************************/
+/* MC_CMD_PORT_READ128
+ * Read a 128-bit register from the indirect port register map.
*/
#define MC_CMD_PORT_READ128 0x16
-#define MC_CMD_PORT_READ128_IN_LEN 4
-#define MC_CMD_PORT_READ128_IN_ADDR_OFST 0
-#define MC_CMD_PORT_READ128_OUT_LEN 20
-#define MC_CMD_PORT_READ128_OUT_VALUE_OFST 0
-#define MC_CMD_PORT_READ128_OUT_STATUS_OFST 16
-
-/* MC_CMD_PORT_WRITE128: (debug)
- * Write a 128-bit register to indirect port register map.
- *
- * The port to access is implied by the Shared memory channel used.
+
+/* MC_CMD_PORT_READ128_IN msgrequest */
+#define MC_CMD_PORT_READ128_IN_LEN 4
+#define MC_CMD_PORT_READ128_IN_ADDR_OFST 0
+
+/* MC_CMD_PORT_READ128_OUT msgresponse */
+#define MC_CMD_PORT_READ128_OUT_LEN 20
+#define MC_CMD_PORT_READ128_OUT_VALUE_OFST 0
+#define MC_CMD_PORT_READ128_OUT_VALUE_LEN 16
+#define MC_CMD_PORT_READ128_OUT_STATUS_OFST 16
+
+
+/***********************************/
+/* MC_CMD_PORT_WRITE128
+ * Write a 128-bit register to the indirect port register map.
*/
#define MC_CMD_PORT_WRITE128 0x17
-#define MC_CMD_PORT_WRITE128_IN_LEN 20
-#define MC_CMD_PORT_WRITE128_IN_ADDR_OFST 0
-#define MC_CMD_PORT_WRITE128_IN_VALUE_OFST 4
-#define MC_CMD_PORT_WRITE128_OUT_LEN 4
-#define MC_CMD_PORT_WRITE128_OUT_STATUS_OFST 0
-
-/* MC_CMD_GET_BOARD_CFG:
- * Returns the MC firmware configuration structure
- *
- * The FW_SUBTYPE_LIST contains a 16-bit value for each of the 12 types of
- * NVRAM area. The values are defined in the firmware/mc/platform/<xxx>.c file
- * for a specific board type, but otherwise have no meaning to the MC; they
- * are used by the driver to manage selection of appropriate firmware updates.
+
+/* MC_CMD_PORT_WRITE128_IN msgrequest */
+#define MC_CMD_PORT_WRITE128_IN_LEN 20
+#define MC_CMD_PORT_WRITE128_IN_ADDR_OFST 0
+#define MC_CMD_PORT_WRITE128_IN_VALUE_OFST 4
+#define MC_CMD_PORT_WRITE128_IN_VALUE_LEN 16
+
+/* MC_CMD_PORT_WRITE128_OUT msgresponse */
+#define MC_CMD_PORT_WRITE128_OUT_LEN 4
+#define MC_CMD_PORT_WRITE128_OUT_STATUS_OFST 0
+
+
+/***********************************/
+/* MC_CMD_GET_BOARD_CFG
+ * Returns the MC firmware configuration structure.
*/
#define MC_CMD_GET_BOARD_CFG 0x18
-#define MC_CMD_GET_BOARD_CFG_IN_LEN 0
-#define MC_CMD_GET_BOARD_CFG_OUT_LEN 96
-#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_TYPE_OFST 0
-#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_OFST 4
-#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_LEN 32
-#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT0_OFST 36
-#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT1_OFST 40
-#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST 44
-#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_LEN 6
-#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST 50
-#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_LEN 6
-#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT0_OFST 56
-#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT1_OFST 60
-#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT0_OFST 64
-#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT1_OFST 68
-#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST 72
-#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN 24
-
-/* MC_CMD_DBI_READX: (debug)
- * Read DBI register(s) -- extended functionality
- *
- * Host: vf selection, address, [,vf selection ...]
- * MC: value [,value ...]
+
+/* MC_CMD_GET_BOARD_CFG_IN msgrequest */
+#define MC_CMD_GET_BOARD_CFG_IN_LEN 0
+
+/* MC_CMD_GET_BOARD_CFG_OUT msgresponse */
+#define MC_CMD_GET_BOARD_CFG_OUT_LENMIN 96
+#define MC_CMD_GET_BOARD_CFG_OUT_LENMAX 136
+#define MC_CMD_GET_BOARD_CFG_OUT_LEN(num) (72+2*(num))
+#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_TYPE_OFST 0
+#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_OFST 4
+#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_LEN 32
+#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT0_OFST 36
+#define MC_CMD_CAPABILITIES_SMALL_BUF_TBL_LBN 0x0 /* enum */
+#define MC_CMD_CAPABILITIES_SMALL_BUF_TBL_WIDTH 0x1 /* enum */
+#define MC_CMD_CAPABILITIES_TURBO_LBN 0x1 /* enum */
+#define MC_CMD_CAPABILITIES_TURBO_WIDTH 0x1 /* enum */
+#define MC_CMD_CAPABILITIES_TURBO_ACTIVE_LBN 0x2 /* enum */
+#define MC_CMD_CAPABILITIES_TURBO_ACTIVE_WIDTH 0x1 /* enum */
+#define MC_CMD_CAPABILITIES_PTP_LBN 0x3 /* enum */
+#define MC_CMD_CAPABILITIES_PTP_WIDTH 0x1 /* enum */
+#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT1_OFST 40
+/* Enum values, see field(s): */
+/* CAPABILITIES_PORT0 */
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST 44
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_LEN 6
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST 50
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_LEN 6
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT0_OFST 56
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT1_OFST 60
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT0_OFST 64
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT1_OFST 68
+#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST 72
+#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN 2
+#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM 12
+#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM 32
+
+
+/***********************************/
+/* MC_CMD_DBI_READX
+ * Read DBI register(s).
*/
#define MC_CMD_DBI_READX 0x19
-#define MC_CMD_DBI_READX_IN_LEN(_numwords) \
- (8*(_numwords))
-#define MC_CMD_DBI_READX_OUT_LEN(_numwords) \
- (4*(_numwords))
-/* MC_CMD_SET_RAND_SEED:
- * Set the 16byte seed for the MC pseudo-random generator
+/* MC_CMD_DBI_READX_IN msgrequest */
+#define MC_CMD_DBI_READX_IN_LENMIN 8
+#define MC_CMD_DBI_READX_IN_LENMAX 248
+#define MC_CMD_DBI_READX_IN_LEN(num) (0+8*(num))
+#define MC_CMD_DBI_READX_IN_DBIRDOP_OFST 0
+#define MC_CMD_DBI_READX_IN_DBIRDOP_LEN 8
+#define MC_CMD_DBI_READX_IN_DBIRDOP_LO_OFST 0
+#define MC_CMD_DBI_READX_IN_DBIRDOP_HI_OFST 4
+#define MC_CMD_DBI_READX_IN_DBIRDOP_MINNUM 1
+#define MC_CMD_DBI_READX_IN_DBIRDOP_MAXNUM 31
+
+/* MC_CMD_DBI_READX_OUT msgresponse */
+#define MC_CMD_DBI_READX_OUT_LENMIN 4
+#define MC_CMD_DBI_READX_OUT_LENMAX 252
+#define MC_CMD_DBI_READX_OUT_LEN(num) (0+4*(num))
+#define MC_CMD_DBI_READX_OUT_VALUE_OFST 0
+#define MC_CMD_DBI_READX_OUT_VALUE_LEN 4
+#define MC_CMD_DBI_READX_OUT_VALUE_MINNUM 1
+#define MC_CMD_DBI_READX_OUT_VALUE_MAXNUM 63
+
+
+/***********************************/
+/* MC_CMD_SET_RAND_SEED
+ * Set the 16byte seed for the MC pseudo-random generator.
*/
#define MC_CMD_SET_RAND_SEED 0x1a
-#define MC_CMD_SET_RAND_SEED_IN_LEN 16
-#define MC_CMD_SET_RAND_SEED_IN_SEED_OFST 0
-#define MC_CMD_SET_RAND_SEED_OUT_LEN 0
-/* MC_CMD_LTSSM_HIST: (debug)
- * Retrieve the history of the LTSSM, if the build supports it.
- *
- * Host: nothing
- * MC: variable number of LTSSM values, as bytes
- * The history is read-to-clear.
+/* MC_CMD_SET_RAND_SEED_IN msgrequest */
+#define MC_CMD_SET_RAND_SEED_IN_LEN 16
+#define MC_CMD_SET_RAND_SEED_IN_SEED_OFST 0
+#define MC_CMD_SET_RAND_SEED_IN_SEED_LEN 16
+
+/* MC_CMD_SET_RAND_SEED_OUT msgresponse */
+#define MC_CMD_SET_RAND_SEED_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_LTSSM_HIST
+ * Retrieve the history of the PCIE LTSSM.
*/
#define MC_CMD_LTSSM_HIST 0x1b
-/* MC_CMD_DRV_ATTACH:
- * Inform MCPU that this port is managed on the host (i.e. driver active)
+/* MC_CMD_LTSSM_HIST_IN msgrequest */
+#define MC_CMD_LTSSM_HIST_IN_LEN 0
+
+/* MC_CMD_LTSSM_HIST_OUT msgresponse */
+#define MC_CMD_LTSSM_HIST_OUT_LENMIN 0
+#define MC_CMD_LTSSM_HIST_OUT_LENMAX 252
+#define MC_CMD_LTSSM_HIST_OUT_LEN(num) (0+4*(num))
+#define MC_CMD_LTSSM_HIST_OUT_DATA_OFST 0
+#define MC_CMD_LTSSM_HIST_OUT_DATA_LEN 4
+#define MC_CMD_LTSSM_HIST_OUT_DATA_MINNUM 0
+#define MC_CMD_LTSSM_HIST_OUT_DATA_MAXNUM 63
+
+
+/***********************************/
+/* MC_CMD_DRV_ATTACH
+ * Inform MCPU that this port is managed on the host.
*/
#define MC_CMD_DRV_ATTACH 0x1c
-#define MC_CMD_DRV_ATTACH_IN_LEN 8
-#define MC_CMD_DRV_ATTACH_IN_NEW_STATE_OFST 0
-#define MC_CMD_DRV_ATTACH_IN_UPDATE_OFST 4
-#define MC_CMD_DRV_ATTACH_OUT_LEN 4
-#define MC_CMD_DRV_ATTACH_OUT_OLD_STATE_OFST 0
-/* MC_CMD_NCSI_PROD: (debug)
- * Trigger an NC-SI event (and possibly an AEN in response)
+/* MC_CMD_DRV_ATTACH_IN msgrequest */
+#define MC_CMD_DRV_ATTACH_IN_LEN 8
+#define MC_CMD_DRV_ATTACH_IN_NEW_STATE_OFST 0
+#define MC_CMD_DRV_ATTACH_IN_UPDATE_OFST 4
+
+/* MC_CMD_DRV_ATTACH_OUT msgresponse */
+#define MC_CMD_DRV_ATTACH_OUT_LEN 4
+#define MC_CMD_DRV_ATTACH_OUT_OLD_STATE_OFST 0
+
+
+/***********************************/
+/* MC_CMD_NCSI_PROD
+ * Trigger an NC-SI event.
*/
#define MC_CMD_NCSI_PROD 0x1d
-#define MC_CMD_NCSI_PROD_IN_LEN 4
-#define MC_CMD_NCSI_PROD_IN_EVENTS_OFST 0
-#define MC_CMD_NCSI_PROD_LINKCHANGE_LBN 0
-#define MC_CMD_NCSI_PROD_LINKCHANGE_WIDTH 1
-#define MC_CMD_NCSI_PROD_RESET_LBN 1
-#define MC_CMD_NCSI_PROD_RESET_WIDTH 1
-#define MC_CMD_NCSI_PROD_DRVATTACH_LBN 2
-#define MC_CMD_NCSI_PROD_DRVATTACH_WIDTH 1
-#define MC_CMD_NCSI_PROD_OUT_LEN 0
-
-/* Enumeration */
-#define MC_CMD_NCSI_PROD_LINKCHANGE 0
-#define MC_CMD_NCSI_PROD_RESET 1
-#define MC_CMD_NCSI_PROD_DRVATTACH 2
-
-/* MC_CMD_DEVEL: (debug)
- * Reserved for development
- */
-#define MC_CMD_DEVEL 0x1e
-
-/* MC_CMD_SHMUART: (debug)
+
+/* MC_CMD_NCSI_PROD_IN msgrequest */
+#define MC_CMD_NCSI_PROD_IN_LEN 4
+#define MC_CMD_NCSI_PROD_IN_EVENTS_OFST 0
+#define MC_CMD_NCSI_PROD_LINKCHANGE 0x0 /* enum */
+#define MC_CMD_NCSI_PROD_RESET 0x1 /* enum */
+#define MC_CMD_NCSI_PROD_DRVATTACH 0x2 /* enum */
+#define MC_CMD_NCSI_PROD_IN_LINKCHANGE_LBN 0
+#define MC_CMD_NCSI_PROD_IN_LINKCHANGE_WIDTH 1
+#define MC_CMD_NCSI_PROD_IN_RESET_LBN 1
+#define MC_CMD_NCSI_PROD_IN_RESET_WIDTH 1
+#define MC_CMD_NCSI_PROD_IN_DRVATTACH_LBN 2
+#define MC_CMD_NCSI_PROD_IN_DRVATTACH_WIDTH 1
+
+/* MC_CMD_NCSI_PROD_OUT msgresponse */
+#define MC_CMD_NCSI_PROD_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SHMUART
* Route UART output to circular buffer in shared memory instead.
*/
#define MC_CMD_SHMUART 0x1f
-#define MC_CMD_SHMUART_IN_FLAG_OFST 0
-#define MC_CMD_SHMUART_IN_LEN 4
-#define MC_CMD_SHMUART_OUT_LEN 0
-/* MC_CMD_PORT_RESET:
- * Generic per-port reset. There is no equivalent for per-board reset.
- *
- * Locks required: None
- * Return code: 0, ETIME
- */
-#define MC_CMD_PORT_RESET 0x20
-#define MC_CMD_PORT_RESET_IN_LEN 0
-#define MC_CMD_PORT_RESET_OUT_LEN 0
-
-/* MC_CMD_RESOURCE_LOCK:
- * Generic resource lock/unlock interface.
- *
- * Locks required: None
- * Return code: 0,
- * EBUSY (if trylock is contended by other port),
- * EDEADLK (if trylock is already acquired by this port)
- * EINVAL (if unlock doesn't own the lock)
- */
-#define MC_CMD_RESOURCE_LOCK 0x21
-#define MC_CMD_RESOURCE_LOCK_IN_LEN 8
-#define MC_CMD_RESOURCE_LOCK_IN_ACTION_OFST 0
-#define MC_CMD_RESOURCE_LOCK_ACTION_TRYLOCK 1
-#define MC_CMD_RESOURCE_LOCK_ACTION_UNLOCK 0
-#define MC_CMD_RESOURCE_LOCK_IN_RESOURCE_OFST 4
-#define MC_CMD_RESOURCE_LOCK_I2C 2
-#define MC_CMD_RESOURCE_LOCK_PHY 3
-#define MC_CMD_RESOURCE_LOCK_OUT_LEN 0
-
-/* MC_CMD_SPI_COMMAND: (variadic in, variadic out)
- * Read/Write to/from the SPI device.
- *
- * Locks required: SPI_LOCK
- * Return code: 0, ETIME, EINVAL, EACCES (if SPI_LOCK is not held)
- */
-#define MC_CMD_SPI_COMMAND 0x22
-#define MC_CMD_SPI_COMMAND_IN_LEN(_write_bytes) (12 + (_write_bytes))
-#define MC_CMD_SPI_COMMAND_IN_ARGS_OFST 0
-#define MC_CMD_SPI_COMMAND_IN_ARGS_ADDRESS_OFST 0
-#define MC_CMD_SPI_COMMAND_IN_ARGS_READ_BYTES_OFST 4
-#define MC_CMD_SPI_COMMAND_IN_ARGS_CHIP_SELECT_OFST 8
-/* Data to write here */
-#define MC_CMD_SPI_COMMAND_IN_WRITE_BUFFER_OFST 12
-#define MC_CMD_SPI_COMMAND_OUT_LEN(_read_bytes) (_read_bytes)
-/* Data read here */
-#define MC_CMD_SPI_COMMAND_OUT_READ_BUFFER_OFST 0
-
-/* MC_CMD_I2C_READ_WRITE: (variadic in, variadic out)
- * Read/Write to/from the I2C bus.
- *
- * Locks required: I2C_LOCK
- * Return code: 0, ETIME, EINVAL, EACCES (if I2C_LOCK is not held)
- */
-#define MC_CMD_I2C_RW 0x23
-#define MC_CMD_I2C_RW_IN_LEN(_write_bytes) (8 + (_write_bytes))
-#define MC_CMD_I2C_RW_IN_ARGS_OFST 0
-#define MC_CMD_I2C_RW_IN_ARGS_ADDR_OFST 0
-#define MC_CMD_I2C_RW_IN_ARGS_READ_BYTES_OFST 4
-/* Data to write here */
-#define MC_CMD_I2C_RW_IN_WRITE_BUFFER_OFSET 8
-#define MC_CMD_I2C_RW_OUT_LEN(_read_bytes) (_read_bytes)
-/* Data read here */
-#define MC_CMD_I2C_RW_OUT_READ_BUFFER_OFST 0
-
-/* Generic phy capability bitmask */
-#define MC_CMD_PHY_CAP_10HDX_LBN 1
-#define MC_CMD_PHY_CAP_10HDX_WIDTH 1
-#define MC_CMD_PHY_CAP_10FDX_LBN 2
-#define MC_CMD_PHY_CAP_10FDX_WIDTH 1
-#define MC_CMD_PHY_CAP_100HDX_LBN 3
-#define MC_CMD_PHY_CAP_100HDX_WIDTH 1
-#define MC_CMD_PHY_CAP_100FDX_LBN 4
-#define MC_CMD_PHY_CAP_100FDX_WIDTH 1
-#define MC_CMD_PHY_CAP_1000HDX_LBN 5
-#define MC_CMD_PHY_CAP_1000HDX_WIDTH 1
-#define MC_CMD_PHY_CAP_1000FDX_LBN 6
-#define MC_CMD_PHY_CAP_1000FDX_WIDTH 1
-#define MC_CMD_PHY_CAP_10000FDX_LBN 7
-#define MC_CMD_PHY_CAP_10000FDX_WIDTH 1
-#define MC_CMD_PHY_CAP_PAUSE_LBN 8
-#define MC_CMD_PHY_CAP_PAUSE_WIDTH 1
-#define MC_CMD_PHY_CAP_ASYM_LBN 9
-#define MC_CMD_PHY_CAP_ASYM_WIDTH 1
-#define MC_CMD_PHY_CAP_AN_LBN 10
-#define MC_CMD_PHY_CAP_AN_WIDTH 1
-
-/* Generic loopback enumeration */
-#define MC_CMD_LOOPBACK_NONE 0
-#define MC_CMD_LOOPBACK_DATA 1
-#define MC_CMD_LOOPBACK_GMAC 2
-#define MC_CMD_LOOPBACK_XGMII 3
-#define MC_CMD_LOOPBACK_XGXS 4
-#define MC_CMD_LOOPBACK_XAUI 5
-#define MC_CMD_LOOPBACK_GMII 6
-#define MC_CMD_LOOPBACK_SGMII 7
-#define MC_CMD_LOOPBACK_XGBR 8
-#define MC_CMD_LOOPBACK_XFI 9
-#define MC_CMD_LOOPBACK_XAUI_FAR 10
-#define MC_CMD_LOOPBACK_GMII_FAR 11
-#define MC_CMD_LOOPBACK_SGMII_FAR 12
-#define MC_CMD_LOOPBACK_XFI_FAR 13
-#define MC_CMD_LOOPBACK_GPHY 14
-#define MC_CMD_LOOPBACK_PHYXS 15
-#define MC_CMD_LOOPBACK_PCS 16
-#define MC_CMD_LOOPBACK_PMAPMD 17
-#define MC_CMD_LOOPBACK_XPORT 18
-#define MC_CMD_LOOPBACK_XGMII_WS 19
-#define MC_CMD_LOOPBACK_XAUI_WS 20
-#define MC_CMD_LOOPBACK_XAUI_WS_FAR 21
-#define MC_CMD_LOOPBACK_XAUI_WS_NEAR 22
-#define MC_CMD_LOOPBACK_GMII_WS 23
-#define MC_CMD_LOOPBACK_XFI_WS 24
-#define MC_CMD_LOOPBACK_XFI_WS_FAR 25
-#define MC_CMD_LOOPBACK_PHYXS_WS 26
-
-/* Generic PHY statistics enumeration */
-#define MC_CMD_OUI 0
-#define MC_CMD_PMA_PMD_LINK_UP 1
-#define MC_CMD_PMA_PMD_RX_FAULT 2
-#define MC_CMD_PMA_PMD_TX_FAULT 3
-#define MC_CMD_PMA_PMD_SIGNAL 4
-#define MC_CMD_PMA_PMD_SNR_A 5
-#define MC_CMD_PMA_PMD_SNR_B 6
-#define MC_CMD_PMA_PMD_SNR_C 7
-#define MC_CMD_PMA_PMD_SNR_D 8
-#define MC_CMD_PCS_LINK_UP 9
-#define MC_CMD_PCS_RX_FAULT 10
-#define MC_CMD_PCS_TX_FAULT 11
-#define MC_CMD_PCS_BER 12
-#define MC_CMD_PCS_BLOCK_ERRORS 13
-#define MC_CMD_PHYXS_LINK_UP 14
-#define MC_CMD_PHYXS_RX_FAULT 15
-#define MC_CMD_PHYXS_TX_FAULT 16
-#define MC_CMD_PHYXS_ALIGN 17
-#define MC_CMD_PHYXS_SYNC 18
-#define MC_CMD_AN_LINK_UP 19
-#define MC_CMD_AN_COMPLETE 20
-#define MC_CMD_AN_10GBT_STATUS 21
-#define MC_CMD_CL22_LINK_UP 22
-#define MC_CMD_PHY_NSTATS 23
-
-/* MC_CMD_GET_PHY_CFG:
- * Report PHY configuration. This guarantees to succeed even if the PHY is in
- * a "zombie" state.
- *
- * Locks required: None
- * Return code: 0
+/* MC_CMD_SHMUART_IN msgrequest */
+#define MC_CMD_SHMUART_IN_LEN 4
+#define MC_CMD_SHMUART_IN_FLAG_OFST 0
+
+/* MC_CMD_SHMUART_OUT msgresponse */
+#define MC_CMD_SHMUART_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_ENTITY_RESET
+ * Generic per-port reset.
+ */
+#define MC_CMD_ENTITY_RESET 0x20
+
+/* MC_CMD_ENTITY_RESET_IN msgrequest */
+#define MC_CMD_ENTITY_RESET_IN_LEN 4
+#define MC_CMD_ENTITY_RESET_IN_FLAG_OFST 0
+#define MC_CMD_ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET_LBN 0
+#define MC_CMD_ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET_WIDTH 1
+
+/* MC_CMD_ENTITY_RESET_OUT msgresponse */
+#define MC_CMD_ENTITY_RESET_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_PCIE_CREDITS
+ * Read instantaneous and minimum flow control thresholds.
+ */
+#define MC_CMD_PCIE_CREDITS 0x21
+
+/* MC_CMD_PCIE_CREDITS_IN msgrequest */
+#define MC_CMD_PCIE_CREDITS_IN_LEN 8
+#define MC_CMD_PCIE_CREDITS_IN_POLL_PERIOD_OFST 0
+#define MC_CMD_PCIE_CREDITS_IN_WIPE_OFST 4
+
+/* MC_CMD_PCIE_CREDITS_OUT msgresponse */
+#define MC_CMD_PCIE_CREDITS_OUT_LEN 16
+#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_HDR_OFST 0
+#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_HDR_LEN 2
+#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_DATA_OFST 2
+#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_DATA_LEN 2
+#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_HDR_OFST 4
+#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_HDR_LEN 2
+#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_DATA_OFST 6
+#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_DATA_LEN 2
+#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_HDR_OFST 8
+#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_HDR_LEN 2
+#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_DATA_OFST 10
+#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_DATA_LEN 2
+#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_HDR_OFST 12
+#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_HDR_LEN 2
+#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_DATA_OFST 14
+#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_DATA_LEN 2
+
+
+/***********************************/
+/* MC_CMD_RXD_MONITOR
+ * Get histogram of RX queue fill level.
+ */
+#define MC_CMD_RXD_MONITOR 0x22
+
+/* MC_CMD_RXD_MONITOR_IN msgrequest */
+#define MC_CMD_RXD_MONITOR_IN_LEN 12
+#define MC_CMD_RXD_MONITOR_IN_QID_OFST 0
+#define MC_CMD_RXD_MONITOR_IN_POLL_PERIOD_OFST 4
+#define MC_CMD_RXD_MONITOR_IN_WIPE_OFST 8
+
+/* MC_CMD_RXD_MONITOR_OUT msgresponse */
+#define MC_CMD_RXD_MONITOR_OUT_LEN 80
+#define MC_CMD_RXD_MONITOR_OUT_QID_OFST 0
+#define MC_CMD_RXD_MONITOR_OUT_RING_FILL_OFST 4
+#define MC_CMD_RXD_MONITOR_OUT_CACHE_FILL_OFST 8
+#define MC_CMD_RXD_MONITOR_OUT_RING_LT_1_OFST 12
+#define MC_CMD_RXD_MONITOR_OUT_RING_LT_2_OFST 16
+#define MC_CMD_RXD_MONITOR_OUT_RING_LT_4_OFST 20
+#define MC_CMD_RXD_MONITOR_OUT_RING_LT_8_OFST 24
+#define MC_CMD_RXD_MONITOR_OUT_RING_LT_16_OFST 28
+#define MC_CMD_RXD_MONITOR_OUT_RING_LT_32_OFST 32
+#define MC_CMD_RXD_MONITOR_OUT_RING_LT_64_OFST 36
+#define MC_CMD_RXD_MONITOR_OUT_RING_LT_128_OFST 40
+#define MC_CMD_RXD_MONITOR_OUT_RING_LT_256_OFST 44
+#define MC_CMD_RXD_MONITOR_OUT_RING_GE_256_OFST 48
+#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_1_OFST 52
+#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_2_OFST 56
+#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_4_OFST 60
+#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_8_OFST 64
+#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_16_OFST 68
+#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_32_OFST 72
+#define MC_CMD_RXD_MONITOR_OUT_CACHE_GE_32_OFST 76
+
+
+/***********************************/
+/* MC_CMD_PUTS
+ * puts(3) implementation over MCDI
+ */
+#define MC_CMD_PUTS 0x23
+
+/* MC_CMD_PUTS_IN msgrequest */
+#define MC_CMD_PUTS_IN_LENMIN 13
+#define MC_CMD_PUTS_IN_LENMAX 255
+#define MC_CMD_PUTS_IN_LEN(num) (12+1*(num))
+#define MC_CMD_PUTS_IN_DEST_OFST 0
+#define MC_CMD_PUTS_IN_UART_LBN 0
+#define MC_CMD_PUTS_IN_UART_WIDTH 1
+#define MC_CMD_PUTS_IN_PORT_LBN 1
+#define MC_CMD_PUTS_IN_PORT_WIDTH 1
+#define MC_CMD_PUTS_IN_DHOST_OFST 4
+#define MC_CMD_PUTS_IN_DHOST_LEN 6
+#define MC_CMD_PUTS_IN_STRING_OFST 12
+#define MC_CMD_PUTS_IN_STRING_LEN 1
+#define MC_CMD_PUTS_IN_STRING_MINNUM 1
+#define MC_CMD_PUTS_IN_STRING_MAXNUM 243
+
+/* MC_CMD_PUTS_OUT msgresponse */
+#define MC_CMD_PUTS_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_PHY_CFG
+ * Report PHY configuration.
*/
#define MC_CMD_GET_PHY_CFG 0x24
-#define MC_CMD_GET_PHY_CFG_IN_LEN 0
-#define MC_CMD_GET_PHY_CFG_OUT_LEN 72
-
-#define MC_CMD_GET_PHY_CFG_OUT_FLAGS_OFST 0
-#define MC_CMD_GET_PHY_CFG_PRESENT_LBN 0
-#define MC_CMD_GET_PHY_CFG_PRESENT_WIDTH 1
-#define MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_LBN 1
-#define MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_WIDTH 1
-#define MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN 2
-#define MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_WIDTH 1
-#define MC_CMD_GET_PHY_CFG_LOWPOWER_LBN 3
-#define MC_CMD_GET_PHY_CFG_LOWPOWER_WIDTH 1
-#define MC_CMD_GET_PHY_CFG_POWEROFF_LBN 4
-#define MC_CMD_GET_PHY_CFG_POWEROFF_WIDTH 1
-#define MC_CMD_GET_PHY_CFG_TXDIS_LBN 5
-#define MC_CMD_GET_PHY_CFG_TXDIS_WIDTH 1
-#define MC_CMD_GET_PHY_CFG_BIST_LBN 6
-#define MC_CMD_GET_PHY_CFG_BIST_WIDTH 1
-#define MC_CMD_GET_PHY_CFG_OUT_TYPE_OFST 4
-/* Bitmask of supported capabilities */
-#define MC_CMD_GET_PHY_CFG_OUT_SUPPORTED_CAP_OFST 8
-#define MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12
-#define MC_CMD_GET_PHY_CFG_OUT_PRT_OFST 16
-/* PHY statistics bitmap */
-#define MC_CMD_GET_PHY_CFG_OUT_STATS_MASK_OFST 20
-/* PHY type/name string */
-#define MC_CMD_GET_PHY_CFG_OUT_NAME_OFST 24
-#define MC_CMD_GET_PHY_CFG_OUT_NAME_LEN 20
-#define MC_CMD_GET_PHY_CFG_OUT_MEDIA_TYPE_OFST 44
-#define MC_CMD_MEDIA_XAUI 1
-#define MC_CMD_MEDIA_CX4 2
-#define MC_CMD_MEDIA_KX4 3
-#define MC_CMD_MEDIA_XFP 4
-#define MC_CMD_MEDIA_SFP_PLUS 5
-#define MC_CMD_MEDIA_BASE_T 6
-/* MDIO "MMDS" supported */
-#define MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48
-/* Native clause 22 */
-#define MC_CMD_MMD_CLAUSE22 0
-#define MC_CMD_MMD_CLAUSE45_PMAPMD 1
-#define MC_CMD_MMD_CLAUSE45_WIS 2
-#define MC_CMD_MMD_CLAUSE45_PCS 3
-#define MC_CMD_MMD_CLAUSE45_PHYXS 4
-#define MC_CMD_MMD_CLAUSE45_DTEXS 5
-#define MC_CMD_MMD_CLAUSE45_TC 6
-#define MC_CMD_MMD_CLAUSE45_AN 7
-/* Clause22 proxied over clause45 by PHY */
-#define MC_CMD_MMD_CLAUSE45_C22EXT 29
-#define MC_CMD_MMD_CLAUSE45_VEND1 30
-#define MC_CMD_MMD_CLAUSE45_VEND2 31
-/* PHY stepping version */
-#define MC_CMD_GET_PHY_CFG_OUT_REVISION_OFST 52
-#define MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN 20
-
-/* MC_CMD_START_BIST:
+/* MC_CMD_GET_PHY_CFG_IN msgrequest */
+#define MC_CMD_GET_PHY_CFG_IN_LEN 0
+
+/* MC_CMD_GET_PHY_CFG_OUT msgresponse */
+#define MC_CMD_GET_PHY_CFG_OUT_LEN 72
+#define MC_CMD_GET_PHY_CFG_OUT_FLAGS_OFST 0
+#define MC_CMD_GET_PHY_CFG_OUT_PRESENT_LBN 0
+#define MC_CMD_GET_PHY_CFG_OUT_PRESENT_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN 1
+#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN 2
+#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_LBN 3
+#define MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_OUT_POWEROFF_LBN 4
+#define MC_CMD_GET_PHY_CFG_OUT_POWEROFF_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_OUT_TXDIS_LBN 5
+#define MC_CMD_GET_PHY_CFG_OUT_TXDIS_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_OUT_BIST_LBN 6
+#define MC_CMD_GET_PHY_CFG_OUT_BIST_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_OUT_TYPE_OFST 4
+#define MC_CMD_GET_PHY_CFG_OUT_SUPPORTED_CAP_OFST 8
+#define MC_CMD_PHY_CAP_10HDX_LBN 1
+#define MC_CMD_PHY_CAP_10HDX_WIDTH 1
+#define MC_CMD_PHY_CAP_10FDX_LBN 2
+#define MC_CMD_PHY_CAP_10FDX_WIDTH 1
+#define MC_CMD_PHY_CAP_100HDX_LBN 3
+#define MC_CMD_PHY_CAP_100HDX_WIDTH 1
+#define MC_CMD_PHY_CAP_100FDX_LBN 4
+#define MC_CMD_PHY_CAP_100FDX_WIDTH 1
+#define MC_CMD_PHY_CAP_1000HDX_LBN 5
+#define MC_CMD_PHY_CAP_1000HDX_WIDTH 1
+#define MC_CMD_PHY_CAP_1000FDX_LBN 6
+#define MC_CMD_PHY_CAP_1000FDX_WIDTH 1
+#define MC_CMD_PHY_CAP_10000FDX_LBN 7
+#define MC_CMD_PHY_CAP_10000FDX_WIDTH 1
+#define MC_CMD_PHY_CAP_PAUSE_LBN 8
+#define MC_CMD_PHY_CAP_PAUSE_WIDTH 1
+#define MC_CMD_PHY_CAP_ASYM_LBN 9
+#define MC_CMD_PHY_CAP_ASYM_WIDTH 1
+#define MC_CMD_PHY_CAP_AN_LBN 10
+#define MC_CMD_PHY_CAP_AN_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12
+#define MC_CMD_GET_PHY_CFG_OUT_PRT_OFST 16
+#define MC_CMD_GET_PHY_CFG_OUT_STATS_MASK_OFST 20
+#define MC_CMD_GET_PHY_CFG_OUT_NAME_OFST 24
+#define MC_CMD_GET_PHY_CFG_OUT_NAME_LEN 20
+#define MC_CMD_GET_PHY_CFG_OUT_MEDIA_TYPE_OFST 44
+#define MC_CMD_MEDIA_XAUI 0x1 /* enum */
+#define MC_CMD_MEDIA_CX4 0x2 /* enum */
+#define MC_CMD_MEDIA_KX4 0x3 /* enum */
+#define MC_CMD_MEDIA_XFP 0x4 /* enum */
+#define MC_CMD_MEDIA_SFP_PLUS 0x5 /* enum */
+#define MC_CMD_MEDIA_BASE_T 0x6 /* enum */
+#define MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48
+#define MC_CMD_MMD_CLAUSE22 0x0 /* enum */
+#define MC_CMD_MMD_CLAUSE45_PMAPMD 0x1 /* enum */
+#define MC_CMD_MMD_CLAUSE45_WIS 0x2 /* enum */
+#define MC_CMD_MMD_CLAUSE45_PCS 0x3 /* enum */
+#define MC_CMD_MMD_CLAUSE45_PHYXS 0x4 /* enum */
+#define MC_CMD_MMD_CLAUSE45_DTEXS 0x5 /* enum */
+#define MC_CMD_MMD_CLAUSE45_TC 0x6 /* enum */
+#define MC_CMD_MMD_CLAUSE45_AN 0x7 /* enum */
+#define MC_CMD_MMD_CLAUSE45_C22EXT 0x1d /* enum */
+#define MC_CMD_MMD_CLAUSE45_VEND1 0x1e /* enum */
+#define MC_CMD_MMD_CLAUSE45_VEND2 0x1f /* enum */
+#define MC_CMD_GET_PHY_CFG_OUT_REVISION_OFST 52
+#define MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN 20
+
+
+/***********************************/
+/* MC_CMD_START_BIST
* Start a BIST test on the PHY.
- *
- * Locks required: PHY_LOCK if doing a PHY BIST
- * Return code: 0, EINVAL, EACCES (if PHY_LOCK is not held)
*/
#define MC_CMD_START_BIST 0x25
-#define MC_CMD_START_BIST_IN_LEN 4
-#define MC_CMD_START_BIST_IN_TYPE_OFST 0
-#define MC_CMD_START_BIST_OUT_LEN 0
-
-/* Run the PHY's short cable BIST */
-#define MC_CMD_PHY_BIST_CABLE_SHORT 1
-/* Run the PHY's long cable BIST */
-#define MC_CMD_PHY_BIST_CABLE_LONG 2
-/* Run BIST on the currently selected BPX Serdes (XAUI or XFI) */
-#define MC_CMD_BPX_SERDES_BIST 3
-/* Run the MC loopback tests */
-#define MC_CMD_MC_LOOPBACK_BIST 4
-/* Run the PHY's standard BIST */
-#define MC_CMD_PHY_BIST 5
-
-/* MC_CMD_POLL_PHY_BIST: (variadic output)
- * Poll for BIST completion
- *
- * Returns a single status code, and optionally some PHY specific
- * bist output. The driver should only consume the BIST output
- * after validating OUTLEN and PHY_CFG.PHY_TYPE.
- *
- * If a driver can't successfully parse the BIST output, it should
- * still respect the pass/Fail in OUT.RESULT
- *
- * Locks required: PHY_LOCK if doing a PHY BIST
- * Return code: 0, EACCES (if PHY_LOCK is not held)
+
+/* MC_CMD_START_BIST_IN msgrequest */
+#define MC_CMD_START_BIST_IN_LEN 4
+#define MC_CMD_START_BIST_IN_TYPE_OFST 0
+#define MC_CMD_PHY_BIST_CABLE_SHORT 0x1 /* enum */
+#define MC_CMD_PHY_BIST_CABLE_LONG 0x2 /* enum */
+#define MC_CMD_BPX_SERDES_BIST 0x3 /* enum */
+#define MC_CMD_MC_LOOPBACK_BIST 0x4 /* enum */
+#define MC_CMD_PHY_BIST 0x5 /* enum */
+
+/* MC_CMD_START_BIST_OUT msgresponse */
+#define MC_CMD_START_BIST_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_POLL_BIST
+ * Poll for BIST completion.
*/
#define MC_CMD_POLL_BIST 0x26
-#define MC_CMD_POLL_BIST_IN_LEN 0
-#define MC_CMD_POLL_BIST_OUT_LEN UNKNOWN
-#define MC_CMD_POLL_BIST_OUT_SFT9001_LEN 36
-#define MC_CMD_POLL_BIST_OUT_MRSFP_LEN 8
-#define MC_CMD_POLL_BIST_OUT_RESULT_OFST 0
-#define MC_CMD_POLL_BIST_RUNNING 1
-#define MC_CMD_POLL_BIST_PASSED 2
-#define MC_CMD_POLL_BIST_FAILED 3
-#define MC_CMD_POLL_BIST_TIMEOUT 4
-/* Generic: */
-#define MC_CMD_POLL_BIST_OUT_PRIVATE_OFST 4
-/* SFT9001-specific: */
-#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A_OFST 4
-#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B_OFST 8
-#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C_OFST 12
-#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D_OFST 16
-#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_A_OFST 20
-#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_B_OFST 24
-#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_C_OFST 28
-#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_D_OFST 32
-#define MC_CMD_POLL_BIST_SFT9001_PAIR_OK 1
-#define MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN 2
-#define MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT 3
-#define MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT 4
-#define MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY 9
-/* mrsfp "PHY" driver: */
-#define MC_CMD_POLL_BIST_OUT_MRSFP_TEST_OFST 4
-#define MC_CMD_POLL_BIST_MRSFP_TEST_COMPLETE 0
-#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_WRITE 1
-#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_IO_EXP 2
-#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_MODULE 3
-#define MC_CMD_POLL_BIST_MRSFP_TEST_IO_EXP_I2C_CONFIGURE 4
-#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_I2C_NO_CROSSTALK 5
-#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_PRESENCE 6
-#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_I2C_ACCESS 7
-#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_SANE_VALUE 8
-
-/* MC_CMD_PHY_SPI: (variadic in, variadic out)
- * Read/Write/Erase the PHY SPI device
- *
- * Locks required: PHY_LOCK
- * Return code: 0, ETIME, EINVAL, EACCES (if PHY_LOCK is not held)
- */
-#define MC_CMD_PHY_SPI 0x27
-#define MC_CMD_PHY_SPI_IN_LEN(_write_bytes) (12 + (_write_bytes))
-#define MC_CMD_PHY_SPI_IN_ARGS_OFST 0
-#define MC_CMD_PHY_SPI_IN_ARGS_ADDR_OFST 0
-#define MC_CMD_PHY_SPI_IN_ARGS_READ_BYTES_OFST 4
-#define MC_CMD_PHY_SPI_IN_ARGS_ERASE_ALL_OFST 8
-/* Data to write here */
-#define MC_CMD_PHY_SPI_IN_WRITE_BUFFER_OFSET 12
-#define MC_CMD_PHY_SPI_OUT_LEN(_read_bytes) (_read_bytes)
-/* Data read here */
-#define MC_CMD_PHY_SPI_OUT_READ_BUFFER_OFST 0
-
-
-/* MC_CMD_GET_LOOPBACK_MODES:
- * Returns a bitmask of loopback modes evailable at each speed.
- *
- * Locks required: None
- * Return code: 0
+
+/* MC_CMD_POLL_BIST_IN msgrequest */
+#define MC_CMD_POLL_BIST_IN_LEN 0
+
+/* MC_CMD_POLL_BIST_OUT msgresponse */
+#define MC_CMD_POLL_BIST_OUT_LEN 8
+#define MC_CMD_POLL_BIST_OUT_RESULT_OFST 0
+#define MC_CMD_POLL_BIST_RUNNING 0x1 /* enum */
+#define MC_CMD_POLL_BIST_PASSED 0x2 /* enum */
+#define MC_CMD_POLL_BIST_FAILED 0x3 /* enum */
+#define MC_CMD_POLL_BIST_TIMEOUT 0x4 /* enum */
+#define MC_CMD_POLL_BIST_OUT_PRIVATE_OFST 4
+
+/* MC_CMD_POLL_BIST_OUT_SFT9001 msgresponse */
+#define MC_CMD_POLL_BIST_OUT_SFT9001_LEN 36
+/* MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 */
+/* Enum values, see field(s): */
+/* MC_CMD_POLL_BIST_OUT/MC_CMD_POLL_BIST_OUT_RESULT */
+#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A_OFST 4
+#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B_OFST 8
+#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C_OFST 12
+#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D_OFST 16
+#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_A_OFST 20
+#define MC_CMD_POLL_BIST_SFT9001_PAIR_OK 0x1 /* enum */
+#define MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN 0x2 /* enum */
+#define MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT 0x3 /* enum */
+#define MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT 0x4 /* enum */
+#define MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY 0x9 /* enum */
+#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_B_OFST 24
+/* Enum values, see field(s): */
+/* CABLE_STATUS_A */
+#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_C_OFST 28
+/* Enum values, see field(s): */
+/* CABLE_STATUS_A */
+#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_D_OFST 32
+/* Enum values, see field(s): */
+/* CABLE_STATUS_A */
+
+/* MC_CMD_POLL_BIST_OUT_MRSFP msgresponse */
+#define MC_CMD_POLL_BIST_OUT_MRSFP_LEN 8
+/* MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 */
+/* Enum values, see field(s): */
+/* MC_CMD_POLL_BIST_OUT/MC_CMD_POLL_BIST_OUT_RESULT */
+#define MC_CMD_POLL_BIST_OUT_MRSFP_TEST_OFST 4
+#define MC_CMD_POLL_BIST_MRSFP_TEST_COMPLETE 0x0 /* enum */
+#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_WRITE 0x1 /* enum */
+#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_IO_EXP 0x2 /* enum */
+#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_MODULE 0x3 /* enum */
+#define MC_CMD_POLL_BIST_MRSFP_TEST_IO_EXP_I2C_CONFIGURE 0x4 /* enum */
+#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_I2C_NO_CROSSTALK 0x5 /* enum */
+#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_PRESENCE 0x6 /* enum */
+#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_I2C_ACCESS 0x7 /* enum */
+#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_SANE_VALUE 0x8 /* enum */
+
+
+/***********************************/
+/* MC_CMD_FLUSH_RX_QUEUES
+ * Flush receive queue(s).
+ */
+#define MC_CMD_FLUSH_RX_QUEUES 0x27
+
+/* MC_CMD_FLUSH_RX_QUEUES_IN msgrequest */
+#define MC_CMD_FLUSH_RX_QUEUES_IN_LENMIN 4
+#define MC_CMD_FLUSH_RX_QUEUES_IN_LENMAX 252
+#define MC_CMD_FLUSH_RX_QUEUES_IN_LEN(num) (0+4*(num))
+#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_OFST 0
+#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_LEN 4
+#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MINNUM 1
+#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM 63
+
+/* MC_CMD_FLUSH_RX_QUEUES_OUT msgresponse */
+#define MC_CMD_FLUSH_RX_QUEUES_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_LOOPBACK_MODES
+ * Get port's loopback modes.
*/
#define MC_CMD_GET_LOOPBACK_MODES 0x28
-#define MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0
-#define MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 32
-#define MC_CMD_GET_LOOPBACK_MODES_100M_OFST 0
-#define MC_CMD_GET_LOOPBACK_MODES_1G_OFST 8
-#define MC_CMD_GET_LOOPBACK_MODES_10G_OFST 16
-#define MC_CMD_GET_LOOPBACK_MODES_SUGGESTED_OFST 24
-
-/* Flow control enumeration */
-#define MC_CMD_FCNTL_OFF 0
-#define MC_CMD_FCNTL_RESPOND 1
-#define MC_CMD_FCNTL_BIDIR 2
-/* Auto - Use what the link has autonegotiated
- * - The driver should modify the advertised capabilities via SET_LINK.CAP
- * to control the negotiated flow control mode.
- * - Can only be set if the PHY supports PAUSE+ASYM capabilities
- * - Never returned by GET_LINK as the value programmed into the MAC
- */
-#define MC_CMD_FCNTL_AUTO 3
-
-/* Generic mac fault bitmask */
-#define MC_CMD_MAC_FAULT_XGMII_LOCAL_LBN 0
-#define MC_CMD_MAC_FAULT_XGMII_LOCAL_WIDTH 1
-#define MC_CMD_MAC_FAULT_XGMII_REMOTE_LBN 1
-#define MC_CMD_MAC_FAULT_XGMII_REMOTE_WIDTH 1
-#define MC_CMD_MAC_FAULT_SGMII_REMOTE_LBN 2
-#define MC_CMD_MAC_FAULT_SGMII_REMOTE_WIDTH 1
-
-/* MC_CMD_GET_LINK:
- * Read the unified MAC/PHY link state
- *
- * Locks required: None
- * Return code: 0, ETIME
+
+/* MC_CMD_GET_LOOPBACK_MODES_IN msgrequest */
+#define MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0
+
+/* MC_CMD_GET_LOOPBACK_MODES_OUT msgresponse */
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 32
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_OFST 0
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_LEN 8
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_LO_OFST 0
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_OFST 4
+#define MC_CMD_LOOPBACK_NONE 0x0 /* enum */
+#define MC_CMD_LOOPBACK_DATA 0x1 /* enum */
+#define MC_CMD_LOOPBACK_GMAC 0x2 /* enum */
+#define MC_CMD_LOOPBACK_XGMII 0x3 /* enum */
+#define MC_CMD_LOOPBACK_XGXS 0x4 /* enum */
+#define MC_CMD_LOOPBACK_XAUI 0x5 /* enum */
+#define MC_CMD_LOOPBACK_GMII 0x6 /* enum */
+#define MC_CMD_LOOPBACK_SGMII 0x7 /* enum */
+#define MC_CMD_LOOPBACK_XGBR 0x8 /* enum */
+#define MC_CMD_LOOPBACK_XFI 0x9 /* enum */
+#define MC_CMD_LOOPBACK_XAUI_FAR 0xa /* enum */
+#define MC_CMD_LOOPBACK_GMII_FAR 0xb /* enum */
+#define MC_CMD_LOOPBACK_SGMII_FAR 0xc /* enum */
+#define MC_CMD_LOOPBACK_XFI_FAR 0xd /* enum */
+#define MC_CMD_LOOPBACK_GPHY 0xe /* enum */
+#define MC_CMD_LOOPBACK_PHYXS 0xf /* enum */
+#define MC_CMD_LOOPBACK_PCS 0x10 /* enum */
+#define MC_CMD_LOOPBACK_PMAPMD 0x11 /* enum */
+#define MC_CMD_LOOPBACK_XPORT 0x12 /* enum */
+#define MC_CMD_LOOPBACK_XGMII_WS 0x13 /* enum */
+#define MC_CMD_LOOPBACK_XAUI_WS 0x14 /* enum */
+#define MC_CMD_LOOPBACK_XAUI_WS_FAR 0x15 /* enum */
+#define MC_CMD_LOOPBACK_XAUI_WS_NEAR 0x16 /* enum */
+#define MC_CMD_LOOPBACK_GMII_WS 0x17 /* enum */
+#define MC_CMD_LOOPBACK_XFI_WS 0x18 /* enum */
+#define MC_CMD_LOOPBACK_XFI_WS_FAR 0x19 /* enum */
+#define MC_CMD_LOOPBACK_PHYXS_WS 0x1a /* enum */
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_OFST 8
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_LEN 8
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_LO_OFST 8
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_OFST 12
+/* Enum values, see field(s): */
+/* 100M */
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_OFST 16
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_LEN 8
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_LO_OFST 16
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_OFST 20
+/* Enum values, see field(s): */
+/* 100M */
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST 24
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN 8
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LO_OFST 24
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_OFST 28
+/* Enum values, see field(s): */
+/* 100M */
+
+
+/***********************************/
+/* MC_CMD_GET_LINK
+ * Read the unified MAC/PHY link state.
*/
#define MC_CMD_GET_LINK 0x29
-#define MC_CMD_GET_LINK_IN_LEN 0
-#define MC_CMD_GET_LINK_OUT_LEN 28
-/* near-side and link-partner advertised capabilities */
-#define MC_CMD_GET_LINK_OUT_CAP_OFST 0
-#define MC_CMD_GET_LINK_OUT_LP_CAP_OFST 4
-/* Autonegotiated speed in mbit/s. The link may still be down
- * even if this reads non-zero */
-#define MC_CMD_GET_LINK_OUT_LINK_SPEED_OFST 8
-#define MC_CMD_GET_LINK_OUT_LOOPBACK_MODE_OFST 12
-#define MC_CMD_GET_LINK_OUT_FLAGS_OFST 16
-/* Whether we have overall link up */
-#define MC_CMD_GET_LINK_LINK_UP_LBN 0
-#define MC_CMD_GET_LINK_LINK_UP_WIDTH 1
-#define MC_CMD_GET_LINK_FULL_DUPLEX_LBN 1
-#define MC_CMD_GET_LINK_FULL_DUPLEX_WIDTH 1
-/* Whether we have link at the layers provided by the BPX */
-#define MC_CMD_GET_LINK_BPX_LINK_LBN 2
-#define MC_CMD_GET_LINK_BPX_LINK_WIDTH 1
-/* Whether the PHY has external link */
-#define MC_CMD_GET_LINK_PHY_LINK_LBN 3
-#define MC_CMD_GET_LINK_PHY_LINK_WIDTH 1
-#define MC_CMD_GET_LINK_OUT_FCNTL_OFST 20
-#define MC_CMD_GET_LINK_OUT_MAC_FAULT_OFST 24
-
-/* MC_CMD_SET_LINK:
- * Write the unified MAC/PHY link configuration
- *
- * A loopback speed of "0" is supported, and means
- * (choose any available speed)
- *
- * Locks required: None
- * Return code: 0, EINVAL, ETIME
+
+/* MC_CMD_GET_LINK_IN msgrequest */
+#define MC_CMD_GET_LINK_IN_LEN 0
+
+/* MC_CMD_GET_LINK_OUT msgresponse */
+#define MC_CMD_GET_LINK_OUT_LEN 28
+#define MC_CMD_GET_LINK_OUT_CAP_OFST 0
+#define MC_CMD_GET_LINK_OUT_LP_CAP_OFST 4
+#define MC_CMD_GET_LINK_OUT_LINK_SPEED_OFST 8
+#define MC_CMD_GET_LINK_OUT_LOOPBACK_MODE_OFST 12
+/* Enum values, see field(s): */
+/* MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */
+#define MC_CMD_GET_LINK_OUT_FLAGS_OFST 16
+#define MC_CMD_GET_LINK_OUT_LINK_UP_LBN 0
+#define MC_CMD_GET_LINK_OUT_LINK_UP_WIDTH 1
+#define MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN 1
+#define MC_CMD_GET_LINK_OUT_FULL_DUPLEX_WIDTH 1
+#define MC_CMD_GET_LINK_OUT_BPX_LINK_LBN 2
+#define MC_CMD_GET_LINK_OUT_BPX_LINK_WIDTH 1
+#define MC_CMD_GET_LINK_OUT_PHY_LINK_LBN 3
+#define MC_CMD_GET_LINK_OUT_PHY_LINK_WIDTH 1
+#define MC_CMD_GET_LINK_OUT_FCNTL_OFST 20
+#define MC_CMD_FCNTL_OFF 0x0 /* enum */
+#define MC_CMD_FCNTL_RESPOND 0x1 /* enum */
+#define MC_CMD_FCNTL_BIDIR 0x2 /* enum */
+#define MC_CMD_GET_LINK_OUT_MAC_FAULT_OFST 24
+#define MC_CMD_MAC_FAULT_XGMII_LOCAL_LBN 0
+#define MC_CMD_MAC_FAULT_XGMII_LOCAL_WIDTH 1
+#define MC_CMD_MAC_FAULT_XGMII_REMOTE_LBN 1
+#define MC_CMD_MAC_FAULT_XGMII_REMOTE_WIDTH 1
+#define MC_CMD_MAC_FAULT_SGMII_REMOTE_LBN 2
+#define MC_CMD_MAC_FAULT_SGMII_REMOTE_WIDTH 1
+#define MC_CMD_MAC_FAULT_PENDING_RECONFIG_LBN 3
+#define MC_CMD_MAC_FAULT_PENDING_RECONFIG_WIDTH 1
+
+
+/***********************************/
+/* MC_CMD_SET_LINK
+ * Write the unified MAC/PHY link configuration.
*/
#define MC_CMD_SET_LINK 0x2a
-#define MC_CMD_SET_LINK_IN_LEN 16
-#define MC_CMD_SET_LINK_IN_CAP_OFST 0
-#define MC_CMD_SET_LINK_IN_FLAGS_OFST 4
-#define MC_CMD_SET_LINK_LOWPOWER_LBN 0
-#define MC_CMD_SET_LINK_LOWPOWER_WIDTH 1
-#define MC_CMD_SET_LINK_POWEROFF_LBN 1
-#define MC_CMD_SET_LINK_POWEROFF_WIDTH 1
-#define MC_CMD_SET_LINK_TXDIS_LBN 2
-#define MC_CMD_SET_LINK_TXDIS_WIDTH 1
-#define MC_CMD_SET_LINK_IN_LOOPBACK_MODE_OFST 8
-#define MC_CMD_SET_LINK_IN_LOOPBACK_SPEED_OFST 12
-#define MC_CMD_SET_LINK_OUT_LEN 0
-
-/* MC_CMD_SET_ID_LED:
- * Set indentification LED state
- *
- * Locks required: None
- * Return code: 0, EINVAL
+
+/* MC_CMD_SET_LINK_IN msgrequest */
+#define MC_CMD_SET_LINK_IN_LEN 16
+#define MC_CMD_SET_LINK_IN_CAP_OFST 0
+#define MC_CMD_SET_LINK_IN_FLAGS_OFST 4
+#define MC_CMD_SET_LINK_IN_LOWPOWER_LBN 0
+#define MC_CMD_SET_LINK_IN_LOWPOWER_WIDTH 1
+#define MC_CMD_SET_LINK_IN_POWEROFF_LBN 1
+#define MC_CMD_SET_LINK_IN_POWEROFF_WIDTH 1
+#define MC_CMD_SET_LINK_IN_TXDIS_LBN 2
+#define MC_CMD_SET_LINK_IN_TXDIS_WIDTH 1
+#define MC_CMD_SET_LINK_IN_LOOPBACK_MODE_OFST 8
+/* Enum values, see field(s): */
+/* MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */
+#define MC_CMD_SET_LINK_IN_LOOPBACK_SPEED_OFST 12
+
+/* MC_CMD_SET_LINK_OUT msgresponse */
+#define MC_CMD_SET_LINK_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SET_ID_LED
+ * Set indentification LED state.
*/
#define MC_CMD_SET_ID_LED 0x2b
-#define MC_CMD_SET_ID_LED_IN_LEN 4
-#define MC_CMD_SET_ID_LED_IN_STATE_OFST 0
-#define MC_CMD_LED_OFF 0
-#define MC_CMD_LED_ON 1
-#define MC_CMD_LED_DEFAULT 2
-#define MC_CMD_SET_ID_LED_OUT_LEN 0
-
-/* MC_CMD_SET_MAC:
- * Set MAC configuration
- *
- * The MTU is the MTU programmed directly into the XMAC/GMAC
- * (inclusive of EtherII, VLAN, bug16011 padding)
- *
- * Locks required: None
- * Return code: 0, EINVAL
+
+/* MC_CMD_SET_ID_LED_IN msgrequest */
+#define MC_CMD_SET_ID_LED_IN_LEN 4
+#define MC_CMD_SET_ID_LED_IN_STATE_OFST 0
+#define MC_CMD_LED_OFF 0x0 /* enum */
+#define MC_CMD_LED_ON 0x1 /* enum */
+#define MC_CMD_LED_DEFAULT 0x2 /* enum */
+
+/* MC_CMD_SET_ID_LED_OUT msgresponse */
+#define MC_CMD_SET_ID_LED_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SET_MAC
+ * Set MAC configuration.
*/
#define MC_CMD_SET_MAC 0x2c
-#define MC_CMD_SET_MAC_IN_LEN 24
-#define MC_CMD_SET_MAC_IN_MTU_OFST 0
-#define MC_CMD_SET_MAC_IN_DRAIN_OFST 4
-#define MC_CMD_SET_MAC_IN_ADDR_OFST 8
-#define MC_CMD_SET_MAC_IN_REJECT_OFST 16
-#define MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN 0
-#define MC_CMD_SET_MAC_IN_REJECT_UNCST_WIDTH 1
-#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_LBN 1
-#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_WIDTH 1
-#define MC_CMD_SET_MAC_IN_FCNTL_OFST 20
-#define MC_CMD_SET_MAC_OUT_LEN 0
-
-/* MC_CMD_PHY_STATS:
- * Get generic PHY statistics
- *
- * This call returns the statistics for a generic PHY in a sparse
- * array (indexed by the enumerate). Each value is represented by
- * a 32bit number.
- *
- * If the DMA_ADDR is 0, then no DMA is performed, and the statistics
- * may be read directly out of shared memory. If DMA_ADDR != 0, then
- * the statistics are dmad to that (page-aligned location)
- *
- * Locks required: None
- * Returns: 0, ETIME
- * Response methods: shared memory, event
+
+/* MC_CMD_SET_MAC_IN msgrequest */
+#define MC_CMD_SET_MAC_IN_LEN 24
+#define MC_CMD_SET_MAC_IN_MTU_OFST 0
+#define MC_CMD_SET_MAC_IN_DRAIN_OFST 4
+#define MC_CMD_SET_MAC_IN_ADDR_OFST 8
+#define MC_CMD_SET_MAC_IN_ADDR_LEN 8
+#define MC_CMD_SET_MAC_IN_ADDR_LO_OFST 8
+#define MC_CMD_SET_MAC_IN_ADDR_HI_OFST 12
+#define MC_CMD_SET_MAC_IN_REJECT_OFST 16
+#define MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN 0
+#define MC_CMD_SET_MAC_IN_REJECT_UNCST_WIDTH 1
+#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_LBN 1
+#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_WIDTH 1
+#define MC_CMD_SET_MAC_IN_FCNTL_OFST 20
+/* MC_CMD_FCNTL_OFF 0x0 */
+/* MC_CMD_FCNTL_RESPOND 0x1 */
+/* MC_CMD_FCNTL_BIDIR 0x2 */
+#define MC_CMD_FCNTL_AUTO 0x3 /* enum */
+
+/* MC_CMD_SET_MAC_OUT msgresponse */
+#define MC_CMD_SET_MAC_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_PHY_STATS
+ * Get generic PHY statistics.
*/
#define MC_CMD_PHY_STATS 0x2d
-#define MC_CMD_PHY_STATS_IN_LEN 8
-#define MC_CMD_PHY_STATS_IN_DMA_ADDR_LO_OFST 0
-#define MC_CMD_PHY_STATS_IN_DMA_ADDR_HI_OFST 4
-#define MC_CMD_PHY_STATS_OUT_DMA_LEN 0
-#define MC_CMD_PHY_STATS_OUT_NO_DMA_LEN (MC_CMD_PHY_NSTATS * 4)
-
-/* Unified MAC statistics enumeration */
-#define MC_CMD_MAC_GENERATION_START 0
-#define MC_CMD_MAC_TX_PKTS 1
-#define MC_CMD_MAC_TX_PAUSE_PKTS 2
-#define MC_CMD_MAC_TX_CONTROL_PKTS 3
-#define MC_CMD_MAC_TX_UNICAST_PKTS 4
-#define MC_CMD_MAC_TX_MULTICAST_PKTS 5
-#define MC_CMD_MAC_TX_BROADCAST_PKTS 6
-#define MC_CMD_MAC_TX_BYTES 7
-#define MC_CMD_MAC_TX_BAD_BYTES 8
-#define MC_CMD_MAC_TX_LT64_PKTS 9
-#define MC_CMD_MAC_TX_64_PKTS 10
-#define MC_CMD_MAC_TX_65_TO_127_PKTS 11
-#define MC_CMD_MAC_TX_128_TO_255_PKTS 12
-#define MC_CMD_MAC_TX_256_TO_511_PKTS 13
-#define MC_CMD_MAC_TX_512_TO_1023_PKTS 14
-#define MC_CMD_MAC_TX_1024_TO_15XX_PKTS 15
-#define MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS 16
-#define MC_CMD_MAC_TX_GTJUMBO_PKTS 17
-#define MC_CMD_MAC_TX_BAD_FCS_PKTS 18
-#define MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS 19
-#define MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS 20
-#define MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS 21
-#define MC_CMD_MAC_TX_LATE_COLLISION_PKTS 22
-#define MC_CMD_MAC_TX_DEFERRED_PKTS 23
-#define MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS 24
-#define MC_CMD_MAC_TX_NON_TCPUDP_PKTS 25
-#define MC_CMD_MAC_TX_MAC_SRC_ERR_PKTS 26
-#define MC_CMD_MAC_TX_IP_SRC_ERR_PKTS 27
-#define MC_CMD_MAC_RX_PKTS 28
-#define MC_CMD_MAC_RX_PAUSE_PKTS 29
-#define MC_CMD_MAC_RX_GOOD_PKTS 30
-#define MC_CMD_MAC_RX_CONTROL_PKTS 31
-#define MC_CMD_MAC_RX_UNICAST_PKTS 32
-#define MC_CMD_MAC_RX_MULTICAST_PKTS 33
-#define MC_CMD_MAC_RX_BROADCAST_PKTS 34
-#define MC_CMD_MAC_RX_BYTES 35
-#define MC_CMD_MAC_RX_BAD_BYTES 36
-#define MC_CMD_MAC_RX_64_PKTS 37
-#define MC_CMD_MAC_RX_65_TO_127_PKTS 38
-#define MC_CMD_MAC_RX_128_TO_255_PKTS 39
-#define MC_CMD_MAC_RX_256_TO_511_PKTS 40
-#define MC_CMD_MAC_RX_512_TO_1023_PKTS 41
-#define MC_CMD_MAC_RX_1024_TO_15XX_PKTS 42
-#define MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS 43
-#define MC_CMD_MAC_RX_GTJUMBO_PKTS 44
-#define MC_CMD_MAC_RX_UNDERSIZE_PKTS 45
-#define MC_CMD_MAC_RX_BAD_FCS_PKTS 46
-#define MC_CMD_MAC_RX_OVERFLOW_PKTS 47
-#define MC_CMD_MAC_RX_FALSE_CARRIER_PKTS 48
-#define MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS 49
-#define MC_CMD_MAC_RX_ALIGN_ERROR_PKTS 50
-#define MC_CMD_MAC_RX_LENGTH_ERROR_PKTS 51
-#define MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS 52
-#define MC_CMD_MAC_RX_JABBER_PKTS 53
-#define MC_CMD_MAC_RX_NODESC_DROPS 54
-#define MC_CMD_MAC_RX_LANES01_CHAR_ERR 55
-#define MC_CMD_MAC_RX_LANES23_CHAR_ERR 56
-#define MC_CMD_MAC_RX_LANES01_DISP_ERR 57
-#define MC_CMD_MAC_RX_LANES23_DISP_ERR 58
-#define MC_CMD_MAC_RX_MATCH_FAULT 59
-#define MC_CMD_GMAC_DMABUF_START 64
-#define MC_CMD_GMAC_DMABUF_END 95
-/* Insert new members here. */
-#define MC_CMD_MAC_GENERATION_END 96
-#define MC_CMD_MAC_NSTATS (MC_CMD_MAC_GENERATION_END+1)
-
-/* MC_CMD_MAC_STATS:
- * Get unified GMAC/XMAC statistics
- *
- * This call returns unified statistics maintained by the MC as it
- * switches between the GMAC and XMAC. The MC will write out all
- * supported stats. The driver should zero initialise the buffer to
- * guarantee consistent results.
- *
- * Locks required: None
- * Returns: 0
- * Response methods: shared memory, event
- */
-#define MC_CMD_MAC_STATS 0x2e
-#define MC_CMD_MAC_STATS_IN_LEN 16
-#define MC_CMD_MAC_STATS_IN_DMA_ADDR_LO_OFST 0
-#define MC_CMD_MAC_STATS_IN_DMA_ADDR_HI_OFST 4
-#define MC_CMD_MAC_STATS_IN_CMD_OFST 8
-#define MC_CMD_MAC_STATS_CMD_DMA_LBN 0
-#define MC_CMD_MAC_STATS_CMD_DMA_WIDTH 1
-#define MC_CMD_MAC_STATS_CMD_CLEAR_LBN 1
-#define MC_CMD_MAC_STATS_CMD_CLEAR_WIDTH 1
-#define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_LBN 2
-#define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_WIDTH 1
-/* Remaining PERIOD* fields only relevant when PERIODIC_CHANGE is set */
-#define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_LBN 3
-#define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_WIDTH 1
-#define MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR_LBN 4
-#define MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR_WIDTH 1
-#define MC_CMD_MAC_STATS_CMD_PERIODIC_NOEVENT_LBN 5
-#define MC_CMD_MAC_STATS_CMD_PERIODIC_NOEVENT_WIDTH 1
-#define MC_CMD_MAC_STATS_CMD_PERIOD_MS_LBN 16
-#define MC_CMD_MAC_STATS_CMD_PERIOD_MS_WIDTH 16
-#define MC_CMD_MAC_STATS_IN_DMA_LEN_OFST 12
-
-#define MC_CMD_MAC_STATS_OUT_LEN 0
-
-/* Callisto flags */
-#define MC_CMD_SFT9001_ROBUST_LBN 0
-#define MC_CMD_SFT9001_ROBUST_WIDTH 1
-#define MC_CMD_SFT9001_SHORT_REACH_LBN 1
-#define MC_CMD_SFT9001_SHORT_REACH_WIDTH 1
-
-/* MC_CMD_SFT9001_GET:
- * Read current callisto specific setting
- *
- * Locks required: None
- * Returns: 0, ETIME
- */
-#define MC_CMD_SFT9001_GET 0x30
-#define MC_CMD_SFT9001_GET_IN_LEN 0
-#define MC_CMD_SFT9001_GET_OUT_LEN 4
-#define MC_CMD_SFT9001_GET_OUT_FLAGS_OFST 0
-/* MC_CMD_SFT9001_SET:
- * Write current callisto specific setting
- *
- * Locks required: None
- * Returns: 0, ETIME, EINVAL
+/* MC_CMD_PHY_STATS_IN msgrequest */
+#define MC_CMD_PHY_STATS_IN_LEN 8
+#define MC_CMD_PHY_STATS_IN_DMA_ADDR_OFST 0
+#define MC_CMD_PHY_STATS_IN_DMA_ADDR_LEN 8
+#define MC_CMD_PHY_STATS_IN_DMA_ADDR_LO_OFST 0
+#define MC_CMD_PHY_STATS_IN_DMA_ADDR_HI_OFST 4
+
+/* MC_CMD_PHY_STATS_OUT_DMA msgresponse */
+#define MC_CMD_PHY_STATS_OUT_DMA_LEN 0
+
+/* MC_CMD_PHY_STATS_OUT_NO_DMA msgresponse */
+#define MC_CMD_PHY_STATS_OUT_NO_DMA_LEN (((MC_CMD_PHY_NSTATS*32))>>3)
+#define MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_OFST 0
+#define MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_LEN 4
+#define MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_PHY_NSTATS
+#define MC_CMD_OUI 0x0 /* enum */
+#define MC_CMD_PMA_PMD_LINK_UP 0x1 /* enum */
+#define MC_CMD_PMA_PMD_RX_FAULT 0x2 /* enum */
+#define MC_CMD_PMA_PMD_TX_FAULT 0x3 /* enum */
+#define MC_CMD_PMA_PMD_SIGNAL 0x4 /* enum */
+#define MC_CMD_PMA_PMD_SNR_A 0x5 /* enum */
+#define MC_CMD_PMA_PMD_SNR_B 0x6 /* enum */
+#define MC_CMD_PMA_PMD_SNR_C 0x7 /* enum */
+#define MC_CMD_PMA_PMD_SNR_D 0x8 /* enum */
+#define MC_CMD_PCS_LINK_UP 0x9 /* enum */
+#define MC_CMD_PCS_RX_FAULT 0xa /* enum */
+#define MC_CMD_PCS_TX_FAULT 0xb /* enum */
+#define MC_CMD_PCS_BER 0xc /* enum */
+#define MC_CMD_PCS_BLOCK_ERRORS 0xd /* enum */
+#define MC_CMD_PHYXS_LINK_UP 0xe /* enum */
+#define MC_CMD_PHYXS_RX_FAULT 0xf /* enum */
+#define MC_CMD_PHYXS_TX_FAULT 0x10 /* enum */
+#define MC_CMD_PHYXS_ALIGN 0x11 /* enum */
+#define MC_CMD_PHYXS_SYNC 0x12 /* enum */
+#define MC_CMD_AN_LINK_UP 0x13 /* enum */
+#define MC_CMD_AN_COMPLETE 0x14 /* enum */
+#define MC_CMD_AN_10GBT_STATUS 0x15 /* enum */
+#define MC_CMD_CL22_LINK_UP 0x16 /* enum */
+#define MC_CMD_PHY_NSTATS 0x17 /* enum */
+
+
+/***********************************/
+/* MC_CMD_MAC_STATS
+ * Get generic MAC statistics.
*/
-#define MC_CMD_SFT9001_SET 0x31
-#define MC_CMD_SFT9001_SET_IN_LEN 4
-#define MC_CMD_SFT9001_SET_IN_FLAGS_OFST 0
-#define MC_CMD_SFT9001_SET_OUT_LEN 0
-
+#define MC_CMD_MAC_STATS 0x2e
-/* MC_CMD_WOL_FILTER_SET:
- * Set a WoL filter
- *
- * Locks required: None
- * Returns: 0, EBUSY, EINVAL, ENOSYS
+/* MC_CMD_MAC_STATS_IN msgrequest */
+#define MC_CMD_MAC_STATS_IN_LEN 16
+#define MC_CMD_MAC_STATS_IN_DMA_ADDR_OFST 0
+#define MC_CMD_MAC_STATS_IN_DMA_ADDR_LEN 8
+#define MC_CMD_MAC_STATS_IN_DMA_ADDR_LO_OFST 0
+#define MC_CMD_MAC_STATS_IN_DMA_ADDR_HI_OFST 4
+#define MC_CMD_MAC_STATS_IN_CMD_OFST 8
+#define MC_CMD_MAC_STATS_IN_DMA_LBN 0
+#define MC_CMD_MAC_STATS_IN_DMA_WIDTH 1
+#define MC_CMD_MAC_STATS_IN_CLEAR_LBN 1
+#define MC_CMD_MAC_STATS_IN_CLEAR_WIDTH 1
+#define MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE_LBN 2
+#define MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE_WIDTH 1
+#define MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE_LBN 3
+#define MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE_WIDTH 1
+#define MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR_LBN 4
+#define MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR_WIDTH 1
+#define MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT_LBN 5
+#define MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT_WIDTH 1
+#define MC_CMD_MAC_STATS_IN_PERIOD_MS_LBN 16
+#define MC_CMD_MAC_STATS_IN_PERIOD_MS_WIDTH 16
+#define MC_CMD_MAC_STATS_IN_DMA_LEN_OFST 12
+
+/* MC_CMD_MAC_STATS_OUT_DMA msgresponse */
+#define MC_CMD_MAC_STATS_OUT_DMA_LEN 0
+
+/* MC_CMD_MAC_STATS_OUT_NO_DMA msgresponse */
+#define MC_CMD_MAC_STATS_OUT_NO_DMA_LEN (((MC_CMD_MAC_NSTATS*64))>>3)
+#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_OFST 0
+#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_LEN 8
+#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_LO_OFST 0
+#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_OFST 4
+#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS
+#define MC_CMD_MAC_GENERATION_START 0x0 /* enum */
+#define MC_CMD_MAC_TX_PKTS 0x1 /* enum */
+#define MC_CMD_MAC_TX_PAUSE_PKTS 0x2 /* enum */
+#define MC_CMD_MAC_TX_CONTROL_PKTS 0x3 /* enum */
+#define MC_CMD_MAC_TX_UNICAST_PKTS 0x4 /* enum */
+#define MC_CMD_MAC_TX_MULTICAST_PKTS 0x5 /* enum */
+#define MC_CMD_MAC_TX_BROADCAST_PKTS 0x6 /* enum */
+#define MC_CMD_MAC_TX_BYTES 0x7 /* enum */
+#define MC_CMD_MAC_TX_BAD_BYTES 0x8 /* enum */
+#define MC_CMD_MAC_TX_LT64_PKTS 0x9 /* enum */
+#define MC_CMD_MAC_TX_64_PKTS 0xa /* enum */
+#define MC_CMD_MAC_TX_65_TO_127_PKTS 0xb /* enum */
+#define MC_CMD_MAC_TX_128_TO_255_PKTS 0xc /* enum */
+#define MC_CMD_MAC_TX_256_TO_511_PKTS 0xd /* enum */
+#define MC_CMD_MAC_TX_512_TO_1023_PKTS 0xe /* enum */
+#define MC_CMD_MAC_TX_1024_TO_15XX_PKTS 0xf /* enum */
+#define MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS 0x10 /* enum */
+#define MC_CMD_MAC_TX_GTJUMBO_PKTS 0x11 /* enum */
+#define MC_CMD_MAC_TX_BAD_FCS_PKTS 0x12 /* enum */
+#define MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS 0x13 /* enum */
+#define MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS 0x14 /* enum */
+#define MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS 0x15 /* enum */
+#define MC_CMD_MAC_TX_LATE_COLLISION_PKTS 0x16 /* enum */
+#define MC_CMD_MAC_TX_DEFERRED_PKTS 0x17 /* enum */
+#define MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS 0x18 /* enum */
+#define MC_CMD_MAC_TX_NON_TCPUDP_PKTS 0x19 /* enum */
+#define MC_CMD_MAC_TX_MAC_SRC_ERR_PKTS 0x1a /* enum */
+#define MC_CMD_MAC_TX_IP_SRC_ERR_PKTS 0x1b /* enum */
+#define MC_CMD_MAC_RX_PKTS 0x1c /* enum */
+#define MC_CMD_MAC_RX_PAUSE_PKTS 0x1d /* enum */
+#define MC_CMD_MAC_RX_GOOD_PKTS 0x1e /* enum */
+#define MC_CMD_MAC_RX_CONTROL_PKTS 0x1f /* enum */
+#define MC_CMD_MAC_RX_UNICAST_PKTS 0x20 /* enum */
+#define MC_CMD_MAC_RX_MULTICAST_PKTS 0x21 /* enum */
+#define MC_CMD_MAC_RX_BROADCAST_PKTS 0x22 /* enum */
+#define MC_CMD_MAC_RX_BYTES 0x23 /* enum */
+#define MC_CMD_MAC_RX_BAD_BYTES 0x24 /* enum */
+#define MC_CMD_MAC_RX_64_PKTS 0x25 /* enum */
+#define MC_CMD_MAC_RX_65_TO_127_PKTS 0x26 /* enum */
+#define MC_CMD_MAC_RX_128_TO_255_PKTS 0x27 /* enum */
+#define MC_CMD_MAC_RX_256_TO_511_PKTS 0x28 /* enum */
+#define MC_CMD_MAC_RX_512_TO_1023_PKTS 0x29 /* enum */
+#define MC_CMD_MAC_RX_1024_TO_15XX_PKTS 0x2a /* enum */
+#define MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS 0x2b /* enum */
+#define MC_CMD_MAC_RX_GTJUMBO_PKTS 0x2c /* enum */
+#define MC_CMD_MAC_RX_UNDERSIZE_PKTS 0x2d /* enum */
+#define MC_CMD_MAC_RX_BAD_FCS_PKTS 0x2e /* enum */
+#define MC_CMD_MAC_RX_OVERFLOW_PKTS 0x2f /* enum */
+#define MC_CMD_MAC_RX_FALSE_CARRIER_PKTS 0x30 /* enum */
+#define MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS 0x31 /* enum */
+#define MC_CMD_MAC_RX_ALIGN_ERROR_PKTS 0x32 /* enum */
+#define MC_CMD_MAC_RX_LENGTH_ERROR_PKTS 0x33 /* enum */
+#define MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS 0x34 /* enum */
+#define MC_CMD_MAC_RX_JABBER_PKTS 0x35 /* enum */
+#define MC_CMD_MAC_RX_NODESC_DROPS 0x36 /* enum */
+#define MC_CMD_MAC_RX_LANES01_CHAR_ERR 0x37 /* enum */
+#define MC_CMD_MAC_RX_LANES23_CHAR_ERR 0x38 /* enum */
+#define MC_CMD_MAC_RX_LANES01_DISP_ERR 0x39 /* enum */
+#define MC_CMD_MAC_RX_LANES23_DISP_ERR 0x3a /* enum */
+#define MC_CMD_MAC_RX_MATCH_FAULT 0x3b /* enum */
+#define MC_CMD_GMAC_DMABUF_START 0x40 /* enum */
+#define MC_CMD_GMAC_DMABUF_END 0x5f /* enum */
+#define MC_CMD_MAC_GENERATION_END 0x60 /* enum */
+#define MC_CMD_MAC_NSTATS 0x61 /* enum */
+
+
+/***********************************/
+/* MC_CMD_SRIOV
+ * to be documented
+ */
+#define MC_CMD_SRIOV 0x30
+
+/* MC_CMD_SRIOV_IN msgrequest */
+#define MC_CMD_SRIOV_IN_LEN 12
+#define MC_CMD_SRIOV_IN_ENABLE_OFST 0
+#define MC_CMD_SRIOV_IN_VI_BASE_OFST 4
+#define MC_CMD_SRIOV_IN_VF_COUNT_OFST 8
+
+/* MC_CMD_SRIOV_OUT msgresponse */
+#define MC_CMD_SRIOV_OUT_LEN 8
+#define MC_CMD_SRIOV_OUT_VI_SCALE_OFST 0
+#define MC_CMD_SRIOV_OUT_VF_TOTAL_OFST 4
+
+/* MC_CMD_MEMCPY_RECORD_TYPEDEF structuredef */
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LEN 32
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_OFST 0
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_LBN 0
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_WIDTH 32
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_OFST 4
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_LBN 32
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_WIDTH 32
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_OFST 8
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LEN 8
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LO_OFST 8
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_HI_OFST 12
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LBN 64
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_WIDTH 64
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_OFST 16
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_RID_INLINE 0x100 /* enum */
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_LBN 128
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_WIDTH 32
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_OFST 20
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LEN 8
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LO_OFST 20
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_HI_OFST 24
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LBN 160
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_WIDTH 64
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_OFST 28
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_LBN 224
+#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_WIDTH 32
+
+
+/***********************************/
+/* MC_CMD_MEMCPY
+ * Perform memory copy operation.
+ */
+#define MC_CMD_MEMCPY 0x31
+
+/* MC_CMD_MEMCPY_IN msgrequest */
+#define MC_CMD_MEMCPY_IN_LENMIN 32
+#define MC_CMD_MEMCPY_IN_LENMAX 224
+#define MC_CMD_MEMCPY_IN_LEN(num) (0+32*(num))
+#define MC_CMD_MEMCPY_IN_RECORD_OFST 0
+#define MC_CMD_MEMCPY_IN_RECORD_LEN 32
+#define MC_CMD_MEMCPY_IN_RECORD_MINNUM 1
+#define MC_CMD_MEMCPY_IN_RECORD_MAXNUM 7
+
+/* MC_CMD_MEMCPY_OUT msgresponse */
+#define MC_CMD_MEMCPY_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_WOL_FILTER_SET
+ * Set a WoL filter.
*/
#define MC_CMD_WOL_FILTER_SET 0x32
-#define MC_CMD_WOL_FILTER_SET_IN_LEN 192 /* 190 rounded up to a word */
-#define MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0
-#define MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4
-
-/* There is a union at offset 8, following defines overlap due to
- * this */
-#define MC_CMD_WOL_FILTER_SET_IN_DATA_OFST 8
-
-#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_OFST \
- MC_CMD_WOL_FILTER_SET_IN_DATA_OFST
-
-#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_IP_OFST \
- MC_CMD_WOL_FILTER_SET_IN_DATA_OFST
-#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_IP_OFST \
- (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 4)
-#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_OFST \
- (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 8)
-#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_OFST \
- (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 10)
-
-#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_OFST \
- MC_CMD_WOL_FILTER_SET_IN_DATA_OFST
-#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_OFST \
- (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 16)
-#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_OFST \
- (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 32)
-#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_OFST \
- (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 34)
-
-#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_OFST \
- MC_CMD_WOL_FILTER_SET_IN_DATA_OFST
-#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_OFST \
- (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 48)
-#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_OFST \
- (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 176)
-#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_OFST \
- (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 177)
-#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_OFST \
- (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 178)
-
-#define MC_CMD_WOL_FILTER_SET_IN_LINK_MASK_OFST \
- MC_CMD_WOL_FILTER_SET_IN_DATA_OFST
-#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_LBN 0
-#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_WIDTH 1
-#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_LBN 1
-#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_WIDTH 1
-
-#define MC_CMD_WOL_FILTER_SET_OUT_LEN 4
-#define MC_CMD_WOL_FILTER_SET_OUT_FILTER_ID_OFST 0
-
-/* WOL Filter types enumeration */
-#define MC_CMD_WOL_TYPE_MAGIC 0x0
- /* unused 0x1 */
-#define MC_CMD_WOL_TYPE_WIN_MAGIC 0x2
-#define MC_CMD_WOL_TYPE_IPV4_SYN 0x3
-#define MC_CMD_WOL_TYPE_IPV6_SYN 0x4
-#define MC_CMD_WOL_TYPE_BITMAP 0x5
-#define MC_CMD_WOL_TYPE_LINK 0x6
-#define MC_CMD_WOL_TYPE_MAX 0x7
-
-#define MC_CMD_FILTER_MODE_SIMPLE 0x0
-#define MC_CMD_FILTER_MODE_STRUCTURED 0xffffffff
-
-/* MC_CMD_WOL_FILTER_REMOVE:
- * Remove a WoL filter
- *
- * Locks required: None
- * Returns: 0, EINVAL, ENOSYS
+
+/* MC_CMD_WOL_FILTER_SET_IN msgrequest */
+#define MC_CMD_WOL_FILTER_SET_IN_LEN 192
+#define MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0
+#define MC_CMD_FILTER_MODE_SIMPLE 0x0 /* enum */
+#define MC_CMD_FILTER_MODE_STRUCTURED 0xffffffff /* enum */
+#define MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4
+#define MC_CMD_WOL_TYPE_MAGIC 0x0 /* enum */
+#define MC_CMD_WOL_TYPE_WIN_MAGIC 0x2 /* enum */
+#define MC_CMD_WOL_TYPE_IPV4_SYN 0x3 /* enum */
+#define MC_CMD_WOL_TYPE_IPV6_SYN 0x4 /* enum */
+#define MC_CMD_WOL_TYPE_BITMAP 0x5 /* enum */
+#define MC_CMD_WOL_TYPE_LINK 0x6 /* enum */
+#define MC_CMD_WOL_TYPE_MAX 0x7 /* enum */
+#define MC_CMD_WOL_FILTER_SET_IN_DATA_OFST 8
+#define MC_CMD_WOL_FILTER_SET_IN_DATA_LEN 4
+#define MC_CMD_WOL_FILTER_SET_IN_DATA_NUM 46
+
+/* MC_CMD_WOL_FILTER_SET_IN_MAGIC msgrequest */
+#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_LEN 16
+/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */
+/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */
+#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_OFST 8
+#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_LEN 8
+#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_LO_OFST 8
+#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_HI_OFST 12
+
+/* MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN msgrequest */
+#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_LEN 20
+/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */
+/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */
+#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_IP_OFST 8
+#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_IP_OFST 12
+#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_OFST 16
+#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_LEN 2
+#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_OFST 18
+#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_LEN 2
+
+/* MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN msgrequest */
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_LEN 44
+/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */
+/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_OFST 8
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_LEN 16
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_OFST 24
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_LEN 16
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_OFST 40
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_LEN 2
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_OFST 42
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_LEN 2
+
+/* MC_CMD_WOL_FILTER_SET_IN_BITMAP msgrequest */
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN 187
+/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */
+/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_OFST 8
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_LEN 48
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_BITMAP_OFST 56
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_BITMAP_LEN 128
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_OFST 184
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_LEN 1
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_OFST 185
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_LEN 1
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_OFST 186
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_LEN 1
+
+/* MC_CMD_WOL_FILTER_SET_IN_LINK msgrequest */
+#define MC_CMD_WOL_FILTER_SET_IN_LINK_LEN 12
+/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */
+/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */
+#define MC_CMD_WOL_FILTER_SET_IN_LINK_MASK_OFST 8
+#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_LBN 0
+#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_WIDTH 1
+#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_LBN 1
+#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_WIDTH 1
+
+/* MC_CMD_WOL_FILTER_SET_OUT msgresponse */
+#define MC_CMD_WOL_FILTER_SET_OUT_LEN 4
+#define MC_CMD_WOL_FILTER_SET_OUT_FILTER_ID_OFST 0
+
+
+/***********************************/
+/* MC_CMD_WOL_FILTER_REMOVE
+ * Remove a WoL filter.
*/
#define MC_CMD_WOL_FILTER_REMOVE 0x33
-#define MC_CMD_WOL_FILTER_REMOVE_IN_LEN 4
-#define MC_CMD_WOL_FILTER_REMOVE_IN_FILTER_ID_OFST 0
-#define MC_CMD_WOL_FILTER_REMOVE_OUT_LEN 0
+/* MC_CMD_WOL_FILTER_REMOVE_IN msgrequest */
+#define MC_CMD_WOL_FILTER_REMOVE_IN_LEN 4
+#define MC_CMD_WOL_FILTER_REMOVE_IN_FILTER_ID_OFST 0
-/* MC_CMD_WOL_FILTER_RESET:
- * Reset (i.e. remove all) WoL filters
- *
- * Locks required: None
- * Returns: 0, ENOSYS
+/* MC_CMD_WOL_FILTER_REMOVE_OUT msgresponse */
+#define MC_CMD_WOL_FILTER_REMOVE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_WOL_FILTER_RESET
+ * Reset (i.e. remove all) WoL filters.
*/
#define MC_CMD_WOL_FILTER_RESET 0x34
-#define MC_CMD_WOL_FILTER_RESET_IN_LEN 0
-#define MC_CMD_WOL_FILTER_RESET_OUT_LEN 0
-/* MC_CMD_SET_MCAST_HASH:
- * Set the MCASH hash value without otherwise
- * reconfiguring the MAC
+/* MC_CMD_WOL_FILTER_RESET_IN msgrequest */
+#define MC_CMD_WOL_FILTER_RESET_IN_LEN 4
+#define MC_CMD_WOL_FILTER_RESET_IN_MASK_OFST 0
+#define MC_CMD_WOL_FILTER_RESET_IN_WAKE_FILTERS 0x1 /* enum */
+#define MC_CMD_WOL_FILTER_RESET_IN_LIGHTSOUT_OFFLOADS 0x2 /* enum */
+
+/* MC_CMD_WOL_FILTER_RESET_OUT msgresponse */
+#define MC_CMD_WOL_FILTER_RESET_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SET_MCAST_HASH
+ * Set the MCASH hash value.
*/
#define MC_CMD_SET_MCAST_HASH 0x35
-#define MC_CMD_SET_MCAST_HASH_IN_LEN 32
-#define MC_CMD_SET_MCAST_HASH_IN_HASH0_OFST 0
-#define MC_CMD_SET_MCAST_HASH_IN_HASH1_OFST 16
-#define MC_CMD_SET_MCAST_HASH_OUT_LEN 0
-/* MC_CMD_NVRAM_TYPES:
- * Return bitfield indicating available types of virtual NVRAM partitions
- *
- * Locks required: none
- * Returns: 0
+/* MC_CMD_SET_MCAST_HASH_IN msgrequest */
+#define MC_CMD_SET_MCAST_HASH_IN_LEN 32
+#define MC_CMD_SET_MCAST_HASH_IN_HASH0_OFST 0
+#define MC_CMD_SET_MCAST_HASH_IN_HASH0_LEN 16
+#define MC_CMD_SET_MCAST_HASH_IN_HASH1_OFST 16
+#define MC_CMD_SET_MCAST_HASH_IN_HASH1_LEN 16
+
+/* MC_CMD_SET_MCAST_HASH_OUT msgresponse */
+#define MC_CMD_SET_MCAST_HASH_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_NVRAM_TYPES
+ * Get virtual NVRAM partitions information.
*/
#define MC_CMD_NVRAM_TYPES 0x36
-#define MC_CMD_NVRAM_TYPES_IN_LEN 0
-#define MC_CMD_NVRAM_TYPES_OUT_LEN 4
-#define MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0
-
-/* Supported NVRAM types */
-#define MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0
-#define MC_CMD_NVRAM_TYPE_MC_FW 1
-#define MC_CMD_NVRAM_TYPE_MC_FW_BACKUP 2
-#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 3
-#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1 4
-#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 5
-#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1 6
-#define MC_CMD_NVRAM_TYPE_EXP_ROM 7
-#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0 8
-#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1 9
-#define MC_CMD_NVRAM_TYPE_PHY_PORT0 10
-#define MC_CMD_NVRAM_TYPE_PHY_PORT1 11
-#define MC_CMD_NVRAM_TYPE_LOG 12
-
-/* MC_CMD_NVRAM_INFO:
- * Read info about a virtual NVRAM partition
- *
- * Locks required: none
- * Returns: 0, EINVAL (bad type)
+
+/* MC_CMD_NVRAM_TYPES_IN msgrequest */
+#define MC_CMD_NVRAM_TYPES_IN_LEN 0
+
+/* MC_CMD_NVRAM_TYPES_OUT msgresponse */
+#define MC_CMD_NVRAM_TYPES_OUT_LEN 4
+#define MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0
+#define MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0x0 /* enum */
+#define MC_CMD_NVRAM_TYPE_MC_FW 0x1 /* enum */
+#define MC_CMD_NVRAM_TYPE_MC_FW_BACKUP 0x2 /* enum */
+#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 0x3 /* enum */
+#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1 0x4 /* enum */
+#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 0x5 /* enum */
+#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1 0x6 /* enum */
+#define MC_CMD_NVRAM_TYPE_EXP_ROM 0x7 /* enum */
+#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0 0x8 /* enum */
+#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1 0x9 /* enum */
+#define MC_CMD_NVRAM_TYPE_PHY_PORT0 0xa /* enum */
+#define MC_CMD_NVRAM_TYPE_PHY_PORT1 0xb /* enum */
+#define MC_CMD_NVRAM_TYPE_LOG 0xc /* enum */
+#define MC_CMD_NVRAM_TYPE_FPGA 0xd /* enum */
+
+
+/***********************************/
+/* MC_CMD_NVRAM_INFO
+ * Read info about a virtual NVRAM partition.
*/
#define MC_CMD_NVRAM_INFO 0x37
-#define MC_CMD_NVRAM_INFO_IN_LEN 4
-#define MC_CMD_NVRAM_INFO_IN_TYPE_OFST 0
-#define MC_CMD_NVRAM_INFO_OUT_LEN 24
-#define MC_CMD_NVRAM_INFO_OUT_TYPE_OFST 0
-#define MC_CMD_NVRAM_INFO_OUT_SIZE_OFST 4
-#define MC_CMD_NVRAM_INFO_OUT_ERASESIZE_OFST 8
-#define MC_CMD_NVRAM_INFO_OUT_FLAGS_OFST 12
-#define MC_CMD_NVRAM_PROTECTED_LBN 0
-#define MC_CMD_NVRAM_PROTECTED_WIDTH 1
-#define MC_CMD_NVRAM_INFO_OUT_PHYSDEV_OFST 16
-#define MC_CMD_NVRAM_INFO_OUT_PHYSADDR_OFST 20
-
-/* MC_CMD_NVRAM_UPDATE_START:
- * Start a group of update operations on a virtual NVRAM partition
- *
- * Locks required: PHY_LOCK if type==*PHY*
- * Returns: 0, EINVAL (bad type), EACCES (if PHY_LOCK required and not held)
+
+/* MC_CMD_NVRAM_INFO_IN msgrequest */
+#define MC_CMD_NVRAM_INFO_IN_LEN 4
+#define MC_CMD_NVRAM_INFO_IN_TYPE_OFST 0
+/* Enum values, see field(s): */
+/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+
+/* MC_CMD_NVRAM_INFO_OUT msgresponse */
+#define MC_CMD_NVRAM_INFO_OUT_LEN 24
+#define MC_CMD_NVRAM_INFO_OUT_TYPE_OFST 0
+/* Enum values, see field(s): */
+/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define MC_CMD_NVRAM_INFO_OUT_SIZE_OFST 4
+#define MC_CMD_NVRAM_INFO_OUT_ERASESIZE_OFST 8
+#define MC_CMD_NVRAM_INFO_OUT_FLAGS_OFST 12
+#define MC_CMD_NVRAM_INFO_OUT_PROTECTED_LBN 0
+#define MC_CMD_NVRAM_INFO_OUT_PROTECTED_WIDTH 1
+#define MC_CMD_NVRAM_INFO_OUT_PHYSDEV_OFST 16
+#define MC_CMD_NVRAM_INFO_OUT_PHYSADDR_OFST 20
+
+
+/***********************************/
+/* MC_CMD_NVRAM_UPDATE_START
+ * Start a group of update operations on a virtual NVRAM partition.
*/
#define MC_CMD_NVRAM_UPDATE_START 0x38
-#define MC_CMD_NVRAM_UPDATE_START_IN_LEN 4
-#define MC_CMD_NVRAM_UPDATE_START_IN_TYPE_OFST 0
-#define MC_CMD_NVRAM_UPDATE_START_OUT_LEN 0
-/* MC_CMD_NVRAM_READ:
- * Read data from a virtual NVRAM partition
- *
- * Locks required: PHY_LOCK if type==*PHY*
- * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held)
+/* MC_CMD_NVRAM_UPDATE_START_IN msgrequest */
+#define MC_CMD_NVRAM_UPDATE_START_IN_LEN 4
+#define MC_CMD_NVRAM_UPDATE_START_IN_TYPE_OFST 0
+/* Enum values, see field(s): */
+/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+
+/* MC_CMD_NVRAM_UPDATE_START_OUT msgresponse */
+#define MC_CMD_NVRAM_UPDATE_START_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_NVRAM_READ
+ * Read data from a virtual NVRAM partition.
*/
#define MC_CMD_NVRAM_READ 0x39
-#define MC_CMD_NVRAM_READ_IN_LEN 12
-#define MC_CMD_NVRAM_READ_IN_TYPE_OFST 0
-#define MC_CMD_NVRAM_READ_IN_OFFSET_OFST 4
-#define MC_CMD_NVRAM_READ_IN_LENGTH_OFST 8
-#define MC_CMD_NVRAM_READ_OUT_LEN(_read_bytes) (_read_bytes)
-#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_OFST 0
-
-/* MC_CMD_NVRAM_WRITE:
- * Write data to a virtual NVRAM partition
- *
- * Locks required: PHY_LOCK if type==*PHY*
- * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held)
+
+/* MC_CMD_NVRAM_READ_IN msgrequest */
+#define MC_CMD_NVRAM_READ_IN_LEN 12
+#define MC_CMD_NVRAM_READ_IN_TYPE_OFST 0
+/* Enum values, see field(s): */
+/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define MC_CMD_NVRAM_READ_IN_OFFSET_OFST 4
+#define MC_CMD_NVRAM_READ_IN_LENGTH_OFST 8
+
+/* MC_CMD_NVRAM_READ_OUT msgresponse */
+#define MC_CMD_NVRAM_READ_OUT_LENMIN 1
+#define MC_CMD_NVRAM_READ_OUT_LENMAX 255
+#define MC_CMD_NVRAM_READ_OUT_LEN(num) (0+1*(num))
+#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_OFST 0
+#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_LEN 1
+#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MINNUM 1
+#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MAXNUM 255
+
+
+/***********************************/
+/* MC_CMD_NVRAM_WRITE
+ * Write data to a virtual NVRAM partition.
*/
#define MC_CMD_NVRAM_WRITE 0x3a
-#define MC_CMD_NVRAM_WRITE_IN_TYPE_OFST 0
-#define MC_CMD_NVRAM_WRITE_IN_OFFSET_OFST 4
-#define MC_CMD_NVRAM_WRITE_IN_LENGTH_OFST 8
-#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_OFST 12
-#define MC_CMD_NVRAM_WRITE_IN_LEN(_write_bytes) (12 + _write_bytes)
-#define MC_CMD_NVRAM_WRITE_OUT_LEN 0
-
-/* MC_CMD_NVRAM_ERASE:
- * Erase sector(s) from a virtual NVRAM partition
- *
- * Locks required: PHY_LOCK if type==*PHY*
- * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held)
+
+/* MC_CMD_NVRAM_WRITE_IN msgrequest */
+#define MC_CMD_NVRAM_WRITE_IN_LENMIN 13
+#define MC_CMD_NVRAM_WRITE_IN_LENMAX 255
+#define MC_CMD_NVRAM_WRITE_IN_LEN(num) (12+1*(num))
+#define MC_CMD_NVRAM_WRITE_IN_TYPE_OFST 0
+/* Enum values, see field(s): */
+/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define MC_CMD_NVRAM_WRITE_IN_OFFSET_OFST 4
+#define MC_CMD_NVRAM_WRITE_IN_LENGTH_OFST 8
+#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_OFST 12
+#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN 1
+#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MINNUM 1
+#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM 243
+
+/* MC_CMD_NVRAM_WRITE_OUT msgresponse */
+#define MC_CMD_NVRAM_WRITE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_NVRAM_ERASE
+ * Erase sector(s) from a virtual NVRAM partition.
*/
#define MC_CMD_NVRAM_ERASE 0x3b
-#define MC_CMD_NVRAM_ERASE_IN_LEN 12
-#define MC_CMD_NVRAM_ERASE_IN_TYPE_OFST 0
-#define MC_CMD_NVRAM_ERASE_IN_OFFSET_OFST 4
-#define MC_CMD_NVRAM_ERASE_IN_LENGTH_OFST 8
-#define MC_CMD_NVRAM_ERASE_OUT_LEN 0
-
-/* MC_CMD_NVRAM_UPDATE_FINISH:
- * Finish a group of update operations on a virtual NVRAM partition
- *
- * Locks required: PHY_LOCK if type==*PHY*
- * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held)
+
+/* MC_CMD_NVRAM_ERASE_IN msgrequest */
+#define MC_CMD_NVRAM_ERASE_IN_LEN 12
+#define MC_CMD_NVRAM_ERASE_IN_TYPE_OFST 0
+/* Enum values, see field(s): */
+/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define MC_CMD_NVRAM_ERASE_IN_OFFSET_OFST 4
+#define MC_CMD_NVRAM_ERASE_IN_LENGTH_OFST 8
+
+/* MC_CMD_NVRAM_ERASE_OUT msgresponse */
+#define MC_CMD_NVRAM_ERASE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_NVRAM_UPDATE_FINISH
+ * Finish a group of update operations on a virtual NVRAM partition.
*/
#define MC_CMD_NVRAM_UPDATE_FINISH 0x3c
-#define MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN 8
-#define MC_CMD_NVRAM_UPDATE_FINISH_IN_TYPE_OFST 0
-#define MC_CMD_NVRAM_UPDATE_FINISH_IN_REBOOT_OFST 4
-#define MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN 0
-/* MC_CMD_REBOOT:
+/* MC_CMD_NVRAM_UPDATE_FINISH_IN msgrequest */
+#define MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN 8
+#define MC_CMD_NVRAM_UPDATE_FINISH_IN_TYPE_OFST 0
+/* Enum values, see field(s): */
+/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+#define MC_CMD_NVRAM_UPDATE_FINISH_IN_REBOOT_OFST 4
+
+/* MC_CMD_NVRAM_UPDATE_FINISH_OUT msgresponse */
+#define MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_REBOOT
* Reboot the MC.
- *
- * The AFTER_ASSERTION flag is intended to be used when the driver notices
- * an assertion failure (at which point it is expected to perform a complete
- * tear down and reinitialise), to allow both ports to reset the MC once
- * in an atomic fashion.
- *
- * Production mc firmwares are generally compiled with REBOOT_ON_ASSERT=1,
- * which means that they will automatically reboot out of the assertion
- * handler, so this is in practise an optional operation. It is still
- * recommended that drivers execute this to support custom firmwares
- * with REBOOT_ON_ASSERT=0.
- *
- * Locks required: NONE
- * Returns: Nothing. You get back a response with ERR=1, DATALEN=0
*/
#define MC_CMD_REBOOT 0x3d
-#define MC_CMD_REBOOT_IN_LEN 4
-#define MC_CMD_REBOOT_IN_FLAGS_OFST 0
-#define MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION 1
-#define MC_CMD_REBOOT_OUT_LEN 0
-/* MC_CMD_SCHEDINFO:
- * Request scheduler info. from the MC.
- *
- * Locks required: NONE
- * Returns: An array of (timeslice,maximum overrun), one for each thread,
- * in ascending order of thread address.s
+/* MC_CMD_REBOOT_IN msgrequest */
+#define MC_CMD_REBOOT_IN_LEN 4
+#define MC_CMD_REBOOT_IN_FLAGS_OFST 0
+#define MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION 0x1 /* enum */
+
+/* MC_CMD_REBOOT_OUT msgresponse */
+#define MC_CMD_REBOOT_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_SCHEDINFO
+ * Request scheduler info.
*/
#define MC_CMD_SCHEDINFO 0x3e
-#define MC_CMD_SCHEDINFO_IN_LEN 0
+/* MC_CMD_SCHEDINFO_IN msgrequest */
+#define MC_CMD_SCHEDINFO_IN_LEN 0
-/* MC_CMD_SET_REBOOT_MODE: (debug)
- * Set the mode for the next MC reboot.
- *
- * Locks required: NONE
- *
- * Sets the reboot mode to the specified value. Returns the old mode.
+/* MC_CMD_SCHEDINFO_OUT msgresponse */
+#define MC_CMD_SCHEDINFO_OUT_LENMIN 4
+#define MC_CMD_SCHEDINFO_OUT_LENMAX 252
+#define MC_CMD_SCHEDINFO_OUT_LEN(num) (0+4*(num))
+#define MC_CMD_SCHEDINFO_OUT_DATA_OFST 0
+#define MC_CMD_SCHEDINFO_OUT_DATA_LEN 4
+#define MC_CMD_SCHEDINFO_OUT_DATA_MINNUM 1
+#define MC_CMD_SCHEDINFO_OUT_DATA_MAXNUM 63
+
+
+/***********************************/
+/* MC_CMD_REBOOT_MODE
*/
#define MC_CMD_REBOOT_MODE 0x3f
-#define MC_CMD_REBOOT_MODE_IN_LEN 4
-#define MC_CMD_REBOOT_MODE_IN_VALUE_OFST 0
-#define MC_CMD_REBOOT_MODE_OUT_LEN 4
-#define MC_CMD_REBOOT_MODE_OUT_VALUE_OFST 0
-#define MC_CMD_REBOOT_MODE_NORMAL 0
-#define MC_CMD_REBOOT_MODE_SNAPPER 3
-
-/* MC_CMD_DEBUG_LOG:
- * Null request/response command (debug)
- * - sequence number is always zero
- * - only supported on the UART interface
- * (the same set of bytes is delivered as an
- * event over PCI)
- */
-#define MC_CMD_DEBUG_LOG 0x40
-#define MC_CMD_DEBUG_LOG_IN_LEN 0
-#define MC_CMD_DEBUG_LOG_OUT_LEN 0
-
-/* Generic sensor enumeration. Note that a dual port NIC
- * will EITHER expose PHY_COMMON_TEMP OR PHY0_TEMP and
- * PHY1_TEMP depending on whether there is a single sensor
- * in the vicinity of the two port, or one per port.
- */
-#define MC_CMD_SENSOR_CONTROLLER_TEMP 0 /* degC */
-#define MC_CMD_SENSOR_PHY_COMMON_TEMP 1 /* degC */
-#define MC_CMD_SENSOR_CONTROLLER_COOLING 2 /* bool */
-#define MC_CMD_SENSOR_PHY0_TEMP 3 /* degC */
-#define MC_CMD_SENSOR_PHY0_COOLING 4 /* bool */
-#define MC_CMD_SENSOR_PHY1_TEMP 5 /* degC */
-#define MC_CMD_SENSOR_PHY1_COOLING 6 /* bool */
-#define MC_CMD_SENSOR_IN_1V0 7 /* mV */
-#define MC_CMD_SENSOR_IN_1V2 8 /* mV */
-#define MC_CMD_SENSOR_IN_1V8 9 /* mV */
-#define MC_CMD_SENSOR_IN_2V5 10 /* mV */
-#define MC_CMD_SENSOR_IN_3V3 11 /* mV */
-#define MC_CMD_SENSOR_IN_12V0 12 /* mV */
-
-
-/* Sensor state */
-#define MC_CMD_SENSOR_STATE_OK 0
-#define MC_CMD_SENSOR_STATE_WARNING 1
-#define MC_CMD_SENSOR_STATE_FATAL 2
-#define MC_CMD_SENSOR_STATE_BROKEN 3
-
-/* MC_CMD_SENSOR_INFO:
+
+/* MC_CMD_REBOOT_MODE_IN msgrequest */
+#define MC_CMD_REBOOT_MODE_IN_LEN 4
+#define MC_CMD_REBOOT_MODE_IN_VALUE_OFST 0
+#define MC_CMD_REBOOT_MODE_NORMAL 0x0 /* enum */
+#define MC_CMD_REBOOT_MODE_SNAPPER 0x3 /* enum */
+
+/* MC_CMD_REBOOT_MODE_OUT msgresponse */
+#define MC_CMD_REBOOT_MODE_OUT_LEN 4
+#define MC_CMD_REBOOT_MODE_OUT_VALUE_OFST 0
+
+
+/***********************************/
+/* MC_CMD_SENSOR_INFO
* Returns information about every available sensor.
- *
- * Each sensor has a single (16bit) value, and a corresponding state.
- * The mapping between value and sensor is nominally determined by the
- * MC, but in practise is implemented as zero (BROKEN), one (TEMPERATURE),
- * or two (VOLTAGE) ranges per sensor per state.
- *
- * This call returns a mask (32bit) of the sensors that are supported
- * by this platform, then an array (indexed by MC_CMD_SENSOR) of byte
- * offsets to the per-sensor arrays. Each sensor array has four 16bit
- * numbers, min1, max1, min2, max2.
- *
- * Locks required: None
- * Returns: 0
*/
#define MC_CMD_SENSOR_INFO 0x41
-#define MC_CMD_SENSOR_INFO_IN_LEN 0
-#define MC_CMD_SENSOR_INFO_OUT_MASK_OFST 0
-#define MC_CMD_SENSOR_INFO_OUT_OFFSET_OFST(_x) \
- (4 + (_x))
-#define MC_CMD_SENSOR_INFO_OUT_MIN1_OFST(_ofst) \
- ((_ofst) + 0)
-#define MC_CMD_SENSOR_INFO_OUT_MAX1_OFST(_ofst) \
- ((_ofst) + 2)
-#define MC_CMD_SENSOR_INFO_OUT_MIN2_OFST(_ofst) \
- ((_ofst) + 4)
-#define MC_CMD_SENSOR_INFO_OUT_MAX2_OFST(_ofst) \
- ((_ofst) + 6)
+/* MC_CMD_SENSOR_INFO_IN msgrequest */
+#define MC_CMD_SENSOR_INFO_IN_LEN 0
+
+/* MC_CMD_SENSOR_INFO_OUT msgresponse */
+#define MC_CMD_SENSOR_INFO_OUT_LENMIN 12
+#define MC_CMD_SENSOR_INFO_OUT_LENMAX 252
+#define MC_CMD_SENSOR_INFO_OUT_LEN(num) (4+8*(num))
+#define MC_CMD_SENSOR_INFO_OUT_MASK_OFST 0
+#define MC_CMD_SENSOR_CONTROLLER_TEMP 0x0 /* enum */
+#define MC_CMD_SENSOR_PHY_COMMON_TEMP 0x1 /* enum */
+#define MC_CMD_SENSOR_CONTROLLER_COOLING 0x2 /* enum */
+#define MC_CMD_SENSOR_PHY0_TEMP 0x3 /* enum */
+#define MC_CMD_SENSOR_PHY0_COOLING 0x4 /* enum */
+#define MC_CMD_SENSOR_PHY1_TEMP 0x5 /* enum */
+#define MC_CMD_SENSOR_PHY1_COOLING 0x6 /* enum */
+#define MC_CMD_SENSOR_IN_1V0 0x7 /* enum */
+#define MC_CMD_SENSOR_IN_1V2 0x8 /* enum */
+#define MC_CMD_SENSOR_IN_1V8 0x9 /* enum */
+#define MC_CMD_SENSOR_IN_2V5 0xa /* enum */
+#define MC_CMD_SENSOR_IN_3V3 0xb /* enum */
+#define MC_CMD_SENSOR_IN_12V0 0xc /* enum */
+#define MC_CMD_SENSOR_IN_1V2A 0xd /* enum */
+#define MC_CMD_SENSOR_IN_VREF 0xe /* enum */
+#define MC_CMD_SENSOR_ENTRY_OFST 4
+#define MC_CMD_SENSOR_ENTRY_LEN 8
+#define MC_CMD_SENSOR_ENTRY_LO_OFST 4
+#define MC_CMD_SENSOR_ENTRY_HI_OFST 8
+#define MC_CMD_SENSOR_ENTRY_MINNUM 1
+#define MC_CMD_SENSOR_ENTRY_MAXNUM 31
+
+/* MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF structuredef */
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_LEN 8
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_OFST 0
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_LEN 2
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_LBN 0
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_WIDTH 16
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_OFST 2
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_LEN 2
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_LBN 16
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_WIDTH 16
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_OFST 4
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_LEN 2
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_LBN 32
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_WIDTH 16
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_OFST 6
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_LEN 2
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_LBN 48
+#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_WIDTH 16
+
+
+/***********************************/
/* MC_CMD_READ_SENSORS
- * Returns the current reading from each sensor
- *
- * Returns a sparse array of sensor readings (indexed by the sensor
- * type) into host memory. Each array element is a dword.
- *
- * The MC will send a SENSOREVT event every time any sensor changes state. The
- * driver is responsible for ensuring that it doesn't miss any events. The board
- * will function normally if all sensors are in STATE_OK or state_WARNING.
- * Otherwise the board should not be expected to function.
+ * Returns the current reading from each sensor.
*/
#define MC_CMD_READ_SENSORS 0x42
-#define MC_CMD_READ_SENSORS_IN_LEN 8
-#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_LO_OFST 0
-#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_HI_OFST 4
-#define MC_CMD_READ_SENSORS_OUT_LEN 0
-/* Sensor reading fields */
-#define MC_CMD_READ_SENSOR_VALUE_LBN 0
-#define MC_CMD_READ_SENSOR_VALUE_WIDTH 16
-#define MC_CMD_READ_SENSOR_STATE_LBN 16
-#define MC_CMD_READ_SENSOR_STATE_WIDTH 8
-
-
-/* MC_CMD_GET_PHY_STATE:
- * Report current state of PHY. A "zombie" PHY is a PHY that has failed to
- * boot (e.g. due to missing or corrupted firmware).
- *
- * Locks required: None
- * Return code: 0
+/* MC_CMD_READ_SENSORS_IN msgrequest */
+#define MC_CMD_READ_SENSORS_IN_LEN 8
+#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_OFST 0
+#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_LEN 8
+#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_LO_OFST 0
+#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_HI_OFST 4
+
+/* MC_CMD_READ_SENSORS_OUT msgresponse */
+#define MC_CMD_READ_SENSORS_OUT_LEN 0
+
+/* MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF structuredef */
+#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_LEN 3
+#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_OFST 0
+#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_LEN 2
+#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_LBN 0
+#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_WIDTH 16
+#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_OFST 2
+#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_LEN 1
+#define MC_CMD_SENSOR_STATE_OK 0x0 /* enum */
+#define MC_CMD_SENSOR_STATE_WARNING 0x1 /* enum */
+#define MC_CMD_SENSOR_STATE_FATAL 0x2 /* enum */
+#define MC_CMD_SENSOR_STATE_BROKEN 0x3 /* enum */
+#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_LBN 16
+#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_WIDTH 8
+
+
+/***********************************/
+/* MC_CMD_GET_PHY_STATE
+ * Report current state of PHY.
*/
#define MC_CMD_GET_PHY_STATE 0x43
-#define MC_CMD_GET_PHY_STATE_IN_LEN 0
-#define MC_CMD_GET_PHY_STATE_OUT_LEN 4
-#define MC_CMD_GET_PHY_STATE_STATE_OFST 0
-/* PHY state enumeration: */
-#define MC_CMD_PHY_STATE_OK 1
-#define MC_CMD_PHY_STATE_ZOMBIE 2
+/* MC_CMD_GET_PHY_STATE_IN msgrequest */
+#define MC_CMD_GET_PHY_STATE_IN_LEN 0
+/* MC_CMD_GET_PHY_STATE_OUT msgresponse */
+#define MC_CMD_GET_PHY_STATE_OUT_LEN 4
+#define MC_CMD_GET_PHY_STATE_OUT_STATE_OFST 0
+#define MC_CMD_PHY_STATE_OK 0x1 /* enum */
+#define MC_CMD_PHY_STATE_ZOMBIE 0x2 /* enum */
-/* 802.1Qbb control. 8 Tx queues that map to priorities 0 - 7. Use all 1s to
- * disable 802.Qbb for a given priority. */
+
+/***********************************/
+/* MC_CMD_SETUP_8021QBB
+ * 802.1Qbb control.
+ */
#define MC_CMD_SETUP_8021QBB 0x44
-#define MC_CMD_SETUP_8021QBB_IN_LEN 32
-#define MC_CMD_SETUP_8021QBB_OUT_LEN 0
-#define MC_CMD_SETUP_8021QBB_IN_TXQS_OFFST 0
+/* MC_CMD_SETUP_8021QBB_IN msgrequest */
+#define MC_CMD_SETUP_8021QBB_IN_LEN 32
+#define MC_CMD_SETUP_8021QBB_IN_TXQS_OFST 0
+#define MC_CMD_SETUP_8021QBB_IN_TXQS_LEN 32
-/* MC_CMD_WOL_FILTER_GET:
- * Retrieve ID of any WoL filters
- *
- * Locks required: None
- * Returns: 0, ENOSYS
- */
-#define MC_CMD_WOL_FILTER_GET 0x45
-#define MC_CMD_WOL_FILTER_GET_IN_LEN 0
-#define MC_CMD_WOL_FILTER_GET_OUT_LEN 4
-#define MC_CMD_WOL_FILTER_GET_OUT_FILTER_ID_OFST 0
+/* MC_CMD_SETUP_8021QBB_OUT msgresponse */
+#define MC_CMD_SETUP_8021QBB_OUT_LEN 0
-/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD:
- * Offload a protocol to NIC for lights-out state
- *
- * Locks required: None
- * Returns: 0, ENOSYS
+/***********************************/
+/* MC_CMD_WOL_FILTER_GET
+ * Retrieve ID of any WoL filters.
*/
-#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD 0x46
+#define MC_CMD_WOL_FILTER_GET 0x45
-#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LEN 16
-#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0
+/* MC_CMD_WOL_FILTER_GET_IN msgrequest */
+#define MC_CMD_WOL_FILTER_GET_IN_LEN 0
-/* There is a union at offset 4, following defines overlap due to
- * this */
-#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_OFST 4
-#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARPMAC_OFST 4
-#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARPIP_OFST 10
-#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSMAC_OFST 4
-#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSSNIPV6_OFST 10
-#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSIPV6_OFST 26
+/* MC_CMD_WOL_FILTER_GET_OUT msgresponse */
+#define MC_CMD_WOL_FILTER_GET_OUT_LEN 4
+#define MC_CMD_WOL_FILTER_GET_OUT_FILTER_ID_OFST 0
-#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN 4
-#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_FILTER_ID_OFST 0
+/***********************************/
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD
+ * Add a protocol offload to NIC for lights-out state.
+ */
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD 0x46
-/* MC_CMD_REMOVE_LIGHTSOUT_PROTOCOL_OFFLOAD:
- * Offload a protocol to NIC for lights-out state
- *
- * Locks required: None
- * Returns: 0, ENOSYS
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN msgrequest */
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LENMIN 8
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LENMAX 252
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LEN(num) (4+4*(num))
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0
+#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP 0x1 /* enum */
+#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS 0x2 /* enum */
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_OFST 4
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_LEN 4
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_MINNUM 1
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_MAXNUM 62
+
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP msgrequest */
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_LEN 14
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 */
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_MAC_OFST 4
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_MAC_LEN 6
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_IP_OFST 10
+
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS msgrequest */
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_LEN 42
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 */
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_MAC_OFST 4
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_MAC_LEN 6
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_SNIPV6_OFST 10
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_SNIPV6_LEN 16
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_IPV6_OFST 26
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_IPV6_LEN 16
+
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT msgresponse */
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN 4
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_FILTER_ID_OFST 0
+
+
+/***********************************/
+/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD
+ * Remove a protocol offload from NIC for lights-out state.
*/
#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD 0x47
-#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN 8
-#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN 0
-#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0
-#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_FILTER_ID_OFST 4
+/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN msgrequest */
+#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN 8
+#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0
+#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_FILTER_ID_OFST 4
-/* Lights-out offload protocols enumeration */
-#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP 0x1
-#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS 0x2
+/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT msgresponse */
+#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN 0
-/* MC_CMD_MAC_RESET_RESTORE:
- * Restore MAC after block reset
- *
- * Locks required: None
- * Returns: 0
+/***********************************/
+/* MC_CMD_MAC_RESET_RESTORE
+ * Restore MAC after block reset.
*/
-
#define MC_CMD_MAC_RESET_RESTORE 0x48
-#define MC_CMD_MAC_RESET_RESTORE_IN_LEN 0
-#define MC_CMD_MAC_RESET_RESTORE_OUT_LEN 0
+/* MC_CMD_MAC_RESET_RESTORE_IN msgrequest */
+#define MC_CMD_MAC_RESET_RESTORE_IN_LEN 0
+
+/* MC_CMD_MAC_RESET_RESTORE_OUT msgresponse */
+#define MC_CMD_MAC_RESET_RESTORE_OUT_LEN 0
-/* MC_CMD_TEST_ASSERT:
- * Deliberately trigger an assert-detonation in the firmware for testing
- * purposes (i.e. to allow tests that the driver copes gracefully).
- *
- * Locks required: None
- * Returns: 0
- */
+/***********************************/
+/* MC_CMD_TESTASSERT
+ */
#define MC_CMD_TESTASSERT 0x49
-#define MC_CMD_TESTASSERT_IN_LEN 0
-#define MC_CMD_TESTASSERT_OUT_LEN 0
-/* MC_CMD_WORKAROUND 0x4a
- *
- * Enable/Disable a given workaround. The mcfw will return EINVAL if it
- * doesn't understand the given workaround number - which should not
- * be treated as a hard error by client code.
- *
- * This op does not imply any semantics about each workaround, that's between
- * the driver and the mcfw on a per-workaround basis.
- *
- * Locks required: None
- * Returns: 0, EINVAL
+/* MC_CMD_TESTASSERT_IN msgrequest */
+#define MC_CMD_TESTASSERT_IN_LEN 0
+
+/* MC_CMD_TESTASSERT_OUT msgresponse */
+#define MC_CMD_TESTASSERT_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_WORKAROUND
+ * Enable/Disable a given workaround.
*/
#define MC_CMD_WORKAROUND 0x4a
-#define MC_CMD_WORKAROUND_IN_LEN 8
-#define MC_CMD_WORKAROUND_IN_TYPE_OFST 0
-#define MC_CMD_WORKAROUND_BUG17230 1
-#define MC_CMD_WORKAROUND_IN_ENABLED_OFST 4
-#define MC_CMD_WORKAROUND_OUT_LEN 0
-
-/* MC_CMD_GET_PHY_MEDIA_INFO:
- * Read media-specific data from PHY (e.g. SFP/SFP+ module ID information for
- * SFP+ PHYs).
- *
- * The "media type" can be found via GET_PHY_CFG (GET_PHY_CFG_OUT_MEDIA_TYPE);
- * the valid "page number" input values, and the output data, are interpreted
- * on a per-type basis.
- *
- * For SFP+: PAGE=0 or 1 returns a 128-byte block read from module I2C address
- * 0xA0 offset 0 or 0x80.
- * Anything else: currently undefined.
- *
- * Locks required: None
- * Return code: 0
+
+/* MC_CMD_WORKAROUND_IN msgrequest */
+#define MC_CMD_WORKAROUND_IN_LEN 8
+#define MC_CMD_WORKAROUND_IN_TYPE_OFST 0
+#define MC_CMD_WORKAROUND_BUG17230 0x1 /* enum */
+#define MC_CMD_WORKAROUND_IN_ENABLED_OFST 4
+
+/* MC_CMD_WORKAROUND_OUT msgresponse */
+#define MC_CMD_WORKAROUND_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_PHY_MEDIA_INFO
+ * Read media-specific data from PHY.
*/
#define MC_CMD_GET_PHY_MEDIA_INFO 0x4b
-#define MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN 4
-#define MC_CMD_GET_PHY_MEDIA_INFO_IN_PAGE_OFST 0
-#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(_num_bytes) (4 + (_num_bytes))
-#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATALEN_OFST 0
-#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST 4
-
-/* MC_CMD_NVRAM_TEST:
- * Test a particular NVRAM partition for valid contents (where "valid"
- * depends on the type of partition).
- *
- * Locks required: None
- * Return code: 0
+
+/* MC_CMD_GET_PHY_MEDIA_INFO_IN msgrequest */
+#define MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN 4
+#define MC_CMD_GET_PHY_MEDIA_INFO_IN_PAGE_OFST 0
+
+/* MC_CMD_GET_PHY_MEDIA_INFO_OUT msgresponse */
+#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMIN 5
+#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX 255
+#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(num) (4+1*(num))
+#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATALEN_OFST 0
+#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST 4
+#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_LEN 1
+#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MINNUM 1
+#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MAXNUM 251
+
+
+/***********************************/
+/* MC_CMD_NVRAM_TEST
+ * Test a particular NVRAM partition.
*/
#define MC_CMD_NVRAM_TEST 0x4c
-#define MC_CMD_NVRAM_TEST_IN_LEN 4
-#define MC_CMD_NVRAM_TEST_IN_TYPE_OFST 0
-#define MC_CMD_NVRAM_TEST_OUT_LEN 4
-#define MC_CMD_NVRAM_TEST_OUT_RESULT_OFST 0
-#define MC_CMD_NVRAM_TEST_PASS 0
-#define MC_CMD_NVRAM_TEST_FAIL 1
-#define MC_CMD_NVRAM_TEST_NOTSUPP 2
-
-/* MC_CMD_MRSFP_TWEAK: (debug)
- * Read status and/or set parameters for the "mrsfp" driver in mr_rusty builds.
- * I2C I/O expander bits are always read; if equaliser parameters are supplied,
- * they are configured first.
- *
- * Locks required: None
- * Return code: 0, EINVAL
+
+/* MC_CMD_NVRAM_TEST_IN msgrequest */
+#define MC_CMD_NVRAM_TEST_IN_LEN 4
+#define MC_CMD_NVRAM_TEST_IN_TYPE_OFST 0
+/* Enum values, see field(s): */
+/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */
+
+/* MC_CMD_NVRAM_TEST_OUT msgresponse */
+#define MC_CMD_NVRAM_TEST_OUT_LEN 4
+#define MC_CMD_NVRAM_TEST_OUT_RESULT_OFST 0
+#define MC_CMD_NVRAM_TEST_PASS 0x0 /* enum */
+#define MC_CMD_NVRAM_TEST_FAIL 0x1 /* enum */
+#define MC_CMD_NVRAM_TEST_NOTSUPP 0x2 /* enum */
+
+
+/***********************************/
+/* MC_CMD_MRSFP_TWEAK
+ * Read status and/or set parameters for the 'mrsfp' driver.
*/
#define MC_CMD_MRSFP_TWEAK 0x4d
-#define MC_CMD_MRSFP_TWEAK_IN_LEN_READ_ONLY 0
-#define MC_CMD_MRSFP_TWEAK_IN_LEN_EQ_CONFIG 16
-#define MC_CMD_MRSFP_TWEAK_IN_TXEQ_LEVEL_OFST 0 /* 0-6 low->high de-emph. */
-#define MC_CMD_MRSFP_TWEAK_IN_TXEQ_DT_CFG_OFST 4 /* 0-8 low->high ref.V */
-#define MC_CMD_MRSFP_TWEAK_IN_RXEQ_BOOST_OFST 8 /* 0-8 low->high boost */
-#define MC_CMD_MRSFP_TWEAK_IN_RXEQ_DT_CFG_OFST 12 /* 0-8 low->high ref.V */
-#define MC_CMD_MRSFP_TWEAK_OUT_LEN 12
-#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_INPUTS_OFST 0 /* input bits */
-#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_OUTPUTS_OFST 4 /* output bits */
-#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OFST 8 /* dirs: 0=out, 1=in */
-
-/* MC_CMD_TEST_HACK: (debug (unsurprisingly))
- * Change bits of network port state for test purposes in ways that would never be
- * useful in normal operation and so need a special command to change. */
-#define MC_CMD_TEST_HACK 0x2f
-#define MC_CMD_TEST_HACK_IN_LEN 8
-#define MC_CMD_TEST_HACK_IN_TXPAD_OFST 0
-#define MC_CMD_TEST_HACK_IN_TXPAD_AUTO 0 /* Let the MC manage things */
-#define MC_CMD_TEST_HACK_IN_TXPAD_ON 1 /* Force on */
-#define MC_CMD_TEST_HACK_IN_TXPAD_OFF 2 /* Force on */
-#define MC_CMD_TEST_HACK_IN_IPG_OFST 4 /* Takes a value in bits */
-#define MC_CMD_TEST_HACK_IN_IPG_AUTO 0 /* The MC picks the value */
-#define MC_CMD_TEST_HACK_OUT_LEN 0
-
-/* MC_CMD_SENSOR_SET_LIMS: (debug) (mostly) adjust the sensor limits. This
- * is a warranty-voiding operation.
- *
- * IN: sensor identifier (one of the enumeration starting with MC_CMD_SENSOR_CONTROLLER_TEMP
- * followed by 4 32-bit values: min(warning) max(warning), min(fatal), max(fatal). Which
- * of these limits are meaningful and what their interpretation is is sensor-specific.
- *
- * OUT: nothing
- *
- * Returns: ENOENT if the sensor specified does not exist, EINVAL if the limits are
- * out of range.
+
+/* MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG msgrequest */
+#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_LEN 16
+#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_TXEQ_LEVEL_OFST 0
+#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_TXEQ_DT_CFG_OFST 4
+#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_RXEQ_BOOST_OFST 8
+#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_RXEQ_DT_CFG_OFST 12
+
+/* MC_CMD_MRSFP_TWEAK_IN_READ_ONLY msgrequest */
+#define MC_CMD_MRSFP_TWEAK_IN_READ_ONLY_LEN 0
+
+/* MC_CMD_MRSFP_TWEAK_OUT msgresponse */
+#define MC_CMD_MRSFP_TWEAK_OUT_LEN 12
+#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_INPUTS_OFST 0
+#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_OUTPUTS_OFST 4
+#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OFST 8
+#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OUT 0x0 /* enum */
+#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_IN 0x1 /* enum */
+
+
+/***********************************/
+/* MC_CMD_SENSOR_SET_LIMS
+ * Adjusts the sensor limits.
*/
#define MC_CMD_SENSOR_SET_LIMS 0x4e
-#define MC_CMD_SENSOR_SET_LIMS_IN_LEN 20
-#define MC_CMD_SENSOR_SET_LIMS_IN_SENSOR_OFST 0
-#define MC_CMD_SENSOR_SET_LIMS_IN_LOW0_OFST 4
-#define MC_CMD_SENSOR_SET_LIMS_IN_HI0_OFST 8
-#define MC_CMD_SENSOR_SET_LIMS_IN_LOW1_OFST 12
-#define MC_CMD_SENSOR_SET_LIMS_IN_HI1_OFST 16
-
-/* Do NOT add new commands beyond 0x4f as part of 3.0 : 0x50 - 0x7f will be
- * used for post-3.0 extensions. If you run out of space, look for gaps or
- * commands that are unused in the existing range. */
+
+/* MC_CMD_SENSOR_SET_LIMS_IN msgrequest */
+#define MC_CMD_SENSOR_SET_LIMS_IN_LEN 20
+#define MC_CMD_SENSOR_SET_LIMS_IN_SENSOR_OFST 0
+/* Enum values, see field(s): */
+/* MC_CMD_SENSOR_INFO/MC_CMD_SENSOR_INFO_OUT/MASK */
+#define MC_CMD_SENSOR_SET_LIMS_IN_LOW0_OFST 4
+#define MC_CMD_SENSOR_SET_LIMS_IN_HI0_OFST 8
+#define MC_CMD_SENSOR_SET_LIMS_IN_LOW1_OFST 12
+#define MC_CMD_SENSOR_SET_LIMS_IN_HI1_OFST 16
+
+/* MC_CMD_SENSOR_SET_LIMS_OUT msgresponse */
+#define MC_CMD_SENSOR_SET_LIMS_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_GET_RESOURCE_LIMITS
+ */
+#define MC_CMD_GET_RESOURCE_LIMITS 0x4f
+
+/* MC_CMD_GET_RESOURCE_LIMITS_IN msgrequest */
+#define MC_CMD_GET_RESOURCE_LIMITS_IN_LEN 0
+
+/* MC_CMD_GET_RESOURCE_LIMITS_OUT msgresponse */
+#define MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN 16
+#define MC_CMD_GET_RESOURCE_LIMITS_OUT_BUFTBL_OFST 0
+#define MC_CMD_GET_RESOURCE_LIMITS_OUT_EVQ_OFST 4
+#define MC_CMD_GET_RESOURCE_LIMITS_OUT_RXQ_OFST 8
+#define MC_CMD_GET_RESOURCE_LIMITS_OUT_TXQ_OFST 12
+
+/* MC_CMD_RESOURCE_SPECIFIER enum */
+#define MC_CMD_RESOURCE_INSTANCE_ANY 0xffffffff /* enum */
+#define MC_CMD_RESOURCE_INSTANCE_NONE 0xfffffffe /* enum */
+
#endif /* MCDI_PCOL_H */
diff --git a/drivers/net/ethernet/sfc/mcdi_phy.c b/drivers/net/ethernet/sfc/mcdi_phy.c
index 6c63ab0710af..7bcad899a936 100644
--- a/drivers/net/ethernet/sfc/mcdi_phy.c
+++ b/drivers/net/ethernet/sfc/mcdi_phy.c
@@ -116,7 +116,7 @@ static int efx_mcdi_loopback_modes(struct efx_nic *efx, u64 *loopback_modes)
goto fail;
}
- *loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_SUGGESTED);
+ *loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_OUT_SUGGESTED);
return 0;
@@ -264,22 +264,22 @@ static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx)
/* TODO: Advertise the capabilities supported by this PHY */
supported = 0;
- if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_TXDIS_LBN))
+ if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_TXDIS_LBN))
supported |= PHY_MODE_TX_DISABLED;
- if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_LOWPOWER_LBN))
+ if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_LBN))
supported |= PHY_MODE_LOW_POWER;
- if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_POWEROFF_LBN))
+ if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_POWEROFF_LBN))
supported |= PHY_MODE_OFF;
mode = efx->phy_mode & supported;
flags = 0;
if (mode & PHY_MODE_TX_DISABLED)
- flags |= (1 << MC_CMD_SET_LINK_TXDIS_LBN);
+ flags |= (1 << MC_CMD_SET_LINK_IN_TXDIS_LBN);
if (mode & PHY_MODE_LOW_POWER)
- flags |= (1 << MC_CMD_SET_LINK_LOWPOWER_LBN);
+ flags |= (1 << MC_CMD_SET_LINK_IN_LOWPOWER_LBN);
if (mode & PHY_MODE_OFF)
- flags |= (1 << MC_CMD_SET_LINK_POWEROFF_LBN);
+ flags |= (1 << MC_CMD_SET_LINK_IN_POWEROFF_LBN);
return flags;
}
@@ -436,8 +436,8 @@ void efx_mcdi_phy_decode_link(struct efx_nic *efx,
break;
}
- link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_LINK_UP_LBN));
- link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_FULL_DUPLEX_LBN));
+ link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN));
+ link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN));
link_state->speed = speed;
}
@@ -592,7 +592,7 @@ static int efx_mcdi_phy_test_alive(struct efx_nic *efx)
if (outlen < MC_CMD_GET_PHY_STATE_OUT_LEN)
return -EIO;
- if (MCDI_DWORD(outbuf, GET_PHY_STATE_STATE) != MC_CMD_PHY_STATE_OK)
+ if (MCDI_DWORD(outbuf, GET_PHY_STATE_OUT_STATE) != MC_CMD_PHY_STATE_OK)
return -EINVAL;
return 0;
@@ -680,7 +680,7 @@ static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
u32 mode;
int rc;
- if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_LBN)) {
+ if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) {
rc = efx_mcdi_bist(efx, MC_CMD_PHY_BIST, results);
if (rc < 0)
return rc;
@@ -691,15 +691,15 @@ static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results,
/* If we support both LONG and SHORT, then run each in response to
* break or not. Otherwise, run the one we support */
mode = 0;
- if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_LBN)) {
+ if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN)) {
if ((flags & ETH_TEST_FL_OFFLINE) &&
(phy_cfg->flags &
- (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN)))
+ (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN)))
mode = MC_CMD_PHY_BIST_CABLE_LONG;
else
mode = MC_CMD_PHY_BIST_CABLE_SHORT;
} else if (phy_cfg->flags &
- (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN))
+ (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))
mode = MC_CMD_PHY_BIST_CABLE_LONG;
if (mode != 0) {
@@ -717,14 +717,14 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic *efx,
{
struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
- if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_LBN)) {
+ if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) {
if (index == 0)
return "bist";
--index;
}
- if (phy_cfg->flags & ((1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_LBN) |
- (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN))) {
+ if (phy_cfg->flags & ((1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN) |
+ (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))) {
if (index == 0)
return "cable";
--index;
@@ -741,7 +741,7 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic *efx,
const struct efx_phy_operations efx_mcdi_phy_ops = {
.probe = efx_mcdi_phy_probe,
- .init = efx_port_dummy_op_int,
+ .init = efx_port_dummy_op_int,
.reconfigure = efx_mcdi_phy_reconfigure,
.poll = efx_mcdi_phy_poll,
.fini = efx_port_dummy_op_void,
diff --git a/drivers/net/ethernet/sfc/mdio_10g.c b/drivers/net/ethernet/sfc/mdio_10g.c
index 7ab385c8136d..9acfd6696ffb 100644
--- a/drivers/net/ethernet/sfc/mdio_10g.c
+++ b/drivers/net/ethernet/sfc/mdio_10g.c
@@ -228,7 +228,7 @@ void efx_mdio_set_mmds_lpower(struct efx_nic *efx,
/**
* efx_mdio_set_settings - Set (some of) the PHY settings over MDIO.
* @efx: Efx NIC
- * @ecmd: New settings
+ * @ecmd: New settings
*/
int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
diff --git a/drivers/net/ethernet/sfc/mtd.c b/drivers/net/ethernet/sfc/mtd.c
index bc9dcd6b30d7..26b3c23b0b6f 100644
--- a/drivers/net/ethernet/sfc/mtd.c
+++ b/drivers/net/ethernet/sfc/mtd.c
@@ -280,7 +280,7 @@ fail:
--part;
efx_mtd_remove_partition(part);
}
- /* mtd_device_register() returns 1 if the MTD table is full */
+ /* Failure is unlikely here, but probably means we're out of memory */
return -ENOMEM;
}
@@ -382,7 +382,7 @@ static int falcon_mtd_sync(struct mtd_info *mtd)
return rc;
}
-static struct efx_mtd_ops falcon_mtd_ops = {
+static const struct efx_mtd_ops falcon_mtd_ops = {
.read = falcon_mtd_read,
.erase = falcon_mtd_erase,
.write = falcon_mtd_write,
@@ -560,7 +560,7 @@ static int siena_mtd_sync(struct mtd_info *mtd)
return rc;
}
-static struct efx_mtd_ops siena_mtd_ops = {
+static const struct efx_mtd_ops siena_mtd_ops = {
.read = siena_mtd_read,
.erase = siena_mtd_erase,
.write = siena_mtd_write,
@@ -572,7 +572,7 @@ struct siena_nvram_type_info {
const char *name;
};
-static struct siena_nvram_type_info siena_nvram_types[] = {
+static const struct siena_nvram_type_info siena_nvram_types[] = {
[MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO] = { 0, "sfc_dummy_phy" },
[MC_CMD_NVRAM_TYPE_MC_FW] = { 0, "sfc_mcfw" },
[MC_CMD_NVRAM_TYPE_MC_FW_BACKUP] = { 0, "sfc_mcfw_backup" },
@@ -593,7 +593,7 @@ static int siena_mtd_probe_partition(struct efx_nic *efx,
unsigned int type)
{
struct efx_mtd_partition *part = &efx_mtd->part[part_id];
- struct siena_nvram_type_info *info;
+ const struct siena_nvram_type_info *info;
size_t size, erase_size;
bool protected;
int rc;
@@ -627,11 +627,10 @@ static int siena_mtd_get_fw_subtypes(struct efx_nic *efx,
struct efx_mtd *efx_mtd)
{
struct efx_mtd_partition *part;
- uint16_t fw_subtype_list[MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN /
- sizeof(uint16_t)];
+ uint16_t fw_subtype_list[MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM];
int rc;
- rc = efx_mcdi_get_board_cfg(efx, NULL, fw_subtype_list);
+ rc = efx_mcdi_get_board_cfg(efx, NULL, fw_subtype_list, NULL);
if (rc)
return rc;
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index c49502bab6a3..0b95505e8968 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -13,10 +13,6 @@
#ifndef EFX_NET_DRIVER_H
#define EFX_NET_DRIVER_H
-#if defined(EFX_ENABLE_DEBUG) && !defined(DEBUG)
-#define DEBUG
-#endif
-
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
@@ -28,6 +24,7 @@
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/workqueue.h>
+#include <linux/mutex.h>
#include <linux/vmalloc.h>
#include <linux/i2c.h>
@@ -42,7 +39,7 @@
#define EFX_DRIVER_VERSION "3.1"
-#ifdef EFX_ENABLE_DEBUG
+#ifdef DEBUG
#define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
#define EFX_WARN_ON_PARANOID(x) WARN_ON(x)
#else
@@ -56,8 +53,10 @@
*
**************************************************************************/
-#define EFX_MAX_CHANNELS 32
+#define EFX_MAX_CHANNELS 32U
#define EFX_MAX_RX_QUEUES EFX_MAX_CHANNELS
+#define EFX_EXTRA_CHANNEL_IOV 0
+#define EFX_MAX_EXTRA_CHANNELS 1U
/* Checksum generation is a per-queue option in hardware, so each
* queue visible to the networking core is backed by two hardware TX
@@ -85,15 +84,8 @@ struct efx_special_buffer {
void *addr;
dma_addr_t dma_addr;
unsigned int len;
- int index;
- int entries;
-};
-
-enum efx_flush_state {
- FLUSH_NONE,
- FLUSH_PENDING,
- FLUSH_FAILED,
- FLUSH_DONE,
+ unsigned int index;
+ unsigned int entries;
};
/**
@@ -142,7 +134,6 @@ struct efx_tx_buffer {
* @txd: The hardware descriptor ring
* @ptr_mask: The size of the ring minus 1.
* @initialised: Has hardware queue been initialised?
- * @flushed: Used when handling queue flushing
* @read_count: Current read pointer.
* This is the number of buffers that have been removed from both rings.
* @old_write_count: The value of @write_count when last checked.
@@ -185,7 +176,6 @@ struct efx_tx_queue {
struct efx_special_buffer txd;
unsigned int ptr_mask;
bool initialised;
- enum efx_flush_state flushed;
/* Members used mainly on the completion path */
unsigned int read_count ____cacheline_aligned_in_smp;
@@ -209,12 +199,12 @@ struct efx_tx_queue {
/**
* struct efx_rx_buffer - An Efx RX data buffer
* @dma_addr: DMA base address of the buffer
- * @skb: The associated socket buffer, if any.
- * If both this and page are %NULL, the buffer slot is currently free.
- * @page: The associated page buffer, if any.
- * If both this and skb are %NULL, the buffer slot is currently free.
+ * @skb: The associated socket buffer. Valid iff !(@flags & %EFX_RX_BUF_PAGE).
+ * Will be %NULL if the buffer slot is currently free.
+ * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE.
+ * Will be %NULL if the buffer slot is currently free.
* @len: Buffer length, in bytes.
- * @is_page: Indicates if @page is valid. If false, @skb is valid.
+ * @flags: Flags for buffer and packet state.
*/
struct efx_rx_buffer {
dma_addr_t dma_addr;
@@ -223,8 +213,11 @@ struct efx_rx_buffer {
struct page *page;
} u;
unsigned int len;
- bool is_page;
+ u16 flags;
};
+#define EFX_RX_BUF_PAGE 0x0001
+#define EFX_RX_PKT_CSUMMED 0x0002
+#define EFX_RX_PKT_DISCARD 0x0004
/**
* struct efx_rx_page_state - Page-based rx buffer state
@@ -250,6 +243,9 @@ struct efx_rx_page_state {
* @buffer: The software buffer ring
* @rxd: The hardware descriptor ring
* @ptr_mask: The size of the ring minus 1.
+ * @enabled: Receive queue enabled indicator.
+ * @flush_pending: Set when a RX flush is pending. Has the same lifetime as
+ * @rxq_flush_pending.
* @added_count: Number of buffers added to the receive queue.
* @notified_count: Number of buffers given to NIC (<= @added_count).
* @removed_count: Number of buffers removed from the receive queue.
@@ -264,13 +260,14 @@ struct efx_rx_page_state {
* @alloc_page_count: RX allocation strategy counter.
* @alloc_skb_count: RX allocation strategy counter.
* @slow_fill: Timer used to defer efx_nic_generate_fill_event().
- * @flushed: Use when handling queue flushing
*/
struct efx_rx_queue {
struct efx_nic *efx;
struct efx_rx_buffer *buffer;
struct efx_special_buffer rxd;
unsigned int ptr_mask;
+ bool enabled;
+ bool flush_pending;
int added_count;
int notified_count;
@@ -284,8 +281,6 @@ struct efx_rx_queue {
unsigned int alloc_skb_count;
struct timer_list slow_fill;
unsigned int slow_fill_count;
-
- enum efx_flush_state flushed;
};
/**
@@ -319,6 +314,7 @@ enum efx_rx_alloc_method {
*
* @efx: Associated Efx NIC
* @channel: Channel instance number
+ * @type: Channel type definition
* @enabled: Channel enabled indicator
* @irq: IRQ number (MSI and MSI-X only)
* @irq_moderation: IRQ moderation value (in hardware ticks)
@@ -329,6 +325,7 @@ enum efx_rx_alloc_method {
* @eventq_mask: Event queue pointer mask
* @eventq_read_ptr: Event queue read pointer
* @last_eventq_read_ptr: Last event queue read pointer value.
+ * @last_irq_cpu: Last CPU to handle interrupt for this channel
* @irq_count: Number of IRQs since last adaptive moderation decision
* @irq_mod_score: IRQ moderation score
* @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
@@ -348,6 +345,7 @@ enum efx_rx_alloc_method {
struct efx_channel {
struct efx_nic *efx;
int channel;
+ const struct efx_channel_type *type;
bool enabled;
int irq;
unsigned int irq_moderation;
@@ -359,6 +357,7 @@ struct efx_channel {
unsigned int eventq_read_ptr;
unsigned int last_eventq_read_ptr;
+ int last_irq_cpu;
unsigned int irq_count;
unsigned int irq_mod_score;
#ifdef CONFIG_RFS_ACCEL
@@ -380,12 +379,31 @@ struct efx_channel {
* access with prefetches.
*/
struct efx_rx_buffer *rx_pkt;
- bool rx_pkt_csummed;
struct efx_rx_queue rx_queue;
struct efx_tx_queue tx_queue[EFX_TXQ_TYPES];
};
+/**
+ * struct efx_channel_type - distinguishes traffic and extra channels
+ * @handle_no_channel: Handle failure to allocate an extra channel
+ * @pre_probe: Set up extra state prior to initialisation
+ * @post_remove: Tear down extra state after finalisation, if allocated.
+ * May be called on channels that have not been probed.
+ * @get_name: Generate the channel's name (used for its IRQ handler)
+ * @copy: Copy the channel state prior to reallocation. May be %NULL if
+ * reallocation is not supported.
+ * @keep_eventq: Flag for whether event queue should be kept initialised
+ * while the device is stopped
+ */
+struct efx_channel_type {
+ void (*handle_no_channel)(struct efx_nic *);
+ int (*pre_probe)(struct efx_channel *);
+ void (*get_name)(struct efx_channel *, char *buf, size_t len);
+ struct efx_channel *(*copy)(const struct efx_channel *);
+ bool keep_eventq;
+};
+
enum efx_led_mode {
EFX_LED_OFF = 0,
EFX_LED_ON = 1,
@@ -395,12 +413,12 @@ enum efx_led_mode {
#define STRING_TABLE_LOOKUP(val, member) \
((val) < member ## _max) ? member ## _names[val] : "(invalid)"
-extern const char *efx_loopback_mode_names[];
+extern const char *const efx_loopback_mode_names[];
extern const unsigned int efx_loopback_mode_max;
#define LOOPBACK_MODE(efx) \
STRING_TABLE_LOOKUP((efx)->loopback_mode, efx_loopback_mode)
-extern const char *efx_reset_type_names[];
+extern const char *const efx_reset_type_names[];
extern const unsigned int efx_reset_type_max;
#define RESET_TYPE(type) \
STRING_TABLE_LOOKUP(type, efx_reset_type)
@@ -474,18 +492,6 @@ static inline bool efx_link_state_equal(const struct efx_link_state *left,
}
/**
- * struct efx_mac_operations - Efx MAC operations table
- * @reconfigure: Reconfigure MAC. Serialised by the mac_lock
- * @update_stats: Update statistics
- * @check_fault: Check fault state. True if fault present.
- */
-struct efx_mac_operations {
- int (*reconfigure) (struct efx_nic *efx);
- void (*update_stats) (struct efx_nic *efx);
- bool (*check_fault)(struct efx_nic *efx);
-};
-
-/**
* struct efx_phy_operations - Efx PHY operations table
* @probe: Probe PHY and initialise efx->mdio.mode_support, efx->mdio.mmds,
* efx->loopback_modes.
@@ -552,64 +558,64 @@ struct efx_mac_stats {
u64 tx_bytes;
u64 tx_good_bytes;
u64 tx_bad_bytes;
- unsigned long tx_packets;
- unsigned long tx_bad;
- unsigned long tx_pause;
- unsigned long tx_control;
- unsigned long tx_unicast;
- unsigned long tx_multicast;
- unsigned long tx_broadcast;
- unsigned long tx_lt64;
- unsigned long tx_64;
- unsigned long tx_65_to_127;
- unsigned long tx_128_to_255;
- unsigned long tx_256_to_511;
- unsigned long tx_512_to_1023;
- unsigned long tx_1024_to_15xx;
- unsigned long tx_15xx_to_jumbo;
- unsigned long tx_gtjumbo;
- unsigned long tx_collision;
- unsigned long tx_single_collision;
- unsigned long tx_multiple_collision;
- unsigned long tx_excessive_collision;
- unsigned long tx_deferred;
- unsigned long tx_late_collision;
- unsigned long tx_excessive_deferred;
- unsigned long tx_non_tcpudp;
- unsigned long tx_mac_src_error;
- unsigned long tx_ip_src_error;
+ u64 tx_packets;
+ u64 tx_bad;
+ u64 tx_pause;
+ u64 tx_control;
+ u64 tx_unicast;
+ u64 tx_multicast;
+ u64 tx_broadcast;
+ u64 tx_lt64;
+ u64 tx_64;
+ u64 tx_65_to_127;
+ u64 tx_128_to_255;
+ u64 tx_256_to_511;
+ u64 tx_512_to_1023;
+ u64 tx_1024_to_15xx;
+ u64 tx_15xx_to_jumbo;
+ u64 tx_gtjumbo;
+ u64 tx_collision;
+ u64 tx_single_collision;
+ u64 tx_multiple_collision;
+ u64 tx_excessive_collision;
+ u64 tx_deferred;
+ u64 tx_late_collision;
+ u64 tx_excessive_deferred;
+ u64 tx_non_tcpudp;
+ u64 tx_mac_src_error;
+ u64 tx_ip_src_error;
u64 rx_bytes;
u64 rx_good_bytes;
u64 rx_bad_bytes;
- unsigned long rx_packets;
- unsigned long rx_good;
- unsigned long rx_bad;
- unsigned long rx_pause;
- unsigned long rx_control;
- unsigned long rx_unicast;
- unsigned long rx_multicast;
- unsigned long rx_broadcast;
- unsigned long rx_lt64;
- unsigned long rx_64;
- unsigned long rx_65_to_127;
- unsigned long rx_128_to_255;
- unsigned long rx_256_to_511;
- unsigned long rx_512_to_1023;
- unsigned long rx_1024_to_15xx;
- unsigned long rx_15xx_to_jumbo;
- unsigned long rx_gtjumbo;
- unsigned long rx_bad_lt64;
- unsigned long rx_bad_64_to_15xx;
- unsigned long rx_bad_15xx_to_jumbo;
- unsigned long rx_bad_gtjumbo;
- unsigned long rx_overflow;
- unsigned long rx_missed;
- unsigned long rx_false_carrier;
- unsigned long rx_symbol_error;
- unsigned long rx_align_error;
- unsigned long rx_length_error;
- unsigned long rx_internal_error;
- unsigned long rx_good_lt64;
+ u64 rx_packets;
+ u64 rx_good;
+ u64 rx_bad;
+ u64 rx_pause;
+ u64 rx_control;
+ u64 rx_unicast;
+ u64 rx_multicast;
+ u64 rx_broadcast;
+ u64 rx_lt64;
+ u64 rx_64;
+ u64 rx_65_to_127;
+ u64 rx_128_to_255;
+ u64 rx_256_to_511;
+ u64 rx_512_to_1023;
+ u64 rx_1024_to_15xx;
+ u64 rx_15xx_to_jumbo;
+ u64 rx_gtjumbo;
+ u64 rx_bad_lt64;
+ u64 rx_bad_64_to_15xx;
+ u64 rx_bad_15xx_to_jumbo;
+ u64 rx_bad_gtjumbo;
+ u64 rx_overflow;
+ u64 rx_missed;
+ u64 rx_false_carrier;
+ u64 rx_symbol_error;
+ u64 rx_align_error;
+ u64 rx_length_error;
+ u64 rx_internal_error;
+ u64 rx_good_lt64;
};
/* Number of bits used in a multicast filter hash address */
@@ -625,6 +631,8 @@ union efx_multicast_hash {
};
struct efx_filter_state;
+struct efx_vf;
+struct vfdi_status;
/**
* struct efx_nic - an Efx NIC
@@ -640,6 +648,7 @@ struct efx_filter_state;
* @membase_phys: Memory BAR value as physical address
* @membase: Memory BAR value
* @interrupt_mode: Interrupt mode
+ * @timer_quantum_ns: Interrupt timer quantum, in nanoseconds
* @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues
* @irq_rx_moderation: IRQ moderation time for RX event queues
* @msg_enable: Log message enable flags
@@ -649,8 +658,13 @@ struct efx_filter_state;
* @rx_queue: RX DMA queues
* @channel: Channels
* @channel_name: Names for channels and their IRQs
+ * @extra_channel_types: Types of extra (non-traffic) channels that
+ * should be allocated for this NIC
* @rxq_entries: Size of receive queues requested by user.
* @txq_entries: Size of transmit queues requested by user.
+ * @tx_dc_base: Base qword address in SRAM of TX queue descriptor caches
+ * @rx_dc_base: Base qword address in SRAM of RX queue descriptor caches
+ * @sram_lim_qw: Qword address limit of SRAM
* @next_buffer_table: First available buffer table id
* @n_channels: Number of channels in use
* @n_rx_channels: Number of channels used for RX (= number of RX queues)
@@ -663,7 +677,7 @@ struct efx_filter_state;
* @int_error_expire: Time at which error count will be expired
* @irq_status: Interrupt status buffer
* @irq_zero_count: Number of legacy IRQs seen with queue flags == 0
- * @fatal_irq_level: IRQ level (bit number) used for serious errors
+ * @irq_level: IRQ level/index for IRQs not triggered by an event queue
* @mtd_list: List of MTDs attached to the NIC
* @nic_data: Hardware dependent state
* @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
@@ -676,7 +690,6 @@ struct efx_filter_state;
* @port_initialized: Port initialized?
* @net_dev: Operating system network device. Consider holding the rtnl lock
* @stats_buffer: DMA buffer for statistics
- * @mac_op: MAC interface
* @phy_type: PHY type
* @phy_op: PHY interface
* @phy_data: PHY private data (including PHY-specific stats)
@@ -689,21 +702,42 @@ struct efx_filter_state;
* @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
* @multicast_hash: Multicast hash table
* @wanted_fc: Wanted flow control flags
+ * @fc_disable: When non-zero flow control is disabled. Typically used to
+ * ensure that network back pressure doesn't delay dma queue flushes.
+ * Serialised by the rtnl lock.
* @mac_work: Work item for changing MAC promiscuity and multicast hash
* @loopback_mode: Loopback status
* @loopback_modes: Supported loopback mode bitmask
* @loopback_selftest: Offline self-test private state
+ * @drain_pending: Count of RX and TX queues that haven't been flushed and drained.
+ * @rxq_flush_pending: Count of number of receive queues that need to be flushed.
+ * Decremented when the efx_flush_rx_queue() is called.
+ * @rxq_flush_outstanding: Count of number of RX flushes started but not yet
+ * completed (either success or failure). Not used when MCDI is used to
+ * flush receive queues.
+ * @flush_wq: wait queue used by efx_nic_flush_queues() to wait for flush completions.
+ * @vf: Array of &struct efx_vf objects.
+ * @vf_count: Number of VFs intended to be enabled.
+ * @vf_init_count: Number of VFs that have been fully initialised.
+ * @vi_scale: log2 number of vnics per VF.
+ * @vf_buftbl_base: The zeroth buffer table index used to back VF queues.
+ * @vfdi_status: Common VFDI status page to be dmad to VF address space.
+ * @local_addr_list: List of local addresses. Protected by %local_lock.
+ * @local_page_list: List of DMA addressable pages used to broadcast
+ * %local_addr_list. Protected by %local_lock.
+ * @local_lock: Mutex protecting %local_addr_list and %local_page_list.
+ * @peer_work: Work item to broadcast peer addresses to VMs.
* @monitor_work: Hardware monitor workitem
* @biu_lock: BIU (bus interface unit) lock
- * @last_irq_cpu: Last CPU to handle interrupt.
- * This register is written with the SMP processor ID whenever an
- * interrupt is handled. It is used by efx_nic_test_interrupt()
- * to verify that an interrupt has occurred.
+ * @last_irq_cpu: Last CPU to handle a possible test interrupt. This
+ * field is used by efx_test_interrupts() to verify that an
+ * interrupt has occurred.
* @n_rx_nodesc_drop_cnt: RX no descriptor drop count
* @mac_stats: MAC statistics. These include all statistics the MACs
* can provide. Generic code converts these into a standard
* &struct net_device_stats.
* @stats_lock: Statistics update lock. Serialises statistics fetches
+ * and access to @mac_stats.
*
* This is stored in the private area of the &struct net_device.
*/
@@ -722,6 +756,7 @@ struct efx_nic {
void __iomem *membase;
enum efx_int_mode interrupt_mode;
+ unsigned int timer_quantum_ns;
bool irq_rx_adaptive;
unsigned int irq_rx_moderation;
u32 msg_enable;
@@ -731,12 +766,18 @@ struct efx_nic {
struct efx_channel *channel[EFX_MAX_CHANNELS];
char channel_name[EFX_MAX_CHANNELS][IFNAMSIZ + 6];
+ const struct efx_channel_type *
+ extra_channel_type[EFX_MAX_EXTRA_CHANNELS];
unsigned rxq_entries;
unsigned txq_entries;
+ unsigned tx_dc_base;
+ unsigned rx_dc_base;
+ unsigned sram_lim_qw;
unsigned next_buffer_table;
unsigned n_channels;
unsigned n_rx_channels;
+ unsigned rss_spread;
unsigned tx_channel_offset;
unsigned n_tx_channels;
unsigned int rx_buffer_len;
@@ -749,7 +790,7 @@ struct efx_nic {
struct efx_buffer irq_status;
unsigned irq_zero_count;
- unsigned fatal_irq_level;
+ unsigned irq_level;
#ifdef CONFIG_SFC_MTD
struct list_head mtd_list;
@@ -766,8 +807,6 @@ struct efx_nic {
struct efx_buffer stats_buffer;
- const struct efx_mac_operations *mac_op;
-
unsigned int phy_type;
const struct efx_phy_operations *phy_op;
void *phy_data;
@@ -782,6 +821,7 @@ struct efx_nic {
bool promiscuous;
union efx_multicast_hash multicast_hash;
u8 wanted_fc;
+ unsigned fc_disable;
atomic_t rx_reset;
enum efx_loopback_mode loopback_mode;
@@ -791,11 +831,30 @@ struct efx_nic {
struct efx_filter_state *filter_state;
+ atomic_t drain_pending;
+ atomic_t rxq_flush_pending;
+ atomic_t rxq_flush_outstanding;
+ wait_queue_head_t flush_wq;
+
+#ifdef CONFIG_SFC_SRIOV
+ struct efx_channel *vfdi_channel;
+ struct efx_vf *vf;
+ unsigned vf_count;
+ unsigned vf_init_count;
+ unsigned vi_scale;
+ unsigned vf_buftbl_base;
+ struct efx_buffer vfdi_status;
+ struct list_head local_addr_list;
+ struct list_head local_page_list;
+ struct mutex local_lock;
+ struct work_struct peer_work;
+#endif
+
/* The following fields may be written more often */
struct delayed_work monitor_work ____cacheline_aligned_in_smp;
spinlock_t biu_lock;
- volatile signed int last_irq_cpu;
+ int last_irq_cpu;
unsigned n_rx_nodesc_drop_cnt;
struct efx_mac_stats mac_stats;
spinlock_t stats_lock;
@@ -806,15 +865,6 @@ static inline int efx_dev_registered(struct efx_nic *efx)
return efx->net_dev->reg_state == NETREG_REGISTERED;
}
-/* Net device name, for inclusion in log messages if it has been registered.
- * Use efx->name not efx->net_dev->name so that races with (un)registration
- * are harmless.
- */
-static inline const char *efx_dev_name(struct efx_nic *efx)
-{
- return efx_dev_registered(efx) ? efx->name : "";
-}
-
static inline unsigned int efx_port_num(struct efx_nic *efx)
{
return efx->net_dev->dev_id;
@@ -825,6 +875,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
* @probe: Probe the controller
* @remove: Free resources allocated by probe()
* @init: Initialise the controller
+ * @dimension_resources: Dimension controller resources (buffer table,
+ * and VIs once the available interrupt resources are clear)
* @fini: Shut down the controller
* @monitor: Periodic function for polling link state and hardware monitor
* @map_reset_reason: Map ethtool reset reason to a reset method
@@ -840,14 +892,15 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
* @stop_stats: Stop the regular fetching of statistics
* @set_id_led: Set state of identifying LED or revert to automatic function
* @push_irq_moderation: Apply interrupt moderation value
- * @push_multicast_hash: Apply multicast hash table
* @reconfigure_port: Push loopback/power/txdis changes to the MAC and PHY
+ * @reconfigure_mac: Push MAC address, MTU, flow control and filter settings
+ * to the hardware. Serialised by the mac_lock.
+ * @check_mac_fault: Check MAC fault state. True if fault present.
* @get_wol: Get WoL configuration from driver state
* @set_wol: Push WoL configuration to the NIC
* @resume_wol: Synchronise WoL state between driver and MC (e.g. after resume)
* @test_registers: Test read/write functionality of control registers
* @test_nvram: Test validity of NVRAM contents
- * @default_mac_ops: efx_mac_operations to set at startup
* @revision: Hardware architecture revision
* @mem_map_size: Memory BAR mapped size
* @txd_ptr_tbl_base: TX descriptor ring base address
@@ -862,8 +915,7 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
* from &enum efx_init_mode.
* @phys_addr_channels: Number of channels with physically addressed
* descriptors
- * @tx_dc_base: Base address in SRAM of TX queue descriptor caches
- * @rx_dc_base: Base address in SRAM of RX queue descriptor caches
+ * @timer_period_max: Maximum period of interrupt timer (in ticks)
* @offload_features: net_device feature flags for protocol offload
* features implemented in hardware
*/
@@ -871,6 +923,7 @@ struct efx_nic_type {
int (*probe)(struct efx_nic *efx);
void (*remove)(struct efx_nic *efx);
int (*init)(struct efx_nic *efx);
+ void (*dimension_resources)(struct efx_nic *efx);
void (*fini)(struct efx_nic *efx);
void (*monitor)(struct efx_nic *efx);
enum reset_type (*map_reset_reason)(enum reset_type reason);
@@ -885,14 +938,14 @@ struct efx_nic_type {
void (*stop_stats)(struct efx_nic *efx);
void (*set_id_led)(struct efx_nic *efx, enum efx_led_mode mode);
void (*push_irq_moderation)(struct efx_channel *channel);
- void (*push_multicast_hash)(struct efx_nic *efx);
int (*reconfigure_port)(struct efx_nic *efx);
+ int (*reconfigure_mac)(struct efx_nic *efx);
+ bool (*check_mac_fault)(struct efx_nic *efx);
void (*get_wol)(struct efx_nic *efx, struct ethtool_wolinfo *wol);
int (*set_wol)(struct efx_nic *efx, u32 type);
void (*resume_wol)(struct efx_nic *efx);
int (*test_registers)(struct efx_nic *efx);
int (*test_nvram)(struct efx_nic *efx);
- const struct efx_mac_operations *default_mac_ops;
int revision;
unsigned int mem_map_size;
@@ -906,8 +959,7 @@ struct efx_nic_type {
unsigned int rx_buffer_padding;
unsigned int max_interrupt_mode;
unsigned int phys_addr_channels;
- unsigned int tx_dc_base;
- unsigned int rx_dc_base;
+ unsigned int timer_period_max;
netdev_features_t offload_features;
};
@@ -931,6 +983,13 @@ efx_get_channel(struct efx_nic *efx, unsigned index)
_channel = (_channel->channel + 1 < (_efx)->n_channels) ? \
(_efx)->channel[_channel->channel + 1] : NULL)
+/* Iterate over all used channels in reverse */
+#define efx_for_each_channel_rev(_channel, _efx) \
+ for (_channel = (_efx)->channel[(_efx)->n_channels - 1]; \
+ _channel; \
+ _channel = _channel->channel ? \
+ (_efx)->channel[_channel->channel - 1] : NULL)
+
static inline struct efx_tx_queue *
efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
{
@@ -971,16 +1030,12 @@ static inline bool efx_tx_queue_used(struct efx_tx_queue *tx_queue)
/* Iterate over all possible TX queues belonging to a channel */
#define efx_for_each_possible_channel_tx_queue(_tx_queue, _channel) \
- for (_tx_queue = (_channel)->tx_queue; \
- _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
- _tx_queue++)
-
-static inline struct efx_rx_queue *
-efx_get_rx_queue(struct efx_nic *efx, unsigned index)
-{
- EFX_BUG_ON_PARANOID(index >= efx->n_rx_channels);
- return &efx->channel[index]->rx_queue;
-}
+ if (!efx_channel_has_tx_queues(_channel)) \
+ ; \
+ else \
+ for (_tx_queue = (_channel)->tx_queue; \
+ _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
+ _tx_queue++)
static inline bool efx_channel_has_rx_queue(struct efx_channel *channel)
{
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 3edfbaf5f022..2bf4283f05fe 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -49,24 +49,29 @@
#define EFX_INT_ERROR_EXPIRE 3600
#define EFX_MAX_INT_ERRORS 5
-/* We poll for events every FLUSH_INTERVAL ms, and check FLUSH_POLL_COUNT times
- */
-#define EFX_FLUSH_INTERVAL 10
-#define EFX_FLUSH_POLL_COUNT 100
-
-/* Size and alignment of special buffers (4KB) */
-#define EFX_BUF_SIZE 4096
-
/* Depth of RX flush request fifo */
#define EFX_RX_FLUSH_COUNT 4
-/* Generated event code for efx_generate_test_event() */
-#define EFX_CHANNEL_MAGIC_TEST(_channel) \
- (0x00010100 + (_channel)->channel)
-
-/* Generated event code for efx_generate_fill_event() */
-#define EFX_CHANNEL_MAGIC_FILL(_channel) \
- (0x00010200 + (_channel)->channel)
+/* Driver generated events */
+#define _EFX_CHANNEL_MAGIC_TEST 0x000101
+#define _EFX_CHANNEL_MAGIC_FILL 0x000102
+#define _EFX_CHANNEL_MAGIC_RX_DRAIN 0x000103
+#define _EFX_CHANNEL_MAGIC_TX_DRAIN 0x000104
+
+#define _EFX_CHANNEL_MAGIC(_code, _data) ((_code) << 8 | (_data))
+#define _EFX_CHANNEL_MAGIC_CODE(_magic) ((_magic) >> 8)
+
+#define EFX_CHANNEL_MAGIC_TEST(_channel) \
+ _EFX_CHANNEL_MAGIC(_EFX_CHANNEL_MAGIC_TEST, (_channel)->channel)
+#define EFX_CHANNEL_MAGIC_FILL(_rx_queue) \
+ _EFX_CHANNEL_MAGIC(_EFX_CHANNEL_MAGIC_FILL, \
+ efx_rx_queue_index(_rx_queue))
+#define EFX_CHANNEL_MAGIC_RX_DRAIN(_rx_queue) \
+ _EFX_CHANNEL_MAGIC(_EFX_CHANNEL_MAGIC_RX_DRAIN, \
+ efx_rx_queue_index(_rx_queue))
+#define EFX_CHANNEL_MAGIC_TX_DRAIN(_tx_queue) \
+ _EFX_CHANNEL_MAGIC(_EFX_CHANNEL_MAGIC_TX_DRAIN, \
+ (_tx_queue)->queue)
/**************************************************************************
*
@@ -187,7 +192,7 @@ static void
efx_init_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer)
{
efx_qword_t buf_desc;
- int index;
+ unsigned int index;
dma_addr_t dma_addr;
int i;
@@ -196,7 +201,7 @@ efx_init_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer)
/* Write buffer descriptors to NIC */
for (i = 0; i < buffer->entries; i++) {
index = buffer->index + i;
- dma_addr = buffer->dma_addr + (i * 4096);
+ dma_addr = buffer->dma_addr + (i * EFX_BUF_SIZE);
netif_dbg(efx, probe, efx->net_dev,
"mapping special buffer %d at %llx\n",
index, (unsigned long long)dma_addr);
@@ -259,6 +264,10 @@ static int efx_alloc_special_buffer(struct efx_nic *efx,
/* Select new buffer ID */
buffer->index = efx->next_buffer_table;
efx->next_buffer_table += buffer->entries;
+#ifdef CONFIG_SFC_SRIOV
+ BUG_ON(efx_sriov_enabled(efx) &&
+ efx->vf_buftbl_base < efx->next_buffer_table);
+#endif
netif_dbg(efx, probe, efx->net_dev,
"allocating special buffers %d-%d at %llx+%x "
@@ -430,8 +439,6 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
struct efx_nic *efx = tx_queue->efx;
efx_oword_t reg;
- tx_queue->flushed = FLUSH_NONE;
-
/* Pin TX descriptor ring */
efx_init_special_buffer(efx, &tx_queue->txd);
@@ -488,9 +495,6 @@ 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;
- tx_queue->flushed = FLUSH_PENDING;
-
- /* Post a flush command */
EFX_POPULATE_OWORD_2(tx_flush_descq,
FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
FRF_AZ_TX_FLUSH_DESCQ, tx_queue->queue);
@@ -502,9 +506,6 @@ void efx_nic_fini_tx(struct efx_tx_queue *tx_queue)
struct efx_nic *efx = tx_queue->efx;
efx_oword_t tx_desc_ptr;
- /* The queue should have been flushed */
- WARN_ON(tx_queue->flushed != FLUSH_DONE);
-
/* Remove TX descriptor ring from card */
EFX_ZERO_OWORD(tx_desc_ptr);
efx_writeo_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
@@ -595,8 +596,6 @@ void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
efx_rx_queue_index(rx_queue), rx_queue->rxd.index,
rx_queue->rxd.index + rx_queue->rxd.entries - 1);
- rx_queue->flushed = FLUSH_NONE;
-
/* Pin RX descriptor ring */
efx_init_special_buffer(efx, &rx_queue->rxd);
@@ -625,9 +624,6 @@ static void efx_flush_rx_queue(struct efx_rx_queue *rx_queue)
struct efx_nic *efx = rx_queue->efx;
efx_oword_t rx_flush_descq;
- rx_queue->flushed = FLUSH_PENDING;
-
- /* Post a flush command */
EFX_POPULATE_OWORD_2(rx_flush_descq,
FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
FRF_AZ_RX_FLUSH_DESCQ,
@@ -640,9 +636,6 @@ void efx_nic_fini_rx(struct efx_rx_queue *rx_queue)
efx_oword_t rx_desc_ptr;
struct efx_nic *efx = rx_queue->efx;
- /* The queue should already have been flushed */
- WARN_ON(rx_queue->flushed != FLUSH_DONE);
-
/* Remove RX descriptor ring from card */
EFX_ZERO_OWORD(rx_desc_ptr);
efx_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
@@ -660,6 +653,103 @@ void efx_nic_remove_rx(struct efx_rx_queue *rx_queue)
/**************************************************************************
*
+ * Flush handling
+ *
+ **************************************************************************/
+
+/* efx_nic_flush_queues() must be woken up when all flushes are completed,
+ * or more RX flushes can be kicked off.
+ */
+static bool efx_flush_wake(struct efx_nic *efx)
+{
+ /* Ensure that all updates are visible to efx_nic_flush_queues() */
+ smp_mb();
+
+ return (atomic_read(&efx->drain_pending) == 0 ||
+ (atomic_read(&efx->rxq_flush_outstanding) < EFX_RX_FLUSH_COUNT
+ && atomic_read(&efx->rxq_flush_pending) > 0));
+}
+
+/* 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. */
+int efx_nic_flush_queues(struct efx_nic *efx)
+{
+ unsigned timeout = msecs_to_jiffies(5000); /* 5s for all flushes and drains */
+ struct efx_channel *channel;
+ struct efx_rx_queue *rx_queue;
+ struct efx_tx_queue *tx_queue;
+ int rc = 0;
+
+ efx->fc_disable++;
+ efx->type->prepare_flush(efx);
+
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ atomic_inc(&efx->drain_pending);
+ efx_flush_tx_queue(tx_queue);
+ }
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
+ atomic_inc(&efx->drain_pending);
+ rx_queue->flush_pending = true;
+ atomic_inc(&efx->rxq_flush_pending);
+ }
+ }
+
+ while (timeout && atomic_read(&efx->drain_pending) > 0) {
+ /* If SRIOV is enabled, then offload receive queue flushing to
+ * the firmware (though we will still have to poll for
+ * completion). If that fails, fall back to the old scheme.
+ */
+ if (efx_sriov_enabled(efx)) {
+ rc = efx_mcdi_flush_rxqs(efx);
+ if (!rc)
+ goto wait;
+ }
+
+ /* The hardware supports four concurrent rx flushes, each of
+ * which may need to be retried if there is an outstanding
+ * descriptor fetch
+ */
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
+ if (atomic_read(&efx->rxq_flush_outstanding) >=
+ EFX_RX_FLUSH_COUNT)
+ break;
+
+ if (rx_queue->flush_pending) {
+ rx_queue->flush_pending = false;
+ atomic_dec(&efx->rxq_flush_pending);
+ atomic_inc(&efx->rxq_flush_outstanding);
+ efx_flush_rx_queue(rx_queue);
+ }
+ }
+ }
+
+ wait:
+ timeout = wait_event_timeout(efx->flush_wq, efx_flush_wake(efx),
+ timeout);
+ }
+
+ if (atomic_read(&efx->drain_pending)) {
+ 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),
+ atomic_read(&efx->rxq_flush_pending));
+ rc = -ETIMEDOUT;
+
+ atomic_set(&efx->drain_pending, 0);
+ atomic_set(&efx->rxq_flush_pending, 0);
+ atomic_set(&efx->rxq_flush_outstanding, 0);
+ }
+
+ efx->fc_disable--;
+
+ return rc;
+}
+
+/**************************************************************************
+ *
* Event queue processing
* Event queues are processed by per-channel tasklets.
*
@@ -682,7 +772,8 @@ void efx_nic_eventq_read_ack(struct efx_channel *channel)
}
/* Use HW to insert a SW defined event */
-static void efx_generate_event(struct efx_channel *channel, efx_qword_t *event)
+void efx_generate_event(struct efx_nic *efx, unsigned int evq,
+ efx_qword_t *event)
{
efx_oword_t drv_ev_reg;
@@ -692,8 +783,18 @@ static void efx_generate_event(struct efx_channel *channel, efx_qword_t *event)
drv_ev_reg.u32[1] = event->u32[1];
drv_ev_reg.u32[2] = 0;
drv_ev_reg.u32[3] = 0;
- EFX_SET_OWORD_FIELD(drv_ev_reg, FRF_AZ_DRV_EV_QID, channel->channel);
- efx_writeo(channel->efx, &drv_ev_reg, FR_AZ_DRV_EV);
+ EFX_SET_OWORD_FIELD(drv_ev_reg, FRF_AZ_DRV_EV_QID, evq);
+ efx_writeo(efx, &drv_ev_reg, FR_AZ_DRV_EV);
+}
+
+static void efx_magic_event(struct efx_channel *channel, u32 magic)
+{
+ efx_qword_t event;
+
+ EFX_POPULATE_QWORD_2(event, FSF_AZ_EV_CODE,
+ FSE_AZ_EV_CODE_DRV_GEN_EV,
+ FSF_AZ_DRV_GEN_EV_MAGIC, magic);
+ efx_generate_event(channel->efx, channel->channel, &event);
}
/* Handle a transmit completion event
@@ -710,6 +811,9 @@ efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
struct efx_nic *efx = channel->efx;
int tx_packets = 0;
+ if (unlikely(ACCESS_ONCE(efx->reset_pending)))
+ return 0;
+
if (likely(EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_COMP))) {
/* Transmit completion */
tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_DESC_PTR);
@@ -726,11 +830,9 @@ efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
tx_queue = efx_channel_get_tx_queue(
channel, tx_ev_q_label % EFX_TXQ_TYPES);
- if (efx_dev_registered(efx))
- netif_tx_lock(efx->net_dev);
+ netif_tx_lock(efx->net_dev);
efx_notify_tx_desc(tx_queue);
- if (efx_dev_registered(efx))
- netif_tx_unlock(efx->net_dev);
+ netif_tx_unlock(efx->net_dev);
} else if (EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_PKT_ERR) &&
EFX_WORKAROUND_10727(efx)) {
efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH);
@@ -745,10 +847,8 @@ efx_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
}
/* Detect errors included in the rx_evt_pkt_ok bit. */
-static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
- const efx_qword_t *event,
- bool *rx_ev_pkt_ok,
- bool *discard)
+static u16 efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
+ const efx_qword_t *event)
{
struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
struct efx_nic *efx = rx_queue->efx;
@@ -793,15 +893,11 @@ static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
++channel->n_rx_tcp_udp_chksum_err;
}
- /* The frame must be discarded if any of these are true. */
- *discard = (rx_ev_eth_crc_err | rx_ev_frm_trunc | rx_ev_drib_nib |
- rx_ev_tobe_disc | rx_ev_pause_frm);
-
/* TOBE_DISC is expected on unicast mismatches; don't print out an
* error message. FRM_TRUNC indicates RXDP dropped the packet due
* to a FIFO overflow.
*/
-#ifdef EFX_ENABLE_DEBUG
+#ifdef DEBUG
if (rx_ev_other_err && net_ratelimit()) {
netif_dbg(efx, rx_err, efx->net_dev,
" RX queue %d unexpected RX event "
@@ -819,6 +915,11 @@ static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
rx_ev_pause_frm ? " [PAUSE]" : "");
}
#endif
+
+ /* The frame must be discarded if any of these are true. */
+ return (rx_ev_eth_crc_err | rx_ev_frm_trunc | rx_ev_drib_nib |
+ rx_ev_tobe_disc | rx_ev_pause_frm) ?
+ EFX_RX_PKT_DISCARD : 0;
}
/* Handle receive events that are not in-order. */
@@ -851,8 +952,13 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
unsigned int rx_ev_desc_ptr, rx_ev_byte_cnt;
unsigned int rx_ev_hdr_type, rx_ev_mcast_pkt;
unsigned expected_ptr;
- bool rx_ev_pkt_ok, discard = false, checksummed;
+ bool rx_ev_pkt_ok;
+ u16 flags;
struct efx_rx_queue *rx_queue;
+ struct efx_nic *efx = channel->efx;
+
+ if (unlikely(ACCESS_ONCE(efx->reset_pending)))
+ return;
/* Basic packet information */
rx_ev_byte_cnt = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_BYTE_CNT);
@@ -874,12 +980,11 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
/* If packet is marked as OK and packet type is TCP/IP or
* UDP/IP, then we can rely on the hardware checksum.
*/
- checksummed =
- rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP ||
- rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP;
+ flags = (rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP ||
+ rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP) ?
+ EFX_RX_PKT_CSUMMED : 0;
} else {
- efx_handle_rx_not_ok(rx_queue, event, &rx_ev_pkt_ok, &discard);
- checksummed = false;
+ flags = efx_handle_rx_not_ok(rx_queue, event);
}
/* Detect multicast packets that didn't match the filter */
@@ -890,35 +995,111 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
if (unlikely(!rx_ev_mcast_hash_match)) {
++channel->n_rx_mcast_mismatch;
- discard = true;
+ flags |= EFX_RX_PKT_DISCARD;
}
}
channel->irq_mod_score += 2;
/* Handle received packet */
- efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt,
- checksummed, discard);
+ efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt, flags);
+}
+
+/* If this flush done event corresponds to a &struct efx_tx_queue, then
+ * send an %EFX_CHANNEL_MAGIC_TX_DRAIN event to drain the event queue
+ * of all transmit completions.
+ */
+static void
+efx_handle_tx_flush_done(struct efx_nic *efx, efx_qword_t *event)
+{
+ struct efx_tx_queue *tx_queue;
+ int qid;
+
+ qid = EFX_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_SUBDATA);
+ 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 this flush done event corresponds to a &struct efx_rx_queue: If the flush
+ * was succesful then send an %EFX_CHANNEL_MAGIC_RX_DRAIN, otherwise add
+ * the RX queue back to the mask of RX queues in need of flushing.
+ */
+static void
+efx_handle_rx_flush_done(struct efx_nic *efx, efx_qword_t *event)
+{
+ struct efx_channel *channel;
+ struct efx_rx_queue *rx_queue;
+ int qid;
+ bool failed;
+
+ qid = EFX_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_RX_DESCQ_ID);
+ failed = EFX_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
+ if (qid >= efx->n_channels)
+ return;
+ channel = efx_get_channel(efx, qid);
+ if (!efx_channel_has_rx_queue(channel))
+ return;
+ rx_queue = efx_channel_get_rx_queue(channel);
+
+ if (failed) {
+ netif_info(efx, hw, efx->net_dev,
+ "RXQ %d flush retry\n", qid);
+ rx_queue->flush_pending = true;
+ atomic_inc(&efx->rxq_flush_pending);
+ } else {
+ efx_magic_event(efx_rx_queue_channel(rx_queue),
+ EFX_CHANNEL_MAGIC_RX_DRAIN(rx_queue));
+ }
+ atomic_dec(&efx->rxq_flush_outstanding);
+ if (efx_flush_wake(efx))
+ wake_up(&efx->flush_wq);
+}
+
+static void
+efx_handle_drain_event(struct efx_channel *channel)
+{
+ struct efx_nic *efx = channel->efx;
+
+ WARN_ON(atomic_read(&efx->drain_pending) == 0);
+ atomic_dec(&efx->drain_pending);
+ if (efx_flush_wake(efx))
+ wake_up(&efx->flush_wq);
}
static void
efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event)
{
struct efx_nic *efx = channel->efx;
- unsigned code;
+ struct efx_rx_queue *rx_queue =
+ efx_channel_has_rx_queue(channel) ?
+ efx_channel_get_rx_queue(channel) : NULL;
+ unsigned magic, code;
- code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC);
- if (code == EFX_CHANNEL_MAGIC_TEST(channel))
- ; /* ignore */
- else if (code == EFX_CHANNEL_MAGIC_FILL(channel))
+ magic = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC);
+ code = _EFX_CHANNEL_MAGIC_CODE(magic);
+
+ if (magic == EFX_CHANNEL_MAGIC_TEST(channel)) {
+ /* ignore */
+ } else if (rx_queue && magic == EFX_CHANNEL_MAGIC_FILL(rx_queue)) {
/* The queue must be empty, so we won't receive any rx
* events, so efx_process_channel() won't refill the
* queue. Refill it here */
- efx_fast_push_rx_descriptors(efx_channel_get_rx_queue(channel));
- else
+ efx_fast_push_rx_descriptors(rx_queue);
+ } else if (rx_queue && magic == EFX_CHANNEL_MAGIC_RX_DRAIN(rx_queue)) {
+ rx_queue->enabled = false;
+ efx_handle_drain_event(channel);
+ } else if (code == _EFX_CHANNEL_MAGIC_TX_DRAIN) {
+ efx_handle_drain_event(channel);
+ } else {
netif_dbg(efx, hw, efx->net_dev, "channel %d received "
"generated event "EFX_QWORD_FMT"\n",
channel->channel, EFX_QWORD_VAL(*event));
+ }
}
static void
@@ -935,10 +1116,14 @@ efx_handle_driver_event(struct efx_channel *channel, efx_qword_t *event)
case FSE_AZ_TX_DESCQ_FLS_DONE_EV:
netif_vdbg(efx, hw, efx->net_dev, "channel %d TXQ %d flushed\n",
channel->channel, ev_sub_data);
+ efx_handle_tx_flush_done(efx, event);
+ efx_sriov_tx_flush_done(efx, event);
break;
case FSE_AZ_RX_DESCQ_FLS_DONE_EV:
netif_vdbg(efx, hw, efx->net_dev, "channel %d RXQ %d flushed\n",
channel->channel, ev_sub_data);
+ efx_handle_rx_flush_done(efx, event);
+ efx_sriov_rx_flush_done(efx, event);
break;
case FSE_AZ_EVQ_INIT_DONE_EV:
netif_dbg(efx, hw, efx->net_dev,
@@ -970,16 +1155,24 @@ efx_handle_driver_event(struct efx_channel *channel, efx_qword_t *event)
RESET_TYPE_DISABLE);
break;
case FSE_BZ_RX_DSC_ERROR_EV:
- netif_err(efx, rx_err, efx->net_dev,
- "RX DMA Q %d reports descriptor fetch error."
- " RX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
- efx_schedule_reset(efx, RESET_TYPE_RX_DESC_FETCH);
+ if (ev_sub_data < EFX_VI_BASE) {
+ netif_err(efx, rx_err, efx->net_dev,
+ "RX DMA Q %d reports descriptor fetch error."
+ " RX Q %d is disabled.\n", ev_sub_data,
+ ev_sub_data);
+ efx_schedule_reset(efx, RESET_TYPE_RX_DESC_FETCH);
+ } else
+ efx_sriov_desc_fetch_err(efx, ev_sub_data);
break;
case FSE_BZ_TX_DSC_ERROR_EV:
- netif_err(efx, tx_err, efx->net_dev,
- "TX DMA Q %d reports descriptor fetch error."
- " TX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
- efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH);
+ if (ev_sub_data < EFX_VI_BASE) {
+ netif_err(efx, tx_err, efx->net_dev,
+ "TX DMA Q %d reports descriptor fetch error."
+ " TX Q %d is disabled.\n", ev_sub_data,
+ ev_sub_data);
+ efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH);
+ } else
+ efx_sriov_desc_fetch_err(efx, ev_sub_data);
break;
default:
netif_vdbg(efx, hw, efx->net_dev,
@@ -1039,6 +1232,9 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
case FSE_AZ_EV_CODE_DRIVER_EV:
efx_handle_driver_event(channel, &event);
break;
+ case FSE_CZ_EV_CODE_USER_EV:
+ efx_sriov_event(channel, &event);
+ break;
case FSE_CZ_EV_CODE_MCDI_EV:
efx_mcdi_process_event(channel, &event);
break;
@@ -1139,161 +1335,13 @@ void efx_nic_remove_eventq(struct efx_channel *channel)
void efx_nic_generate_test_event(struct efx_channel *channel)
{
- unsigned int magic = EFX_CHANNEL_MAGIC_TEST(channel);
- efx_qword_t test_event;
-
- EFX_POPULATE_QWORD_2(test_event, FSF_AZ_EV_CODE,
- FSE_AZ_EV_CODE_DRV_GEN_EV,
- FSF_AZ_DRV_GEN_EV_MAGIC, magic);
- efx_generate_event(channel, &test_event);
+ efx_magic_event(channel, EFX_CHANNEL_MAGIC_TEST(channel));
}
-void efx_nic_generate_fill_event(struct efx_channel *channel)
+void efx_nic_generate_fill_event(struct efx_rx_queue *rx_queue)
{
- unsigned int magic = EFX_CHANNEL_MAGIC_FILL(channel);
- efx_qword_t test_event;
-
- EFX_POPULATE_QWORD_2(test_event, FSF_AZ_EV_CODE,
- FSE_AZ_EV_CODE_DRV_GEN_EV,
- FSF_AZ_DRV_GEN_EV_MAGIC, magic);
- efx_generate_event(channel, &test_event);
-}
-
-/**************************************************************************
- *
- * Flush handling
- *
- **************************************************************************/
-
-
-static void efx_poll_flush_events(struct efx_nic *efx)
-{
- struct efx_channel *channel = efx_get_channel(efx, 0);
- struct efx_tx_queue *tx_queue;
- struct efx_rx_queue *rx_queue;
- unsigned int read_ptr = channel->eventq_read_ptr;
- unsigned int end_ptr = read_ptr + channel->eventq_mask - 1;
-
- do {
- efx_qword_t *event = efx_event(channel, read_ptr);
- int ev_code, ev_sub_code, ev_queue;
- bool ev_failed;
-
- if (!efx_event_present(event))
- break;
-
- ev_code = EFX_QWORD_FIELD(*event, FSF_AZ_EV_CODE);
- ev_sub_code = EFX_QWORD_FIELD(*event,
- FSF_AZ_DRIVER_EV_SUBCODE);
- if (ev_code == FSE_AZ_EV_CODE_DRIVER_EV &&
- ev_sub_code == FSE_AZ_TX_DESCQ_FLS_DONE_EV) {
- ev_queue = EFX_QWORD_FIELD(*event,
- FSF_AZ_DRIVER_EV_SUBDATA);
- if (ev_queue < EFX_TXQ_TYPES * efx->n_tx_channels) {
- tx_queue = efx_get_tx_queue(
- efx, ev_queue / EFX_TXQ_TYPES,
- ev_queue % EFX_TXQ_TYPES);
- tx_queue->flushed = FLUSH_DONE;
- }
- } else if (ev_code == FSE_AZ_EV_CODE_DRIVER_EV &&
- ev_sub_code == FSE_AZ_RX_DESCQ_FLS_DONE_EV) {
- ev_queue = EFX_QWORD_FIELD(
- *event, FSF_AZ_DRIVER_EV_RX_DESCQ_ID);
- ev_failed = EFX_QWORD_FIELD(
- *event, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
- if (ev_queue < efx->n_rx_channels) {
- rx_queue = efx_get_rx_queue(efx, ev_queue);
- rx_queue->flushed =
- ev_failed ? FLUSH_FAILED : FLUSH_DONE;
- }
- }
-
- /* We're about to destroy the queue anyway, so
- * it's ok to throw away every non-flush event */
- EFX_SET_QWORD(*event);
-
- ++read_ptr;
- } while (read_ptr != end_ptr);
-
- channel->eventq_read_ptr = read_ptr;
-}
-
-/* Handle tx and rx flushes at the same time, since they run in
- * parallel in the hardware and there's no reason for us to
- * serialise them */
-int efx_nic_flush_queues(struct efx_nic *efx)
-{
- struct efx_channel *channel;
- struct efx_rx_queue *rx_queue;
- struct efx_tx_queue *tx_queue;
- int i, tx_pending, rx_pending;
-
- /* If necessary prepare the hardware for flushing */
- efx->type->prepare_flush(efx);
-
- /* Flush all tx queues in parallel */
- efx_for_each_channel(channel, efx) {
- efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
- if (tx_queue->initialised)
- efx_flush_tx_queue(tx_queue);
- }
- }
-
- /* The hardware supports four concurrent rx flushes, each of which may
- * need to be retried if there is an outstanding descriptor fetch */
- for (i = 0; i < EFX_FLUSH_POLL_COUNT; ++i) {
- rx_pending = tx_pending = 0;
- efx_for_each_channel(channel, efx) {
- efx_for_each_channel_rx_queue(rx_queue, channel) {
- if (rx_queue->flushed == FLUSH_PENDING)
- ++rx_pending;
- }
- }
- efx_for_each_channel(channel, efx) {
- efx_for_each_channel_rx_queue(rx_queue, channel) {
- if (rx_pending == EFX_RX_FLUSH_COUNT)
- break;
- if (rx_queue->flushed == FLUSH_FAILED ||
- rx_queue->flushed == FLUSH_NONE) {
- efx_flush_rx_queue(rx_queue);
- ++rx_pending;
- }
- }
- efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
- if (tx_queue->initialised &&
- tx_queue->flushed != FLUSH_DONE)
- ++tx_pending;
- }
- }
-
- if (rx_pending == 0 && tx_pending == 0)
- return 0;
-
- msleep(EFX_FLUSH_INTERVAL);
- efx_poll_flush_events(efx);
- }
-
- /* Mark the queues as all flushed. We're going to return failure
- * leading to a reset, or fake up success anyway */
- efx_for_each_channel(channel, efx) {
- efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
- if (tx_queue->initialised &&
- tx_queue->flushed != FLUSH_DONE)
- netif_err(efx, hw, efx->net_dev,
- "tx queue %d flush command timed out\n",
- tx_queue->queue);
- tx_queue->flushed = FLUSH_DONE;
- }
- efx_for_each_channel_rx_queue(rx_queue, channel) {
- if (rx_queue->flushed != FLUSH_DONE)
- netif_err(efx, hw, efx->net_dev,
- "rx queue %d flush command timed out\n",
- efx_rx_queue_index(rx_queue));
- rx_queue->flushed = FLUSH_DONE;
- }
- }
-
- return -ETIMEDOUT;
+ efx_magic_event(efx_rx_queue_channel(rx_queue),
+ EFX_CHANNEL_MAGIC_FILL(rx_queue));
}
/**************************************************************************
@@ -1311,7 +1359,7 @@ static inline void efx_nic_interrupts(struct efx_nic *efx,
efx_oword_t int_en_reg_ker;
EFX_POPULATE_OWORD_3(int_en_reg_ker,
- FRF_AZ_KER_INT_LEVE_SEL, efx->fatal_irq_level,
+ FRF_AZ_KER_INT_LEVE_SEL, efx->irq_level,
FRF_AZ_KER_INT_KER, force,
FRF_AZ_DRV_INT_EN_KER, enabled);
efx_writeo(efx, &int_en_reg_ker, FR_AZ_INT_EN_KER);
@@ -1319,18 +1367,10 @@ static inline void efx_nic_interrupts(struct efx_nic *efx,
void efx_nic_enable_interrupts(struct efx_nic *efx)
{
- struct efx_channel *channel;
-
EFX_ZERO_OWORD(*((efx_oword_t *) efx->irq_status.addr));
wmb(); /* Ensure interrupt vector is clear before interrupts enabled */
- /* Enable interrupts */
efx_nic_interrupts(efx, true, false);
-
- /* Force processing of all the channels to get the EVQ RPTRs up to
- date */
- efx_for_each_channel(channel, efx)
- efx_schedule_channel(channel);
}
void efx_nic_disable_interrupts(struct efx_nic *efx)
@@ -1427,11 +1467,12 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
efx_readd(efx, &reg, FR_BZ_INT_ISR0);
queues = EFX_EXTRACT_DWORD(reg, 0, 31);
- /* Check to see if we have a serious error condition */
- if (queues & (1U << efx->fatal_irq_level)) {
+ /* Handle non-event-queue sources */
+ if (queues & (1U << efx->irq_level)) {
syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
if (unlikely(syserr))
return efx_nic_fatal_interrupt(efx);
+ efx->last_irq_cpu = raw_smp_processor_id();
}
if (queues != 0) {
@@ -1441,7 +1482,7 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
/* Schedule processing of any interrupting queues */
efx_for_each_channel(channel, efx) {
if (queues & 1)
- efx_schedule_channel(channel);
+ efx_schedule_channel_irq(channel);
queues >>= 1;
}
result = IRQ_HANDLED;
@@ -1458,18 +1499,16 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
efx_for_each_channel(channel, efx) {
event = efx_event(channel, channel->eventq_read_ptr);
if (efx_event_present(event))
- efx_schedule_channel(channel);
+ efx_schedule_channel_irq(channel);
else
efx_nic_eventq_read_ack(channel);
}
}
- if (result == IRQ_HANDLED) {
- efx->last_irq_cpu = raw_smp_processor_id();
+ if (result == IRQ_HANDLED)
netif_vdbg(efx, intr, efx->net_dev,
"IRQ %d on CPU %d status " EFX_DWORD_FMT "\n",
irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg));
- }
return result;
}
@@ -1488,20 +1527,20 @@ static irqreturn_t efx_msi_interrupt(int irq, void *dev_id)
efx_oword_t *int_ker = efx->irq_status.addr;
int syserr;
- efx->last_irq_cpu = raw_smp_processor_id();
netif_vdbg(efx, intr, efx->net_dev,
"IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
- /* Check to see if we have a serious error condition */
- if (channel->channel == efx->fatal_irq_level) {
+ /* Handle non-event-queue sources */
+ if (channel->channel == efx->irq_level) {
syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
if (unlikely(syserr))
return efx_nic_fatal_interrupt(efx);
+ efx->last_irq_cpu = raw_smp_processor_id();
}
/* Schedule processing of the channel */
- efx_schedule_channel(channel);
+ efx_schedule_channel_irq(channel);
return IRQ_HANDLED;
}
@@ -1598,6 +1637,58 @@ void efx_nic_fini_interrupt(struct efx_nic *efx)
free_irq(efx->legacy_irq, efx);
}
+/* Looks at available SRAM resources and works out how many queues we
+ * can support, and where things like descriptor caches should live.
+ *
+ * SRAM is split up as follows:
+ * 0 buftbl entries for channels
+ * efx->vf_buftbl_base buftbl entries for SR-IOV
+ * efx->rx_dc_base RX descriptor caches
+ * efx->tx_dc_base TX descriptor caches
+ */
+void efx_nic_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw)
+{
+ unsigned vi_count, buftbl_min;
+
+ /* Account for the buffer table entries backing the datapath channels
+ * and the descriptor caches for those channels.
+ */
+ buftbl_min = ((efx->n_rx_channels * EFX_MAX_DMAQ_SIZE +
+ efx->n_tx_channels * EFX_TXQ_TYPES * EFX_MAX_DMAQ_SIZE +
+ efx->n_channels * EFX_MAX_EVQ_SIZE)
+ * sizeof(efx_qword_t) / EFX_BUF_SIZE);
+ vi_count = max(efx->n_channels, efx->n_tx_channels * EFX_TXQ_TYPES);
+
+#ifdef CONFIG_SFC_SRIOV
+ if (efx_sriov_wanted(efx)) {
+ unsigned vi_dc_entries, buftbl_free, entries_per_vf, vf_limit;
+
+ efx->vf_buftbl_base = buftbl_min;
+
+ vi_dc_entries = RX_DC_ENTRIES + TX_DC_ENTRIES;
+ vi_count = max(vi_count, EFX_VI_BASE);
+ buftbl_free = (sram_lim_qw - buftbl_min -
+ vi_count * vi_dc_entries);
+
+ entries_per_vf = ((vi_dc_entries + EFX_VF_BUFTBL_PER_VI) *
+ efx_vf_size(efx));
+ vf_limit = min(buftbl_free / entries_per_vf,
+ (1024U - EFX_VI_BASE) >> efx->vi_scale);
+
+ if (efx->vf_count > vf_limit) {
+ netif_err(efx, probe, efx->net_dev,
+ "Reducing VF count from from %d to %d\n",
+ efx->vf_count, vf_limit);
+ efx->vf_count = vf_limit;
+ }
+ vi_count += efx->vf_count * efx_vf_size(efx);
+ }
+#endif
+
+ efx->tx_dc_base = sram_lim_qw - vi_count * TX_DC_ENTRIES;
+ efx->rx_dc_base = efx->tx_dc_base - vi_count * RX_DC_ENTRIES;
+}
+
u32 efx_nic_fpga_ver(struct efx_nic *efx)
{
efx_oword_t altera_build;
@@ -1610,11 +1701,9 @@ void efx_nic_init_common(struct efx_nic *efx)
efx_oword_t temp;
/* Set positions of descriptor caches in SRAM. */
- EFX_POPULATE_OWORD_1(temp, FRF_AZ_SRM_TX_DC_BASE_ADR,
- efx->type->tx_dc_base / 8);
+ EFX_POPULATE_OWORD_1(temp, FRF_AZ_SRM_TX_DC_BASE_ADR, efx->tx_dc_base);
efx_writeo(efx, &temp, FR_AZ_SRM_TX_DC_CFG);
- EFX_POPULATE_OWORD_1(temp, FRF_AZ_SRM_RX_DC_BASE_ADR,
- efx->type->rx_dc_base / 8);
+ EFX_POPULATE_OWORD_1(temp, FRF_AZ_SRM_RX_DC_BASE_ADR, efx->rx_dc_base);
efx_writeo(efx, &temp, FR_AZ_SRM_RX_DC_CFG);
/* Set TX descriptor cache size. */
@@ -1640,10 +1729,10 @@ void efx_nic_init_common(struct efx_nic *efx)
if (EFX_WORKAROUND_17213(efx) && !EFX_INT_MODE_USE_MSI(efx))
/* Use an interrupt level unused by event queues */
- efx->fatal_irq_level = 0x1f;
+ efx->irq_level = 0x1f;
else
/* Use a valid MSI-X vector */
- efx->fatal_irq_level = 0;
+ efx->irq_level = 0;
/* Enable all the genuinely fatal interrupts. (They are still
* masked by the overall interrupt mask, controlled by
@@ -1837,7 +1926,7 @@ struct efx_nic_reg_table {
REGISTER_REVISION_ ## min_rev, REGISTER_REVISION_ ## max_rev, \
step, rows \
}
-#define REGISTER_TABLE(name, min_rev, max_rev) \
+#define REGISTER_TABLE(name, min_rev, max_rev) \
REGISTER_TABLE_DIMENSIONS( \
name, FR_ ## min_rev ## max_rev ## _ ## name, \
min_rev, max_rev, \
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 5fb24d3aa3ca..246c4140453c 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -65,6 +65,11 @@ enum {
#define FALCON_GMAC_LOOPBACKS \
(1 << LOOPBACK_GMAC)
+/* Alignment of PCIe DMA boundaries (4KB) */
+#define EFX_PAGE_SIZE 4096
+/* Size and alignment of buffer table entries (same) */
+#define EFX_BUF_SIZE EFX_PAGE_SIZE
+
/**
* struct falcon_board_type - board operations and type information
* @id: Board type id, as found in NVRAM
@@ -144,12 +149,115 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx)
* struct siena_nic_data - Siena NIC state
* @mcdi: Management-Controller-to-Driver Interface
* @wol_filter_id: Wake-on-LAN packet filter id
+ * @hwmon: Hardware monitor state
*/
struct siena_nic_data {
struct efx_mcdi_iface mcdi;
int wol_filter_id;
+#ifdef CONFIG_SFC_MCDI_MON
+ struct efx_mcdi_mon hwmon;
+#endif
};
+#ifdef CONFIG_SFC_MCDI_MON
+static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx)
+{
+ struct siena_nic_data *nic_data;
+ EFX_BUG_ON_PARANOID(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
+ nic_data = efx->nic_data;
+ return &nic_data->hwmon;
+}
+#endif
+
+/*
+ * On the SFC9000 family each port is associated with 1 PCI physical
+ * function (PF) handled by sfc and a configurable number of virtual
+ * functions (VFs) that may be handled by some other driver, often in
+ * a VM guest. The queue pointer registers are mapped in both PF and
+ * VF BARs such that an 8K region provides access to a single RX, TX
+ * and event queue (collectively a Virtual Interface, VI or VNIC).
+ *
+ * The PF has access to all 1024 VIs while VFs are mapped to VIs
+ * according to VI_BASE and VI_SCALE: VF i has access to VIs numbered
+ * in range [VI_BASE + i << VI_SCALE, VI_BASE + i + 1 << VI_SCALE).
+ * The number of VIs and the VI_SCALE value are configurable but must
+ * be established at boot time by firmware.
+ */
+
+/* Maximum VI_SCALE parameter supported by Siena */
+#define EFX_VI_SCALE_MAX 6
+/* Base VI to use for SR-IOV. Must be aligned to (1 << EFX_VI_SCALE_MAX),
+ * so this is the smallest allowed value. */
+#define EFX_VI_BASE 128U
+/* Maximum number of VFs allowed */
+#define EFX_VF_COUNT_MAX 127
+/* Limit EVQs on VFs to be only 8k to reduce buffer table reservation */
+#define EFX_MAX_VF_EVQ_SIZE 8192UL
+/* The number of buffer table entries reserved for each VI on a VF */
+#define EFX_VF_BUFTBL_PER_VI \
+ ((EFX_MAX_VF_EVQ_SIZE + 2 * EFX_MAX_DMAQ_SIZE) * \
+ sizeof(efx_qword_t) / EFX_BUF_SIZE)
+
+#ifdef CONFIG_SFC_SRIOV
+
+static inline bool efx_sriov_wanted(struct efx_nic *efx)
+{
+ return efx->vf_count != 0;
+}
+static inline bool efx_sriov_enabled(struct efx_nic *efx)
+{
+ return efx->vf_init_count != 0;
+}
+static inline unsigned int efx_vf_size(struct efx_nic *efx)
+{
+ return 1 << efx->vi_scale;
+}
+
+extern int efx_init_sriov(void);
+extern void efx_sriov_probe(struct efx_nic *efx);
+extern int efx_sriov_init(struct efx_nic *efx);
+extern void efx_sriov_mac_address_changed(struct efx_nic *efx);
+extern void efx_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event);
+extern void efx_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event);
+extern void efx_sriov_event(struct efx_channel *channel, efx_qword_t *event);
+extern void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq);
+extern void efx_sriov_flr(struct efx_nic *efx, unsigned flr);
+extern void efx_sriov_reset(struct efx_nic *efx);
+extern void efx_sriov_fini(struct efx_nic *efx);
+extern void efx_fini_sriov(void);
+
+#else
+
+static inline bool efx_sriov_wanted(struct efx_nic *efx) { return false; }
+static inline bool efx_sriov_enabled(struct efx_nic *efx) { return false; }
+static inline unsigned int efx_vf_size(struct efx_nic *efx) { return 0; }
+
+static inline int efx_init_sriov(void) { return 0; }
+static inline void efx_sriov_probe(struct efx_nic *efx) {}
+static inline int efx_sriov_init(struct efx_nic *efx) { return -EOPNOTSUPP; }
+static inline void efx_sriov_mac_address_changed(struct efx_nic *efx) {}
+static inline void efx_sriov_tx_flush_done(struct efx_nic *efx,
+ efx_qword_t *event) {}
+static inline void efx_sriov_rx_flush_done(struct efx_nic *efx,
+ efx_qword_t *event) {}
+static inline void efx_sriov_event(struct efx_channel *channel,
+ efx_qword_t *event) {}
+static inline void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq) {}
+static inline void efx_sriov_flr(struct efx_nic *efx, unsigned flr) {}
+static inline void efx_sriov_reset(struct efx_nic *efx) {}
+static inline void efx_sriov_fini(struct efx_nic *efx) {}
+static inline void efx_fini_sriov(void) {}
+
+#endif
+
+extern int efx_sriov_set_vf_mac(struct net_device *dev, int vf, u8 *mac);
+extern int efx_sriov_set_vf_vlan(struct net_device *dev, int vf,
+ u16 vlan, u8 qos);
+extern int efx_sriov_get_vf_config(struct net_device *dev, int vf,
+ struct ifla_vf_info *ivf);
+extern int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf,
+ bool spoofchk);
+
extern const struct efx_nic_type falcon_a1_nic_type;
extern const struct efx_nic_type falcon_b0_nic_type;
extern const struct efx_nic_type siena_a0_nic_type;
@@ -176,6 +284,7 @@ extern void efx_nic_init_rx(struct efx_rx_queue *rx_queue);
extern void efx_nic_fini_rx(struct efx_rx_queue *rx_queue);
extern void efx_nic_remove_rx(struct efx_rx_queue *rx_queue);
extern void efx_nic_notify_rx_desc(struct efx_rx_queue *rx_queue);
+extern void efx_nic_generate_fill_event(struct efx_rx_queue *rx_queue);
/* Event data path */
extern int efx_nic_probe_eventq(struct efx_channel *channel);
@@ -189,12 +298,14 @@ extern bool efx_nic_event_present(struct efx_channel *channel);
/* MAC/PHY */
extern void falcon_drain_tx_fifo(struct efx_nic *efx);
extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx);
+extern bool falcon_xmac_check_fault(struct efx_nic *efx);
+extern int falcon_reconfigure_xmac(struct efx_nic *efx);
+extern void falcon_update_stats_xmac(struct efx_nic *efx);
/* Interrupts and test events */
extern int efx_nic_init_interrupt(struct efx_nic *efx);
extern void efx_nic_enable_interrupts(struct efx_nic *efx);
extern void efx_nic_generate_test_event(struct efx_channel *channel);
-extern void efx_nic_generate_fill_event(struct efx_channel *channel);
extern void efx_nic_generate_interrupt(struct efx_nic *efx);
extern void efx_nic_disable_interrupts(struct efx_nic *efx);
extern void efx_nic_fini_interrupt(struct efx_nic *efx);
@@ -202,15 +313,14 @@ extern irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx);
extern irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id);
extern void falcon_irq_ack_a1(struct efx_nic *efx);
-#define EFX_IRQ_MOD_RESOLUTION 5
-#define EFX_IRQ_MOD_MAX 0x1000
-
/* Global Resources */
extern int efx_nic_flush_queues(struct efx_nic *efx);
extern void falcon_start_nic_stats(struct efx_nic *efx);
extern void falcon_stop_nic_stats(struct efx_nic *efx);
extern void falcon_setup_xaui(struct efx_nic *efx);
extern int falcon_reset_xaui(struct efx_nic *efx);
+extern void
+efx_nic_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw);
extern void efx_nic_init_common(struct efx_nic *efx);
extern void efx_nic_push_rx_indir_table(struct efx_nic *efx);
@@ -264,8 +374,8 @@ extern void efx_nic_get_regs(struct efx_nic *efx, void *buf);
#define MAC_DATA_LBN 0
#define MAC_DATA_WIDTH 32
-extern void efx_nic_generate_event(struct efx_channel *channel,
- efx_qword_t *event);
+extern void efx_generate_event(struct efx_nic *efx, unsigned int evq,
+ efx_qword_t *event);
extern void falcon_poll_xmac(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/qt202x_phy.c b/drivers/net/ethernet/sfc/qt202x_phy.c
index 7ad97e397406..8a7caf88ffb6 100644
--- a/drivers/net/ethernet/sfc/qt202x_phy.c
+++ b/drivers/net/ethernet/sfc/qt202x_phy.c
@@ -47,7 +47,7 @@
#define PMA_PMD_FTX_STATIC_LBN 13
#define PMA_PMD_VEND1_REG 0xc001
#define PMA_PMD_VEND1_LBTXD_LBN 15
-#define PCS_VEND1_REG 0xc000
+#define PCS_VEND1_REG 0xc000
#define PCS_VEND1_LBTXD_LBN 5
void falcon_qt202x_set_led(struct efx_nic *p, int led, int mode)
@@ -453,9 +453,9 @@ const struct efx_phy_operations falcon_qt202x_phy_ops = {
.probe = qt202x_phy_probe,
.init = qt202x_phy_init,
.reconfigure = qt202x_phy_reconfigure,
- .poll = qt202x_phy_poll,
+ .poll = qt202x_phy_poll,
.fini = efx_port_dummy_op_void,
- .remove = qt202x_phy_remove,
+ .remove = qt202x_phy_remove,
.get_settings = qt202x_phy_get_settings,
.set_settings = efx_mdio_set_settings,
.test_alive = efx_mdio_test_alive,
diff --git a/drivers/net/ethernet/sfc/regs.h b/drivers/net/ethernet/sfc/regs.h
index cc2c86b76a7b..ade4c4dc56ca 100644
--- a/drivers/net/ethernet/sfc/regs.h
+++ b/drivers/net/ethernet/sfc/regs.h
@@ -2446,8 +2446,8 @@
#define FRF_CZ_RMFT_RXQ_ID_WIDTH 12
#define FRF_CZ_RMFT_WILDCARD_MATCH_LBN 60
#define FRF_CZ_RMFT_WILDCARD_MATCH_WIDTH 1
-#define FRF_CZ_RMFT_DEST_MAC_LBN 16
-#define FRF_CZ_RMFT_DEST_MAC_WIDTH 44
+#define FRF_CZ_RMFT_DEST_MAC_LBN 12
+#define FRF_CZ_RMFT_DEST_MAC_WIDTH 48
#define FRF_CZ_RMFT_VLAN_ID_LBN 0
#define FRF_CZ_RMFT_VLAN_ID_WIDTH 12
@@ -2523,8 +2523,8 @@
#define FRF_CZ_TMFT_TXQ_ID_WIDTH 12
#define FRF_CZ_TMFT_WILDCARD_MATCH_LBN 60
#define FRF_CZ_TMFT_WILDCARD_MATCH_WIDTH 1
-#define FRF_CZ_TMFT_SRC_MAC_LBN 16
-#define FRF_CZ_TMFT_SRC_MAC_WIDTH 44
+#define FRF_CZ_TMFT_SRC_MAC_LBN 12
+#define FRF_CZ_TMFT_SRC_MAC_WIDTH 48
#define FRF_CZ_TMFT_VLAN_ID_LBN 0
#define FRF_CZ_TMFT_VLAN_ID_WIDTH 12
@@ -2895,17 +2895,17 @@
/* RX_MAC_FILTER_TBL0 */
/* RMFT_DEST_MAC is wider than 32 bits */
-#define FRF_CZ_RMFT_DEST_MAC_LO_LBN 12
+#define FRF_CZ_RMFT_DEST_MAC_LO_LBN FRF_CZ_RMFT_DEST_MAC_LBN
#define FRF_CZ_RMFT_DEST_MAC_LO_WIDTH 32
-#define FRF_CZ_RMFT_DEST_MAC_HI_LBN 44
-#define FRF_CZ_RMFT_DEST_MAC_HI_WIDTH 16
+#define FRF_CZ_RMFT_DEST_MAC_HI_LBN (FRF_CZ_RMFT_DEST_MAC_LBN + 32)
+#define FRF_CZ_RMFT_DEST_MAC_HI_WIDTH (FRF_CZ_RMFT_DEST_MAC_WIDTH - 32)
/* TX_MAC_FILTER_TBL0 */
/* TMFT_SRC_MAC is wider than 32 bits */
-#define FRF_CZ_TMFT_SRC_MAC_LO_LBN 12
+#define FRF_CZ_TMFT_SRC_MAC_LO_LBN FRF_CZ_TMFT_SRC_MAC_LBN
#define FRF_CZ_TMFT_SRC_MAC_LO_WIDTH 32
-#define FRF_CZ_TMFT_SRC_MAC_HI_LBN 44
-#define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH 16
+#define FRF_CZ_TMFT_SRC_MAC_HI_LBN (FRF_CZ_TMFT_SRC_MAC_LBN + 32)
+#define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH (FRF_CZ_TMFT_SRC_MAC_WIDTH - 32)
/* TX_PACE_TBL */
/* Values >20 are documented as reserved, but will result in a queue going
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index fc52fca74193..1ba290d0c21c 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -98,8 +98,8 @@ static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx,
/* Offset is always within one page, so we don't need to consider
* the page order.
*/
- return (((__force unsigned long) buf->dma_addr & (PAGE_SIZE - 1)) +
- efx->type->rx_buffer_hash_size);
+ return ((unsigned int) buf->dma_addr & (PAGE_SIZE - 1)) +
+ efx->type->rx_buffer_hash_size;
}
static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
{
@@ -108,11 +108,10 @@ static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
static u8 *efx_rx_buf_eh(struct efx_nic *efx, struct efx_rx_buffer *buf)
{
- if (buf->is_page)
+ if (buf->flags & EFX_RX_BUF_PAGE)
return page_address(buf->u.page) + efx_rx_buf_offset(efx, buf);
else
- return ((u8 *)buf->u.skb->data +
- efx->type->rx_buffer_hash_size);
+ return (u8 *)buf->u.skb->data + efx->type->rx_buffer_hash_size;
}
static inline u32 efx_rx_buf_hash(const u8 *eh)
@@ -122,10 +121,10 @@ static inline u32 efx_rx_buf_hash(const u8 *eh)
return __le32_to_cpup((const __le32 *)(eh - 4));
#else
const u8 *data = eh - 4;
- return ((u32)data[0] |
- (u32)data[1] << 8 |
- (u32)data[2] << 16 |
- (u32)data[3] << 24);
+ return (u32)data[0] |
+ (u32)data[1] << 8 |
+ (u32)data[2] << 16 |
+ (u32)data[3] << 24;
#endif
}
@@ -159,7 +158,7 @@ static int efx_init_rx_buffers_skb(struct efx_rx_queue *rx_queue)
/* Adjust the SKB for padding */
skb_reserve(skb, NET_IP_ALIGN);
rx_buf->len = skb_len - NET_IP_ALIGN;
- rx_buf->is_page = false;
+ rx_buf->flags = 0;
rx_buf->dma_addr = pci_map_single(efx->pci_dev,
skb->data, rx_buf->len,
@@ -227,7 +226,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
rx_buf->u.page = page;
rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
- rx_buf->is_page = true;
+ rx_buf->flags = EFX_RX_BUF_PAGE;
++rx_queue->added_count;
++rx_queue->alloc_page_count;
++state->refcnt;
@@ -248,7 +247,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
static void efx_unmap_rx_buffer(struct efx_nic *efx,
struct efx_rx_buffer *rx_buf)
{
- if (rx_buf->is_page && rx_buf->u.page) {
+ if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) {
struct efx_rx_page_state *state;
state = page_address(rx_buf->u.page);
@@ -258,7 +257,7 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx,
efx_rx_buf_size(efx),
PCI_DMA_FROMDEVICE);
}
- } else if (!rx_buf->is_page && rx_buf->u.skb) {
+ } else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) {
pci_unmap_single(efx->pci_dev, rx_buf->dma_addr,
rx_buf->len, PCI_DMA_FROMDEVICE);
}
@@ -267,10 +266,10 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx,
static void efx_free_rx_buffer(struct efx_nic *efx,
struct efx_rx_buffer *rx_buf)
{
- if (rx_buf->is_page && rx_buf->u.page) {
+ if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) {
__free_pages(rx_buf->u.page, efx->rx_buffer_order);
rx_buf->u.page = NULL;
- } else if (!rx_buf->is_page && rx_buf->u.skb) {
+ } else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) {
dev_kfree_skb_any(rx_buf->u.skb);
rx_buf->u.skb = NULL;
}
@@ -310,7 +309,7 @@ static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue,
new_buf->dma_addr = rx_buf->dma_addr ^ (PAGE_SIZE >> 1);
new_buf->u.page = rx_buf->u.page;
new_buf->len = rx_buf->len;
- new_buf->is_page = true;
+ new_buf->flags = EFX_RX_BUF_PAGE;
++rx_queue->added_count;
}
@@ -324,7 +323,10 @@ static void efx_recycle_rx_buffer(struct efx_channel *channel,
struct efx_rx_buffer *new_buf;
unsigned index;
- if (rx_buf->is_page && efx->rx_buffer_len <= EFX_RX_HALF_PAGE &&
+ rx_buf->flags &= EFX_RX_BUF_PAGE;
+
+ if ((rx_buf->flags & EFX_RX_BUF_PAGE) &&
+ efx->rx_buffer_len <= EFX_RX_HALF_PAGE &&
page_count(rx_buf->u.page) == 1)
efx_resurrect_rx_buffer(rx_queue, rx_buf);
@@ -402,17 +404,15 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
void efx_rx_slow_fill(unsigned long context)
{
struct efx_rx_queue *rx_queue = (struct efx_rx_queue *)context;
- struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
/* Post an event to cause NAPI to run and refill the queue */
- efx_nic_generate_fill_event(channel);
+ efx_nic_generate_fill_event(rx_queue);
++rx_queue->slow_fill_count;
}
static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
struct efx_rx_buffer *rx_buf,
- int len, bool *discard,
- bool *leak_packet)
+ int len, bool *leak_packet)
{
struct efx_nic *efx = rx_queue->efx;
unsigned max_len = rx_buf->len - efx->type->rx_buffer_padding;
@@ -423,7 +423,7 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
/* The packet must be discarded, but this is only a fatal error
* if the caller indicated it was
*/
- *discard = true;
+ rx_buf->flags |= EFX_RX_PKT_DISCARD;
if ((len > rx_buf->len) && EFX_WORKAROUND_8071(efx)) {
if (net_ratelimit())
@@ -436,7 +436,7 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
* data at the end of the skb will be trashed. So
* we have no choice but to leak the fragment.
*/
- *leak_packet = !rx_buf->is_page;
+ *leak_packet = !(rx_buf->flags & EFX_RX_BUF_PAGE);
efx_schedule_reset(efx, RESET_TYPE_RX_RECOVERY);
} else {
if (net_ratelimit())
@@ -456,13 +456,13 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
*/
static void efx_rx_packet_gro(struct efx_channel *channel,
struct efx_rx_buffer *rx_buf,
- const u8 *eh, bool checksummed)
+ const u8 *eh)
{
struct napi_struct *napi = &channel->napi_str;
gro_result_t gro_result;
/* Pass the skb/page into the GRO engine */
- if (rx_buf->is_page) {
+ if (rx_buf->flags & EFX_RX_BUF_PAGE) {
struct efx_nic *efx = channel->efx;
struct page *page = rx_buf->u.page;
struct sk_buff *skb;
@@ -484,8 +484,8 @@ static void efx_rx_packet_gro(struct efx_channel *channel,
skb->len = rx_buf->len;
skb->data_len = rx_buf->len;
skb->truesize += rx_buf->len;
- skb->ip_summed =
- checksummed ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
+ skb->ip_summed = ((rx_buf->flags & EFX_RX_PKT_CSUMMED) ?
+ CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
skb_record_rx_queue(skb, channel->channel);
@@ -493,7 +493,7 @@ static void efx_rx_packet_gro(struct efx_channel *channel,
} else {
struct sk_buff *skb = rx_buf->u.skb;
- EFX_BUG_ON_PARANOID(!checksummed);
+ EFX_BUG_ON_PARANOID(!(rx_buf->flags & EFX_RX_PKT_CSUMMED));
rx_buf->u.skb = NULL;
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -509,7 +509,7 @@ static void efx_rx_packet_gro(struct efx_channel *channel,
}
void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
- unsigned int len, bool checksummed, bool discard)
+ unsigned int len, u16 flags)
{
struct efx_nic *efx = rx_queue->efx;
struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
@@ -517,6 +517,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
bool leak_packet = false;
rx_buf = efx_rx_buffer(rx_queue, index);
+ rx_buf->flags |= flags;
/* This allows the refill path to post another buffer.
* EFX_RXD_HEAD_ROOM ensures that the slot we are using
@@ -525,18 +526,17 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
rx_queue->removed_count++;
/* Validate the length encoded in the event vs the descriptor pushed */
- efx_rx_packet__check_len(rx_queue, rx_buf, len,
- &discard, &leak_packet);
+ efx_rx_packet__check_len(rx_queue, rx_buf, len, &leak_packet);
netif_vdbg(efx, rx_status, efx->net_dev,
"RX queue %d received id %x at %llx+%x %s%s\n",
efx_rx_queue_index(rx_queue), index,
(unsigned long long)rx_buf->dma_addr, len,
- (checksummed ? " [SUMMED]" : ""),
- (discard ? " [DISCARD]" : ""));
+ (rx_buf->flags & EFX_RX_PKT_CSUMMED) ? " [SUMMED]" : "",
+ (rx_buf->flags & EFX_RX_PKT_DISCARD) ? " [DISCARD]" : "");
/* Discard packet, if instructed to do so */
- if (unlikely(discard)) {
+ if (unlikely(rx_buf->flags & EFX_RX_PKT_DISCARD)) {
if (unlikely(leak_packet))
channel->n_skbuff_leaks++;
else
@@ -563,18 +563,33 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
rx_buf->len = len - efx->type->rx_buffer_hash_size;
out:
if (channel->rx_pkt)
- __efx_rx_packet(channel,
- channel->rx_pkt, channel->rx_pkt_csummed);
+ __efx_rx_packet(channel, channel->rx_pkt);
channel->rx_pkt = rx_buf;
- channel->rx_pkt_csummed = checksummed;
+}
+
+static void efx_rx_deliver(struct efx_channel *channel,
+ struct efx_rx_buffer *rx_buf)
+{
+ struct sk_buff *skb;
+
+ /* We now own the SKB */
+ skb = rx_buf->u.skb;
+ rx_buf->u.skb = NULL;
+
+ /* Set the SKB flags */
+ skb_checksum_none_assert(skb);
+
+ /* Pass the packet up */
+ netif_receive_skb(skb);
+
+ /* Update allocation strategy method */
+ channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
}
/* Handle a received packet. Second half: Touches packet payload. */
-void __efx_rx_packet(struct efx_channel *channel,
- struct efx_rx_buffer *rx_buf, bool checksummed)
+void __efx_rx_packet(struct efx_channel *channel, struct efx_rx_buffer *rx_buf)
{
struct efx_nic *efx = channel->efx;
- struct sk_buff *skb;
u8 *eh = efx_rx_buf_eh(efx, rx_buf);
/* If we're in loopback test, then pass the packet directly to the
@@ -586,8 +601,8 @@ void __efx_rx_packet(struct efx_channel *channel,
return;
}
- if (!rx_buf->is_page) {
- skb = rx_buf->u.skb;
+ if (!(rx_buf->flags & EFX_RX_BUF_PAGE)) {
+ struct sk_buff *skb = rx_buf->u.skb;
prefetch(skb_shinfo(skb));
@@ -605,25 +620,12 @@ void __efx_rx_packet(struct efx_channel *channel,
}
if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM)))
- checksummed = false;
-
- if (likely(checksummed || rx_buf->is_page)) {
- efx_rx_packet_gro(channel, rx_buf, eh, checksummed);
- return;
- }
+ rx_buf->flags &= ~EFX_RX_PKT_CSUMMED;
- /* We now own the SKB */
- skb = rx_buf->u.skb;
- rx_buf->u.skb = NULL;
-
- /* Set the SKB flags */
- skb_checksum_none_assert(skb);
-
- /* Pass the packet up */
- netif_receive_skb(skb);
-
- /* Update allocation strategy method */
- channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
+ if (likely(rx_buf->flags & (EFX_RX_BUF_PAGE | EFX_RX_PKT_CSUMMED)))
+ efx_rx_packet_gro(channel, rx_buf, eh);
+ else
+ efx_rx_deliver(channel, rx_buf);
}
void efx_rx_strategy(struct efx_channel *channel)
@@ -703,6 +705,7 @@ void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
rx_queue->fast_fill_limit = limit;
/* Set up RX descriptor ring */
+ rx_queue->enabled = true;
efx_nic_init_rx(rx_queue);
}
@@ -714,6 +717,9 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
"shutting down RX queue %d\n", efx_rx_queue_index(rx_queue));
+ /* A flush failure might have left rx_queue->enabled */
+ rx_queue->enabled = false;
+
del_timer_sync(&rx_queue->slow_fill);
efx_nic_fini_rx(rx_queue);
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index 52edd24fcde3..febe2a9e6211 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -19,7 +19,6 @@
#include <linux/udp.h>
#include <linux/rtnetlink.h>
#include <linux/slab.h>
-#include <asm/io.h>
#include "net_driver.h"
#include "efx.h"
#include "nic.h"
@@ -50,7 +49,7 @@ static const char payload_msg[] =
/* Interrupt mode names */
static const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX;
-static const char *efx_interrupt_mode_names[] = {
+static const char *const efx_interrupt_mode_names[] = {
[EFX_INT_MODE_MSIX] = "MSI-X",
[EFX_INT_MODE_MSI] = "MSI",
[EFX_INT_MODE_LEGACY] = "legacy",
@@ -131,6 +130,8 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
static int efx_test_interrupts(struct efx_nic *efx,
struct efx_self_tests *tests)
{
+ int cpu;
+
netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n");
tests->interrupt = -1;
@@ -143,7 +144,8 @@ static int efx_test_interrupts(struct efx_nic *efx,
/* Wait for arrival of test interrupt. */
netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n");
schedule_timeout_uninterruptible(HZ / 10);
- if (efx->last_irq_cpu >= 0)
+ cpu = ACCESS_ONCE(efx->last_irq_cpu);
+ if (cpu >= 0)
goto success;
netif_err(efx, drv, efx->net_dev, "timed out waiting for interrupt\n");
@@ -151,8 +153,7 @@ static int efx_test_interrupts(struct efx_nic *efx,
success:
netif_dbg(efx, drv, efx->net_dev, "%s test interrupt seen on CPU%d\n",
- INT_MODE(efx),
- efx->last_irq_cpu);
+ INT_MODE(efx), cpu);
tests->interrupt = 1;
return 0;
}
@@ -162,56 +163,57 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
struct efx_self_tests *tests)
{
struct efx_nic *efx = channel->efx;
- unsigned int read_ptr, count;
-
- tests->eventq_dma[channel->channel] = -1;
- tests->eventq_int[channel->channel] = -1;
- tests->eventq_poll[channel->channel] = -1;
+ unsigned int read_ptr;
+ bool napi_ran, dma_seen, int_seen;
read_ptr = channel->eventq_read_ptr;
- channel->efx->last_irq_cpu = -1;
+ channel->last_irq_cpu = -1;
smp_wmb();
efx_nic_generate_test_event(channel);
- /* Wait for arrival of interrupt */
- count = 0;
- do {
- schedule_timeout_uninterruptible(HZ / 100);
-
- if (ACCESS_ONCE(channel->eventq_read_ptr) != read_ptr)
- goto eventq_ok;
- } while (++count < 2);
-
- netif_err(efx, drv, efx->net_dev,
- "channel %d timed out waiting for event queue\n",
- channel->channel);
-
- /* See if interrupt arrived */
- if (channel->efx->last_irq_cpu >= 0) {
- netif_err(efx, drv, efx->net_dev,
- "channel %d saw interrupt on CPU%d "
- "during event queue test\n", channel->channel,
- raw_smp_processor_id());
- tests->eventq_int[channel->channel] = 1;
+ /* Wait for arrival of interrupt. NAPI processing may or may
+ * not complete in time, but we can cope in any case.
+ */
+ msleep(10);
+ napi_disable(&channel->napi_str);
+ if (channel->eventq_read_ptr != read_ptr) {
+ napi_ran = true;
+ dma_seen = true;
+ int_seen = true;
+ } else {
+ napi_ran = false;
+ dma_seen = efx_nic_event_present(channel);
+ int_seen = ACCESS_ONCE(channel->last_irq_cpu) >= 0;
}
+ napi_enable(&channel->napi_str);
+ efx_nic_eventq_read_ack(channel);
+
+ tests->eventq_dma[channel->channel] = dma_seen ? 1 : -1;
+ tests->eventq_int[channel->channel] = int_seen ? 1 : -1;
- /* Check to see if event was received even if interrupt wasn't */
- if (efx_nic_event_present(channel)) {
+ if (dma_seen && int_seen) {
+ netif_dbg(efx, drv, efx->net_dev,
+ "channel %d event queue passed (with%s NAPI)\n",
+ channel->channel, napi_ran ? "" : "out");
+ return 0;
+ } else {
+ /* Report failure and whether either interrupt or DMA worked */
netif_err(efx, drv, efx->net_dev,
- "channel %d event was generated, but "
- "failed to trigger an interrupt\n", channel->channel);
- tests->eventq_dma[channel->channel] = 1;
+ "channel %d timed out waiting for event queue\n",
+ channel->channel);
+ if (int_seen)
+ netif_err(efx, drv, efx->net_dev,
+ "channel %d saw interrupt "
+ "during event queue test\n",
+ channel->channel);
+ if (dma_seen)
+ netif_err(efx, drv, efx->net_dev,
+ "channel %d event was generated, but "
+ "failed to trigger an interrupt\n",
+ channel->channel);
+ return -ETIMEDOUT;
}
-
- return -ETIMEDOUT;
- eventq_ok:
- netif_dbg(efx, drv, efx->net_dev, "channel %d event queue passed\n",
- channel->channel);
- tests->eventq_dma[channel->channel] = 1;
- tests->eventq_int[channel->channel] = 1;
- tests->eventq_poll[channel->channel] = 1;
- return 0;
}
static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests,
@@ -316,7 +318,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
return;
err:
-#ifdef EFX_ENABLE_DEBUG
+#ifdef DEBUG
if (atomic_read(&state->rx_bad) == 0) {
netif_err(efx, drv, efx->net_dev, "received packet:\n");
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
@@ -395,11 +397,9 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
* interrupt handler. */
smp_wmb();
- if (efx_dev_registered(efx))
- netif_tx_lock_bh(efx->net_dev);
+ netif_tx_lock_bh(efx->net_dev);
rc = efx_enqueue_skb(tx_queue, skb);
- if (efx_dev_registered(efx))
- netif_tx_unlock_bh(efx->net_dev);
+ netif_tx_unlock_bh(efx->net_dev);
if (rc != NETDEV_TX_OK) {
netif_err(efx, drv, efx->net_dev,
@@ -440,20 +440,18 @@ static int efx_end_loopback(struct efx_tx_queue *tx_queue,
int tx_done = 0, rx_good, rx_bad;
int i, rc = 0;
- if (efx_dev_registered(efx))
- netif_tx_lock_bh(efx->net_dev);
+ netif_tx_lock_bh(efx->net_dev);
/* Count the number of tx completions, and decrement the refcnt. Any
* skbs not already completed will be free'd when the queue is flushed */
- for (i=0; i < state->packet_count; i++) {
+ for (i = 0; i < state->packet_count; i++) {
skb = state->skbs[i];
if (skb && !skb_shared(skb))
++tx_done;
dev_kfree_skb_any(skb);
}
- if (efx_dev_registered(efx))
- netif_tx_unlock_bh(efx->net_dev);
+ netif_tx_unlock_bh(efx->net_dev);
/* Check TX completion and received packet counts */
rx_good = atomic_read(&state->rx_good);
@@ -570,7 +568,7 @@ static int efx_wait_for_link(struct efx_nic *efx)
mutex_lock(&efx->mac_lock);
link_up = link_state->up;
if (link_up)
- link_up = !efx->mac_op->check_fault(efx);
+ link_up = !efx->type->check_mac_fault(efx);
mutex_unlock(&efx->mac_lock);
if (link_up) {
diff --git a/drivers/net/ethernet/sfc/selftest.h b/drivers/net/ethernet/sfc/selftest.h
index dba5456e70f3..87abe2a53846 100644
--- a/drivers/net/ethernet/sfc/selftest.h
+++ b/drivers/net/ethernet/sfc/selftest.h
@@ -37,7 +37,6 @@ struct efx_self_tests {
int interrupt;
int eventq_dma[EFX_MAX_CHANNELS];
int eventq_int[EFX_MAX_CHANNELS];
- int eventq_poll[EFX_MAX_CHANNELS];
/* offline tests */
int registers;
int phy_ext[EFX_MAX_PHY_TESTS];
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 4d5d619feaa6..7bea79017a05 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -18,7 +18,6 @@
#include "bitfield.h"
#include "efx.h"
#include "nic.h"
-#include "mac.h"
#include "spi.h"
#include "regs.h"
#include "io.h"
@@ -36,8 +35,6 @@ static void siena_push_irq_moderation(struct efx_channel *channel)
{
efx_dword_t timer_cmd;
- BUILD_BUG_ON(EFX_IRQ_MOD_MAX > (1 << FRF_CZ_TC_TIMER_VAL_WIDTH));
-
if (channel->irq_moderation)
EFX_POPULATE_DWORD_2(timer_cmd,
FRF_CZ_TC_TIMER_MODE,
@@ -53,15 +50,6 @@ static void siena_push_irq_moderation(struct efx_channel *channel)
channel->channel);
}
-static void siena_push_multicast_hash(struct efx_nic *efx)
-{
- WARN_ON(!mutex_is_locked(&efx->mac_lock));
-
- efx_mcdi_rpc(efx, MC_CMD_SET_MCAST_HASH,
- efx->multicast_hash.byte, sizeof(efx->multicast_hash),
- NULL, 0, NULL);
-}
-
static int siena_mdio_write(struct net_device *net_dev,
int prtad, int devad, u16 addr, u16 value)
{
@@ -226,7 +214,24 @@ static int siena_reset_hw(struct efx_nic *efx, enum reset_type method)
static int siena_probe_nvconfig(struct efx_nic *efx)
{
- return efx_mcdi_get_board_cfg(efx, efx->net_dev->perm_addr, NULL);
+ u32 caps = 0;
+ int rc;
+
+ rc = efx_mcdi_get_board_cfg(efx, efx->net_dev->perm_addr, NULL, &caps);
+
+ efx->timer_quantum_ns =
+ (caps & (1 << MC_CMD_CAPABILITIES_TURBO_ACTIVE_LBN)) ?
+ 3072 : 6144; /* 768 cycles */
+ return rc;
+}
+
+static void siena_dimension_resources(struct efx_nic *efx)
+{
+ /* Each port has a small block of internal SRAM dedicated to
+ * the buffer table and descriptor caches. In theory we can
+ * map both blocks to one port, but we don't.
+ */
+ efx_nic_dimension_resources(efx, FR_CZ_BUF_FULL_TBL_ROWS / 2);
}
static int siena_probe_nic(struct efx_nic *efx)
@@ -304,6 +309,12 @@ static int siena_probe_nic(struct efx_nic *efx)
goto fail5;
}
+ rc = efx_mcdi_mon_probe(efx);
+ if (rc)
+ goto fail5;
+
+ efx_sriov_probe(efx);
+
return 0;
fail5:
@@ -391,6 +402,8 @@ static int siena_init_nic(struct efx_nic *efx)
static void siena_remove_nic(struct efx_nic *efx)
{
+ efx_mcdi_mon_remove(efx);
+
efx_nic_free_buffer(efx, &efx->irq_status);
siena_reset_hw(efx, RESET_TYPE_ALL);
@@ -617,6 +630,7 @@ const struct efx_nic_type siena_a0_nic_type = {
.probe = siena_probe_nic,
.remove = siena_remove_nic,
.init = siena_init_nic,
+ .dimension_resources = siena_dimension_resources,
.fini = efx_port_dummy_op_void,
.monitor = NULL,
.map_reset_reason = siena_map_reset_reason,
@@ -630,14 +644,14 @@ const struct efx_nic_type siena_a0_nic_type = {
.stop_stats = siena_stop_nic_stats,
.set_id_led = efx_mcdi_set_id_led,
.push_irq_moderation = siena_push_irq_moderation,
- .push_multicast_hash = siena_push_multicast_hash,
+ .reconfigure_mac = efx_mcdi_mac_reconfigure,
+ .check_mac_fault = efx_mcdi_mac_check_fault,
.reconfigure_port = efx_mcdi_phy_reconfigure,
.get_wol = siena_get_wol,
.set_wol = siena_set_wol,
.resume_wol = siena_init_wol,
.test_registers = siena_test_registers,
.test_nvram = efx_mcdi_nvram_test_all,
- .default_mac_ops = &efx_mcdi_mac_operations,
.revision = EFX_REV_SIENA_A0,
.mem_map_size = (FR_CZ_MC_TREG_SMEM +
@@ -654,8 +668,7 @@ const struct efx_nic_type siena_a0_nic_type = {
.phys_addr_channels = 32, /* Hardware limit is 64, but the legacy
* interrupt handler only supports 32
* channels */
- .tx_dc_base = 0x88000,
- .rx_dc_base = 0x68000,
+ .timer_period_max = 1 << FRF_CZ_TC_TIMER_VAL_WIDTH,
.offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_RXHASH | NETIF_F_NTUPLE),
};
diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c
new file mode 100644
index 000000000000..80976e84eee6
--- /dev/null
+++ b/drivers/net/ethernet/sfc/siena_sriov.c
@@ -0,0 +1,1643 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2010-2011 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+#include "net_driver.h"
+#include "efx.h"
+#include "nic.h"
+#include "io.h"
+#include "mcdi.h"
+#include "filter.h"
+#include "mcdi_pcol.h"
+#include "regs.h"
+#include "vfdi.h"
+
+/* Number of longs required to track all the VIs in a VF */
+#define VI_MASK_LENGTH BITS_TO_LONGS(1 << EFX_VI_SCALE_MAX)
+
+/**
+ * enum efx_vf_tx_filter_mode - TX MAC filtering behaviour
+ * @VF_TX_FILTER_OFF: Disabled
+ * @VF_TX_FILTER_AUTO: Enabled if MAC address assigned to VF and only
+ * 2 TX queues allowed per VF.
+ * @VF_TX_FILTER_ON: Enabled
+ */
+enum efx_vf_tx_filter_mode {
+ VF_TX_FILTER_OFF,
+ VF_TX_FILTER_AUTO,
+ VF_TX_FILTER_ON,
+};
+
+/**
+ * struct efx_vf - Back-end resource and protocol state for a PCI VF
+ * @efx: The Efx NIC owning this VF
+ * @pci_rid: The PCI requester ID for this VF
+ * @pci_name: The PCI name (formatted address) of this VF
+ * @index: Index of VF within its port and PF.
+ * @req: VFDI incoming request work item. Incoming USR_EV events are received
+ * by the NAPI handler, but must be handled by executing MCDI requests
+ * inside a work item.
+ * @req_addr: VFDI incoming request DMA address (in VF's PCI address space).
+ * @req_type: Expected next incoming (from VF) %VFDI_EV_TYPE member.
+ * @req_seqno: Expected next incoming (from VF) %VFDI_EV_SEQ member.
+ * @msg_seqno: Next %VFDI_EV_SEQ member to reply to VF. Protected by
+ * @status_lock
+ * @busy: VFDI request queued to be processed or being processed. Receiving
+ * a VFDI request when @busy is set is an error condition.
+ * @buf: Incoming VFDI requests are DMA from the VF into this buffer.
+ * @buftbl_base: Buffer table entries for this VF start at this index.
+ * @rx_filtering: Receive filtering has been requested by the VF driver.
+ * @rx_filter_flags: The flags sent in the %VFDI_OP_INSERT_FILTER request.
+ * @rx_filter_qid: VF relative qid for RX filter requested by VF.
+ * @rx_filter_id: Receive MAC filter ID. Only one filter per VF is supported.
+ * @tx_filter_mode: Transmit MAC filtering mode.
+ * @tx_filter_id: Transmit MAC filter ID.
+ * @addr: The MAC address and outer vlan tag of the VF.
+ * @status_addr: VF DMA address of page for &struct vfdi_status updates.
+ * @status_lock: Mutex protecting @msg_seqno, @status_addr, @addr,
+ * @peer_page_addrs and @peer_page_count from simultaneous
+ * updates by the VM and consumption by
+ * efx_sriov_update_vf_addr()
+ * @peer_page_addrs: Pointer to an array of guest pages for local addresses.
+ * @peer_page_count: Number of entries in @peer_page_count.
+ * @evq0_addrs: Array of guest pages backing evq0.
+ * @evq0_count: Number of entries in @evq0_addrs.
+ * @flush_waitq: wait queue used by %VFDI_OP_FINI_ALL_QUEUES handler
+ * to wait for flush completions.
+ * @txq_lock: Mutex for TX queue allocation.
+ * @txq_mask: Mask of initialized transmit queues.
+ * @txq_count: Number of initialized transmit queues.
+ * @rxq_mask: Mask of initialized receive queues.
+ * @rxq_count: Number of initialized receive queues.
+ * @rxq_retry_mask: Mask or receive queues that need to be flushed again
+ * due to flush failure.
+ * @rxq_retry_count: Number of receive queues in @rxq_retry_mask.
+ * @reset_work: Work item to schedule a VF reset.
+ */
+struct efx_vf {
+ struct efx_nic *efx;
+ unsigned int pci_rid;
+ char pci_name[13]; /* dddd:bb:dd.f */
+ unsigned int index;
+ struct work_struct req;
+ u64 req_addr;
+ int req_type;
+ unsigned req_seqno;
+ unsigned msg_seqno;
+ bool busy;
+ struct efx_buffer buf;
+ unsigned buftbl_base;
+ bool rx_filtering;
+ enum efx_filter_flags rx_filter_flags;
+ unsigned rx_filter_qid;
+ int rx_filter_id;
+ enum efx_vf_tx_filter_mode tx_filter_mode;
+ int tx_filter_id;
+ struct vfdi_endpoint addr;
+ u64 status_addr;
+ struct mutex status_lock;
+ u64 *peer_page_addrs;
+ unsigned peer_page_count;
+ u64 evq0_addrs[EFX_MAX_VF_EVQ_SIZE * sizeof(efx_qword_t) /
+ EFX_BUF_SIZE];
+ unsigned evq0_count;
+ wait_queue_head_t flush_waitq;
+ struct mutex txq_lock;
+ unsigned long txq_mask[VI_MASK_LENGTH];
+ unsigned txq_count;
+ unsigned long rxq_mask[VI_MASK_LENGTH];
+ unsigned rxq_count;
+ unsigned long rxq_retry_mask[VI_MASK_LENGTH];
+ atomic_t rxq_retry_count;
+ struct work_struct reset_work;
+};
+
+struct efx_memcpy_req {
+ unsigned int from_rid;
+ void *from_buf;
+ u64 from_addr;
+ unsigned int to_rid;
+ u64 to_addr;
+ unsigned length;
+};
+
+/**
+ * struct efx_local_addr - A MAC address on the vswitch without a VF.
+ *
+ * Siena does not have a switch, so VFs can't transmit data to each
+ * other. Instead the VFs must be made aware of the local addresses
+ * on the vswitch, so that they can arrange for an alternative
+ * software datapath to be used.
+ *
+ * @link: List head for insertion into efx->local_addr_list.
+ * @addr: Ethernet address
+ */
+struct efx_local_addr {
+ struct list_head link;
+ u8 addr[ETH_ALEN];
+};
+
+/**
+ * struct efx_endpoint_page - Page of vfdi_endpoint structures
+ *
+ * @link: List head for insertion into efx->local_page_list.
+ * @ptr: Pointer to page.
+ * @addr: DMA address of page.
+ */
+struct efx_endpoint_page {
+ struct list_head link;
+ void *ptr;
+ dma_addr_t addr;
+};
+
+/* Buffer table entries are reserved txq0,rxq0,evq0,txq1,rxq1,evq1 */
+#define EFX_BUFTBL_TXQ_BASE(_vf, _qid) \
+ ((_vf)->buftbl_base + EFX_VF_BUFTBL_PER_VI * (_qid))
+#define EFX_BUFTBL_RXQ_BASE(_vf, _qid) \
+ (EFX_BUFTBL_TXQ_BASE(_vf, _qid) + \
+ (EFX_MAX_DMAQ_SIZE * sizeof(efx_qword_t) / EFX_BUF_SIZE))
+#define EFX_BUFTBL_EVQ_BASE(_vf, _qid) \
+ (EFX_BUFTBL_TXQ_BASE(_vf, _qid) + \
+ (2 * EFX_MAX_DMAQ_SIZE * sizeof(efx_qword_t) / EFX_BUF_SIZE))
+
+#define EFX_FIELD_MASK(_field) \
+ ((1 << _field ## _WIDTH) - 1)
+
+/* VFs can only use this many transmit channels */
+static unsigned int vf_max_tx_channels = 2;
+module_param(vf_max_tx_channels, uint, 0444);
+MODULE_PARM_DESC(vf_max_tx_channels,
+ "Limit the number of TX channels VFs can use");
+
+static int max_vfs = -1;
+module_param(max_vfs, int, 0444);
+MODULE_PARM_DESC(max_vfs,
+ "Reduce the number of VFs initialized by the driver");
+
+/* Workqueue used by VFDI communication. We can't use the global
+ * workqueue because it may be running the VF driver's probe()
+ * routine, which will be blocked there waiting for a VFDI response.
+ */
+static struct workqueue_struct *vfdi_workqueue;
+
+static unsigned abs_index(struct efx_vf *vf, unsigned index)
+{
+ return EFX_VI_BASE + vf->index * efx_vf_size(vf->efx) + index;
+}
+
+static int efx_sriov_cmd(struct efx_nic *efx, bool enable,
+ unsigned *vi_scale_out, unsigned *vf_total_out)
+{
+ u8 inbuf[MC_CMD_SRIOV_IN_LEN];
+ u8 outbuf[MC_CMD_SRIOV_OUT_LEN];
+ unsigned vi_scale, vf_total;
+ size_t outlen;
+ int rc;
+
+ MCDI_SET_DWORD(inbuf, SRIOV_IN_ENABLE, enable ? 1 : 0);
+ MCDI_SET_DWORD(inbuf, SRIOV_IN_VI_BASE, EFX_VI_BASE);
+ MCDI_SET_DWORD(inbuf, SRIOV_IN_VF_COUNT, efx->vf_count);
+
+ rc = efx_mcdi_rpc(efx, MC_CMD_SRIOV, inbuf, MC_CMD_SRIOV_IN_LEN,
+ outbuf, MC_CMD_SRIOV_OUT_LEN, &outlen);
+ if (rc)
+ return rc;
+ if (outlen < MC_CMD_SRIOV_OUT_LEN)
+ return -EIO;
+
+ vf_total = MCDI_DWORD(outbuf, SRIOV_OUT_VF_TOTAL);
+ vi_scale = MCDI_DWORD(outbuf, SRIOV_OUT_VI_SCALE);
+ if (vi_scale > EFX_VI_SCALE_MAX)
+ return -EOPNOTSUPP;
+
+ if (vi_scale_out)
+ *vi_scale_out = vi_scale;
+ if (vf_total_out)
+ *vf_total_out = vf_total;
+
+ return 0;
+}
+
+static void efx_sriov_usrev(struct efx_nic *efx, bool enabled)
+{
+ efx_oword_t reg;
+
+ EFX_POPULATE_OWORD_2(reg,
+ FRF_CZ_USREV_DIS, enabled ? 0 : 1,
+ FRF_CZ_DFLT_EVQ, efx->vfdi_channel->channel);
+ efx_writeo(efx, &reg, FR_CZ_USR_EV_CFG);
+}
+
+static int efx_sriov_memcpy(struct efx_nic *efx, struct efx_memcpy_req *req,
+ unsigned int count)
+{
+ u8 *inbuf, *record;
+ unsigned int used;
+ u32 from_rid, from_hi, from_lo;
+ int rc;
+
+ mb(); /* Finish writing source/reading dest before DMA starts */
+
+ used = MC_CMD_MEMCPY_IN_LEN(count);
+ if (WARN_ON(used > MCDI_CTL_SDU_LEN_MAX))
+ return -ENOBUFS;
+
+ /* Allocate room for the largest request */
+ inbuf = kzalloc(MCDI_CTL_SDU_LEN_MAX, GFP_KERNEL);
+ if (inbuf == NULL)
+ return -ENOMEM;
+
+ record = inbuf;
+ MCDI_SET_DWORD(record, MEMCPY_IN_RECORD, count);
+ while (count-- > 0) {
+ MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_TO_RID,
+ req->to_rid);
+ MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_TO_ADDR_LO,
+ (u32)req->to_addr);
+ MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_TO_ADDR_HI,
+ (u32)(req->to_addr >> 32));
+ if (req->from_buf == NULL) {
+ from_rid = req->from_rid;
+ from_lo = (u32)req->from_addr;
+ from_hi = (u32)(req->from_addr >> 32);
+ } else {
+ if (WARN_ON(used + req->length > MCDI_CTL_SDU_LEN_MAX)) {
+ rc = -ENOBUFS;
+ goto out;
+ }
+
+ from_rid = MC_CMD_MEMCPY_RECORD_TYPEDEF_RID_INLINE;
+ from_lo = used;
+ from_hi = 0;
+ memcpy(inbuf + used, req->from_buf, req->length);
+ used += req->length;
+ }
+
+ MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_FROM_RID, from_rid);
+ MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LO,
+ from_lo);
+ MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_FROM_ADDR_HI,
+ from_hi);
+ MCDI_SET_DWORD(record, MEMCPY_RECORD_TYPEDEF_LENGTH,
+ req->length);
+
+ ++req;
+ record += MC_CMD_MEMCPY_IN_RECORD_LEN;
+ }
+
+ rc = efx_mcdi_rpc(efx, MC_CMD_MEMCPY, inbuf, used, NULL, 0, NULL);
+out:
+ kfree(inbuf);
+
+ mb(); /* Don't write source/read dest before DMA is complete */
+
+ return rc;
+}
+
+/* The TX filter is entirely controlled by this driver, and is modified
+ * underneath the feet of the VF
+ */
+static void efx_sriov_reset_tx_filter(struct efx_vf *vf)
+{
+ struct efx_nic *efx = vf->efx;
+ struct efx_filter_spec filter;
+ u16 vlan;
+ int rc;
+
+ if (vf->tx_filter_id != -1) {
+ efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
+ vf->tx_filter_id);
+ netif_dbg(efx, hw, efx->net_dev, "Removed vf %s tx filter %d\n",
+ vf->pci_name, vf->tx_filter_id);
+ vf->tx_filter_id = -1;
+ }
+
+ if (is_zero_ether_addr(vf->addr.mac_addr))
+ return;
+
+ /* Turn on TX filtering automatically if not explicitly
+ * enabled or disabled.
+ */
+ if (vf->tx_filter_mode == VF_TX_FILTER_AUTO && vf_max_tx_channels <= 2)
+ vf->tx_filter_mode = VF_TX_FILTER_ON;
+
+ vlan = ntohs(vf->addr.tci) & VLAN_VID_MASK;
+ efx_filter_init_tx(&filter, abs_index(vf, 0));
+ rc = efx_filter_set_eth_local(&filter,
+ vlan ? vlan : EFX_FILTER_VID_UNSPEC,
+ vf->addr.mac_addr);
+ BUG_ON(rc);
+
+ rc = efx_filter_insert_filter(efx, &filter, true);
+ if (rc < 0) {
+ netif_warn(efx, hw, efx->net_dev,
+ "Unable to migrate tx filter for vf %s\n",
+ vf->pci_name);
+ } else {
+ netif_dbg(efx, hw, efx->net_dev, "Inserted vf %s tx filter %d\n",
+ vf->pci_name, rc);
+ vf->tx_filter_id = rc;
+ }
+}
+
+/* The RX filter is managed here on behalf of the VF driver */
+static void efx_sriov_reset_rx_filter(struct efx_vf *vf)
+{
+ struct efx_nic *efx = vf->efx;
+ struct efx_filter_spec filter;
+ u16 vlan;
+ int rc;
+
+ if (vf->rx_filter_id != -1) {
+ efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
+ vf->rx_filter_id);
+ netif_dbg(efx, hw, efx->net_dev, "Removed vf %s rx filter %d\n",
+ vf->pci_name, vf->rx_filter_id);
+ vf->rx_filter_id = -1;
+ }
+
+ if (!vf->rx_filtering || is_zero_ether_addr(vf->addr.mac_addr))
+ return;
+
+ vlan = ntohs(vf->addr.tci) & VLAN_VID_MASK;
+ efx_filter_init_rx(&filter, EFX_FILTER_PRI_REQUIRED,
+ vf->rx_filter_flags,
+ abs_index(vf, vf->rx_filter_qid));
+ rc = efx_filter_set_eth_local(&filter,
+ vlan ? vlan : EFX_FILTER_VID_UNSPEC,
+ vf->addr.mac_addr);
+ BUG_ON(rc);
+
+ rc = efx_filter_insert_filter(efx, &filter, true);
+ if (rc < 0) {
+ netif_warn(efx, hw, efx->net_dev,
+ "Unable to insert rx filter for vf %s\n",
+ vf->pci_name);
+ } else {
+ netif_dbg(efx, hw, efx->net_dev, "Inserted vf %s rx filter %d\n",
+ vf->pci_name, rc);
+ vf->rx_filter_id = rc;
+ }
+}
+
+static void __efx_sriov_update_vf_addr(struct efx_vf *vf)
+{
+ efx_sriov_reset_tx_filter(vf);
+ efx_sriov_reset_rx_filter(vf);
+ queue_work(vfdi_workqueue, &vf->efx->peer_work);
+}
+
+/* Push the peer list to this VF. The caller must hold status_lock to interlock
+ * with VFDI requests, and they must be serialised against manipulation of
+ * local_page_list, either by acquiring local_lock or by running from
+ * efx_sriov_peer_work()
+ */
+static void __efx_sriov_push_vf_status(struct efx_vf *vf)
+{
+ struct efx_nic *efx = vf->efx;
+ struct vfdi_status *status = efx->vfdi_status.addr;
+ struct efx_memcpy_req copy[4];
+ struct efx_endpoint_page *epp;
+ unsigned int pos, count;
+ unsigned data_offset;
+ efx_qword_t event;
+
+ WARN_ON(!mutex_is_locked(&vf->status_lock));
+ WARN_ON(!vf->status_addr);
+
+ status->local = vf->addr;
+ status->generation_end = ++status->generation_start;
+
+ memset(copy, '\0', sizeof(copy));
+ /* Write generation_start */
+ copy[0].from_buf = &status->generation_start;
+ copy[0].to_rid = vf->pci_rid;
+ copy[0].to_addr = vf->status_addr + offsetof(struct vfdi_status,
+ generation_start);
+ copy[0].length = sizeof(status->generation_start);
+ /* DMA the rest of the structure (excluding the generations). This
+ * assumes that the non-generation portion of vfdi_status is in
+ * one chunk starting at the version member.
+ */
+ data_offset = offsetof(struct vfdi_status, version);
+ copy[1].from_rid = efx->pci_dev->devfn;
+ copy[1].from_addr = efx->vfdi_status.dma_addr + data_offset;
+ copy[1].to_rid = vf->pci_rid;
+ copy[1].to_addr = vf->status_addr + data_offset;
+ copy[1].length = status->length - data_offset;
+
+ /* Copy the peer pages */
+ pos = 2;
+ count = 0;
+ list_for_each_entry(epp, &efx->local_page_list, link) {
+ if (count == vf->peer_page_count) {
+ /* The VF driver will know they need to provide more
+ * pages because peer_addr_count is too large.
+ */
+ break;
+ }
+ copy[pos].from_buf = NULL;
+ copy[pos].from_rid = efx->pci_dev->devfn;
+ copy[pos].from_addr = epp->addr;
+ copy[pos].to_rid = vf->pci_rid;
+ copy[pos].to_addr = vf->peer_page_addrs[count];
+ copy[pos].length = EFX_PAGE_SIZE;
+
+ if (++pos == ARRAY_SIZE(copy)) {
+ efx_sriov_memcpy(efx, copy, ARRAY_SIZE(copy));
+ pos = 0;
+ }
+ ++count;
+ }
+
+ /* Write generation_end */
+ copy[pos].from_buf = &status->generation_end;
+ copy[pos].to_rid = vf->pci_rid;
+ copy[pos].to_addr = vf->status_addr + offsetof(struct vfdi_status,
+ generation_end);
+ copy[pos].length = sizeof(status->generation_end);
+ efx_sriov_memcpy(efx, copy, pos + 1);
+
+ /* Notify the guest */
+ EFX_POPULATE_QWORD_3(event,
+ FSF_AZ_EV_CODE, FSE_CZ_EV_CODE_USER_EV,
+ VFDI_EV_SEQ, (vf->msg_seqno & 0xff),
+ VFDI_EV_TYPE, VFDI_EV_TYPE_STATUS);
+ ++vf->msg_seqno;
+ efx_generate_event(efx, EFX_VI_BASE + vf->index * efx_vf_size(efx),
+ &event);
+}
+
+static void efx_sriov_bufs(struct efx_nic *efx, unsigned offset,
+ u64 *addr, unsigned count)
+{
+ efx_qword_t buf;
+ unsigned pos;
+
+ for (pos = 0; pos < count; ++pos) {
+ EFX_POPULATE_QWORD_3(buf,
+ FRF_AZ_BUF_ADR_REGION, 0,
+ FRF_AZ_BUF_ADR_FBUF,
+ addr ? addr[pos] >> 12 : 0,
+ FRF_AZ_BUF_OWNER_ID_FBUF, 0);
+ efx_sram_writeq(efx, efx->membase + FR_BZ_BUF_FULL_TBL,
+ &buf, offset + pos);
+ }
+}
+
+static bool bad_vf_index(struct efx_nic *efx, unsigned index)
+{
+ return index >= efx_vf_size(efx);
+}
+
+static bool bad_buf_count(unsigned buf_count, unsigned max_entry_count)
+{
+ unsigned max_buf_count = max_entry_count *
+ sizeof(efx_qword_t) / EFX_BUF_SIZE;
+
+ return ((buf_count & (buf_count - 1)) || buf_count > max_buf_count);
+}
+
+/* Check that VI specified by per-port index belongs to a VF.
+ * Optionally set VF index and VI index within the VF.
+ */
+static bool map_vi_index(struct efx_nic *efx, unsigned abs_index,
+ struct efx_vf **vf_out, unsigned *rel_index_out)
+{
+ unsigned vf_i;
+
+ if (abs_index < EFX_VI_BASE)
+ return true;
+ vf_i = (abs_index - EFX_VI_BASE) * efx_vf_size(efx);
+ if (vf_i >= efx->vf_init_count)
+ return true;
+
+ if (vf_out)
+ *vf_out = efx->vf + vf_i;
+ if (rel_index_out)
+ *rel_index_out = abs_index % efx_vf_size(efx);
+ return false;
+}
+
+static int efx_vfdi_init_evq(struct efx_vf *vf)
+{
+ struct efx_nic *efx = vf->efx;
+ struct vfdi_req *req = vf->buf.addr;
+ unsigned vf_evq = req->u.init_evq.index;
+ unsigned buf_count = req->u.init_evq.buf_count;
+ unsigned abs_evq = abs_index(vf, vf_evq);
+ unsigned buftbl = EFX_BUFTBL_EVQ_BASE(vf, vf_evq);
+ efx_oword_t reg;
+
+ if (bad_vf_index(efx, vf_evq) ||
+ bad_buf_count(buf_count, EFX_MAX_VF_EVQ_SIZE)) {
+ if (net_ratelimit())
+ netif_err(efx, hw, efx->net_dev,
+ "ERROR: Invalid INIT_EVQ from %s: evq %d bufs %d\n",
+ vf->pci_name, vf_evq, buf_count);
+ return VFDI_RC_EINVAL;
+ }
+
+ efx_sriov_bufs(efx, buftbl, req->u.init_evq.addr, buf_count);
+
+ EFX_POPULATE_OWORD_3(reg,
+ FRF_CZ_TIMER_Q_EN, 1,
+ FRF_CZ_HOST_NOTIFY_MODE, 0,
+ FRF_CZ_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS);
+ efx_writeo_table(efx, &reg, FR_BZ_TIMER_TBL, abs_evq);
+ EFX_POPULATE_OWORD_3(reg,
+ FRF_AZ_EVQ_EN, 1,
+ FRF_AZ_EVQ_SIZE, __ffs(buf_count),
+ FRF_AZ_EVQ_BUF_BASE_ID, buftbl);
+ efx_writeo_table(efx, &reg, FR_BZ_EVQ_PTR_TBL, abs_evq);
+
+ if (vf_evq == 0) {
+ memcpy(vf->evq0_addrs, req->u.init_evq.addr,
+ buf_count * sizeof(u64));
+ vf->evq0_count = buf_count;
+ }
+
+ return VFDI_RC_SUCCESS;
+}
+
+static int efx_vfdi_init_rxq(struct efx_vf *vf)
+{
+ struct efx_nic *efx = vf->efx;
+ struct vfdi_req *req = vf->buf.addr;
+ unsigned vf_rxq = req->u.init_rxq.index;
+ unsigned vf_evq = req->u.init_rxq.evq;
+ unsigned buf_count = req->u.init_rxq.buf_count;
+ unsigned buftbl = EFX_BUFTBL_RXQ_BASE(vf, vf_rxq);
+ unsigned label;
+ efx_oword_t reg;
+
+ if (bad_vf_index(efx, vf_evq) || bad_vf_index(efx, vf_rxq) ||
+ bad_buf_count(buf_count, EFX_MAX_DMAQ_SIZE)) {
+ if (net_ratelimit())
+ netif_err(efx, hw, efx->net_dev,
+ "ERROR: Invalid INIT_RXQ from %s: rxq %d evq %d "
+ "buf_count %d\n", vf->pci_name, vf_rxq,
+ vf_evq, buf_count);
+ return VFDI_RC_EINVAL;
+ }
+ if (__test_and_set_bit(req->u.init_rxq.index, vf->rxq_mask))
+ ++vf->rxq_count;
+ efx_sriov_bufs(efx, buftbl, req->u.init_rxq.addr, buf_count);
+
+ label = req->u.init_rxq.label & EFX_FIELD_MASK(FRF_AZ_RX_DESCQ_LABEL);
+ EFX_POPULATE_OWORD_6(reg,
+ FRF_AZ_RX_DESCQ_BUF_BASE_ID, buftbl,
+ FRF_AZ_RX_DESCQ_EVQ_ID, abs_index(vf, vf_evq),
+ FRF_AZ_RX_DESCQ_LABEL, label,
+ FRF_AZ_RX_DESCQ_SIZE, __ffs(buf_count),
+ FRF_AZ_RX_DESCQ_JUMBO,
+ !!(req->u.init_rxq.flags &
+ VFDI_RXQ_FLAG_SCATTER_EN),
+ FRF_AZ_RX_DESCQ_EN, 1);
+ efx_writeo_table(efx, &reg, FR_BZ_RX_DESC_PTR_TBL,
+ abs_index(vf, vf_rxq));
+
+ return VFDI_RC_SUCCESS;
+}
+
+static int efx_vfdi_init_txq(struct efx_vf *vf)
+{
+ struct efx_nic *efx = vf->efx;
+ struct vfdi_req *req = vf->buf.addr;
+ unsigned vf_txq = req->u.init_txq.index;
+ unsigned vf_evq = req->u.init_txq.evq;
+ unsigned buf_count = req->u.init_txq.buf_count;
+ unsigned buftbl = EFX_BUFTBL_TXQ_BASE(vf, vf_txq);
+ unsigned label, eth_filt_en;
+ efx_oword_t reg;
+
+ if (bad_vf_index(efx, vf_evq) || bad_vf_index(efx, vf_txq) ||
+ vf_txq >= vf_max_tx_channels ||
+ bad_buf_count(buf_count, EFX_MAX_DMAQ_SIZE)) {
+ if (net_ratelimit())
+ netif_err(efx, hw, efx->net_dev,
+ "ERROR: Invalid INIT_TXQ from %s: txq %d evq %d "
+ "buf_count %d\n", vf->pci_name, vf_txq,
+ vf_evq, buf_count);
+ return VFDI_RC_EINVAL;
+ }
+
+ mutex_lock(&vf->txq_lock);
+ if (__test_and_set_bit(req->u.init_txq.index, vf->txq_mask))
+ ++vf->txq_count;
+ mutex_unlock(&vf->txq_lock);
+ efx_sriov_bufs(efx, buftbl, req->u.init_txq.addr, buf_count);
+
+ eth_filt_en = vf->tx_filter_mode == VF_TX_FILTER_ON;
+
+ label = req->u.init_txq.label & EFX_FIELD_MASK(FRF_AZ_TX_DESCQ_LABEL);
+ EFX_POPULATE_OWORD_8(reg,
+ FRF_CZ_TX_DPT_Q_MASK_WIDTH, min(efx->vi_scale, 1U),
+ FRF_CZ_TX_DPT_ETH_FILT_EN, eth_filt_en,
+ FRF_AZ_TX_DESCQ_EN, 1,
+ FRF_AZ_TX_DESCQ_BUF_BASE_ID, buftbl,
+ FRF_AZ_TX_DESCQ_EVQ_ID, abs_index(vf, vf_evq),
+ FRF_AZ_TX_DESCQ_LABEL, label,
+ FRF_AZ_TX_DESCQ_SIZE, __ffs(buf_count),
+ FRF_BZ_TX_NON_IP_DROP_DIS, 1);
+ efx_writeo_table(efx, &reg, FR_BZ_TX_DESC_PTR_TBL,
+ abs_index(vf, vf_txq));
+
+ return VFDI_RC_SUCCESS;
+}
+
+/* Returns true when efx_vfdi_fini_all_queues should wake */
+static bool efx_vfdi_flush_wake(struct efx_vf *vf)
+{
+ /* Ensure that all updates are visible to efx_vfdi_fini_all_queues() */
+ smp_mb();
+
+ return (!vf->txq_count && !vf->rxq_count) ||
+ atomic_read(&vf->rxq_retry_count);
+}
+
+static void efx_vfdi_flush_clear(struct efx_vf *vf)
+{
+ memset(vf->txq_mask, 0, sizeof(vf->txq_mask));
+ vf->txq_count = 0;
+ memset(vf->rxq_mask, 0, sizeof(vf->rxq_mask));
+ vf->rxq_count = 0;
+ memset(vf->rxq_retry_mask, 0, sizeof(vf->rxq_retry_mask));
+ atomic_set(&vf->rxq_retry_count, 0);
+}
+
+static int efx_vfdi_fini_all_queues(struct efx_vf *vf)
+{
+ struct efx_nic *efx = vf->efx;
+ efx_oword_t reg;
+ unsigned count = efx_vf_size(efx);
+ unsigned vf_offset = EFX_VI_BASE + vf->index * efx_vf_size(efx);
+ unsigned timeout = HZ;
+ unsigned index, rxqs_count;
+ __le32 *rxqs;
+ int rc;
+
+ rxqs = kmalloc(count * sizeof(*rxqs), GFP_KERNEL);
+ if (rxqs == NULL)
+ return VFDI_RC_ENOMEM;
+
+ rtnl_lock();
+ if (efx->fc_disable++ == 0)
+ efx_mcdi_set_mac(efx);
+ rtnl_unlock();
+
+ /* Flush all the initialized queues */
+ rxqs_count = 0;
+ for (index = 0; index < count; ++index) {
+ if (test_bit(index, vf->txq_mask)) {
+ EFX_POPULATE_OWORD_2(reg,
+ FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
+ FRF_AZ_TX_FLUSH_DESCQ,
+ vf_offset + index);
+ efx_writeo(efx, &reg, FR_AZ_TX_FLUSH_DESCQ);
+ }
+ if (test_bit(index, vf->rxq_mask))
+ rxqs[rxqs_count++] = cpu_to_le32(vf_offset + index);
+ }
+
+ atomic_set(&vf->rxq_retry_count, 0);
+ while (timeout && (vf->rxq_count || vf->txq_count)) {
+ rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, (u8 *)rxqs,
+ rxqs_count * sizeof(*rxqs), NULL, 0, NULL);
+ WARN_ON(rc < 0);
+
+ timeout = wait_event_timeout(vf->flush_waitq,
+ efx_vfdi_flush_wake(vf),
+ timeout);
+ rxqs_count = 0;
+ for (index = 0; index < count; ++index) {
+ if (test_and_clear_bit(index, vf->rxq_retry_mask)) {
+ atomic_dec(&vf->rxq_retry_count);
+ rxqs[rxqs_count++] =
+ cpu_to_le32(vf_offset + index);
+ }
+ }
+ }
+
+ rtnl_lock();
+ if (--efx->fc_disable == 0)
+ efx_mcdi_set_mac(efx);
+ rtnl_unlock();
+
+ /* Irrespective of success/failure, fini the queues */
+ EFX_ZERO_OWORD(reg);
+ for (index = 0; index < count; ++index) {
+ efx_writeo_table(efx, &reg, FR_BZ_RX_DESC_PTR_TBL,
+ vf_offset + index);
+ efx_writeo_table(efx, &reg, FR_BZ_TX_DESC_PTR_TBL,
+ vf_offset + index);
+ efx_writeo_table(efx, &reg, FR_BZ_EVQ_PTR_TBL,
+ vf_offset + index);
+ efx_writeo_table(efx, &reg, FR_BZ_TIMER_TBL,
+ vf_offset + index);
+ }
+ efx_sriov_bufs(efx, vf->buftbl_base, NULL,
+ EFX_VF_BUFTBL_PER_VI * efx_vf_size(efx));
+ kfree(rxqs);
+ efx_vfdi_flush_clear(vf);
+
+ vf->evq0_count = 0;
+
+ return timeout ? 0 : VFDI_RC_ETIMEDOUT;
+}
+
+static int efx_vfdi_insert_filter(struct efx_vf *vf)
+{
+ struct efx_nic *efx = vf->efx;
+ struct vfdi_req *req = vf->buf.addr;
+ unsigned vf_rxq = req->u.mac_filter.rxq;
+ unsigned flags;
+
+ if (bad_vf_index(efx, vf_rxq) || vf->rx_filtering) {
+ if (net_ratelimit())
+ netif_err(efx, hw, efx->net_dev,
+ "ERROR: Invalid INSERT_FILTER from %s: rxq %d "
+ "flags 0x%x\n", vf->pci_name, vf_rxq,
+ req->u.mac_filter.flags);
+ return VFDI_RC_EINVAL;
+ }
+
+ flags = 0;
+ if (req->u.mac_filter.flags & VFDI_MAC_FILTER_FLAG_RSS)
+ flags |= EFX_FILTER_FLAG_RX_RSS;
+ if (req->u.mac_filter.flags & VFDI_MAC_FILTER_FLAG_SCATTER)
+ flags |= EFX_FILTER_FLAG_RX_SCATTER;
+ vf->rx_filter_flags = flags;
+ vf->rx_filter_qid = vf_rxq;
+ vf->rx_filtering = true;
+
+ efx_sriov_reset_rx_filter(vf);
+ queue_work(vfdi_workqueue, &efx->peer_work);
+
+ return VFDI_RC_SUCCESS;
+}
+
+static int efx_vfdi_remove_all_filters(struct efx_vf *vf)
+{
+ vf->rx_filtering = false;
+ efx_sriov_reset_rx_filter(vf);
+ queue_work(vfdi_workqueue, &vf->efx->peer_work);
+
+ return VFDI_RC_SUCCESS;
+}
+
+static int efx_vfdi_set_status_page(struct efx_vf *vf)
+{
+ struct efx_nic *efx = vf->efx;
+ struct vfdi_req *req = vf->buf.addr;
+ u64 page_count = req->u.set_status_page.peer_page_count;
+ u64 max_page_count =
+ (EFX_PAGE_SIZE -
+ offsetof(struct vfdi_req, u.set_status_page.peer_page_addr[0]))
+ / sizeof(req->u.set_status_page.peer_page_addr[0]);
+
+ if (!req->u.set_status_page.dma_addr || page_count > max_page_count) {
+ if (net_ratelimit())
+ netif_err(efx, hw, efx->net_dev,
+ "ERROR: Invalid SET_STATUS_PAGE from %s\n",
+ vf->pci_name);
+ return VFDI_RC_EINVAL;
+ }
+
+ mutex_lock(&efx->local_lock);
+ mutex_lock(&vf->status_lock);
+ vf->status_addr = req->u.set_status_page.dma_addr;
+
+ kfree(vf->peer_page_addrs);
+ vf->peer_page_addrs = NULL;
+ vf->peer_page_count = 0;
+
+ if (page_count) {
+ vf->peer_page_addrs = kcalloc(page_count, sizeof(u64),
+ GFP_KERNEL);
+ if (vf->peer_page_addrs) {
+ memcpy(vf->peer_page_addrs,
+ req->u.set_status_page.peer_page_addr,
+ page_count * sizeof(u64));
+ vf->peer_page_count = page_count;
+ }
+ }
+
+ __efx_sriov_push_vf_status(vf);
+ mutex_unlock(&vf->status_lock);
+ mutex_unlock(&efx->local_lock);
+
+ return VFDI_RC_SUCCESS;
+}
+
+static int efx_vfdi_clear_status_page(struct efx_vf *vf)
+{
+ mutex_lock(&vf->status_lock);
+ vf->status_addr = 0;
+ mutex_unlock(&vf->status_lock);
+
+ return VFDI_RC_SUCCESS;
+}
+
+typedef int (*efx_vfdi_op_t)(struct efx_vf *vf);
+
+static const efx_vfdi_op_t vfdi_ops[VFDI_OP_LIMIT] = {
+ [VFDI_OP_INIT_EVQ] = efx_vfdi_init_evq,
+ [VFDI_OP_INIT_TXQ] = efx_vfdi_init_txq,
+ [VFDI_OP_INIT_RXQ] = efx_vfdi_init_rxq,
+ [VFDI_OP_FINI_ALL_QUEUES] = efx_vfdi_fini_all_queues,
+ [VFDI_OP_INSERT_FILTER] = efx_vfdi_insert_filter,
+ [VFDI_OP_REMOVE_ALL_FILTERS] = efx_vfdi_remove_all_filters,
+ [VFDI_OP_SET_STATUS_PAGE] = efx_vfdi_set_status_page,
+ [VFDI_OP_CLEAR_STATUS_PAGE] = efx_vfdi_clear_status_page,
+};
+
+static void efx_sriov_vfdi(struct work_struct *work)
+{
+ struct efx_vf *vf = container_of(work, struct efx_vf, req);
+ struct efx_nic *efx = vf->efx;
+ struct vfdi_req *req = vf->buf.addr;
+ struct efx_memcpy_req copy[2];
+ int rc;
+
+ /* Copy this page into the local address space */
+ memset(copy, '\0', sizeof(copy));
+ copy[0].from_rid = vf->pci_rid;
+ copy[0].from_addr = vf->req_addr;
+ copy[0].to_rid = efx->pci_dev->devfn;
+ copy[0].to_addr = vf->buf.dma_addr;
+ copy[0].length = EFX_PAGE_SIZE;
+ rc = efx_sriov_memcpy(efx, copy, 1);
+ if (rc) {
+ /* If we can't get the request, we can't reply to the caller */
+ if (net_ratelimit())
+ netif_err(efx, hw, efx->net_dev,
+ "ERROR: Unable to fetch VFDI request from %s rc %d\n",
+ vf->pci_name, -rc);
+ vf->busy = false;
+ return;
+ }
+
+ if (req->op < VFDI_OP_LIMIT && vfdi_ops[req->op] != NULL) {
+ rc = vfdi_ops[req->op](vf);
+ if (rc == 0) {
+ netif_dbg(efx, hw, efx->net_dev,
+ "vfdi request %d from %s ok\n",
+ req->op, vf->pci_name);
+ }
+ } else {
+ netif_dbg(efx, hw, efx->net_dev,
+ "ERROR: Unrecognised request %d from VF %s addr "
+ "%llx\n", req->op, vf->pci_name,
+ (unsigned long long)vf->req_addr);
+ rc = VFDI_RC_EOPNOTSUPP;
+ }
+
+ /* Allow subsequent VF requests */
+ vf->busy = false;
+ smp_wmb();
+
+ /* Respond to the request */
+ req->rc = rc;
+ req->op = VFDI_OP_RESPONSE;
+
+ memset(copy, '\0', sizeof(copy));
+ copy[0].from_buf = &req->rc;
+ copy[0].to_rid = vf->pci_rid;
+ copy[0].to_addr = vf->req_addr + offsetof(struct vfdi_req, rc);
+ copy[0].length = sizeof(req->rc);
+ copy[1].from_buf = &req->op;
+ copy[1].to_rid = vf->pci_rid;
+ copy[1].to_addr = vf->req_addr + offsetof(struct vfdi_req, op);
+ copy[1].length = sizeof(req->op);
+
+ (void) efx_sriov_memcpy(efx, copy, ARRAY_SIZE(copy));
+}
+
+
+
+/* After a reset the event queues inside the guests no longer exist. Fill the
+ * event ring in guest memory with VFDI reset events, then (re-initialise) the
+ * event queue to raise an interrupt. The guest driver will then recover.
+ */
+static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer)
+{
+ struct efx_nic *efx = vf->efx;
+ struct efx_memcpy_req copy_req[4];
+ efx_qword_t event;
+ unsigned int pos, count, k, buftbl, abs_evq;
+ efx_oword_t reg;
+ efx_dword_t ptr;
+ int rc;
+
+ BUG_ON(buffer->len != EFX_PAGE_SIZE);
+
+ if (!vf->evq0_count)
+ return;
+ BUG_ON(vf->evq0_count & (vf->evq0_count - 1));
+
+ mutex_lock(&vf->status_lock);
+ EFX_POPULATE_QWORD_3(event,
+ FSF_AZ_EV_CODE, FSE_CZ_EV_CODE_USER_EV,
+ VFDI_EV_SEQ, vf->msg_seqno,
+ VFDI_EV_TYPE, VFDI_EV_TYPE_RESET);
+ vf->msg_seqno++;
+ for (pos = 0; pos < EFX_PAGE_SIZE; pos += sizeof(event))
+ memcpy(buffer->addr + pos, &event, sizeof(event));
+
+ for (pos = 0; pos < vf->evq0_count; pos += count) {
+ count = min_t(unsigned, vf->evq0_count - pos,
+ ARRAY_SIZE(copy_req));
+ for (k = 0; k < count; k++) {
+ copy_req[k].from_buf = NULL;
+ copy_req[k].from_rid = efx->pci_dev->devfn;
+ copy_req[k].from_addr = buffer->dma_addr;
+ copy_req[k].to_rid = vf->pci_rid;
+ copy_req[k].to_addr = vf->evq0_addrs[pos + k];
+ copy_req[k].length = EFX_PAGE_SIZE;
+ }
+ rc = efx_sriov_memcpy(efx, copy_req, count);
+ if (rc) {
+ if (net_ratelimit())
+ netif_err(efx, hw, efx->net_dev,
+ "ERROR: Unable to notify %s of reset"
+ ": %d\n", vf->pci_name, -rc);
+ break;
+ }
+ }
+
+ /* Reinitialise, arm and trigger evq0 */
+ abs_evq = abs_index(vf, 0);
+ buftbl = EFX_BUFTBL_EVQ_BASE(vf, 0);
+ efx_sriov_bufs(efx, buftbl, vf->evq0_addrs, vf->evq0_count);
+
+ EFX_POPULATE_OWORD_3(reg,
+ FRF_CZ_TIMER_Q_EN, 1,
+ FRF_CZ_HOST_NOTIFY_MODE, 0,
+ FRF_CZ_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS);
+ efx_writeo_table(efx, &reg, FR_BZ_TIMER_TBL, abs_evq);
+ EFX_POPULATE_OWORD_3(reg,
+ FRF_AZ_EVQ_EN, 1,
+ FRF_AZ_EVQ_SIZE, __ffs(vf->evq0_count),
+ FRF_AZ_EVQ_BUF_BASE_ID, buftbl);
+ efx_writeo_table(efx, &reg, 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);
+
+ mutex_unlock(&vf->status_lock);
+}
+
+static void efx_sriov_reset_vf_work(struct work_struct *work)
+{
+ struct efx_vf *vf = container_of(work, struct efx_vf, req);
+ struct efx_nic *efx = vf->efx;
+ struct efx_buffer buf;
+
+ if (!efx_nic_alloc_buffer(efx, &buf, EFX_PAGE_SIZE)) {
+ efx_sriov_reset_vf(vf, &buf);
+ efx_nic_free_buffer(efx, &buf);
+ }
+}
+
+static void efx_sriov_handle_no_channel(struct efx_nic *efx)
+{
+ netif_err(efx, drv, efx->net_dev,
+ "ERROR: IOV requires MSI-X and 1 additional interrupt"
+ "vector. IOV disabled\n");
+ efx->vf_count = 0;
+}
+
+static int efx_sriov_probe_channel(struct efx_channel *channel)
+{
+ channel->efx->vfdi_channel = channel;
+ return 0;
+}
+
+static void
+efx_sriov_get_channel_name(struct efx_channel *channel, char *buf, size_t len)
+{
+ snprintf(buf, len, "%s-iov", channel->efx->name);
+}
+
+static const struct efx_channel_type efx_sriov_channel_type = {
+ .handle_no_channel = efx_sriov_handle_no_channel,
+ .pre_probe = efx_sriov_probe_channel,
+ .get_name = efx_sriov_get_channel_name,
+ /* no copy operation; channel must not be reallocated */
+ .keep_eventq = true,
+};
+
+void efx_sriov_probe(struct efx_nic *efx)
+{
+ unsigned count;
+
+ if (!max_vfs)
+ return;
+
+ if (efx_sriov_cmd(efx, false, &efx->vi_scale, &count))
+ return;
+ if (count > 0 && count > max_vfs)
+ count = max_vfs;
+
+ /* efx_nic_dimension_resources() will reduce vf_count as appopriate */
+ efx->vf_count = count;
+
+ efx->extra_channel_type[EFX_EXTRA_CHANNEL_IOV] = &efx_sriov_channel_type;
+}
+
+/* Copy the list of individual addresses into the vfdi_status.peers
+ * array and auxillary pages, protected by %local_lock. Drop that lock
+ * and then broadcast the address list to every VF.
+ */
+static void efx_sriov_peer_work(struct work_struct *data)
+{
+ struct efx_nic *efx = container_of(data, struct efx_nic, peer_work);
+ struct vfdi_status *vfdi_status = efx->vfdi_status.addr;
+ struct efx_vf *vf;
+ struct efx_local_addr *local_addr;
+ struct vfdi_endpoint *peer;
+ struct efx_endpoint_page *epp;
+ struct list_head pages;
+ unsigned int peer_space;
+ unsigned int peer_count;
+ unsigned int pos;
+
+ mutex_lock(&efx->local_lock);
+
+ /* Move the existing peer pages off %local_page_list */
+ INIT_LIST_HEAD(&pages);
+ list_splice_tail_init(&efx->local_page_list, &pages);
+
+ /* Populate the VF addresses starting from entry 1 (entry 0 is
+ * the PF address)
+ */
+ peer = vfdi_status->peers + 1;
+ peer_space = ARRAY_SIZE(vfdi_status->peers) - 1;
+ peer_count = 1;
+ for (pos = 0; pos < efx->vf_count; ++pos) {
+ vf = efx->vf + pos;
+
+ mutex_lock(&vf->status_lock);
+ if (vf->rx_filtering && !is_zero_ether_addr(vf->addr.mac_addr)) {
+ *peer++ = vf->addr;
+ ++peer_count;
+ --peer_space;
+ BUG_ON(peer_space == 0);
+ }
+ mutex_unlock(&vf->status_lock);
+ }
+
+ /* Fill the remaining addresses */
+ list_for_each_entry(local_addr, &efx->local_addr_list, link) {
+ memcpy(peer->mac_addr, local_addr->addr, ETH_ALEN);
+ peer->tci = 0;
+ ++peer;
+ ++peer_count;
+ if (--peer_space == 0) {
+ if (list_empty(&pages)) {
+ epp = kmalloc(sizeof(*epp), GFP_KERNEL);
+ if (!epp)
+ break;
+ epp->ptr = dma_alloc_coherent(
+ &efx->pci_dev->dev, EFX_PAGE_SIZE,
+ &epp->addr, GFP_KERNEL);
+ if (!epp->ptr) {
+ kfree(epp);
+ break;
+ }
+ } else {
+ epp = list_first_entry(
+ &pages, struct efx_endpoint_page, link);
+ list_del(&epp->link);
+ }
+
+ list_add_tail(&epp->link, &efx->local_page_list);
+ peer = (struct vfdi_endpoint *)epp->ptr;
+ peer_space = EFX_PAGE_SIZE / sizeof(struct vfdi_endpoint);
+ }
+ }
+ vfdi_status->peer_count = peer_count;
+ mutex_unlock(&efx->local_lock);
+
+ /* Free any now unused endpoint pages */
+ while (!list_empty(&pages)) {
+ epp = list_first_entry(
+ &pages, struct efx_endpoint_page, link);
+ list_del(&epp->link);
+ dma_free_coherent(&efx->pci_dev->dev, EFX_PAGE_SIZE,
+ epp->ptr, epp->addr);
+ kfree(epp);
+ }
+
+ /* Finally, push the pages */
+ for (pos = 0; pos < efx->vf_count; ++pos) {
+ vf = efx->vf + pos;
+
+ mutex_lock(&vf->status_lock);
+ if (vf->status_addr)
+ __efx_sriov_push_vf_status(vf);
+ mutex_unlock(&vf->status_lock);
+ }
+}
+
+static void efx_sriov_free_local(struct efx_nic *efx)
+{
+ struct efx_local_addr *local_addr;
+ struct efx_endpoint_page *epp;
+
+ while (!list_empty(&efx->local_addr_list)) {
+ local_addr = list_first_entry(&efx->local_addr_list,
+ struct efx_local_addr, link);
+ list_del(&local_addr->link);
+ kfree(local_addr);
+ }
+
+ while (!list_empty(&efx->local_page_list)) {
+ epp = list_first_entry(&efx->local_page_list,
+ struct efx_endpoint_page, link);
+ list_del(&epp->link);
+ dma_free_coherent(&efx->pci_dev->dev, EFX_PAGE_SIZE,
+ epp->ptr, epp->addr);
+ kfree(epp);
+ }
+}
+
+static int efx_sriov_vf_alloc(struct efx_nic *efx)
+{
+ unsigned index;
+ struct efx_vf *vf;
+
+ efx->vf = kzalloc(sizeof(struct efx_vf) * efx->vf_count, GFP_KERNEL);
+ if (!efx->vf)
+ return -ENOMEM;
+
+ for (index = 0; index < efx->vf_count; ++index) {
+ vf = efx->vf + index;
+
+ vf->efx = efx;
+ vf->index = index;
+ vf->rx_filter_id = -1;
+ vf->tx_filter_mode = VF_TX_FILTER_AUTO;
+ vf->tx_filter_id = -1;
+ INIT_WORK(&vf->req, efx_sriov_vfdi);
+ INIT_WORK(&vf->reset_work, efx_sriov_reset_vf_work);
+ init_waitqueue_head(&vf->flush_waitq);
+ mutex_init(&vf->status_lock);
+ mutex_init(&vf->txq_lock);
+ }
+
+ return 0;
+}
+
+static void efx_sriov_vfs_fini(struct efx_nic *efx)
+{
+ struct efx_vf *vf;
+ unsigned int pos;
+
+ for (pos = 0; pos < efx->vf_count; ++pos) {
+ vf = efx->vf + pos;
+
+ efx_nic_free_buffer(efx, &vf->buf);
+ kfree(vf->peer_page_addrs);
+ vf->peer_page_addrs = NULL;
+ vf->peer_page_count = 0;
+
+ vf->evq0_count = 0;
+ }
+}
+
+static int efx_sriov_vfs_init(struct efx_nic *efx)
+{
+ struct pci_dev *pci_dev = efx->pci_dev;
+ unsigned index, devfn, sriov, buftbl_base;
+ u16 offset, stride;
+ struct efx_vf *vf;
+ int rc;
+
+ sriov = pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV);
+ if (!sriov)
+ return -ENOENT;
+
+ pci_read_config_word(pci_dev, sriov + PCI_SRIOV_VF_OFFSET, &offset);
+ pci_read_config_word(pci_dev, sriov + PCI_SRIOV_VF_STRIDE, &stride);
+
+ buftbl_base = efx->vf_buftbl_base;
+ devfn = pci_dev->devfn + offset;
+ for (index = 0; index < efx->vf_count; ++index) {
+ vf = efx->vf + index;
+
+ /* Reserve buffer entries */
+ vf->buftbl_base = buftbl_base;
+ buftbl_base += EFX_VF_BUFTBL_PER_VI * efx_vf_size(efx);
+
+ vf->pci_rid = devfn;
+ snprintf(vf->pci_name, sizeof(vf->pci_name),
+ "%04x:%02x:%02x.%d",
+ pci_domain_nr(pci_dev->bus), pci_dev->bus->number,
+ PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+ rc = efx_nic_alloc_buffer(efx, &vf->buf, EFX_PAGE_SIZE);
+ if (rc)
+ goto fail;
+
+ devfn += stride;
+ }
+
+ return 0;
+
+fail:
+ efx_sriov_vfs_fini(efx);
+ return rc;
+}
+
+int efx_sriov_init(struct efx_nic *efx)
+{
+ struct net_device *net_dev = efx->net_dev;
+ struct vfdi_status *vfdi_status;
+ int rc;
+
+ /* Ensure there's room for vf_channel */
+ BUILD_BUG_ON(EFX_MAX_CHANNELS + 1 >= EFX_VI_BASE);
+ /* Ensure that VI_BASE is aligned on VI_SCALE */
+ BUILD_BUG_ON(EFX_VI_BASE & ((1 << EFX_VI_SCALE_MAX) - 1));
+
+ if (efx->vf_count == 0)
+ return 0;
+
+ rc = efx_sriov_cmd(efx, true, NULL, NULL);
+ if (rc)
+ goto fail_cmd;
+
+ rc = efx_nic_alloc_buffer(efx, &efx->vfdi_status, sizeof(*vfdi_status));
+ if (rc)
+ goto fail_status;
+ vfdi_status = efx->vfdi_status.addr;
+ memset(vfdi_status, 0, sizeof(*vfdi_status));
+ vfdi_status->version = 1;
+ vfdi_status->length = sizeof(*vfdi_status);
+ vfdi_status->max_tx_channels = vf_max_tx_channels;
+ vfdi_status->vi_scale = efx->vi_scale;
+ vfdi_status->rss_rxq_count = efx->rss_spread;
+ vfdi_status->peer_count = 1 + efx->vf_count;
+ vfdi_status->timer_quantum_ns = efx->timer_quantum_ns;
+
+ rc = efx_sriov_vf_alloc(efx);
+ if (rc)
+ goto fail_alloc;
+
+ mutex_init(&efx->local_lock);
+ INIT_WORK(&efx->peer_work, efx_sriov_peer_work);
+ INIT_LIST_HEAD(&efx->local_addr_list);
+ INIT_LIST_HEAD(&efx->local_page_list);
+
+ rc = efx_sriov_vfs_init(efx);
+ if (rc)
+ goto fail_vfs;
+
+ rtnl_lock();
+ memcpy(vfdi_status->peers[0].mac_addr,
+ net_dev->dev_addr, ETH_ALEN);
+ efx->vf_init_count = efx->vf_count;
+ rtnl_unlock();
+
+ efx_sriov_usrev(efx, true);
+
+ /* At this point we must be ready to accept VFDI requests */
+
+ rc = pci_enable_sriov(efx->pci_dev, efx->vf_count);
+ if (rc)
+ goto fail_pci;
+
+ netif_info(efx, probe, net_dev,
+ "enabled SR-IOV for %d VFs, %d VI per VF\n",
+ efx->vf_count, efx_vf_size(efx));
+ return 0;
+
+fail_pci:
+ efx_sriov_usrev(efx, false);
+ rtnl_lock();
+ efx->vf_init_count = 0;
+ rtnl_unlock();
+ efx_sriov_vfs_fini(efx);
+fail_vfs:
+ cancel_work_sync(&efx->peer_work);
+ efx_sriov_free_local(efx);
+ kfree(efx->vf);
+fail_alloc:
+ efx_nic_free_buffer(efx, &efx->vfdi_status);
+fail_status:
+ efx_sriov_cmd(efx, false, NULL, NULL);
+fail_cmd:
+ return rc;
+}
+
+void efx_sriov_fini(struct efx_nic *efx)
+{
+ struct efx_vf *vf;
+ unsigned int pos;
+
+ if (efx->vf_init_count == 0)
+ return;
+
+ /* Disable all interfaces to reconfiguration */
+ BUG_ON(efx->vfdi_channel->enabled);
+ efx_sriov_usrev(efx, false);
+ rtnl_lock();
+ efx->vf_init_count = 0;
+ rtnl_unlock();
+
+ /* Flush all reconfiguration work */
+ for (pos = 0; pos < efx->vf_count; ++pos) {
+ vf = efx->vf + pos;
+ cancel_work_sync(&vf->req);
+ cancel_work_sync(&vf->reset_work);
+ }
+ cancel_work_sync(&efx->peer_work);
+
+ pci_disable_sriov(efx->pci_dev);
+
+ /* Tear down back-end state */
+ efx_sriov_vfs_fini(efx);
+ efx_sriov_free_local(efx);
+ kfree(efx->vf);
+ efx_nic_free_buffer(efx, &efx->vfdi_status);
+ efx_sriov_cmd(efx, false, NULL, NULL);
+}
+
+void efx_sriov_event(struct efx_channel *channel, efx_qword_t *event)
+{
+ struct efx_nic *efx = channel->efx;
+ struct efx_vf *vf;
+ unsigned qid, seq, type, data;
+
+ qid = EFX_QWORD_FIELD(*event, FSF_CZ_USER_QID);
+
+ /* USR_EV_REG_VALUE is dword0, so access the VFDI_EV fields directly */
+ BUILD_BUG_ON(FSF_CZ_USER_EV_REG_VALUE_LBN != 0);
+ seq = EFX_QWORD_FIELD(*event, VFDI_EV_SEQ);
+ type = EFX_QWORD_FIELD(*event, VFDI_EV_TYPE);
+ data = EFX_QWORD_FIELD(*event, VFDI_EV_DATA);
+
+ netif_vdbg(efx, hw, efx->net_dev,
+ "USR_EV event from qid %d seq 0x%x type %d data 0x%x\n",
+ qid, seq, type, data);
+
+ if (map_vi_index(efx, qid, &vf, NULL))
+ return;
+ if (vf->busy)
+ goto error;
+
+ if (type == VFDI_EV_TYPE_REQ_WORD0) {
+ /* Resynchronise */
+ vf->req_type = VFDI_EV_TYPE_REQ_WORD0;
+ vf->req_seqno = seq + 1;
+ vf->req_addr = 0;
+ } else if (seq != (vf->req_seqno++ & 0xff) || type != vf->req_type)
+ goto error;
+
+ switch (vf->req_type) {
+ case VFDI_EV_TYPE_REQ_WORD0:
+ case VFDI_EV_TYPE_REQ_WORD1:
+ case VFDI_EV_TYPE_REQ_WORD2:
+ vf->req_addr |= (u64)data << (vf->req_type << 4);
+ ++vf->req_type;
+ return;
+
+ case VFDI_EV_TYPE_REQ_WORD3:
+ vf->req_addr |= (u64)data << 48;
+ vf->req_type = VFDI_EV_TYPE_REQ_WORD0;
+ vf->busy = true;
+ queue_work(vfdi_workqueue, &vf->req);
+ return;
+ }
+
+error:
+ if (net_ratelimit())
+ netif_err(efx, hw, efx->net_dev,
+ "ERROR: Screaming VFDI request from %s\n",
+ vf->pci_name);
+ /* Reset the request and sequence number */
+ vf->req_type = VFDI_EV_TYPE_REQ_WORD0;
+ vf->req_seqno = seq + 1;
+}
+
+void efx_sriov_flr(struct efx_nic *efx, unsigned vf_i)
+{
+ struct efx_vf *vf;
+
+ if (vf_i > efx->vf_init_count)
+ return;
+ vf = efx->vf + vf_i;
+ netif_info(efx, hw, efx->net_dev,
+ "FLR on VF %s\n", vf->pci_name);
+
+ vf->status_addr = 0;
+ efx_vfdi_remove_all_filters(vf);
+ efx_vfdi_flush_clear(vf);
+
+ vf->evq0_count = 0;
+}
+
+void efx_sriov_mac_address_changed(struct efx_nic *efx)
+{
+ struct vfdi_status *vfdi_status = efx->vfdi_status.addr;
+
+ if (!efx->vf_init_count)
+ return;
+ memcpy(vfdi_status->peers[0].mac_addr,
+ efx->net_dev->dev_addr, ETH_ALEN);
+ queue_work(vfdi_workqueue, &efx->peer_work);
+}
+
+void efx_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event)
+{
+ struct efx_vf *vf;
+ unsigned queue, qid;
+
+ queue = EFX_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_SUBDATA);
+ if (map_vi_index(efx, queue, &vf, &qid))
+ return;
+ /* Ignore flush completions triggered by an FLR */
+ if (!test_bit(qid, vf->txq_mask))
+ return;
+
+ __clear_bit(qid, vf->txq_mask);
+ --vf->txq_count;
+
+ if (efx_vfdi_flush_wake(vf))
+ wake_up(&vf->flush_waitq);
+}
+
+void efx_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event)
+{
+ struct efx_vf *vf;
+ unsigned ev_failed, queue, qid;
+
+ queue = EFX_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_RX_DESCQ_ID);
+ ev_failed = EFX_QWORD_FIELD(*event,
+ FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
+ if (map_vi_index(efx, queue, &vf, &qid))
+ return;
+ if (!test_bit(qid, vf->rxq_mask))
+ return;
+
+ if (ev_failed) {
+ set_bit(qid, vf->rxq_retry_mask);
+ atomic_inc(&vf->rxq_retry_count);
+ } else {
+ __clear_bit(qid, vf->rxq_mask);
+ --vf->rxq_count;
+ }
+ if (efx_vfdi_flush_wake(vf))
+ wake_up(&vf->flush_waitq);
+}
+
+/* Called from napi. Schedule the reset work item */
+void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq)
+{
+ struct efx_vf *vf;
+ unsigned int rel;
+
+ if (map_vi_index(efx, dmaq, &vf, &rel))
+ return;
+
+ if (net_ratelimit())
+ netif_err(efx, hw, efx->net_dev,
+ "VF %d DMA Q %d reports descriptor fetch error.\n",
+ vf->index, rel);
+ queue_work(vfdi_workqueue, &vf->reset_work);
+}
+
+/* Reset all VFs */
+void efx_sriov_reset(struct efx_nic *efx)
+{
+ unsigned int vf_i;
+ struct efx_buffer buf;
+ struct efx_vf *vf;
+
+ ASSERT_RTNL();
+
+ if (efx->vf_init_count == 0)
+ return;
+
+ efx_sriov_usrev(efx, true);
+ (void)efx_sriov_cmd(efx, true, NULL, NULL);
+
+ if (efx_nic_alloc_buffer(efx, &buf, EFX_PAGE_SIZE))
+ return;
+
+ for (vf_i = 0; vf_i < efx->vf_init_count; ++vf_i) {
+ vf = efx->vf + vf_i;
+ efx_sriov_reset_vf(vf, &buf);
+ }
+
+ efx_nic_free_buffer(efx, &buf);
+}
+
+int efx_init_sriov(void)
+{
+ /* A single threaded workqueue is sufficient. efx_sriov_vfdi() and
+ * efx_sriov_peer_work() spend almost all their time sleeping for
+ * MCDI to complete anyway
+ */
+ vfdi_workqueue = create_singlethread_workqueue("sfc_vfdi");
+ if (!vfdi_workqueue)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void efx_fini_sriov(void)
+{
+ destroy_workqueue(vfdi_workqueue);
+}
+
+int efx_sriov_set_vf_mac(struct net_device *net_dev, int vf_i, u8 *mac)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ struct efx_vf *vf;
+
+ if (vf_i >= efx->vf_init_count)
+ return -EINVAL;
+ vf = efx->vf + vf_i;
+
+ mutex_lock(&vf->status_lock);
+ memcpy(vf->addr.mac_addr, mac, ETH_ALEN);
+ __efx_sriov_update_vf_addr(vf);
+ mutex_unlock(&vf->status_lock);
+
+ return 0;
+}
+
+int efx_sriov_set_vf_vlan(struct net_device *net_dev, int vf_i,
+ u16 vlan, u8 qos)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ struct efx_vf *vf;
+ u16 tci;
+
+ if (vf_i >= efx->vf_init_count)
+ return -EINVAL;
+ vf = efx->vf + vf_i;
+
+ mutex_lock(&vf->status_lock);
+ tci = (vlan & VLAN_VID_MASK) | ((qos & 0x7) << VLAN_PRIO_SHIFT);
+ vf->addr.tci = htons(tci);
+ __efx_sriov_update_vf_addr(vf);
+ mutex_unlock(&vf->status_lock);
+
+ return 0;
+}
+
+int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf_i,
+ bool spoofchk)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ struct efx_vf *vf;
+ int rc;
+
+ if (vf_i >= efx->vf_init_count)
+ return -EINVAL;
+ vf = efx->vf + vf_i;
+
+ mutex_lock(&vf->txq_lock);
+ if (vf->txq_count == 0) {
+ vf->tx_filter_mode =
+ spoofchk ? VF_TX_FILTER_ON : VF_TX_FILTER_OFF;
+ rc = 0;
+ } else {
+ /* This cannot be changed while TX queues are running */
+ rc = -EBUSY;
+ }
+ mutex_unlock(&vf->txq_lock);
+ return rc;
+}
+
+int efx_sriov_get_vf_config(struct net_device *net_dev, int vf_i,
+ struct ifla_vf_info *ivi)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ struct efx_vf *vf;
+ u16 tci;
+
+ if (vf_i >= efx->vf_init_count)
+ return -EINVAL;
+ vf = efx->vf + vf_i;
+
+ ivi->vf = vf_i;
+ memcpy(ivi->mac, vf->addr.mac_addr, ETH_ALEN);
+ ivi->tx_rate = 0;
+ tci = ntohs(vf->addr.tci);
+ ivi->vlan = tci & VLAN_VID_MASK;
+ ivi->qos = (tci >> VLAN_PRIO_SHIFT) & 0x7;
+ ivi->spoofchk = vf->tx_filter_mode == VF_TX_FILTER_ON;
+
+ return 0;
+}
+
diff --git a/drivers/net/ethernet/sfc/spi.h b/drivers/net/ethernet/sfc/spi.h
index 71f2e3ebe1c7..5431a1bbff5c 100644
--- a/drivers/net/ethernet/sfc/spi.h
+++ b/drivers/net/ethernet/sfc/spi.h
@@ -68,7 +68,7 @@ static inline bool efx_spi_present(const struct efx_spi_device *spi)
int falcon_spi_cmd(struct efx_nic *efx,
const struct efx_spi_device *spi, unsigned int command,
- int address, const void* in, void *out, size_t len);
+ int address, const void *in, void *out, size_t len);
int falcon_spi_wait_write(struct efx_nic *efx,
const struct efx_spi_device *spi);
int falcon_spi_read(struct efx_nic *efx,
diff --git a/drivers/net/ethernet/sfc/tenxpress.c b/drivers/net/ethernet/sfc/tenxpress.c
index 7b0fd89e7b85..d37cb5017129 100644
--- a/drivers/net/ethernet/sfc/tenxpress.c
+++ b/drivers/net/ethernet/sfc/tenxpress.c
@@ -121,7 +121,7 @@
#define GPHY_XCONTROL_REG 49152
#define GPHY_ISOLATE_LBN 10
#define GPHY_ISOLATE_WIDTH 1
-#define GPHY_DUPLEX_LBN 8
+#define GPHY_DUPLEX_LBN 8
#define GPHY_DUPLEX_WIDTH 1
#define GPHY_LOOPBACK_NEAR_LBN 14
#define GPHY_LOOPBACK_NEAR_WIDTH 1
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 72f0fbc73b1a..94d0365b31cd 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -110,7 +110,7 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr)
* little benefit from using descriptors that cross those
* boundaries and we keep things simple by not doing so.
*/
- unsigned len = (~dma_addr & 0xfff) + 1;
+ unsigned len = (~dma_addr & (EFX_PAGE_SIZE - 1)) + 1;
/* Work around hardware bug for unaligned buffers. */
if (EFX_WORKAROUND_5391(efx) && (dma_addr & 0xf))
@@ -339,7 +339,7 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
* OS to free the skb.
*/
netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
- struct net_device *net_dev)
+ struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_tx_queue *tx_queue;
@@ -446,10 +446,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
likely(efx->port_enabled) &&
likely(netif_device_present(efx->net_dev))) {
fill_level = tx_queue->insert_count - tx_queue->read_count;
- if (fill_level < EFX_TXQ_THRESHOLD(efx)) {
- EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
+ if (fill_level < EFX_TXQ_THRESHOLD(efx))
netif_tx_wake_queue(tx_queue->core_txq);
- }
}
/* Check whether the hardware queue is now empty */
diff --git a/drivers/net/ethernet/sfc/txc43128_phy.c b/drivers/net/ethernet/sfc/txc43128_phy.c
index 7c21b334a75b..29bb3f9941c0 100644
--- a/drivers/net/ethernet/sfc/txc43128_phy.c
+++ b/drivers/net/ethernet/sfc/txc43128_phy.c
@@ -512,7 +512,7 @@ static bool txc43128_phy_poll(struct efx_nic *efx)
return efx->link_state.up != was_up;
}
-static const char *txc43128_test_names[] = {
+static const char *const txc43128_test_names[] = {
"bist"
};
diff --git a/drivers/net/ethernet/sfc/vfdi.h b/drivers/net/ethernet/sfc/vfdi.h
new file mode 100644
index 000000000000..225557caaf5a
--- /dev/null
+++ b/drivers/net/ethernet/sfc/vfdi.h
@@ -0,0 +1,255 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2010-2012 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+#ifndef _VFDI_H
+#define _VFDI_H
+
+/**
+ * DOC: Virtual Function Driver Interface
+ *
+ * This file contains software structures used to form a two way
+ * communication channel between the VF driver and the PF driver,
+ * named Virtual Function Driver Interface (VFDI).
+ *
+ * For the purposes of VFDI, a page is a memory region with size and
+ * alignment of 4K. All addresses are DMA addresses to be used within
+ * the domain of the relevant VF.
+ *
+ * The only hardware-defined channels for a VF driver to communicate
+ * with the PF driver are the event mailboxes (%FR_CZ_USR_EV
+ * registers). Writing to these registers generates an event with
+ * EV_CODE = EV_CODE_USR_EV, USER_QID set to the index of the mailbox
+ * and USER_EV_REG_VALUE set to the value written. The PF driver may
+ * direct or disable delivery of these events by setting
+ * %FR_CZ_USR_EV_CFG.
+ *
+ * The PF driver can send arbitrary events to arbitrary event queues.
+ * However, for consistency, VFDI events from the PF are defined to
+ * follow the same form and be sent to the first event queue assigned
+ * to the VF while that queue is enabled by the VF driver.
+ *
+ * The general form of the variable bits of VFDI events is:
+ *
+ * 0 16 24 31
+ * | DATA | TYPE | SEQ |
+ *
+ * SEQ is a sequence number which should be incremented by 1 (modulo
+ * 256) for each event. The sequence numbers used in each direction
+ * are independent.
+ *
+ * The VF submits requests of type &struct vfdi_req by sending the
+ * address of the request (ADDR) in a series of 4 events:
+ *
+ * 0 16 24 31
+ * | ADDR[0:15] | VFDI_EV_TYPE_REQ_WORD0 | SEQ |
+ * | ADDR[16:31] | VFDI_EV_TYPE_REQ_WORD1 | SEQ+1 |
+ * | ADDR[32:47] | VFDI_EV_TYPE_REQ_WORD2 | SEQ+2 |
+ * | ADDR[48:63] | VFDI_EV_TYPE_REQ_WORD3 | SEQ+3 |
+ *
+ * The address must be page-aligned. After receiving such a valid
+ * series of events, the PF driver will attempt to read the request
+ * and write a response to the same address. In case of an invalid
+ * sequence of events or a DMA error, there will be no response.
+ *
+ * The VF driver may request that the PF driver writes status
+ * information into its domain asynchronously. After writing the
+ * status, the PF driver will send an event of the form:
+ *
+ * 0 16 24 31
+ * | reserved | VFDI_EV_TYPE_STATUS | SEQ |
+ *
+ * In case the VF must be reset for any reason, the PF driver will
+ * send an event of the form:
+ *
+ * 0 16 24 31
+ * | reserved | VFDI_EV_TYPE_RESET | SEQ |
+ *
+ * It is then the responsibility of the VF driver to request
+ * reinitialisation of its queues.
+ */
+#define VFDI_EV_SEQ_LBN 24
+#define VFDI_EV_SEQ_WIDTH 8
+#define VFDI_EV_TYPE_LBN 16
+#define VFDI_EV_TYPE_WIDTH 8
+#define VFDI_EV_TYPE_REQ_WORD0 0
+#define VFDI_EV_TYPE_REQ_WORD1 1
+#define VFDI_EV_TYPE_REQ_WORD2 2
+#define VFDI_EV_TYPE_REQ_WORD3 3
+#define VFDI_EV_TYPE_STATUS 4
+#define VFDI_EV_TYPE_RESET 5
+#define VFDI_EV_DATA_LBN 0
+#define VFDI_EV_DATA_WIDTH 16
+
+struct vfdi_endpoint {
+ u8 mac_addr[ETH_ALEN];
+ __be16 tci;
+};
+
+/**
+ * enum vfdi_op - VFDI operation enumeration
+ * @VFDI_OP_RESPONSE: Indicates a response to the request.
+ * @VFDI_OP_INIT_EVQ: Initialize SRAM entries and initialize an EVQ.
+ * @VFDI_OP_INIT_RXQ: Initialize SRAM entries and initialize an RXQ.
+ * @VFDI_OP_INIT_TXQ: Initialize SRAM entries and initialize a TXQ.
+ * @VFDI_OP_FINI_ALL_QUEUES: Flush all queues, finalize all queues, then
+ * finalize the SRAM entries.
+ * @VFDI_OP_INSERT_FILTER: Insert a MAC filter targetting the given RXQ.
+ * @VFDI_OP_REMOVE_ALL_FILTERS: Remove all filters.
+ * @VFDI_OP_SET_STATUS_PAGE: Set the DMA page(s) used for status updates
+ * from PF and write the initial status.
+ * @VFDI_OP_CLEAR_STATUS_PAGE: Clear the DMA page(s) used for status
+ * updates from PF.
+ */
+enum vfdi_op {
+ VFDI_OP_RESPONSE = 0,
+ VFDI_OP_INIT_EVQ = 1,
+ VFDI_OP_INIT_RXQ = 2,
+ VFDI_OP_INIT_TXQ = 3,
+ VFDI_OP_FINI_ALL_QUEUES = 4,
+ VFDI_OP_INSERT_FILTER = 5,
+ VFDI_OP_REMOVE_ALL_FILTERS = 6,
+ VFDI_OP_SET_STATUS_PAGE = 7,
+ VFDI_OP_CLEAR_STATUS_PAGE = 8,
+ VFDI_OP_LIMIT,
+};
+
+/* Response codes for VFDI operations. Other values may be used in future. */
+#define VFDI_RC_SUCCESS 0
+#define VFDI_RC_ENOMEM (-12)
+#define VFDI_RC_EINVAL (-22)
+#define VFDI_RC_EOPNOTSUPP (-95)
+#define VFDI_RC_ETIMEDOUT (-110)
+
+/**
+ * struct vfdi_req - Request from VF driver to PF driver
+ * @op: Operation code or response indicator, taken from &enum vfdi_op.
+ * @rc: Response code. Set to 0 on success or a negative error code on failure.
+ * @u.init_evq.index: Index of event queue to create.
+ * @u.init_evq.buf_count: Number of 4k buffers backing event queue.
+ * @u.init_evq.addr: Array of length %u.init_evq.buf_count containing DMA
+ * address of each page backing the event queue.
+ * @u.init_rxq.index: Index of receive queue to create.
+ * @u.init_rxq.buf_count: Number of 4k buffers backing receive queue.
+ * @u.init_rxq.evq: Instance of event queue to target receive events at.
+ * @u.init_rxq.label: Label used in receive events.
+ * @u.init_rxq.flags: Unused.
+ * @u.init_rxq.addr: Array of length %u.init_rxq.buf_count containing DMA
+ * address of each page backing the receive queue.
+ * @u.init_txq.index: Index of transmit queue to create.
+ * @u.init_txq.buf_count: Number of 4k buffers backing transmit queue.
+ * @u.init_txq.evq: Instance of event queue to target transmit completion
+ * events at.
+ * @u.init_txq.label: Label used in transmit completion events.
+ * @u.init_txq.flags: Checksum offload flags.
+ * @u.init_txq.addr: Array of length %u.init_txq.buf_count containing DMA
+ * address of each page backing the transmit queue.
+ * @u.mac_filter.rxq: Insert MAC filter at VF local address/VLAN targetting
+ * all traffic at this receive queue.
+ * @u.mac_filter.flags: MAC filter flags.
+ * @u.set_status_page.dma_addr: Base address for the &struct vfdi_status.
+ * This address must be page-aligned and the PF may write up to a
+ * whole page (allowing for extension of the structure).
+ * @u.set_status_page.peer_page_count: Number of additional pages the VF
+ * has provided into which peer addresses may be DMAd.
+ * @u.set_status_page.peer_page_addr: Array of DMA addresses of pages.
+ * If the number of peers exceeds 256, then the VF must provide
+ * additional pages in this array. The PF will then DMA up to
+ * 512 vfdi_endpoint structures into each page. These addresses
+ * must be page-aligned.
+ */
+struct vfdi_req {
+ u32 op;
+ u32 reserved1;
+ s32 rc;
+ u32 reserved2;
+ union {
+ struct {
+ u32 index;
+ u32 buf_count;
+ u64 addr[];
+ } init_evq;
+ struct {
+ u32 index;
+ u32 buf_count;
+ u32 evq;
+ u32 label;
+ u32 flags;
+#define VFDI_RXQ_FLAG_SCATTER_EN 1
+ u32 reserved;
+ u64 addr[];
+ } init_rxq;
+ struct {
+ u32 index;
+ u32 buf_count;
+ u32 evq;
+ u32 label;
+ u32 flags;
+#define VFDI_TXQ_FLAG_IP_CSUM_DIS 1
+#define VFDI_TXQ_FLAG_TCPUDP_CSUM_DIS 2
+ u32 reserved;
+ u64 addr[];
+ } init_txq;
+ struct {
+ u32 rxq;
+ u32 flags;
+#define VFDI_MAC_FILTER_FLAG_RSS 1
+#define VFDI_MAC_FILTER_FLAG_SCATTER 2
+ } mac_filter;
+ struct {
+ u64 dma_addr;
+ u64 peer_page_count;
+ u64 peer_page_addr[];
+ } set_status_page;
+ } u;
+};
+
+/**
+ * struct vfdi_status - Status provided by PF driver to VF driver
+ * @generation_start: A generation count DMA'd to VF *before* the
+ * rest of the structure.
+ * @generation_end: A generation count DMA'd to VF *after* the
+ * rest of the structure.
+ * @version: Version of this structure; currently set to 1. Later
+ * versions must either be layout-compatible or only be sent to VFs
+ * that specifically request them.
+ * @length: Total length of this structure including embedded tables
+ * @vi_scale: log2 the number of VIs available on this VF. This quantity
+ * is used by the hardware for register decoding.
+ * @max_tx_channels: The maximum number of transmit queues the VF can use.
+ * @rss_rxq_count: The number of receive queues present in the shared RSS
+ * indirection table.
+ * @peer_count: Total number of peers in the complete peer list. If larger
+ * than ARRAY_SIZE(%peers), then the VF must provide sufficient
+ * additional pages each of which is filled with vfdi_endpoint structures.
+ * @local: The MAC address and outer VLAN tag of *this* VF
+ * @peers: Table of peer addresses. The @tci fields in these structures
+ * are currently unused and must be ignored. Additional peers are
+ * written into any additional pages provided by the VF.
+ * @timer_quantum_ns: Timer quantum (nominal period between timer ticks)
+ * for interrupt moderation timers, in nanoseconds. This member is only
+ * present if @length is sufficiently large.
+ */
+struct vfdi_status {
+ u32 generation_start;
+ u32 generation_end;
+ u32 version;
+ u32 length;
+ u8 vi_scale;
+ u8 max_tx_channels;
+ u8 rss_rxq_count;
+ u8 reserved1;
+ u16 peer_count;
+ u16 reserved2;
+ struct vfdi_endpoint local;
+ struct vfdi_endpoint peers[256];
+
+ /* Members below here extend version 1 of this structure */
+ u32 timer_quantum_ns;
+};
+
+#endif
diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c
index 5b118cd5bf94..a9deda8eaf63 100644
--- a/drivers/net/ethernet/sis/sis190.c
+++ b/drivers/net/ethernet/sis/sis190.c
@@ -1462,8 +1462,6 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
dev = alloc_etherdev(sizeof(*tp));
if (!dev) {
- if (netif_msg_drv(&debug))
- pr_err("unable to alloc new ethernet\n");
rc = -ENOMEM;
goto err_out_0;
}
diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c
index c8efc708c792..5ccf02e7e3ad 100644
--- a/drivers/net/ethernet/sis/sis900.c
+++ b/drivers/net/ethernet/sis/sis900.c
@@ -527,7 +527,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
ret = sis900_get_mac_addr(pci_dev, net_dev);
if (!ret || !is_valid_ether_addr(net_dev->dev_addr)) {
- random_ether_addr(net_dev->dev_addr);
+ eth_hw_addr_random(net_dev);
printk(KERN_WARNING "%s: Unreadable or invalid MAC address,"
"using random generated one\n", dev_name);
}
@@ -619,7 +619,6 @@ static int __devinit sis900_mii_probe(struct net_device * net_dev)
}
if ((mii_phy = kmalloc(sizeof(struct mii_phy), GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING "Cannot allocate mem for struct mii_phy\n");
mii_phy = sis_priv->first_mii;
while (mii_phy) {
struct mii_phy *phy;
@@ -1167,7 +1166,7 @@ sis900_init_rx_ring(struct net_device *net_dev)
for (i = 0; i < NUM_RX_DESC; i++) {
struct sk_buff *skb;
- if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
+ if ((skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE)) == NULL) {
/* not enough memory for skbuff, this makes a "hole"
on the buffer ring, it is not clear how the
hardware will react to this kind of degenerated
@@ -1770,7 +1769,7 @@ static int sis900_rx(struct net_device *net_dev)
/* refill the Rx buffer, what if there is not enough
* memory for new socket buffer ?? */
- if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
+ if ((skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE)) == NULL) {
/*
* Not enough memory to refill the buffer
* so we need to recycle the old one so
@@ -1828,7 +1827,7 @@ refill_rx_ring:
entry = sis_priv->dirty_rx % NUM_RX_DESC;
if (sis_priv->rx_skbuff[entry] == NULL) {
- if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
+ if ((skb = netdev_alloc_skb(net_dev, RX_BUF_SIZE)) == NULL) {
/* not enough memory for skbuff, this makes a
* "hole" on the buffer ring, it is not clear
* how the hardware will react to this kind
diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c
index 2c077ce0b6d6..2a662e6112e9 100644
--- a/drivers/net/ethernet/smsc/epic100.c
+++ b/drivers/net/ethernet/smsc/epic100.c
@@ -363,10 +363,9 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
ret = -ENOMEM;
dev = alloc_etherdev(sizeof (*ep));
- if (!dev) {
- dev_err(&pdev->dev, "no memory for eth device\n");
+ if (!dev)
goto err_out_free_res;
- }
+
SET_NETDEV_DEV(dev, &pdev->dev);
#ifdef USE_IO_OPS
@@ -935,7 +934,7 @@ static void epic_init_ring(struct net_device *dev)
/* Fill in the Rx buffers. Handle allocation failure gracefully. */
for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = dev_alloc_skb(ep->rx_buf_sz + 2);
+ struct sk_buff *skb = netdev_alloc_skb(dev, ep->rx_buf_sz + 2);
ep->rx_skbuff[i] = skb;
if (skb == NULL)
break;
@@ -1200,7 +1199,7 @@ static int epic_rx(struct net_device *dev, int budget)
/* Check if the packet is long enough to accept without copying
to a minimally-sized skbuff. */
if (pkt_len < rx_copybreak &&
- (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
skb_reserve(skb, 2); /* 16 byte align the IP header */
pci_dma_sync_single_for_cpu(ep->pci_dev,
ep->rx_ring[entry].bufaddr,
@@ -1233,7 +1232,7 @@ static int epic_rx(struct net_device *dev, int budget)
entry = ep->dirty_rx % RX_RING_SIZE;
if (ep->rx_skbuff[entry] == NULL) {
struct sk_buff *skb;
- skb = ep->rx_skbuff[entry] = dev_alloc_skb(ep->rx_buf_sz + 2);
+ skb = ep->rx_skbuff[entry] = netdev_alloc_skb(dev, ep->rx_buf_sz + 2);
if (skb == NULL)
break;
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index 313ba3b32ab4..8814b2f5d46f 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -401,7 +401,7 @@ static inline void smc911x_rcv(struct net_device *dev)
} else {
/* Receive a valid packet */
/* Alloc a buffer with extra room for DMA alignment */
- skb=dev_alloc_skb(pkt_len+32);
+ skb = netdev_alloc_skb(dev, pkt_len+32);
if (unlikely(skb == NULL)) {
PRINTK( "%s: Low memory, rcvd packet dropped.\n",
dev->name);
@@ -2065,7 +2065,6 @@ static int __devinit smc911x_drv_probe(struct platform_device *pdev)
ndev = alloc_etherdev(sizeof(struct smc911x_local));
if (!ndev) {
- printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM;
goto release_1;
}
diff --git a/drivers/net/ethernet/smsc/smc9194.c b/drivers/net/ethernet/smsc/smc9194.c
index 4e45094efb18..50823da9dc1e 100644
--- a/drivers/net/ethernet/smsc/smc9194.c
+++ b/drivers/net/ethernet/smsc/smc9194.c
@@ -1222,7 +1222,7 @@ static void smc_rcv(struct net_device *dev)
if ( status & RS_MULTICAST )
dev->stats.multicast++;
- skb = dev_alloc_skb( packet_length + 5);
+ skb = netdev_alloc_skb(dev, packet_length + 5);
if ( skb == NULL ) {
printk(KERN_NOTICE CARDNAME ": Low memory, packet dropped.\n");
diff --git a/drivers/net/ethernet/smsc/smc91c92_cs.c b/drivers/net/ethernet/smsc/smc91c92_cs.c
index ada927aba7a5..d12e48a7861d 100644
--- a/drivers/net/ethernet/smsc/smc91c92_cs.c
+++ b/drivers/net/ethernet/smsc/smc91c92_cs.c
@@ -1500,7 +1500,7 @@ static void smc_rx(struct net_device *dev)
struct sk_buff *skb;
/* Note: packet_length adds 5 or 6 extra bytes here! */
- skb = dev_alloc_skb(packet_length+2);
+ skb = netdev_alloc_skb(dev, packet_length+2);
if (skb == NULL) {
pr_debug("%s: Low memory, packet dropped.\n", dev->name);
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 64ad3ed74495..1dc4fad593e7 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -463,7 +463,7 @@ static inline void smc_rcv(struct net_device *dev)
* multiple of 4 bytes on 32 bit buses.
* Hence packet_len - 6 + 2 + 2 + 2.
*/
- skb = dev_alloc_skb(packet_len);
+ skb = netdev_alloc_skb(dev, packet_len);
if (unlikely(skb == NULL)) {
printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
dev->name);
@@ -2223,7 +2223,6 @@ static int __devinit smc_drv_probe(struct platform_device *pdev)
ndev = alloc_etherdev(sizeof(struct smc_local));
if (!ndev) {
- printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM;
goto out;
}
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 24d2df068d71..4a6971027076 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -1833,6 +1833,7 @@ static int smsc911x_set_mac_address(struct net_device *dev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
spin_lock_irq(&pdata->mac_lock);
@@ -2374,7 +2375,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
dev = alloc_etherdev(sizeof(struct smsc911x_data));
if (!dev) {
- pr_warn("Could not allocate device\n");
retval = -ENOMEM;
goto out_release_io_1;
}
@@ -2486,7 +2486,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
"Mac Address is read from LAN911x EEPROM");
} else {
/* eeprom values are invalid, generate random MAC */
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
smsc911x_set_hw_mac_address(pdata, dev->dev_addr);
SMSC_TRACE(pdata, probe,
"MAC Address is set to random_ether_addr");
diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
index a9efbdfe5302..38386478532b 100644
--- a/drivers/net/ethernet/smsc/smsc9420.c
+++ b/drivers/net/ethernet/smsc/smsc9420.c
@@ -509,10 +509,9 @@ static void smsc9420_check_mac_address(struct net_device *dev)
smsc_dbg(PROBE, "Mac Address is read from EEPROM");
} else {
/* eeprom values are invalid, generate random MAC */
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
smsc9420_set_mac_address(dev);
- smsc_dbg(PROBE,
- "MAC Address is set to random_ether_addr");
+ smsc_dbg(PROBE, "MAC Address is set to random");
}
}
}
@@ -850,8 +849,6 @@ static int smsc9420_alloc_rx_buffer(struct smsc9420_pdata *pd, int index)
return -ENOMEM;
}
- skb->dev = pd->dev;
-
mapping = pci_map_single(pd->pdev, skb_tail_pointer(skb),
PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(pd->pdev, mapping)) {
@@ -1598,10 +1595,8 @@ smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
dev = alloc_etherdev(sizeof(*pd));
- if (!dev) {
- printk(KERN_ERR "ether device alloc failed\n");
+ if (!dev)
goto out_disable_pci_device_1;
- }
SET_NETDEV_DEV(dev, &pdev->dev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 6ee593a55a64..e85ffbd54830 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -878,7 +878,7 @@ static void stmmac_check_ether_addr(struct stmmac_priv *priv)
priv->dev->base_addr,
priv->dev->dev_addr, 0);
if (!is_valid_ether_addr(priv->dev->dev_addr))
- random_ether_addr(priv->dev->dev_addr);
+ eth_hw_addr_random(priv->dev);
}
pr_warning("%s: device MAC address %pM\n", priv->dev->name,
priv->dev->dev_addr);
@@ -910,10 +910,9 @@ static int stmmac_open(struct net_device *dev)
#ifdef CONFIG_STMMAC_TIMER
priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
- if (unlikely(priv->tm == NULL)) {
- pr_err("%s: ERROR: timer memory alloc failed\n", __func__);
+ if (unlikely(priv->tm == NULL))
return -ENOMEM;
- }
+
priv->tm->freq = tmrate;
/* Test if the external timer can be actually used.
@@ -1801,10 +1800,8 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
struct stmmac_priv *priv;
ndev = alloc_etherdev(sizeof(struct stmmac_priv));
- if (!ndev) {
- pr_err("%s: ERROR: allocating the device\n", __func__);
+ if (!ndev)
return NULL;
- }
SET_NETDEV_DEV(ndev, device);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 50ad5b80cfaf..da66ed7c3c5d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -85,7 +85,7 @@ static int __devinit stmmac_pci_probe(struct pci_dev *pdev,
continue;
addr = pci_iomap(pdev, i, 0);
if (addr == NULL) {
- pr_err("%s: ERROR: cannot map regiser memory, aborting",
+ pr_err("%s: ERROR: cannot map register memory, aborting",
__func__);
ret = -EIO;
goto err_out_map_failed;
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index f10665f594c4..b36edbd625dd 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -835,7 +835,6 @@ static int cas_saturn_firmware_init(struct cas *cp)
cp->fw_data = vmalloc(cp->fw_size);
if (!cp->fw_data) {
err = -ENOMEM;
- pr_err("\"%s\" Failed %d\n", fw_name, err);
goto out;
}
memcpy(cp->fw_data, &fw->data[2], cp->fw_size);
@@ -1975,7 +1974,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
else
alloclen = max(hlen, RX_COPY_MIN);
- skb = dev_alloc_skb(alloclen + swivel + cp->crc_size);
+ skb = netdev_alloc_skb(cp->dev, alloclen + swivel + cp->crc_size);
if (skb == NULL)
return -1;
@@ -4947,7 +4946,6 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(*cp));
if (!dev) {
- dev_err(&pdev->dev, "Etherdev alloc failed, aborting\n");
err = -ENOMEM;
goto err_out_disable_pdev;
}
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index cf433931304f..c99b3b0e2eae 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -6412,7 +6412,7 @@ static int niu_set_mac_addr(struct net_device *dev, void *p)
unsigned long flags;
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
@@ -9685,10 +9685,8 @@ static struct net_device * __devinit niu_alloc_and_init(
struct niu *np;
dev = alloc_etherdev_mq(sizeof(struct niu), NIU_NUM_TXCHAN);
- if (!dev) {
- dev_err(gen_dev, "Etherdev alloc failed, aborting\n");
+ if (!dev)
return NULL;
- }
SET_NETDEV_DEV(dev, gen_dev);
diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c
index 220f724c3377..f359863b5340 100644
--- a/drivers/net/ethernet/sun/sunbmac.c
+++ b/drivers/net/ethernet/sun/sunbmac.c
@@ -853,7 +853,7 @@ static void bigmac_rx(struct bigmac *bp)
/* Trim the original skb for the netif. */
skb_trim(skb, len);
} else {
- struct sk_buff *copy_skb = dev_alloc_skb(len + 2);
+ struct sk_buff *copy_skb = netdev_alloc_skb(bp->dev, len + 2);
if (copy_skb == NULL) {
drops++;
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index 31441a870b0b..ba041596e046 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -2885,7 +2885,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(*gp));
if (!dev) {
- pr_err("Etherdev alloc failed, aborting\n");
err = -ENOMEM;
goto err_disable_device;
}
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index 09c518655db2..8b627e2f798d 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -2043,7 +2043,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
/* Trim the original skb for the netif. */
skb_trim(skb, len);
} else {
- struct sk_buff *copy_skb = dev_alloc_skb(len + 2);
+ struct sk_buff *copy_skb = netdev_alloc_skb(dev, len + 2);
if (copy_skb == NULL) {
drops++;
diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c
index b28f74367ebe..139d6b410d68 100644
--- a/drivers/net/ethernet/sun/sunqe.c
+++ b/drivers/net/ethernet/sun/sunqe.c
@@ -435,7 +435,7 @@ static void qe_rx(struct sunqe *qep)
dev->stats.rx_length_errors++;
dev->stats.rx_dropped++;
} else {
- skb = dev_alloc_skb(len + 2);
+ skb = netdev_alloc_skb(dev, len + 2);
if (skb == NULL) {
drops++;
dev->stats.rx_dropped++;
@@ -907,14 +907,8 @@ static int __devinit qec_ether_init(struct platform_device *op)
dev_set_drvdata(&op->dev, qe);
- printk(KERN_INFO "%s: qe channel[%d] ", dev->name, qe->channel);
- for (i = 0; i < 6; i++)
- printk ("%2.2x%c",
- dev->dev_addr[i],
- i == 5 ? ' ': ':');
- printk("\n");
-
-
+ printk(KERN_INFO "%s: qe channel[%d] %pM\n", dev->name, qe->channel,
+ dev->dev_addr);
return 0;
fail:
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index 8c6c059f3489..92a037a8228a 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -949,10 +949,9 @@ static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port)
int map_len = (ETH_FRAME_LEN + 7) & ~7;
err = -ENOMEM;
- if (!buf) {
- pr_err("TX buffer allocation failure\n");
+ if (!buf)
goto err_out;
- }
+
err = -EFAULT;
if ((unsigned long)buf & (8UL - 1)) {
pr_err("TX buffer misaligned\n");
@@ -1027,10 +1026,8 @@ static struct vnet * __devinit vnet_new(const u64 *local_mac)
int err, i;
dev = alloc_etherdev(sizeof(*vp));
- if (!dev) {
- pr_err("Etherdev alloc failed, aborting\n");
+ if (!dev)
return ERR_PTR(-ENOMEM);
- }
for (i = 0; i < ETH_ALEN; i++)
dev->dev_addr[i] = (*local_mac >> (5 - i) * 8) & 0xff;
@@ -1165,10 +1162,8 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev,
port = kzalloc(sizeof(*port), GFP_KERNEL);
err = -ENOMEM;
- if (!port) {
- pr_err("Cannot allocate vnet_port\n");
+ if (!port)
goto err_out_put_mdesc;
- }
for (i = 0; i < ETH_ALEN; i++)
port->raddr[i] = (*rmac >> (5 - i) * 8) & 0xff;
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index 4b19e9b0606b..ad973ffc9ff3 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -1089,12 +1089,11 @@ static void bdx_rx_alloc_skbs(struct bdx_priv *priv, struct rxf_fifo *f)
ENTER;
dno = bdx_rxdb_available(db) - 1;
while (dno > 0) {
- skb = dev_alloc_skb(f->m.pktsz + NET_IP_ALIGN);
+ skb = netdev_alloc_skb(priv->ndev, f->m.pktsz + NET_IP_ALIGN);
if (!skb) {
- pr_err("NO MEM: dev_alloc_skb failed\n");
+ pr_err("NO MEM: netdev_alloc_skb failed\n");
break;
}
- skb->dev = priv->ndev;
skb_reserve(skb, NET_IP_ALIGN);
idx = bdx_rxdb_alloc_elem(db);
@@ -1258,7 +1257,7 @@ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget)
skb = dm->skb;
if (len < BDX_COPYBREAK &&
- (skb2 = dev_alloc_skb(len + NET_IP_ALIGN))) {
+ (skb2 = netdev_alloc_skb(priv->ndev, len + NET_IP_ALIGN))) {
skb_reserve(skb2, NET_IP_ALIGN);
/*skb_put(skb2, len); */
pci_dma_sync_single_for_cpu(priv->pdev,
@@ -1978,7 +1977,6 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ndev = alloc_etherdev(sizeof(struct bdx_priv));
if (!ndev) {
err = -ENOMEM;
- pr_err("alloc_etherdev failed\n");
goto err_out_iomap;
}
diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index cbc8df78d84b..860c2526f08d 100644
--- a/drivers/net/ethernet/ti/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -1143,11 +1143,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
}
dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES);
-
- if (!dev) {
- printk(KERN_ERR "cpmac: Unable to allocate net_device\n");
+ if (!dev)
return -ENOMEM;
- }
platform_set_drvdata(pdev, dev);
priv = netdev_priv(dev);
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index c97d2f590855..34558766cbf0 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -822,7 +822,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan)
dma_reg_write(ctlr, chan->int_clear, chan->mask);
/* trigger teardown */
- dma_reg_write(ctlr, chan->td, chan->chan_num);
+ dma_reg_write(ctlr, chan->td, chan_linear(chan));
/* wait for teardown complete */
timeout = jiffies + HZ/10; /* 100 msec */
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 4b2f54565f64..174a3348f676 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -992,10 +992,9 @@ static irqreturn_t emac_irq(int irq, void *dev_id)
static struct sk_buff *emac_rx_alloc(struct emac_priv *priv)
{
- struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size);
+ struct sk_buff *skb = netdev_alloc_skb(priv->ndev, priv->rx_buf_size);
if (WARN_ON(!skb))
return NULL;
- skb->dev = priv->ndev;
skb_reserve(skb, NET_IP_ALIGN);
return skb;
}
@@ -1257,15 +1256,15 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
struct sockaddr *sa = addr;
if (!is_valid_ether_addr(sa->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
/* Store mac addr in priv and rx channel and set it in EMAC hw */
memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len);
+ ndev->addr_assign_type &= ~NET_ADDR_RANDOM;
/* MAC address is configured only after the interface is enabled. */
if (netif_running(ndev)) {
- memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr);
}
@@ -1792,7 +1791,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
ndev = alloc_etherdev(sizeof(struct emac_priv));
if (!ndev) {
- dev_err(&pdev->dev, "error allocating net_device\n");
rc = -ENOMEM;
goto free_clk;
}
@@ -1900,7 +1898,8 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
if (!is_valid_ether_addr(priv->mac_addr)) {
/* Use random MAC if none passed */
- random_ether_addr(priv->mac_addr);
+ eth_hw_addr_random(ndev);
+ memcpy(priv->mac_addr, ndev->dev_addr, ndev->addr_len);
dev_warn(&pdev->dev, "using random MAC addr: %pM\n",
priv->mac_addr);
}
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index af8b8fc39eb2..2757c7d6e633 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -53,7 +53,7 @@ struct davinci_mdio_regs {
u32 control;
#define CONTROL_IDLE BIT(31)
#define CONTROL_ENABLE BIT(30)
-#define CONTROL_MAX_DIV (0xff)
+#define CONTROL_MAX_DIV (0xffff)
u32 alive;
u32 link;
diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c
index 9c0dd6b8d6c9..817ad3bc4957 100644
--- a/drivers/net/ethernet/ti/tlan.c
+++ b/drivers/net/ethernet/ti/tlan.c
@@ -486,7 +486,6 @@ static int __devinit tlan_probe1(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(struct tlan_priv));
if (dev == NULL) {
- pr_err("Could not allocate memory for device\n");
rc = -ENOMEM;
goto err_out_regions;
}
diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c
index d9951afb9269..261356c2dc99 100644
--- a/drivers/net/ethernet/tile/tilepro.c
+++ b/drivers/net/ethernet/tile/tilepro.c
@@ -419,7 +419,7 @@ static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info,
#endif
/* Avoid "false sharing" with last cache line. */
- /* ISSUE: This is already done by "dev_alloc_skb()". */
+ /* ISSUE: This is already done by "netdev_alloc_skb()". */
unsigned int len =
(((small ? LIPP_SMALL_PACKET_SIZE : large_size) +
CHIP_L2_LINE_SIZE() - 1) & -CHIP_L2_LINE_SIZE());
@@ -433,7 +433,7 @@ static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info,
struct sk_buff **skb_ptr;
/* Request 96 extra bytes for alignment purposes. */
- skb = dev_alloc_skb(len + padding);
+ skb = netdev_alloc_skb(info->napi->dev, len + padding);
if (skb == NULL)
return false;
@@ -2186,10 +2186,11 @@ static int tile_net_set_mac_address(struct net_device *dev, void *p)
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
/* ISSUE: Note that "dev_addr" is now a pointer. */
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
return 0;
}
@@ -2254,7 +2255,7 @@ static int tile_net_get_mac(struct net_device *dev)
* can't get its MAC address, we are most likely running
* the simulator, so let's generate a random MAC address.
*/
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
}
return 0;
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
index fd4ed7f8cfa1..5c14f82c4954 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
@@ -1621,10 +1621,9 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
kfree(target->hwinfo);
target->hwinfo = kzalloc(be16_to_cpu(scan_info->size),
GFP_KERNEL);
- if (!target->hwinfo) {
- pr_info("%s: kzalloc failed\n", __func__);
+ if (!target->hwinfo)
continue;
- }
+
/* copy hw scan info */
memcpy(target->hwinfo, scan_info, scan_info->size);
target->essid_len = strnlen(scan_info->essid,
diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c
index 71b785cd7563..651a70c55e6e 100644
--- a/drivers/net/ethernet/toshiba/tc35815.c
+++ b/drivers/net/ethernet/toshiba/tc35815.c
@@ -453,7 +453,7 @@ static struct sk_buff *alloc_rxbuf_skb(struct net_device *dev,
dma_addr_t *dma_handle)
{
struct sk_buff *skb;
- skb = dev_alloc_skb(RX_BUF_SIZE);
+ skb = netdev_alloc_skb(dev, RX_BUF_SIZE);
if (!skb)
return NULL;
*dma_handle = pci_map_single(hwdev, skb->data, RX_BUF_SIZE,
@@ -808,10 +808,9 @@ static int __devinit tc35815_init_one(struct pci_dev *pdev,
/* dev zeroed in alloc_etherdev */
dev = alloc_etherdev(sizeof(*lp));
- if (dev == NULL) {
- dev_err(&pdev->dev, "unable to alloc new ethernet\n");
+ if (dev == NULL)
return -ENOMEM;
- }
+
SET_NETDEV_DEV(dev, &pdev->dev);
lp = netdev_priv(dev);
lp->dev = dev;
@@ -850,7 +849,7 @@ static int __devinit tc35815_init_one(struct pci_dev *pdev,
/* Retrieve the ethernet address. */
if (tc35815_init_dev_addr(dev)) {
dev_warn(&pdev->dev, "not valid ether addr\n");
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
}
rc = register_netdev(dev);
diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c
index 164fb775d7b3..840e0e9031f5 100644
--- a/drivers/net/ethernet/tundra/tsi108_eth.c
+++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -1148,7 +1148,7 @@ static int tsi108_set_mac(struct net_device *dev, void *addr)
int i;
if (!is_valid_ether_addr(addr))
- return -EINVAL;
+ return -EADDRNOTAVAIL;
for (i = 0; i < 6; i++)
/* +2 is for the offset of the HW addr type */
@@ -1582,10 +1582,8 @@ tsi108_init_one(struct platform_device *pdev)
/* Create an ethernet device instance */
dev = alloc_etherdev(sizeof(struct tsi108_prv_data));
- if (!dev) {
- printk("tsi108_eth: Could not allocate a device structure\n");
+ if (!dev)
return -ENOMEM;
- }
printk("tsi108_eth%d: probe...\n", pdev->id);
data = netdev_priv(dev);
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 10b18eb63d25..39b8cf3dafcd 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -927,7 +927,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(struct rhine_private));
if (!dev) {
rc = -ENOMEM;
- dev_err(&pdev->dev, "alloc_etherdev failed\n");
goto err_out;
}
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -984,7 +983,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
if (!is_valid_ether_addr(dev->dev_addr)) {
/* Report it and use a random ethernet address instead */
netdev_err(dev, "Invalid MAC address: %pM\n", dev->dev_addr);
- random_ether_addr(dev->dev_addr);
+ eth_hw_addr_random(dev);
netdev_info(dev, "Using random MAC address: %pM\n",
dev->dev_addr);
}
@@ -1156,7 +1155,6 @@ static void alloc_rbufs(struct net_device *dev)
rp->rx_skbuff[i] = skb;
if (skb == NULL)
break;
- skb->dev = dev; /* Mark as being used by this device. */
rp->rx_skbuff_dma[i] =
pci_map_single(rp->pdev, skb->data, rp->rx_buf_sz,
@@ -1941,7 +1939,6 @@ static int rhine_rx(struct net_device *dev, int limit)
rp->rx_skbuff[entry] = skb;
if (skb == NULL)
break; /* Better luck next round. */
- skb->dev = dev; /* Mark as being used by this device. */
rp->rx_skbuff_dma[entry] =
pci_map_single(rp->pdev, skb->data,
rp->rx_buf_sz,
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index cb35b14b73bb..8a5d7c100a5e 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -1509,7 +1509,7 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
struct rx_desc *rd = &(vptr->rx.ring[idx]);
struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]);
- rd_info->skb = dev_alloc_skb(vptr->rx.buf_sz + 64);
+ rd_info->skb = netdev_alloc_skb(vptr->dev, vptr->rx.buf_sz + 64);
if (rd_info->skb == NULL)
return -ENOMEM;
@@ -2730,10 +2730,8 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
}
dev = alloc_etherdev(sizeof(struct velocity_info));
- if (!dev) {
- dev_err(&pdev->dev, "allocate net device failed.\n");
+ if (!dev)
goto out;
- }
/* Chain it all together */
diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig
index d5a826063a82..5778a4ae1164 100644
--- a/drivers/net/ethernet/xilinx/Kconfig
+++ b/drivers/net/ethernet/xilinx/Kconfig
@@ -25,6 +25,14 @@ config XILINX_EMACLITE
---help---
This driver supports the 10/100 Ethernet Lite from Xilinx.
+config XILINX_AXI_EMAC
+ tristate "Xilinx 10/100/1000 AXI Ethernet support"
+ depends on (PPC32 || MICROBLAZE)
+ select PHYLIB
+ ---help---
+ This driver supports the 10/100/1000 Ethernet from Xilinx for the
+ AXI bus interface used in Xilinx Virtex FPGAs.
+
config XILINX_LL_TEMAC
tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
depends on (PPC || MICROBLAZE)
diff --git a/drivers/net/ethernet/xilinx/Makefile b/drivers/net/ethernet/xilinx/Makefile
index 5feac734ea45..214205e975e3 100644
--- a/drivers/net/ethernet/xilinx/Makefile
+++ b/drivers/net/ethernet/xilinx/Makefile
@@ -5,3 +5,5 @@
ll_temac-objs := ll_temac_main.o ll_temac_mdio.o
obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o
obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
+xilinx_emac-objs := xilinx_axienet_main.o xilinx_axienet_mdio.o
+obj-$(CONFIG_XILINX_AXI_EMAC) += xilinx_emac.o
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index f21addb1db95..d21591a2c593 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -327,7 +327,9 @@ static int temac_set_mac_address(struct net_device *ndev, void *address)
memcpy(ndev->dev_addr, address, ETH_ALEN);
if (!is_valid_ether_addr(ndev->dev_addr))
- random_ether_addr(ndev->dev_addr);
+ eth_hw_addr_random(ndev);
+ else
+ ndev->addr_assign_type &= ~NET_ADDR_RANDOM;
/* set up unicast MAC address filter set its mac address */
mutex_lock(&lp->indirect_mutex);
@@ -1011,10 +1013,9 @@ static int __devinit temac_of_probe(struct platform_device *op)
/* Init network device structure */
ndev = alloc_etherdev(sizeof(*lp));
- if (!ndev) {
- dev_err(&op->dev, "could not allocate device.\n");
+ if (!ndev)
return -ENOMEM;
- }
+
ether_setup(ndev);
dev_set_drvdata(&op->dev, ndev);
SET_NETDEV_DEV(ndev, &op->dev);
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h
new file mode 100644
index 000000000000..cc83af083fd7
--- /dev/null
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
@@ -0,0 +1,508 @@
+/*
+ * Definitions for Xilinx Axi Ethernet device driver.
+ *
+ * Copyright (c) 2009 Secret Lab Technologies, Ltd.
+ * Copyright (c) 2010 Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch>
+ * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch>
+ */
+
+#ifndef XILINX_AXIENET_H
+#define XILINX_AXIENET_H
+
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+/* Packet size info */
+#define XAE_HDR_SIZE 14 /* Size of Ethernet header */
+#define XAE_HDR_VLAN_SIZE 18 /* Size of an Ethernet hdr + VLAN */
+#define XAE_TRL_SIZE 4 /* Size of Ethernet trailer (FCS) */
+#define XAE_MTU 1500 /* Max MTU of an Ethernet frame */
+#define XAE_JUMBO_MTU 9000 /* Max MTU of a jumbo Eth. frame */
+
+#define XAE_MAX_FRAME_SIZE (XAE_MTU + XAE_HDR_SIZE + XAE_TRL_SIZE)
+#define XAE_MAX_VLAN_FRAME_SIZE (XAE_MTU + XAE_HDR_VLAN_SIZE + XAE_TRL_SIZE)
+#define XAE_MAX_JUMBO_FRAME_SIZE (XAE_JUMBO_MTU + XAE_HDR_SIZE + XAE_TRL_SIZE)
+
+/* Configuration options */
+
+/* Accept all incoming packets. Default: disabled (cleared) */
+#define XAE_OPTION_PROMISC (1 << 0)
+
+/* Jumbo frame support for Tx & Rx. Default: disabled (cleared) */
+#define XAE_OPTION_JUMBO (1 << 1)
+
+/* VLAN Rx & Tx frame support. Default: disabled (cleared) */
+#define XAE_OPTION_VLAN (1 << 2)
+
+/* Enable recognition of flow control frames on Rx. Default: enabled (set) */
+#define XAE_OPTION_FLOW_CONTROL (1 << 4)
+
+/* Strip FCS and PAD from incoming frames. Note: PAD from VLAN frames is not
+ * stripped. Default: disabled (set) */
+#define XAE_OPTION_FCS_STRIP (1 << 5)
+
+/* Generate FCS field and add PAD automatically for outgoing frames.
+ * Default: enabled (set) */
+#define XAE_OPTION_FCS_INSERT (1 << 6)
+
+/* Enable Length/Type error checking for incoming frames. When this option is
+ * set, the MAC will filter frames that have a mismatched type/length field
+ * and if XAE_OPTION_REPORT_RXERR is set, the user is notified when these
+ * types of frames are encountered. When this option is cleared, the MAC will
+ * allow these types of frames to be received. Default: enabled (set) */
+#define XAE_OPTION_LENTYPE_ERR (1 << 7)
+
+/* Enable the transmitter. Default: enabled (set) */
+#define XAE_OPTION_TXEN (1 << 11)
+
+/* Enable the receiver. Default: enabled (set) */
+#define XAE_OPTION_RXEN (1 << 12)
+
+/* Default options set when device is initialized or reset */
+#define XAE_OPTION_DEFAULTS \
+ (XAE_OPTION_TXEN | \
+ XAE_OPTION_FLOW_CONTROL | \
+ XAE_OPTION_RXEN)
+
+/* Axi DMA Register definitions */
+
+#define XAXIDMA_TX_CR_OFFSET 0x00000000 /* Channel control */
+#define XAXIDMA_TX_SR_OFFSET 0x00000004 /* Status */
+#define XAXIDMA_TX_CDESC_OFFSET 0x00000008 /* Current descriptor pointer */
+#define XAXIDMA_TX_TDESC_OFFSET 0x00000010 /* Tail descriptor pointer */
+
+#define XAXIDMA_RX_CR_OFFSET 0x00000030 /* Channel control */
+#define XAXIDMA_RX_SR_OFFSET 0x00000034 /* Status */
+#define XAXIDMA_RX_CDESC_OFFSET 0x00000038 /* Current descriptor pointer */
+#define XAXIDMA_RX_TDESC_OFFSET 0x00000040 /* Tail descriptor pointer */
+
+#define XAXIDMA_CR_RUNSTOP_MASK 0x00000001 /* Start/stop DMA channel */
+#define XAXIDMA_CR_RESET_MASK 0x00000004 /* Reset DMA engine */
+
+#define XAXIDMA_BD_NDESC_OFFSET 0x00 /* Next descriptor pointer */
+#define XAXIDMA_BD_BUFA_OFFSET 0x08 /* Buffer address */
+#define XAXIDMA_BD_CTRL_LEN_OFFSET 0x18 /* Control/buffer length */
+#define XAXIDMA_BD_STS_OFFSET 0x1C /* Status */
+#define XAXIDMA_BD_USR0_OFFSET 0x20 /* User IP specific word0 */
+#define XAXIDMA_BD_USR1_OFFSET 0x24 /* User IP specific word1 */
+#define XAXIDMA_BD_USR2_OFFSET 0x28 /* User IP specific word2 */
+#define XAXIDMA_BD_USR3_OFFSET 0x2C /* User IP specific word3 */
+#define XAXIDMA_BD_USR4_OFFSET 0x30 /* User IP specific word4 */
+#define XAXIDMA_BD_ID_OFFSET 0x34 /* Sw ID */
+#define XAXIDMA_BD_HAS_STSCNTRL_OFFSET 0x38 /* Whether has stscntrl strm */
+#define XAXIDMA_BD_HAS_DRE_OFFSET 0x3C /* Whether has DRE */
+
+#define XAXIDMA_BD_HAS_DRE_SHIFT 8 /* Whether has DRE shift */
+#define XAXIDMA_BD_HAS_DRE_MASK 0xF00 /* Whether has DRE mask */
+#define XAXIDMA_BD_WORDLEN_MASK 0xFF /* Whether has DRE mask */
+
+#define XAXIDMA_BD_CTRL_LENGTH_MASK 0x007FFFFF /* Requested len */
+#define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /* First tx packet */
+#define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /* Last tx packet */
+#define XAXIDMA_BD_CTRL_ALL_MASK 0x0C000000 /* All control bits */
+
+#define XAXIDMA_DELAY_MASK 0xFF000000 /* Delay timeout counter */
+#define XAXIDMA_COALESCE_MASK 0x00FF0000 /* Coalesce counter */
+
+#define XAXIDMA_DELAY_SHIFT 24
+#define XAXIDMA_COALESCE_SHIFT 16
+
+#define XAXIDMA_IRQ_IOC_MASK 0x00001000 /* Completion intr */
+#define XAXIDMA_IRQ_DELAY_MASK 0x00002000 /* Delay interrupt */
+#define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /* Error interrupt */
+#define XAXIDMA_IRQ_ALL_MASK 0x00007000 /* All interrupts */
+
+/* Default TX/RX Threshold and waitbound values for SGDMA mode */
+#define XAXIDMA_DFT_TX_THRESHOLD 24
+#define XAXIDMA_DFT_TX_WAITBOUND 254
+#define XAXIDMA_DFT_RX_THRESHOLD 24
+#define XAXIDMA_DFT_RX_WAITBOUND 254
+
+#define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /* First tx packet */
+#define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /* Last tx packet */
+#define XAXIDMA_BD_CTRL_ALL_MASK 0x0C000000 /* All control bits */
+
+#define XAXIDMA_BD_STS_ACTUAL_LEN_MASK 0x007FFFFF /* Actual len */
+#define XAXIDMA_BD_STS_COMPLETE_MASK 0x80000000 /* Completed */
+#define XAXIDMA_BD_STS_DEC_ERR_MASK 0x40000000 /* Decode error */
+#define XAXIDMA_BD_STS_SLV_ERR_MASK 0x20000000 /* Slave error */
+#define XAXIDMA_BD_STS_INT_ERR_MASK 0x10000000 /* Internal err */
+#define XAXIDMA_BD_STS_ALL_ERR_MASK 0x70000000 /* All errors */
+#define XAXIDMA_BD_STS_RXSOF_MASK 0x08000000 /* First rx pkt */
+#define XAXIDMA_BD_STS_RXEOF_MASK 0x04000000 /* Last rx pkt */
+#define XAXIDMA_BD_STS_ALL_MASK 0xFC000000 /* All status bits */
+
+#define XAXIDMA_BD_MINIMUM_ALIGNMENT 0x40
+
+/* Axi Ethernet registers definition */
+#define XAE_RAF_OFFSET 0x00000000 /* Reset and Address filter */
+#define XAE_TPF_OFFSET 0x00000004 /* Tx Pause Frame */
+#define XAE_IFGP_OFFSET 0x00000008 /* Tx Inter-frame gap adjustment*/
+#define XAE_IS_OFFSET 0x0000000C /* Interrupt status */
+#define XAE_IP_OFFSET 0x00000010 /* Interrupt pending */
+#define XAE_IE_OFFSET 0x00000014 /* Interrupt enable */
+#define XAE_TTAG_OFFSET 0x00000018 /* Tx VLAN TAG */
+#define XAE_RTAG_OFFSET 0x0000001C /* Rx VLAN TAG */
+#define XAE_UAWL_OFFSET 0x00000020 /* Unicast address word lower */
+#define XAE_UAWU_OFFSET 0x00000024 /* Unicast address word upper */
+#define XAE_TPID0_OFFSET 0x00000028 /* VLAN TPID0 register */
+#define XAE_TPID1_OFFSET 0x0000002C /* VLAN TPID1 register */
+#define XAE_PPST_OFFSET 0x00000030 /* PCS PMA Soft Temac Status Reg */
+#define XAE_RCW0_OFFSET 0x00000400 /* Rx Configuration Word 0 */
+#define XAE_RCW1_OFFSET 0x00000404 /* Rx Configuration Word 1 */
+#define XAE_TC_OFFSET 0x00000408 /* Tx Configuration */
+#define XAE_FCC_OFFSET 0x0000040C /* Flow Control Configuration */
+#define XAE_EMMC_OFFSET 0x00000410 /* EMAC mode configuration */
+#define XAE_PHYC_OFFSET 0x00000414 /* RGMII/SGMII configuration */
+#define XAE_MDIO_MC_OFFSET 0x00000500 /* MII Management Config */
+#define XAE_MDIO_MCR_OFFSET 0x00000504 /* MII Management Control */
+#define XAE_MDIO_MWD_OFFSET 0x00000508 /* MII Management Write Data */
+#define XAE_MDIO_MRD_OFFSET 0x0000050C /* MII Management Read Data */
+#define XAE_MDIO_MIS_OFFSET 0x00000600 /* MII Management Interrupt Status */
+#define XAE_MDIO_MIP_OFFSET 0x00000620 /* MII Mgmt Interrupt Pending
+ * register offset */
+#define XAE_MDIO_MIE_OFFSET 0x00000640 /* MII Management Interrupt Enable
+ * register offset */
+#define XAE_MDIO_MIC_OFFSET 0x00000660 /* MII Management Interrupt Clear
+ * register offset. */
+#define XAE_UAW0_OFFSET 0x00000700 /* Unicast address word 0 */
+#define XAE_UAW1_OFFSET 0x00000704 /* Unicast address word 1 */
+#define XAE_FMI_OFFSET 0x00000708 /* Filter Mask Index */
+#define XAE_AF0_OFFSET 0x00000710 /* Address Filter 0 */
+#define XAE_AF1_OFFSET 0x00000714 /* Address Filter 1 */
+
+#define XAE_TX_VLAN_DATA_OFFSET 0x00004000 /* TX VLAN data table address */
+#define XAE_RX_VLAN_DATA_OFFSET 0x00008000 /* RX VLAN data table address */
+#define XAE_MCAST_TABLE_OFFSET 0x00020000 /* Multicast table address */
+
+/* Bit Masks for Axi Ethernet RAF register */
+#define XAE_RAF_MCSTREJ_MASK 0x00000002 /* Reject receive multicast
+ * destination address */
+#define XAE_RAF_BCSTREJ_MASK 0x00000004 /* Reject receive broadcast
+ * destination address */
+#define XAE_RAF_TXVTAGMODE_MASK 0x00000018 /* Tx VLAN TAG mode */
+#define XAE_RAF_RXVTAGMODE_MASK 0x00000060 /* Rx VLAN TAG mode */
+#define XAE_RAF_TXVSTRPMODE_MASK 0x00000180 /* Tx VLAN STRIP mode */
+#define XAE_RAF_RXVSTRPMODE_MASK 0x00000600 /* Rx VLAN STRIP mode */
+#define XAE_RAF_NEWFNCENBL_MASK 0x00000800 /* New function mode */
+#define XAE_RAF_EMULTIFLTRENBL_MASK 0x00001000 /* Exteneded Multicast
+ * Filtering mode
+ */
+#define XAE_RAF_STATSRST_MASK 0x00002000 /* Stats. Counter Reset */
+#define XAE_RAF_RXBADFRMEN_MASK 0x00004000 /* Recv Bad Frame Enable */
+#define XAE_RAF_TXVTAGMODE_SHIFT 3 /* Tx Tag mode shift bits */
+#define XAE_RAF_RXVTAGMODE_SHIFT 5 /* Rx Tag mode shift bits */
+#define XAE_RAF_TXVSTRPMODE_SHIFT 7 /* Tx strip mode shift bits*/
+#define XAE_RAF_RXVSTRPMODE_SHIFT 9 /* Rx Strip mode shift bits*/
+
+/* Bit Masks for Axi Ethernet TPF and IFGP registers */
+#define XAE_TPF_TPFV_MASK 0x0000FFFF /* Tx pause frame value */
+#define XAE_IFGP0_IFGP_MASK 0x0000007F /* Transmit inter-frame
+ * gap adjustment value */
+
+/* Bit Masks for Axi Ethernet IS, IE and IP registers, Same masks apply
+ * for all 3 registers. */
+#define XAE_INT_HARDACSCMPLT_MASK 0x00000001 /* Hard register access
+ * complete */
+#define XAE_INT_AUTONEG_MASK 0x00000002 /* Auto negotiation
+ * complete */
+#define XAE_INT_RXCMPIT_MASK 0x00000004 /* Rx complete */
+#define XAE_INT_RXRJECT_MASK 0x00000008 /* Rx frame rejected */
+#define XAE_INT_RXFIFOOVR_MASK 0x00000010 /* Rx fifo overrun */
+#define XAE_INT_TXCMPIT_MASK 0x00000020 /* Tx complete */
+#define XAE_INT_RXDCMLOCK_MASK 0x00000040 /* Rx Dcm Lock */
+#define XAE_INT_MGTRDY_MASK 0x00000080 /* MGT clock Lock */
+#define XAE_INT_PHYRSTCMPLT_MASK 0x00000100 /* Phy Reset complete */
+#define XAE_INT_ALL_MASK 0x0000003F /* All the ints */
+
+#define XAE_INT_RECV_ERROR_MASK \
+ (XAE_INT_RXRJECT_MASK | XAE_INT_RXFIFOOVR_MASK) /* INT bits that
+ * indicate receive
+ * errors */
+
+/* Bit masks for Axi Ethernet VLAN TPID Word 0 register */
+#define XAE_TPID_0_MASK 0x0000FFFF /* TPID 0 */
+#define XAE_TPID_1_MASK 0xFFFF0000 /* TPID 1 */
+
+/* Bit masks for Axi Ethernet VLAN TPID Word 1 register */
+#define XAE_TPID_2_MASK 0x0000FFFF /* TPID 0 */
+#define XAE_TPID_3_MASK 0xFFFF0000 /* TPID 1 */
+
+/* Bit masks for Axi Ethernet RCW1 register */
+#define XAE_RCW1_RST_MASK 0x80000000 /* Reset */
+#define XAE_RCW1_JUM_MASK 0x40000000 /* Jumbo frame enable */
+#define XAE_RCW1_FCS_MASK 0x20000000 /* In-Band FCS enable
+ * (FCS not stripped) */
+#define XAE_RCW1_RX_MASK 0x10000000 /* Receiver enable */
+#define XAE_RCW1_VLAN_MASK 0x08000000 /* VLAN frame enable */
+#define XAE_RCW1_LT_DIS_MASK 0x02000000 /* Length/type field valid check
+ * disable */
+#define XAE_RCW1_CL_DIS_MASK 0x01000000 /* Control frame Length check
+ * disable */
+#define XAE_RCW1_PAUSEADDR_MASK 0x0000FFFF /* Pause frame source address
+ * bits [47:32]. Bits [31:0] are
+ * stored in register RCW0 */
+
+/* Bit masks for Axi Ethernet TC register */
+#define XAE_TC_RST_MASK 0x80000000 /* Reset */
+#define XAE_TC_JUM_MASK 0x40000000 /* Jumbo frame enable */
+#define XAE_TC_FCS_MASK 0x20000000 /* In-Band FCS enable
+ * (FCS not generated) */
+#define XAE_TC_TX_MASK 0x10000000 /* Transmitter enable */
+#define XAE_TC_VLAN_MASK 0x08000000 /* VLAN frame enable */
+#define XAE_TC_IFG_MASK 0x02000000 /* Inter-frame gap adjustment
+ * enable */
+
+/* Bit masks for Axi Ethernet FCC register */
+#define XAE_FCC_FCRX_MASK 0x20000000 /* Rx flow control enable */
+#define XAE_FCC_FCTX_MASK 0x40000000 /* Tx flow control enable */
+
+/* Bit masks for Axi Ethernet EMMC register */
+#define XAE_EMMC_LINKSPEED_MASK 0xC0000000 /* Link speed */
+#define XAE_EMMC_RGMII_MASK 0x20000000 /* RGMII mode enable */
+#define XAE_EMMC_SGMII_MASK 0x10000000 /* SGMII mode enable */
+#define XAE_EMMC_GPCS_MASK 0x08000000 /* 1000BaseX mode enable */
+#define XAE_EMMC_HOST_MASK 0x04000000 /* Host interface enable */
+#define XAE_EMMC_TX16BIT 0x02000000 /* 16 bit Tx client enable */
+#define XAE_EMMC_RX16BIT 0x01000000 /* 16 bit Rx client enable */
+#define XAE_EMMC_LINKSPD_10 0x00000000 /* Link Speed mask for 10 Mbit */
+#define XAE_EMMC_LINKSPD_100 0x40000000 /* Link Speed mask for 100 Mbit */
+#define XAE_EMMC_LINKSPD_1000 0x80000000 /* Link Speed mask for 1000 Mbit */
+
+/* Bit masks for Axi Ethernet PHYC register */
+#define XAE_PHYC_SGMIILINKSPEED_MASK 0xC0000000 /* SGMII link speed mask*/
+#define XAE_PHYC_RGMIILINKSPEED_MASK 0x0000000C /* RGMII link speed */
+#define XAE_PHYC_RGMIIHD_MASK 0x00000002 /* RGMII Half-duplex */
+#define XAE_PHYC_RGMIILINK_MASK 0x00000001 /* RGMII link status */
+#define XAE_PHYC_RGLINKSPD_10 0x00000000 /* RGMII link 10 Mbit */
+#define XAE_PHYC_RGLINKSPD_100 0x00000004 /* RGMII link 100 Mbit */
+#define XAE_PHYC_RGLINKSPD_1000 0x00000008 /* RGMII link 1000 Mbit */
+#define XAE_PHYC_SGLINKSPD_10 0x00000000 /* SGMII link 10 Mbit */
+#define XAE_PHYC_SGLINKSPD_100 0x40000000 /* SGMII link 100 Mbit */
+#define XAE_PHYC_SGLINKSPD_1000 0x80000000 /* SGMII link 1000 Mbit */
+
+/* Bit masks for Axi Ethernet MDIO interface MC register */
+#define XAE_MDIO_MC_MDIOEN_MASK 0x00000040 /* MII management enable */
+#define XAE_MDIO_MC_CLOCK_DIVIDE_MAX 0x3F /* Maximum MDIO divisor */
+
+/* Bit masks for Axi Ethernet MDIO interface MCR register */
+#define XAE_MDIO_MCR_PHYAD_MASK 0x1F000000 /* Phy Address Mask */
+#define XAE_MDIO_MCR_PHYAD_SHIFT 24 /* Phy Address Shift */
+#define XAE_MDIO_MCR_REGAD_MASK 0x001F0000 /* Reg Address Mask */
+#define XAE_MDIO_MCR_REGAD_SHIFT 16 /* Reg Address Shift */
+#define XAE_MDIO_MCR_OP_MASK 0x0000C000 /* Operation Code Mask */
+#define XAE_MDIO_MCR_OP_SHIFT 13 /* Operation Code Shift */
+#define XAE_MDIO_MCR_OP_READ_MASK 0x00008000 /* Op Code Read Mask */
+#define XAE_MDIO_MCR_OP_WRITE_MASK 0x00004000 /* Op Code Write Mask */
+#define XAE_MDIO_MCR_INITIATE_MASK 0x00000800 /* Ready Mask */
+#define XAE_MDIO_MCR_READY_MASK 0x00000080 /* Ready Mask */
+
+/* Bit masks for Axi Ethernet MDIO interface MIS, MIP, MIE, MIC registers */
+#define XAE_MDIO_INT_MIIM_RDY_MASK 0x00000001 /* MIIM Interrupt */
+
+/* Bit masks for Axi Ethernet UAW1 register */
+#define XAE_UAW1_UNICASTADDR_MASK 0x0000FFFF /* Station address bits
+ * [47:32]; Station address
+ * bits [31:0] are stored in
+ * register UAW0 */
+
+/* Bit masks for Axi Ethernet FMI register */
+#define XAE_FMI_PM_MASK 0x80000000 /* Promis. mode enable */
+#define XAE_FMI_IND_MASK 0x00000003 /* Index Mask */
+
+#define XAE_MDIO_DIV_DFT 29 /* Default MDIO clock divisor */
+
+/* Defines for different options for C_PHY_TYPE parameter in Axi Ethernet IP */
+#define XAE_PHY_TYPE_MII 0
+#define XAE_PHY_TYPE_GMII 1
+#define XAE_PHY_TYPE_RGMII_1_3 2
+#define XAE_PHY_TYPE_RGMII_2_0 3
+#define XAE_PHY_TYPE_SGMII 4
+#define XAE_PHY_TYPE_1000BASE_X 5
+
+#define XAE_MULTICAST_CAM_TABLE_NUM 4 /* Total number of entries in the
+ * hardware multicast table. */
+
+/* Axi Ethernet Synthesis features */
+#define XAE_FEATURE_PARTIAL_RX_CSUM (1 << 0)
+#define XAE_FEATURE_PARTIAL_TX_CSUM (1 << 1)
+#define XAE_FEATURE_FULL_RX_CSUM (1 << 2)
+#define XAE_FEATURE_FULL_TX_CSUM (1 << 3)
+
+#define XAE_NO_CSUM_OFFLOAD 0
+
+#define XAE_FULL_CSUM_STATUS_MASK 0x00000038
+#define XAE_IP_UDP_CSUM_VALIDATED 0x00000003
+#define XAE_IP_TCP_CSUM_VALIDATED 0x00000002
+
+#define DELAY_OF_ONE_MILLISEC 1000
+
+/**
+ * struct axidma_bd - Axi Dma buffer descriptor layout
+ * @next: MM2S/S2MM Next Descriptor Pointer
+ * @reserved1: Reserved and not used
+ * @phys: MM2S/S2MM Buffer Address
+ * @reserved2: Reserved and not used
+ * @reserved3: Reserved and not used
+ * @reserved4: Reserved and not used
+ * @cntrl: MM2S/S2MM Control value
+ * @status: MM2S/S2MM Status value
+ * @app0: MM2S/S2MM User Application Field 0.
+ * @app1: MM2S/S2MM User Application Field 1.
+ * @app2: MM2S/S2MM User Application Field 2.
+ * @app3: MM2S/S2MM User Application Field 3.
+ * @app4: MM2S/S2MM User Application Field 4.
+ * @sw_id_offset: MM2S/S2MM Sw ID
+ * @reserved5: Reserved and not used
+ * @reserved6: Reserved and not used
+ */
+struct axidma_bd {
+ u32 next; /* Physical address of next buffer descriptor */
+ u32 reserved1;
+ u32 phys;
+ u32 reserved2;
+ u32 reserved3;
+ u32 reserved4;
+ u32 cntrl;
+ u32 status;
+ u32 app0;
+ u32 app1; /* TX start << 16 | insert */
+ u32 app2; /* TX csum seed */
+ u32 app3;
+ u32 app4;
+ u32 sw_id_offset;
+ u32 reserved5;
+ u32 reserved6;
+};
+
+/**
+ * struct axienet_local - axienet private per device data
+ * @ndev: Pointer for net_device to which it will be attached.
+ * @dev: Pointer to device structure
+ * @phy_dev: Pointer to PHY device structure attached to the axienet_local
+ * @phy_node: Pointer to device node structure
+ * @mii_bus: Pointer to MII bus structure
+ * @mdio_irqs: IRQs table for MDIO bus required in mii_bus structure
+ * @regs: Base address for the axienet_local device address space
+ * @dma_regs: Base address for the axidma device address space
+ * @dma_err_tasklet: Tasklet structure to process Axi DMA errors
+ * @tx_irq: Axidma TX IRQ number
+ * @rx_irq: Axidma RX IRQ number
+ * @temac_type: axienet type to identify between soft and hard temac
+ * @phy_type: Phy type to identify between MII/GMII/RGMII/SGMII/1000 Base-X
+ * @options: AxiEthernet option word
+ * @last_link: Phy link state in which the PHY was negotiated earlier
+ * @features: Stores the extended features supported by the axienet hw
+ * @tx_bd_v: Virtual address of the TX buffer descriptor ring
+ * @tx_bd_p: Physical address(start address) of the TX buffer descr. ring
+ * @rx_bd_v: Virtual address of the RX buffer descriptor ring
+ * @rx_bd_p: Physical address(start address) of the RX buffer descr. ring
+ * @tx_bd_ci: Stores the index of the Tx buffer descriptor in the ring being
+ * accessed currently. Used while alloc. BDs before a TX starts
+ * @tx_bd_tail: Stores the index of the Tx buffer descriptor in the ring being
+ * accessed currently. Used while processing BDs after the TX
+ * completed.
+ * @rx_bd_ci: Stores the index of the Rx buffer descriptor in the ring being
+ * accessed currently.
+ * @max_frm_size: Stores the maximum size of the frame that can be that
+ * Txed/Rxed in the existing hardware. If jumbo option is
+ * supported, the maximum frame size would be 9k. Else it is
+ * 1522 bytes (assuming support for basic VLAN)
+ * @jumbo_support: Stores hardware configuration for jumbo support. If hardware
+ * can handle jumbo packets, this entry will be 1, else 0.
+ */
+struct axienet_local {
+ struct net_device *ndev;
+ struct device *dev;
+
+ /* Connection to PHY device */
+ struct phy_device *phy_dev; /* Pointer to PHY device */
+ struct device_node *phy_node;
+
+ /* MDIO bus data */
+ struct mii_bus *mii_bus; /* MII bus reference */
+ int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */
+
+ /* IO registers, dma functions and IRQs */
+ void __iomem *regs;
+ void __iomem *dma_regs;
+
+ struct tasklet_struct dma_err_tasklet;
+
+ int tx_irq;
+ int rx_irq;
+ u32 temac_type;
+ u32 phy_type;
+
+ u32 options; /* Current options word */
+ u32 last_link;
+ u32 features;
+
+ /* Buffer descriptors */
+ struct axidma_bd *tx_bd_v;
+ dma_addr_t tx_bd_p;
+ struct axidma_bd *rx_bd_v;
+ dma_addr_t rx_bd_p;
+ u32 tx_bd_ci;
+ u32 tx_bd_tail;
+ u32 rx_bd_ci;
+
+ u32 max_frm_size;
+ u32 jumbo_support;
+
+ int csum_offload_on_tx_path;
+ int csum_offload_on_rx_path;
+
+ u32 coalesce_count_rx;
+ u32 coalesce_count_tx;
+};
+
+/**
+ * struct axiethernet_option - Used to set axi ethernet hardware options
+ * @opt: Option to be set.
+ * @reg: Register offset to be written for setting the option
+ * @m_or: Mask to be ORed for setting the option in the register
+ */
+struct axienet_option {
+ u32 opt;
+ u32 reg;
+ u32 m_or;
+};
+
+/**
+ * axienet_ior - Memory mapped Axi Ethernet register read
+ * @lp: Pointer to axienet local structure
+ * @offset: Address offset from the base address of Axi Ethernet core
+ *
+ * returns: The contents of the Axi Ethernet register
+ *
+ * This function returns the contents of the corresponding register.
+ */
+static inline u32 axienet_ior(struct axienet_local *lp, off_t offset)
+{
+ return in_be32(lp->regs + offset);
+}
+
+/**
+ * axienet_iow - Memory mapped Axi Ethernet register write
+ * @lp: Pointer to axienet local structure
+ * @offset: Address offset from the base address of Axi Ethernet core
+ * @value: Value to be written into the Axi Ethernet register
+ *
+ * This function writes the desired value into the corresponding Axi Ethernet
+ * register.
+ */
+static inline void axienet_iow(struct axienet_local *lp, off_t offset,
+ u32 value)
+{
+ out_be32((lp->regs + offset), value);
+}
+
+/* Function prototypes visible in xilinx_axienet_mdio.c for other files */
+int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np);
+int axienet_mdio_wait_until_ready(struct axienet_local *lp);
+void axienet_mdio_teardown(struct axienet_local *lp);
+
+#endif /* XILINX_AXI_ENET_H */
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
new file mode 100644
index 000000000000..2fcbeba6814b
--- /dev/null
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -0,0 +1,1669 @@
+/*
+ * Xilinx Axi Ethernet device driver
+ *
+ * Copyright (c) 2008 Nissin Systems Co., Ltd., Yoshio Kashiwagi
+ * Copyright (c) 2005-2008 DLA Systems, David H. Lynch Jr. <dhlii@dlasys.net>
+ * Copyright (c) 2008-2009 Secret Lab Technologies Ltd.
+ * Copyright (c) 2010 Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch>
+ * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch>
+ *
+ * This is a driver for the Xilinx Axi Ethernet which is used in the Virtex6
+ * and Spartan6.
+ *
+ * TODO:
+ * - Add Axi Fifo support.
+ * - Factor out Axi DMA code into separate driver.
+ * - Test and fix basic multicast filtering.
+ * - Add support for extended multicast filtering.
+ * - Test basic VLAN support.
+ * - Add support for extended VLAN support.
+ */
+
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of_mdio.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/phy.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+
+#include "xilinx_axienet.h"
+
+/* Descriptors defines for Tx and Rx DMA - 2^n for the best performance */
+#define TX_BD_NUM 64
+#define RX_BD_NUM 128
+
+/* Must be shorter than length of ethtool_drvinfo.driver field to fit */
+#define DRIVER_NAME "xaxienet"
+#define DRIVER_DESCRIPTION "Xilinx Axi Ethernet driver"
+#define DRIVER_VERSION "1.00a"
+
+#define AXIENET_REGS_N 32
+
+/* Match table for of_platform binding */
+static struct of_device_id axienet_of_match[] __devinitdata = {
+ { .compatible = "xlnx,axi-ethernet-1.00.a", },
+ { .compatible = "xlnx,axi-ethernet-1.01.a", },
+ { .compatible = "xlnx,axi-ethernet-2.01.a", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, axienet_of_match);
+
+/* Option table for setting up Axi Ethernet hardware options */
+static struct axienet_option axienet_options[] = {
+ /* Turn on jumbo packet support for both Rx and Tx */
+ {
+ .opt = XAE_OPTION_JUMBO,
+ .reg = XAE_TC_OFFSET,
+ .m_or = XAE_TC_JUM_MASK,
+ }, {
+ .opt = XAE_OPTION_JUMBO,
+ .reg = XAE_RCW1_OFFSET,
+ .m_or = XAE_RCW1_JUM_MASK,
+ }, { /* Turn on VLAN packet support for both Rx and Tx */
+ .opt = XAE_OPTION_VLAN,
+ .reg = XAE_TC_OFFSET,
+ .m_or = XAE_TC_VLAN_MASK,
+ }, {
+ .opt = XAE_OPTION_VLAN,
+ .reg = XAE_RCW1_OFFSET,
+ .m_or = XAE_RCW1_VLAN_MASK,
+ }, { /* Turn on FCS stripping on receive packets */
+ .opt = XAE_OPTION_FCS_STRIP,
+ .reg = XAE_RCW1_OFFSET,
+ .m_or = XAE_RCW1_FCS_MASK,
+ }, { /* Turn on FCS insertion on transmit packets */
+ .opt = XAE_OPTION_FCS_INSERT,
+ .reg = XAE_TC_OFFSET,
+ .m_or = XAE_TC_FCS_MASK,
+ }, { /* Turn off length/type field checking on receive packets */
+ .opt = XAE_OPTION_LENTYPE_ERR,
+ .reg = XAE_RCW1_OFFSET,
+ .m_or = XAE_RCW1_LT_DIS_MASK,
+ }, { /* Turn on Rx flow control */
+ .opt = XAE_OPTION_FLOW_CONTROL,
+ .reg = XAE_FCC_OFFSET,
+ .m_or = XAE_FCC_FCRX_MASK,
+ }, { /* Turn on Tx flow control */
+ .opt = XAE_OPTION_FLOW_CONTROL,
+ .reg = XAE_FCC_OFFSET,
+ .m_or = XAE_FCC_FCTX_MASK,
+ }, { /* Turn on promiscuous frame filtering */
+ .opt = XAE_OPTION_PROMISC,
+ .reg = XAE_FMI_OFFSET,
+ .m_or = XAE_FMI_PM_MASK,
+ }, { /* Enable transmitter */
+ .opt = XAE_OPTION_TXEN,
+ .reg = XAE_TC_OFFSET,
+ .m_or = XAE_TC_TX_MASK,
+ }, { /* Enable receiver */
+ .opt = XAE_OPTION_RXEN,
+ .reg = XAE_RCW1_OFFSET,
+ .m_or = XAE_RCW1_RX_MASK,
+ },
+ {}
+};
+
+/**
+ * axienet_dma_in32 - Memory mapped Axi DMA register read
+ * @lp: Pointer to axienet local structure
+ * @reg: Address offset from the base address of the Axi DMA core
+ *
+ * returns: The contents of the Axi DMA register
+ *
+ * This function returns the contents of the corresponding Axi DMA register.
+ */
+static inline u32 axienet_dma_in32(struct axienet_local *lp, off_t reg)
+{
+ return in_be32(lp->dma_regs + reg);
+}
+
+/**
+ * axienet_dma_out32 - Memory mapped Axi DMA register write.
+ * @lp: Pointer to axienet local structure
+ * @reg: Address offset from the base address of the Axi DMA core
+ * @value: Value to be written into the Axi DMA register
+ *
+ * This function writes the desired value into the corresponding Axi DMA
+ * register.
+ */
+static inline void axienet_dma_out32(struct axienet_local *lp,
+ off_t reg, u32 value)
+{
+ out_be32((lp->dma_regs + reg), value);
+}
+
+/**
+ * axienet_dma_bd_release - Release buffer descriptor rings
+ * @ndev: Pointer to the net_device structure
+ *
+ * This function is used to release the descriptors allocated in
+ * axienet_dma_bd_init. axienet_dma_bd_release is called when Axi Ethernet
+ * driver stop api is called.
+ */
+static void axienet_dma_bd_release(struct net_device *ndev)
+{
+ int i;
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ for (i = 0; i < RX_BD_NUM; i++) {
+ dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys,
+ lp->max_frm_size, DMA_FROM_DEVICE);
+ dev_kfree_skb((struct sk_buff *)
+ (lp->rx_bd_v[i].sw_id_offset));
+ }
+
+ if (lp->rx_bd_v) {
+ dma_free_coherent(ndev->dev.parent,
+ sizeof(*lp->rx_bd_v) * RX_BD_NUM,
+ lp->rx_bd_v,
+ lp->rx_bd_p);
+ }
+ if (lp->tx_bd_v) {
+ dma_free_coherent(ndev->dev.parent,
+ sizeof(*lp->tx_bd_v) * TX_BD_NUM,
+ lp->tx_bd_v,
+ lp->tx_bd_p);
+ }
+}
+
+/**
+ * axienet_dma_bd_init - Setup buffer descriptor rings for Axi DMA
+ * @ndev: Pointer to the net_device structure
+ *
+ * returns: 0, on success
+ * -ENOMEM, on failure
+ *
+ * This function is called to initialize the Rx and Tx DMA descriptor
+ * rings. This initializes the descriptors with required default values
+ * and is called when Axi Ethernet driver reset is called.
+ */
+static int axienet_dma_bd_init(struct net_device *ndev)
+{
+ u32 cr;
+ int i;
+ struct sk_buff *skb;
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ /* Reset the indexes which are used for accessing the BDs */
+ lp->tx_bd_ci = 0;
+ lp->tx_bd_tail = 0;
+ lp->rx_bd_ci = 0;
+
+ /*
+ * Allocate the Tx and Rx buffer descriptors.
+ */
+ lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+ sizeof(*lp->tx_bd_v) * TX_BD_NUM,
+ &lp->tx_bd_p,
+ GFP_KERNEL);
+ if (!lp->tx_bd_v) {
+ dev_err(&ndev->dev, "unable to allocate DMA Tx buffer "
+ "descriptors");
+ goto out;
+ }
+
+ lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+ sizeof(*lp->rx_bd_v) * RX_BD_NUM,
+ &lp->rx_bd_p,
+ GFP_KERNEL);
+ if (!lp->rx_bd_v) {
+ dev_err(&ndev->dev, "unable to allocate DMA Rx buffer "
+ "descriptors");
+ goto out;
+ }
+
+ memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM);
+ for (i = 0; i < TX_BD_NUM; i++) {
+ lp->tx_bd_v[i].next = lp->tx_bd_p +
+ sizeof(*lp->tx_bd_v) *
+ ((i + 1) % TX_BD_NUM);
+ }
+
+ memset(lp->rx_bd_v, 0, sizeof(*lp->rx_bd_v) * RX_BD_NUM);
+ for (i = 0; i < RX_BD_NUM; i++) {
+ lp->rx_bd_v[i].next = lp->rx_bd_p +
+ sizeof(*lp->rx_bd_v) *
+ ((i + 1) % RX_BD_NUM);
+
+ skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
+ if (!skb) {
+ dev_err(&ndev->dev, "alloc_skb error %d\n", i);
+ goto out;
+ }
+
+ lp->rx_bd_v[i].sw_id_offset = (u32) skb;
+ lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
+ skb->data,
+ lp->max_frm_size,
+ DMA_FROM_DEVICE);
+ lp->rx_bd_v[i].cntrl = lp->max_frm_size;
+ }
+
+ /* Start updating the Rx channel control register */
+ cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
+ /* Update the interrupt coalesce count */
+ cr = ((cr & ~XAXIDMA_COALESCE_MASK) |
+ ((lp->coalesce_count_rx) << XAXIDMA_COALESCE_SHIFT));
+ /* Update the delay timer count */
+ cr = ((cr & ~XAXIDMA_DELAY_MASK) |
+ (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
+ /* Enable coalesce, delay timer and error interrupts */
+ cr |= XAXIDMA_IRQ_ALL_MASK;
+ /* Write to the Rx channel control register */
+ axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
+
+ /* Start updating the Tx channel control register */
+ cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
+ /* Update the interrupt coalesce count */
+ cr = (((cr & ~XAXIDMA_COALESCE_MASK)) |
+ ((lp->coalesce_count_tx) << XAXIDMA_COALESCE_SHIFT));
+ /* Update the delay timer count */
+ cr = (((cr & ~XAXIDMA_DELAY_MASK)) |
+ (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
+ /* Enable coalesce, delay timer and error interrupts */
+ cr |= XAXIDMA_IRQ_ALL_MASK;
+ /* Write to the Tx channel control register */
+ axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
+
+ /* Populate the tail pointer and bring the Rx Axi DMA engine out of
+ * halted state. This will make the Rx side ready for reception.*/
+ axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
+ cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
+ axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
+ cr | XAXIDMA_CR_RUNSTOP_MASK);
+ axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
+ (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
+
+ /* Write to the RS (Run-stop) bit in the Tx channel control register.
+ * Tx channel is now ready to run. But only after we write to the
+ * tail pointer register that the Tx channel will start transmitting */
+ axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
+ cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
+ axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
+ cr | XAXIDMA_CR_RUNSTOP_MASK);
+
+ return 0;
+out:
+ axienet_dma_bd_release(ndev);
+ return -ENOMEM;
+}
+
+/**
+ * axienet_set_mac_address - Write the MAC address
+ * @ndev: Pointer to the net_device structure
+ * @address: 6 byte Address to be written as MAC address
+ *
+ * This function is called to initialize the MAC address of the Axi Ethernet
+ * core. It writes to the UAW0 and UAW1 registers of the core.
+ */
+static void axienet_set_mac_address(struct net_device *ndev, void *address)
+{
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ if (address)
+ memcpy(ndev->dev_addr, address, ETH_ALEN);
+ if (!is_valid_ether_addr(ndev->dev_addr))
+ random_ether_addr(ndev->dev_addr);
+
+ /* Set up unicast MAC address filter set its mac address */
+ axienet_iow(lp, XAE_UAW0_OFFSET,
+ (ndev->dev_addr[0]) |
+ (ndev->dev_addr[1] << 8) |
+ (ndev->dev_addr[2] << 16) |
+ (ndev->dev_addr[3] << 24));
+ axienet_iow(lp, XAE_UAW1_OFFSET,
+ (((axienet_ior(lp, XAE_UAW1_OFFSET)) &
+ ~XAE_UAW1_UNICASTADDR_MASK) |
+ (ndev->dev_addr[4] |
+ (ndev->dev_addr[5] << 8))));
+}
+
+/**
+ * netdev_set_mac_address - Write the MAC address (from outside the driver)
+ * @ndev: Pointer to the net_device structure
+ * @p: 6 byte Address to be written as MAC address
+ *
+ * returns: 0 for all conditions. Presently, there is no failure case.
+ *
+ * This function is called to initialize the MAC address of the Axi Ethernet
+ * core. It calls the core specific axienet_set_mac_address. This is the
+ * function that goes into net_device_ops structure entry ndo_set_mac_address.
+ */
+static int netdev_set_mac_address(struct net_device *ndev, void *p)
+{
+ struct sockaddr *addr = p;
+ axienet_set_mac_address(ndev, addr->sa_data);
+ return 0;
+}
+
+/**
+ * axienet_set_multicast_list - Prepare the multicast table
+ * @ndev: Pointer to the net_device structure
+ *
+ * This function is called to initialize the multicast table during
+ * initialization. The Axi Ethernet basic multicast support has a four-entry
+ * multicast table which is initialized here. Additionally this function
+ * goes into the net_device_ops structure entry ndo_set_multicast_list. This
+ * means whenever the multicast table entries need to be updated this
+ * function gets called.
+ */
+static void axienet_set_multicast_list(struct net_device *ndev)
+{
+ int i;
+ u32 reg, af0reg, af1reg;
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) ||
+ netdev_mc_count(ndev) > XAE_MULTICAST_CAM_TABLE_NUM) {
+ /* We must make the kernel realize we had to move into
+ * promiscuous mode. If it was a promiscuous mode request
+ * the flag is already set. If not we set it. */
+ ndev->flags |= IFF_PROMISC;
+ reg = axienet_ior(lp, XAE_FMI_OFFSET);
+ reg |= XAE_FMI_PM_MASK;
+ axienet_iow(lp, XAE_FMI_OFFSET, reg);
+ dev_info(&ndev->dev, "Promiscuous mode enabled.\n");
+ } else if (!netdev_mc_empty(ndev)) {
+ struct netdev_hw_addr *ha;
+
+ i = 0;
+ netdev_for_each_mc_addr(ha, ndev) {
+ if (i >= XAE_MULTICAST_CAM_TABLE_NUM)
+ break;
+
+ af0reg = (ha->addr[0]);
+ af0reg |= (ha->addr[1] << 8);
+ af0reg |= (ha->addr[2] << 16);
+ af0reg |= (ha->addr[3] << 24);
+
+ af1reg = (ha->addr[4]);
+ af1reg |= (ha->addr[5] << 8);
+
+ reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
+ reg |= i;
+
+ axienet_iow(lp, XAE_FMI_OFFSET, reg);
+ axienet_iow(lp, XAE_AF0_OFFSET, af0reg);
+ axienet_iow(lp, XAE_AF1_OFFSET, af1reg);
+ i++;
+ }
+ } else {
+ reg = axienet_ior(lp, XAE_FMI_OFFSET);
+ reg &= ~XAE_FMI_PM_MASK;
+
+ axienet_iow(lp, XAE_FMI_OFFSET, reg);
+
+ for (i = 0; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) {
+ reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
+ reg |= i;
+
+ axienet_iow(lp, XAE_FMI_OFFSET, reg);
+ axienet_iow(lp, XAE_AF0_OFFSET, 0);
+ axienet_iow(lp, XAE_AF1_OFFSET, 0);
+ }
+
+ dev_info(&ndev->dev, "Promiscuous mode disabled.\n");
+ }
+}
+
+/**
+ * axienet_setoptions - Set an Axi Ethernet option
+ * @ndev: Pointer to the net_device structure
+ * @options: Option to be enabled/disabled
+ *
+ * The Axi Ethernet core has multiple features which can be selectively turned
+ * on or off. The typical options could be jumbo frame option, basic VLAN
+ * option, promiscuous mode option etc. This function is used to set or clear
+ * these options in the Axi Ethernet hardware. This is done through
+ * axienet_option structure .
+ */
+static void axienet_setoptions(struct net_device *ndev, u32 options)
+{
+ int reg;
+ struct axienet_local *lp = netdev_priv(ndev);
+ struct axienet_option *tp = &axienet_options[0];
+
+ while (tp->opt) {
+ reg = ((axienet_ior(lp, tp->reg)) & ~(tp->m_or));
+ if (options & tp->opt)
+ reg |= tp->m_or;
+ axienet_iow(lp, tp->reg, reg);
+ tp++;
+ }
+
+ lp->options |= options;
+}
+
+static void __axienet_device_reset(struct axienet_local *lp,
+ struct device *dev, off_t offset)
+{
+ u32 timeout;
+ /* Reset Axi DMA. This would reset Axi Ethernet core as well. The reset
+ * process of Axi DMA takes a while to complete as all pending
+ * commands/transfers will be flushed or completed during this
+ * reset process. */
+ axienet_dma_out32(lp, offset, XAXIDMA_CR_RESET_MASK);
+ timeout = DELAY_OF_ONE_MILLISEC;
+ while (axienet_dma_in32(lp, offset) & XAXIDMA_CR_RESET_MASK) {
+ udelay(1);
+ if (--timeout == 0) {
+ dev_err(dev, "axienet_device_reset DMA "
+ "reset timeout!\n");
+ break;
+ }
+ }
+}
+
+/**
+ * axienet_device_reset - Reset and initialize the Axi Ethernet hardware.
+ * @ndev: Pointer to the net_device structure
+ *
+ * This function is called to reset and initialize the Axi Ethernet core. This
+ * is typically called during initialization. It does a reset of the Axi DMA
+ * Rx/Tx channels and initializes the Axi DMA BDs. Since Axi DMA reset lines
+ * areconnected to Axi Ethernet reset lines, this in turn resets the Axi
+ * Ethernet core. No separate hardware reset is done for the Axi Ethernet
+ * core.
+ */
+static void axienet_device_reset(struct net_device *ndev)
+{
+ u32 axienet_status;
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ __axienet_device_reset(lp, &ndev->dev, XAXIDMA_TX_CR_OFFSET);
+ __axienet_device_reset(lp, &ndev->dev, XAXIDMA_RX_CR_OFFSET);
+
+ lp->max_frm_size = XAE_MAX_VLAN_FRAME_SIZE;
+ lp->options &= (~XAE_OPTION_JUMBO);
+
+ if ((ndev->mtu > XAE_MTU) &&
+ (ndev->mtu <= XAE_JUMBO_MTU) &&
+ (lp->jumbo_support)) {
+ lp->max_frm_size = ndev->mtu + XAE_HDR_VLAN_SIZE +
+ XAE_TRL_SIZE;
+ lp->options |= XAE_OPTION_JUMBO;
+ }
+
+ if (axienet_dma_bd_init(ndev)) {
+ dev_err(&ndev->dev, "axienet_device_reset descriptor "
+ "allocation failed\n");
+ }
+
+ axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
+ axienet_status &= ~XAE_RCW1_RX_MASK;
+ axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status);
+
+ axienet_status = axienet_ior(lp, XAE_IP_OFFSET);
+ if (axienet_status & XAE_INT_RXRJECT_MASK)
+ axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
+
+ axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK);
+
+ /* Sync default options with HW but leave receiver and
+ * transmitter disabled.*/
+ axienet_setoptions(ndev, lp->options &
+ ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
+ axienet_set_mac_address(ndev, NULL);
+ axienet_set_multicast_list(ndev);
+ axienet_setoptions(ndev, lp->options);
+
+ ndev->trans_start = jiffies;
+}
+
+/**
+ * axienet_adjust_link - Adjust the PHY link speed/duplex.
+ * @ndev: Pointer to the net_device structure
+ *
+ * This function is called to change the speed and duplex setting after
+ * auto negotiation is done by the PHY. This is the function that gets
+ * registered with the PHY interface through the "of_phy_connect" call.
+ */
+static void axienet_adjust_link(struct net_device *ndev)
+{
+ u32 emmc_reg;
+ u32 link_state;
+ u32 setspeed = 1;
+ struct axienet_local *lp = netdev_priv(ndev);
+ struct phy_device *phy = lp->phy_dev;
+
+ link_state = phy->speed | (phy->duplex << 1) | phy->link;
+ if (lp->last_link != link_state) {
+ if ((phy->speed == SPEED_10) || (phy->speed == SPEED_100)) {
+ if (lp->phy_type == XAE_PHY_TYPE_1000BASE_X)
+ setspeed = 0;
+ } else {
+ if ((phy->speed == SPEED_1000) &&
+ (lp->phy_type == XAE_PHY_TYPE_MII))
+ setspeed = 0;
+ }
+
+ if (setspeed == 1) {
+ emmc_reg = axienet_ior(lp, XAE_EMMC_OFFSET);
+ emmc_reg &= ~XAE_EMMC_LINKSPEED_MASK;
+
+ switch (phy->speed) {
+ case SPEED_1000:
+ emmc_reg |= XAE_EMMC_LINKSPD_1000;
+ break;
+ case SPEED_100:
+ emmc_reg |= XAE_EMMC_LINKSPD_100;
+ break;
+ case SPEED_10:
+ emmc_reg |= XAE_EMMC_LINKSPD_10;
+ break;
+ default:
+ dev_err(&ndev->dev, "Speed other than 10, 100 "
+ "or 1Gbps is not supported\n");
+ break;
+ }
+
+ axienet_iow(lp, XAE_EMMC_OFFSET, emmc_reg);
+ lp->last_link = link_state;
+ phy_print_status(phy);
+ } else {
+ dev_err(&ndev->dev, "Error setting Axi Ethernet "
+ "mac speed\n");
+ }
+ }
+}
+
+/**
+ * axienet_start_xmit_done - Invoked once a transmit is completed by the
+ * Axi DMA Tx channel.
+ * @ndev: Pointer to the net_device structure
+ *
+ * This function is invoked from the Axi DMA Tx isr to notify the completion
+ * of transmit operation. It clears fields in the corresponding Tx BDs and
+ * unmaps the corresponding buffer so that CPU can regain ownership of the
+ * buffer. It finally invokes "netif_wake_queue" to restart transmission if
+ * required.
+ */
+static void axienet_start_xmit_done(struct net_device *ndev)
+{
+ u32 size = 0;
+ u32 packets = 0;
+ struct axienet_local *lp = netdev_priv(ndev);
+ struct axidma_bd *cur_p;
+ unsigned int status = 0;
+
+ cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
+ status = cur_p->status;
+ while (status & XAXIDMA_BD_STS_COMPLETE_MASK) {
+ dma_unmap_single(ndev->dev.parent, cur_p->phys,
+ (cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK),
+ DMA_TO_DEVICE);
+ if (cur_p->app4)
+ dev_kfree_skb_irq((struct sk_buff *)cur_p->app4);
+ /*cur_p->phys = 0;*/
+ cur_p->app0 = 0;
+ cur_p->app1 = 0;
+ cur_p->app2 = 0;
+ cur_p->app4 = 0;
+ cur_p->status = 0;
+
+ size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
+ packets++;
+
+ lp->tx_bd_ci = ++lp->tx_bd_ci % TX_BD_NUM;
+ cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
+ status = cur_p->status;
+ }
+
+ ndev->stats.tx_packets += packets;
+ ndev->stats.tx_bytes += size;
+ netif_wake_queue(ndev);
+}
+
+/**
+ * axienet_check_tx_bd_space - Checks if a BD/group of BDs are currently busy
+ * @lp: Pointer to the axienet_local structure
+ * @num_frag: The number of BDs to check for
+ *
+ * returns: 0, on success
+ * NETDEV_TX_BUSY, if any of the descriptors are not free
+ *
+ * This function is invoked before BDs are allocated and transmission starts.
+ * This function returns 0 if a BD or group of BDs can be allocated for
+ * transmission. If the BD or any of the BDs are not free the function
+ * returns a busy status. This is invoked from axienet_start_xmit.
+ */
+static inline int axienet_check_tx_bd_space(struct axienet_local *lp,
+ int num_frag)
+{
+ struct axidma_bd *cur_p;
+ cur_p = &lp->tx_bd_v[(lp->tx_bd_tail + num_frag) % TX_BD_NUM];
+ if (cur_p->status & XAXIDMA_BD_STS_ALL_MASK)
+ return NETDEV_TX_BUSY;
+ return 0;
+}
+
+/**
+ * axienet_start_xmit - Starts the transmission.
+ * @skb: sk_buff pointer that contains data to be Txed.
+ * @ndev: Pointer to net_device structure.
+ *
+ * returns: NETDEV_TX_OK, on success
+ * NETDEV_TX_BUSY, if any of the descriptors are not free
+ *
+ * This function is invoked from upper layers to initiate transmission. The
+ * function uses the next available free BDs and populates their fields to
+ * start the transmission. Additionally if checksum offloading is supported,
+ * it populates AXI Stream Control fields with appropriate values.
+ */
+static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ u32 ii;
+ u32 num_frag;
+ u32 csum_start_off;
+ u32 csum_index_off;
+ skb_frag_t *frag;
+ dma_addr_t tail_p;
+ struct axienet_local *lp = netdev_priv(ndev);
+ struct axidma_bd *cur_p;
+
+ num_frag = skb_shinfo(skb)->nr_frags;
+ cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+
+ if (axienet_check_tx_bd_space(lp, num_frag)) {
+ if (!netif_queue_stopped(ndev))
+ netif_stop_queue(ndev);
+ return NETDEV_TX_BUSY;
+ }
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (lp->features & XAE_FEATURE_FULL_TX_CSUM) {
+ /* Tx Full Checksum Offload Enabled */
+ cur_p->app0 |= 2;
+ } else if (lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) {
+ csum_start_off = skb_transport_offset(skb);
+ csum_index_off = csum_start_off + skb->csum_offset;
+ /* Tx Partial Checksum Offload Enabled */
+ cur_p->app0 |= 1;
+ cur_p->app1 = (csum_start_off << 16) | csum_index_off;
+ }
+ } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+ cur_p->app0 |= 2; /* Tx Full Checksum Offload Enabled */
+ }
+
+ cur_p->cntrl = skb_headlen(skb) | XAXIDMA_BD_CTRL_TXSOF_MASK;
+ cur_p->phys = dma_map_single(ndev->dev.parent, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+
+ for (ii = 0; ii < num_frag; ii++) {
+ lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
+ cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+ frag = &skb_shinfo(skb)->frags[ii];
+ cur_p->phys = dma_map_single(ndev->dev.parent,
+ skb_frag_address(frag),
+ skb_frag_size(frag),
+ DMA_TO_DEVICE);
+ cur_p->cntrl = skb_frag_size(frag);
+ }
+
+ cur_p->cntrl |= XAXIDMA_BD_CTRL_TXEOF_MASK;
+ cur_p->app4 = (unsigned long)skb;
+
+ tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
+ /* Start the transfer */
+ axienet_dma_out32(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p);
+ lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
+
+ return NETDEV_TX_OK;
+}
+
+/**
+ * axienet_recv - Is called from Axi DMA Rx Isr to complete the received
+ * BD processing.
+ * @ndev: Pointer to net_device structure.
+ *
+ * This function is invoked from the Axi DMA Rx isr to process the Rx BDs. It
+ * does minimal processing and invokes "netif_rx" to complete further
+ * processing.
+ */
+static void axienet_recv(struct net_device *ndev)
+{
+ u32 length;
+ u32 csumstatus;
+ u32 size = 0;
+ u32 packets = 0;
+ dma_addr_t tail_p;
+ struct axienet_local *lp = netdev_priv(ndev);
+ struct sk_buff *skb, *new_skb;
+ struct axidma_bd *cur_p;
+
+ tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
+ cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
+
+ while ((cur_p->status & XAXIDMA_BD_STS_COMPLETE_MASK)) {
+ skb = (struct sk_buff *) (cur_p->sw_id_offset);
+ length = cur_p->app4 & 0x0000FFFF;
+
+ dma_unmap_single(ndev->dev.parent, cur_p->phys,
+ lp->max_frm_size,
+ DMA_FROM_DEVICE);
+
+ skb_put(skb, length);
+ skb->protocol = eth_type_trans(skb, ndev);
+ /*skb_checksum_none_assert(skb);*/
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* if we're doing Rx csum offload, set it up */
+ if (lp->features & XAE_FEATURE_FULL_RX_CSUM) {
+ csumstatus = (cur_p->app2 &
+ XAE_FULL_CSUM_STATUS_MASK) >> 3;
+ if ((csumstatus == XAE_IP_TCP_CSUM_VALIDATED) ||
+ (csumstatus == XAE_IP_UDP_CSUM_VALIDATED)) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+ } else if ((lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) != 0 &&
+ skb->protocol == __constant_htons(ETH_P_IP) &&
+ skb->len > 64) {
+ skb->csum = be32_to_cpu(cur_p->app3 & 0xFFFF);
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ }
+
+ netif_rx(skb);
+
+ size += length;
+ packets++;
+
+ new_skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
+ if (!new_skb) {
+ dev_err(&ndev->dev, "no memory for new sk_buff\n");
+ return;
+ }
+ cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
+ lp->max_frm_size,
+ DMA_FROM_DEVICE);
+ cur_p->cntrl = lp->max_frm_size;
+ cur_p->status = 0;
+ cur_p->sw_id_offset = (u32) new_skb;
+
+ lp->rx_bd_ci = ++lp->rx_bd_ci % RX_BD_NUM;
+ cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
+ }
+
+ ndev->stats.rx_packets += packets;
+ ndev->stats.rx_bytes += size;
+
+ axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, tail_p);
+}
+
+/**
+ * axienet_tx_irq - Tx Done Isr.
+ * @irq: irq number
+ * @_ndev: net_device pointer
+ *
+ * returns: IRQ_HANDLED for all cases.
+ *
+ * This is the Axi DMA Tx done Isr. It invokes "axienet_start_xmit_done"
+ * to complete the BD processing.
+ */
+static irqreturn_t axienet_tx_irq(int irq, void *_ndev)
+{
+ u32 cr;
+ unsigned int status;
+ struct net_device *ndev = _ndev;
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ status = axienet_dma_in32(lp, XAXIDMA_TX_SR_OFFSET);
+ if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) {
+ axienet_start_xmit_done(lp->ndev);
+ goto out;
+ }
+ if (!(status & XAXIDMA_IRQ_ALL_MASK))
+ dev_err(&ndev->dev, "No interrupts asserted in Tx path");
+ if (status & XAXIDMA_IRQ_ERROR_MASK) {
+ dev_err(&ndev->dev, "DMA Tx error 0x%x\n", status);
+ dev_err(&ndev->dev, "Current BD is at: 0x%x\n",
+ (lp->tx_bd_v[lp->tx_bd_ci]).phys);
+
+ cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
+ /* Disable coalesce, delay timer and error interrupts */
+ cr &= (~XAXIDMA_IRQ_ALL_MASK);
+ /* Write to the Tx channel control register */
+ axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
+
+ cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
+ /* Disable coalesce, delay timer and error interrupts */
+ cr &= (~XAXIDMA_IRQ_ALL_MASK);
+ /* Write to the Rx channel control register */
+ axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
+
+ tasklet_schedule(&lp->dma_err_tasklet);
+ }
+out:
+ axienet_dma_out32(lp, XAXIDMA_TX_SR_OFFSET, status);
+ return IRQ_HANDLED;
+}
+
+/**
+ * axienet_rx_irq - Rx Isr.
+ * @irq: irq number
+ * @_ndev: net_device pointer
+ *
+ * returns: IRQ_HANDLED for all cases.
+ *
+ * This is the Axi DMA Rx Isr. It invokes "axienet_recv" to complete the BD
+ * processing.
+ */
+static irqreturn_t axienet_rx_irq(int irq, void *_ndev)
+{
+ u32 cr;
+ unsigned int status;
+ struct net_device *ndev = _ndev;
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ status = axienet_dma_in32(lp, XAXIDMA_RX_SR_OFFSET);
+ if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) {
+ axienet_recv(lp->ndev);
+ goto out;
+ }
+ if (!(status & XAXIDMA_IRQ_ALL_MASK))
+ dev_err(&ndev->dev, "No interrupts asserted in Rx path");
+ if (status & XAXIDMA_IRQ_ERROR_MASK) {
+ dev_err(&ndev->dev, "DMA Rx error 0x%x\n", status);
+ dev_err(&ndev->dev, "Current BD is at: 0x%x\n",
+ (lp->rx_bd_v[lp->rx_bd_ci]).phys);
+
+ cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
+ /* Disable coalesce, delay timer and error interrupts */
+ cr &= (~XAXIDMA_IRQ_ALL_MASK);
+ /* Finally write to the Tx channel control register */
+ axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
+
+ cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
+ /* Disable coalesce, delay timer and error interrupts */
+ cr &= (~XAXIDMA_IRQ_ALL_MASK);
+ /* write to the Rx channel control register */
+ axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
+
+ tasklet_schedule(&lp->dma_err_tasklet);
+ }
+out:
+ axienet_dma_out32(lp, XAXIDMA_RX_SR_OFFSET, status);
+ return IRQ_HANDLED;
+}
+
+/**
+ * axienet_open - Driver open routine.
+ * @ndev: Pointer to net_device structure
+ *
+ * returns: 0, on success.
+ * -ENODEV, if PHY cannot be connected to
+ * non-zero error value on failure
+ *
+ * This is the driver open routine. It calls phy_start to start the PHY device.
+ * It also allocates interrupt service routines, enables the interrupt lines
+ * and ISR handling. Axi Ethernet core is reset through Axi DMA core. Buffer
+ * descriptors are initialized.
+ */
+static int axienet_open(struct net_device *ndev)
+{
+ int ret, mdio_mcreg;
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ dev_dbg(&ndev->dev, "axienet_open()\n");
+
+ mdio_mcreg = axienet_ior(lp, XAE_MDIO_MC_OFFSET);
+ ret = axienet_mdio_wait_until_ready(lp);
+ if (ret < 0)
+ return ret;
+ /* Disable the MDIO interface till Axi Ethernet Reset is completed.
+ * When we do an Axi Ethernet reset, it resets the complete core
+ * including the MDIO. If MDIO is not disabled when the reset
+ * process is started, MDIO will be broken afterwards. */
+ axienet_iow(lp, XAE_MDIO_MC_OFFSET,
+ (mdio_mcreg & (~XAE_MDIO_MC_MDIOEN_MASK)));
+ axienet_device_reset(ndev);
+ /* Enable the MDIO */
+ axienet_iow(lp, XAE_MDIO_MC_OFFSET, mdio_mcreg);
+ ret = axienet_mdio_wait_until_ready(lp);
+ if (ret < 0)
+ return ret;
+
+ if (lp->phy_node) {
+ lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
+ axienet_adjust_link, 0,
+ PHY_INTERFACE_MODE_GMII);
+ if (!lp->phy_dev) {
+ dev_err(lp->dev, "of_phy_connect() failed\n");
+ return -ENODEV;
+ }
+ phy_start(lp->phy_dev);
+ }
+
+ /* Enable interrupts for Axi DMA Tx */
+ ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev);
+ if (ret)
+ goto err_tx_irq;
+ /* Enable interrupts for Axi DMA Rx */
+ ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev);
+ if (ret)
+ goto err_rx_irq;
+ /* Enable tasklets for Axi DMA error handling */
+ tasklet_enable(&lp->dma_err_tasklet);
+ return 0;
+
+err_rx_irq:
+ free_irq(lp->tx_irq, ndev);
+err_tx_irq:
+ if (lp->phy_dev)
+ phy_disconnect(lp->phy_dev);
+ lp->phy_dev = NULL;
+ dev_err(lp->dev, "request_irq() failed\n");
+ return ret;
+}
+
+/**
+ * axienet_stop - Driver stop routine.
+ * @ndev: Pointer to net_device structure
+ *
+ * returns: 0, on success.
+ *
+ * This is the driver stop routine. It calls phy_disconnect to stop the PHY
+ * device. It also removes the interrupt handlers and disables the interrupts.
+ * The Axi DMA Tx/Rx BDs are released.
+ */
+static int axienet_stop(struct net_device *ndev)
+{
+ u32 cr;
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ dev_dbg(&ndev->dev, "axienet_close()\n");
+
+ cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
+ axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
+ cr & (~XAXIDMA_CR_RUNSTOP_MASK));
+ cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
+ axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
+ cr & (~XAXIDMA_CR_RUNSTOP_MASK));
+ axienet_setoptions(ndev, lp->options &
+ ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
+
+ tasklet_disable(&lp->dma_err_tasklet);
+
+ free_irq(lp->tx_irq, ndev);
+ free_irq(lp->rx_irq, ndev);
+
+ if (lp->phy_dev)
+ phy_disconnect(lp->phy_dev);
+ lp->phy_dev = NULL;
+
+ axienet_dma_bd_release(ndev);
+ return 0;
+}
+
+/**
+ * axienet_change_mtu - Driver change mtu routine.
+ * @ndev: Pointer to net_device structure
+ * @new_mtu: New mtu value to be applied
+ *
+ * returns: Always returns 0 (success).
+ *
+ * This is the change mtu driver routine. It checks if the Axi Ethernet
+ * hardware supports jumbo frames before changing the mtu. This can be
+ * called only when the device is not up.
+ */
+static int axienet_change_mtu(struct net_device *ndev, int new_mtu)
+{
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ if (netif_running(ndev))
+ return -EBUSY;
+ if (lp->jumbo_support) {
+ if ((new_mtu > XAE_JUMBO_MTU) || (new_mtu < 64))
+ return -EINVAL;
+ ndev->mtu = new_mtu;
+ } else {
+ if ((new_mtu > XAE_MTU) || (new_mtu < 64))
+ return -EINVAL;
+ ndev->mtu = new_mtu;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * axienet_poll_controller - Axi Ethernet poll mechanism.
+ * @ndev: Pointer to net_device structure
+ *
+ * This implements Rx/Tx ISR poll mechanisms. The interrupts are disabled prior
+ * to polling the ISRs and are enabled back after the polling is done.
+ */
+static void axienet_poll_controller(struct net_device *ndev)
+{
+ struct axienet_local *lp = netdev_priv(ndev);
+ disable_irq(lp->tx_irq);
+ disable_irq(lp->rx_irq);
+ axienet_rx_irq(lp->tx_irq, ndev);
+ axienet_tx_irq(lp->rx_irq, ndev);
+ enable_irq(lp->tx_irq);
+ enable_irq(lp->rx_irq);
+}
+#endif
+
+static const struct net_device_ops axienet_netdev_ops = {
+ .ndo_open = axienet_open,
+ .ndo_stop = axienet_stop,
+ .ndo_start_xmit = axienet_start_xmit,
+ .ndo_change_mtu = axienet_change_mtu,
+ .ndo_set_mac_address = netdev_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_rx_mode = axienet_set_multicast_list,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = axienet_poll_controller,
+#endif
+};
+
+/**
+ * axienet_ethtools_get_settings - Get Axi Ethernet settings related to PHY.
+ * @ndev: Pointer to net_device structure
+ * @ecmd: Pointer to ethtool_cmd structure
+ *
+ * This implements ethtool command for getting PHY settings. If PHY could
+ * not be found, the function returns -ENODEV. This function calls the
+ * relevant PHY ethtool API to get the PHY settings.
+ * Issue "ethtool ethX" under linux prompt to execute this function.
+ */
+static int axienet_ethtools_get_settings(struct net_device *ndev,
+ struct ethtool_cmd *ecmd)
+{
+ struct axienet_local *lp = netdev_priv(ndev);
+ struct phy_device *phydev = lp->phy_dev;
+ if (!phydev)
+ return -ENODEV;
+ return phy_ethtool_gset(phydev, ecmd);
+}
+
+/**
+ * axienet_ethtools_set_settings - Set PHY settings as passed in the argument.
+ * @ndev: Pointer to net_device structure
+ * @ecmd: Pointer to ethtool_cmd structure
+ *
+ * This implements ethtool command for setting various PHY settings. If PHY
+ * could not be found, the function returns -ENODEV. This function calls the
+ * relevant PHY ethtool API to set the PHY.
+ * Issue e.g. "ethtool -s ethX speed 1000" under linux prompt to execute this
+ * function.
+ */
+static int axienet_ethtools_set_settings(struct net_device *ndev,
+ struct ethtool_cmd *ecmd)
+{
+ struct axienet_local *lp = netdev_priv(ndev);
+ struct phy_device *phydev = lp->phy_dev;
+ if (!phydev)
+ return -ENODEV;
+ return phy_ethtool_sset(phydev, ecmd);
+}
+
+/**
+ * axienet_ethtools_get_drvinfo - Get various Axi Ethernet driver information.
+ * @ndev: Pointer to net_device structure
+ * @ed: Pointer to ethtool_drvinfo structure
+ *
+ * This implements ethtool command for getting the driver information.
+ * Issue "ethtool -i ethX" under linux prompt to execute this function.
+ */
+static void axienet_ethtools_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *ed)
+{
+ memset(ed, 0, sizeof(struct ethtool_drvinfo));
+ strcpy(ed->driver, DRIVER_NAME);
+ strcpy(ed->version, DRIVER_VERSION);
+ ed->regdump_len = sizeof(u32) * AXIENET_REGS_N;
+}
+
+/**
+ * axienet_ethtools_get_regs_len - Get the total regs length present in the
+ * AxiEthernet core.
+ * @ndev: Pointer to net_device structure
+ *
+ * This implements ethtool command for getting the total register length
+ * information.
+ */
+static int axienet_ethtools_get_regs_len(struct net_device *ndev)
+{
+ return sizeof(u32) * AXIENET_REGS_N;
+}
+
+/**
+ * axienet_ethtools_get_regs - Dump the contents of all registers present
+ * in AxiEthernet core.
+ * @ndev: Pointer to net_device structure
+ * @regs: Pointer to ethtool_regs structure
+ * @ret: Void pointer used to return the contents of the registers.
+ *
+ * This implements ethtool command for getting the Axi Ethernet register dump.
+ * Issue "ethtool -d ethX" to execute this function.
+ */
+static void axienet_ethtools_get_regs(struct net_device *ndev,
+ struct ethtool_regs *regs, void *ret)
+{
+ u32 *data = (u32 *) ret;
+ size_t len = sizeof(u32) * AXIENET_REGS_N;
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ regs->version = 0;
+ regs->len = len;
+
+ memset(data, 0, len);
+ data[0] = axienet_ior(lp, XAE_RAF_OFFSET);
+ data[1] = axienet_ior(lp, XAE_TPF_OFFSET);
+ data[2] = axienet_ior(lp, XAE_IFGP_OFFSET);
+ data[3] = axienet_ior(lp, XAE_IS_OFFSET);
+ data[4] = axienet_ior(lp, XAE_IP_OFFSET);
+ data[5] = axienet_ior(lp, XAE_IE_OFFSET);
+ data[6] = axienet_ior(lp, XAE_TTAG_OFFSET);
+ data[7] = axienet_ior(lp, XAE_RTAG_OFFSET);
+ data[8] = axienet_ior(lp, XAE_UAWL_OFFSET);
+ data[9] = axienet_ior(lp, XAE_UAWU_OFFSET);
+ data[10] = axienet_ior(lp, XAE_TPID0_OFFSET);
+ data[11] = axienet_ior(lp, XAE_TPID1_OFFSET);
+ data[12] = axienet_ior(lp, XAE_PPST_OFFSET);
+ data[13] = axienet_ior(lp, XAE_RCW0_OFFSET);
+ data[14] = axienet_ior(lp, XAE_RCW1_OFFSET);
+ data[15] = axienet_ior(lp, XAE_TC_OFFSET);
+ data[16] = axienet_ior(lp, XAE_FCC_OFFSET);
+ data[17] = axienet_ior(lp, XAE_EMMC_OFFSET);
+ data[18] = axienet_ior(lp, XAE_PHYC_OFFSET);
+ data[19] = axienet_ior(lp, XAE_MDIO_MC_OFFSET);
+ data[20] = axienet_ior(lp, XAE_MDIO_MCR_OFFSET);
+ data[21] = axienet_ior(lp, XAE_MDIO_MWD_OFFSET);
+ data[22] = axienet_ior(lp, XAE_MDIO_MRD_OFFSET);
+ data[23] = axienet_ior(lp, XAE_MDIO_MIS_OFFSET);
+ data[24] = axienet_ior(lp, XAE_MDIO_MIP_OFFSET);
+ data[25] = axienet_ior(lp, XAE_MDIO_MIE_OFFSET);
+ data[26] = axienet_ior(lp, XAE_MDIO_MIC_OFFSET);
+ data[27] = axienet_ior(lp, XAE_UAW0_OFFSET);
+ data[28] = axienet_ior(lp, XAE_UAW1_OFFSET);
+ data[29] = axienet_ior(lp, XAE_FMI_OFFSET);
+ data[30] = axienet_ior(lp, XAE_AF0_OFFSET);
+ data[31] = axienet_ior(lp, XAE_AF1_OFFSET);
+}
+
+/**
+ * axienet_ethtools_get_pauseparam - Get the pause parameter setting for
+ * Tx and Rx paths.
+ * @ndev: Pointer to net_device structure
+ * @epauseparm: Pointer to ethtool_pauseparam structure.
+ *
+ * This implements ethtool command for getting axi ethernet pause frame
+ * setting. Issue "ethtool -a ethX" to execute this function.
+ */
+static void
+axienet_ethtools_get_pauseparam(struct net_device *ndev,
+ struct ethtool_pauseparam *epauseparm)
+{
+ u32 regval;
+ struct axienet_local *lp = netdev_priv(ndev);
+ epauseparm->autoneg = 0;
+ regval = axienet_ior(lp, XAE_FCC_OFFSET);
+ epauseparm->tx_pause = regval & XAE_FCC_FCTX_MASK;
+ epauseparm->rx_pause = regval & XAE_FCC_FCRX_MASK;
+}
+
+/**
+ * axienet_ethtools_set_pauseparam - Set device pause parameter(flow control)
+ * settings.
+ * @ndev: Pointer to net_device structure
+ * @epauseparam:Pointer to ethtool_pauseparam structure
+ *
+ * This implements ethtool command for enabling flow control on Rx and Tx
+ * paths. Issue "ethtool -A ethX tx on|off" under linux prompt to execute this
+ * function.
+ */
+static int
+axienet_ethtools_set_pauseparam(struct net_device *ndev,
+ struct ethtool_pauseparam *epauseparm)
+{
+ u32 regval = 0;
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ printk(KERN_ERR "%s: Please stop netif before applying "
+ "configruation\n", ndev->name);
+ return -EFAULT;
+ }
+
+ regval = axienet_ior(lp, XAE_FCC_OFFSET);
+ if (epauseparm->tx_pause)
+ regval |= XAE_FCC_FCTX_MASK;
+ else
+ regval &= ~XAE_FCC_FCTX_MASK;
+ if (epauseparm->rx_pause)
+ regval |= XAE_FCC_FCRX_MASK;
+ else
+ regval &= ~XAE_FCC_FCRX_MASK;
+ axienet_iow(lp, XAE_FCC_OFFSET, regval);
+
+ return 0;
+}
+
+/**
+ * axienet_ethtools_get_coalesce - Get DMA interrupt coalescing count.
+ * @ndev: Pointer to net_device structure
+ * @ecoalesce: Pointer to ethtool_coalesce structure
+ *
+ * This implements ethtool command for getting the DMA interrupt coalescing
+ * count on Tx and Rx paths. Issue "ethtool -c ethX" under linux prompt to
+ * execute this function.
+ */
+static int axienet_ethtools_get_coalesce(struct net_device *ndev,
+ struct ethtool_coalesce *ecoalesce)
+{
+ u32 regval = 0;
+ struct axienet_local *lp = netdev_priv(ndev);
+ regval = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
+ ecoalesce->rx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK)
+ >> XAXIDMA_COALESCE_SHIFT;
+ regval = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
+ ecoalesce->tx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK)
+ >> XAXIDMA_COALESCE_SHIFT;
+ return 0;
+}
+
+/**
+ * axienet_ethtools_set_coalesce - Set DMA interrupt coalescing count.
+ * @ndev: Pointer to net_device structure
+ * @ecoalesce: Pointer to ethtool_coalesce structure
+ *
+ * This implements ethtool command for setting the DMA interrupt coalescing
+ * count on Tx and Rx paths. Issue "ethtool -C ethX rx-frames 5" under linux
+ * prompt to execute this function.
+ */
+static int axienet_ethtools_set_coalesce(struct net_device *ndev,
+ struct ethtool_coalesce *ecoalesce)
+{
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ printk(KERN_ERR "%s: Please stop netif before applying "
+ "configruation\n", ndev->name);
+ return -EFAULT;
+ }
+
+ if ((ecoalesce->rx_coalesce_usecs) ||
+ (ecoalesce->rx_coalesce_usecs_irq) ||
+ (ecoalesce->rx_max_coalesced_frames_irq) ||
+ (ecoalesce->tx_coalesce_usecs) ||
+ (ecoalesce->tx_coalesce_usecs_irq) ||
+ (ecoalesce->tx_max_coalesced_frames_irq) ||
+ (ecoalesce->stats_block_coalesce_usecs) ||
+ (ecoalesce->use_adaptive_rx_coalesce) ||
+ (ecoalesce->use_adaptive_tx_coalesce) ||
+ (ecoalesce->pkt_rate_low) ||
+ (ecoalesce->rx_coalesce_usecs_low) ||
+ (ecoalesce->rx_max_coalesced_frames_low) ||
+ (ecoalesce->tx_coalesce_usecs_low) ||
+ (ecoalesce->tx_max_coalesced_frames_low) ||
+ (ecoalesce->pkt_rate_high) ||
+ (ecoalesce->rx_coalesce_usecs_high) ||
+ (ecoalesce->rx_max_coalesced_frames_high) ||
+ (ecoalesce->tx_coalesce_usecs_high) ||
+ (ecoalesce->tx_max_coalesced_frames_high) ||
+ (ecoalesce->rate_sample_interval))
+ return -EOPNOTSUPP;
+ if (ecoalesce->rx_max_coalesced_frames)
+ lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames;
+ if (ecoalesce->tx_max_coalesced_frames)
+ lp->coalesce_count_tx = ecoalesce->tx_max_coalesced_frames;
+
+ return 0;
+}
+
+static struct ethtool_ops axienet_ethtool_ops = {
+ .get_settings = axienet_ethtools_get_settings,
+ .set_settings = axienet_ethtools_set_settings,
+ .get_drvinfo = axienet_ethtools_get_drvinfo,
+ .get_regs_len = axienet_ethtools_get_regs_len,
+ .get_regs = axienet_ethtools_get_regs,
+ .get_link = ethtool_op_get_link,
+ .get_pauseparam = axienet_ethtools_get_pauseparam,
+ .set_pauseparam = axienet_ethtools_set_pauseparam,
+ .get_coalesce = axienet_ethtools_get_coalesce,
+ .set_coalesce = axienet_ethtools_set_coalesce,
+};
+
+/**
+ * axienet_dma_err_handler - Tasklet handler for Axi DMA Error
+ * @data: Data passed
+ *
+ * Resets the Axi DMA and Axi Ethernet devices, and reconfigures the
+ * Tx/Rx BDs.
+ */
+static void axienet_dma_err_handler(unsigned long data)
+{
+ u32 axienet_status;
+ u32 cr, i;
+ int mdio_mcreg;
+ struct axienet_local *lp = (struct axienet_local *) data;
+ struct net_device *ndev = lp->ndev;
+ struct axidma_bd *cur_p;
+
+ axienet_setoptions(ndev, lp->options &
+ ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
+ mdio_mcreg = axienet_ior(lp, XAE_MDIO_MC_OFFSET);
+ axienet_mdio_wait_until_ready(lp);
+ /* Disable the MDIO interface till Axi Ethernet Reset is completed.
+ * When we do an Axi Ethernet reset, it resets the complete core
+ * including the MDIO. So if MDIO is not disabled when the reset
+ * process is started, MDIO will be broken afterwards. */
+ axienet_iow(lp, XAE_MDIO_MC_OFFSET, (mdio_mcreg &
+ ~XAE_MDIO_MC_MDIOEN_MASK));
+
+ __axienet_device_reset(lp, &ndev->dev, XAXIDMA_TX_CR_OFFSET);
+ __axienet_device_reset(lp, &ndev->dev, XAXIDMA_RX_CR_OFFSET);
+
+ axienet_iow(lp, XAE_MDIO_MC_OFFSET, mdio_mcreg);
+ axienet_mdio_wait_until_ready(lp);
+
+ for (i = 0; i < TX_BD_NUM; i++) {
+ cur_p = &lp->tx_bd_v[i];
+ if (cur_p->phys)
+ dma_unmap_single(ndev->dev.parent, cur_p->phys,
+ (cur_p->cntrl &
+ XAXIDMA_BD_CTRL_LENGTH_MASK),
+ DMA_TO_DEVICE);
+ if (cur_p->app4)
+ dev_kfree_skb_irq((struct sk_buff *) cur_p->app4);
+ cur_p->phys = 0;
+ cur_p->cntrl = 0;
+ cur_p->status = 0;
+ cur_p->app0 = 0;
+ cur_p->app1 = 0;
+ cur_p->app2 = 0;
+ cur_p->app3 = 0;
+ cur_p->app4 = 0;
+ cur_p->sw_id_offset = 0;
+ }
+
+ for (i = 0; i < RX_BD_NUM; i++) {
+ cur_p = &lp->rx_bd_v[i];
+ cur_p->status = 0;
+ cur_p->app0 = 0;
+ cur_p->app1 = 0;
+ cur_p->app2 = 0;
+ cur_p->app3 = 0;
+ cur_p->app4 = 0;
+ }
+
+ lp->tx_bd_ci = 0;
+ lp->tx_bd_tail = 0;
+ lp->rx_bd_ci = 0;
+
+ /* Start updating the Rx channel control register */
+ cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
+ /* Update the interrupt coalesce count */
+ cr = ((cr & ~XAXIDMA_COALESCE_MASK) |
+ (XAXIDMA_DFT_RX_THRESHOLD << XAXIDMA_COALESCE_SHIFT));
+ /* Update the delay timer count */
+ cr = ((cr & ~XAXIDMA_DELAY_MASK) |
+ (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
+ /* Enable coalesce, delay timer and error interrupts */
+ cr |= XAXIDMA_IRQ_ALL_MASK;
+ /* Finally write to the Rx channel control register */
+ axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
+
+ /* Start updating the Tx channel control register */
+ cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
+ /* Update the interrupt coalesce count */
+ cr = (((cr & ~XAXIDMA_COALESCE_MASK)) |
+ (XAXIDMA_DFT_TX_THRESHOLD << XAXIDMA_COALESCE_SHIFT));
+ /* Update the delay timer count */
+ cr = (((cr & ~XAXIDMA_DELAY_MASK)) |
+ (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
+ /* Enable coalesce, delay timer and error interrupts */
+ cr |= XAXIDMA_IRQ_ALL_MASK;
+ /* Finally write to the Tx channel control register */
+ axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
+
+ /* Populate the tail pointer and bring the Rx Axi DMA engine out of
+ * halted state. This will make the Rx side ready for reception.*/
+ axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
+ cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
+ axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
+ cr | XAXIDMA_CR_RUNSTOP_MASK);
+ axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
+ (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
+
+ /* Write to the RS (Run-stop) bit in the Tx channel control register.
+ * Tx channel is now ready to run. But only after we write to the
+ * tail pointer register that the Tx channel will start transmitting */
+ axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
+ cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
+ axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
+ cr | XAXIDMA_CR_RUNSTOP_MASK);
+
+ axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
+ axienet_status &= ~XAE_RCW1_RX_MASK;
+ axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status);
+
+ axienet_status = axienet_ior(lp, XAE_IP_OFFSET);
+ if (axienet_status & XAE_INT_RXRJECT_MASK)
+ axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
+ axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK);
+
+ /* Sync default options with HW but leave receiver and
+ * transmitter disabled.*/
+ axienet_setoptions(ndev, lp->options &
+ ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
+ axienet_set_mac_address(ndev, NULL);
+ axienet_set_multicast_list(ndev);
+ axienet_setoptions(ndev, lp->options);
+}
+
+/**
+ * axienet_of_probe - Axi Ethernet probe function.
+ * @op: Pointer to platform device structure.
+ * @match: Pointer to device id structure
+ *
+ * returns: 0, on success
+ * Non-zero error value on failure.
+ *
+ * This is the probe routine for Axi Ethernet driver. This is called before
+ * any other driver routines are invoked. It allocates and sets up the Ethernet
+ * device. Parses through device tree and populates fields of
+ * axienet_local. It registers the Ethernet device.
+ */
+static int __devinit axienet_of_probe(struct platform_device *op)
+{
+ __be32 *p;
+ int size, ret = 0;
+ struct device_node *np;
+ struct axienet_local *lp;
+ struct net_device *ndev;
+ const void *addr;
+
+ ndev = alloc_etherdev(sizeof(*lp));
+ if (!ndev)
+ return -ENOMEM;
+
+ ether_setup(ndev);
+ dev_set_drvdata(&op->dev, ndev);
+
+ SET_NETDEV_DEV(ndev, &op->dev);
+ ndev->flags &= ~IFF_MULTICAST; /* clear multicast */
+ ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
+ ndev->netdev_ops = &axienet_netdev_ops;
+ ndev->ethtool_ops = &axienet_ethtool_ops;
+
+ lp = netdev_priv(ndev);
+ lp->ndev = ndev;
+ lp->dev = &op->dev;
+ lp->options = XAE_OPTION_DEFAULTS;
+ /* Map device registers */
+ lp->regs = of_iomap(op->dev.of_node, 0);
+ if (!lp->regs) {
+ dev_err(&op->dev, "could not map Axi Ethernet regs.\n");
+ goto nodev;
+ }
+ /* Setup checksum offload, but default to off if not specified */
+ lp->features = 0;
+
+ p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,txcsum", NULL);
+ if (p) {
+ switch (be32_to_cpup(p)) {
+ case 1:
+ lp->csum_offload_on_tx_path =
+ XAE_FEATURE_PARTIAL_TX_CSUM;
+ lp->features |= XAE_FEATURE_PARTIAL_TX_CSUM;
+ /* Can checksum TCP/UDP over IPv4. */
+ ndev->features |= NETIF_F_IP_CSUM;
+ break;
+ case 2:
+ lp->csum_offload_on_tx_path =
+ XAE_FEATURE_FULL_TX_CSUM;
+ lp->features |= XAE_FEATURE_FULL_TX_CSUM;
+ /* Can checksum TCP/UDP over IPv4. */
+ ndev->features |= NETIF_F_IP_CSUM;
+ break;
+ default:
+ lp->csum_offload_on_tx_path = XAE_NO_CSUM_OFFLOAD;
+ }
+ }
+ p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL);
+ if (p) {
+ switch (be32_to_cpup(p)) {
+ case 1:
+ lp->csum_offload_on_rx_path =
+ XAE_FEATURE_PARTIAL_RX_CSUM;
+ lp->features |= XAE_FEATURE_PARTIAL_RX_CSUM;
+ break;
+ case 2:
+ lp->csum_offload_on_rx_path =
+ XAE_FEATURE_FULL_RX_CSUM;
+ lp->features |= XAE_FEATURE_FULL_RX_CSUM;
+ break;
+ default:
+ lp->csum_offload_on_rx_path = XAE_NO_CSUM_OFFLOAD;
+ }
+ }
+ /* For supporting jumbo frames, the Axi Ethernet hardware must have
+ * a larger Rx/Tx Memory. Typically, the size must be more than or
+ * equal to 16384 bytes, so that we can enable jumbo option and start
+ * supporting jumbo frames. Here we check for memory allocated for
+ * Rx/Tx in the hardware from the device-tree and accordingly set
+ * flags. */
+ p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,rxmem", NULL);
+ if (p) {
+ if ((be32_to_cpup(p)) >= 0x4000)
+ lp->jumbo_support = 1;
+ }
+ p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,temac-type",
+ NULL);
+ if (p)
+ lp->temac_type = be32_to_cpup(p);
+ p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,phy-type", NULL);
+ if (p)
+ lp->phy_type = be32_to_cpup(p);
+
+ /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
+ np = of_parse_phandle(op->dev.of_node, "axistream-connected", 0);
+ if (!np) {
+ dev_err(&op->dev, "could not find DMA node\n");
+ goto err_iounmap;
+ }
+ lp->dma_regs = of_iomap(np, 0);
+ if (lp->dma_regs) {
+ dev_dbg(&op->dev, "MEM base: %p\n", lp->dma_regs);
+ } else {
+ dev_err(&op->dev, "unable to map DMA registers\n");
+ of_node_put(np);
+ }
+ lp->rx_irq = irq_of_parse_and_map(np, 1);
+ lp->tx_irq = irq_of_parse_and_map(np, 0);
+ of_node_put(np);
+ if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
+ dev_err(&op->dev, "could not determine irqs\n");
+ ret = -ENOMEM;
+ goto err_iounmap_2;
+ }
+
+ /* Retrieve the MAC address */
+ addr = of_get_property(op->dev.of_node, "local-mac-address", &size);
+ if ((!addr) || (size != 6)) {
+ dev_err(&op->dev, "could not find MAC address\n");
+ ret = -ENODEV;
+ goto err_iounmap_2;
+ }
+ axienet_set_mac_address(ndev, (void *) addr);
+
+ lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
+ lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
+
+ lp->phy_node = of_parse_phandle(op->dev.of_node, "phy-handle", 0);
+ ret = axienet_mdio_setup(lp, op->dev.of_node);
+ if (ret)
+ dev_warn(&op->dev, "error registering MDIO bus\n");
+
+ ret = register_netdev(lp->ndev);
+ if (ret) {
+ dev_err(lp->dev, "register_netdev() error (%i)\n", ret);
+ goto err_iounmap_2;
+ }
+
+ tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
+ (unsigned long) lp);
+ tasklet_disable(&lp->dma_err_tasklet);
+
+ return 0;
+
+err_iounmap_2:
+ if (lp->dma_regs)
+ iounmap(lp->dma_regs);
+err_iounmap:
+ iounmap(lp->regs);
+nodev:
+ free_netdev(ndev);
+ ndev = NULL;
+ return ret;
+}
+
+static int __devexit axienet_of_remove(struct platform_device *op)
+{
+ struct net_device *ndev = dev_get_drvdata(&op->dev);
+ struct axienet_local *lp = netdev_priv(ndev);
+
+ axienet_mdio_teardown(lp);
+ unregister_netdev(ndev);
+
+ if (lp->phy_node)
+ of_node_put(lp->phy_node);
+ lp->phy_node = NULL;
+
+ dev_set_drvdata(&op->dev, NULL);
+
+ iounmap(lp->regs);
+ if (lp->dma_regs)
+ iounmap(lp->dma_regs);
+ free_netdev(ndev);
+
+ return 0;
+}
+
+static struct platform_driver axienet_of_driver = {
+ .probe = axienet_of_probe,
+ .remove = __devexit_p(axienet_of_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "xilinx_axienet",
+ .of_match_table = axienet_of_match,
+ },
+};
+
+module_platform_driver(axienet_of_driver);
+
+MODULE_DESCRIPTION("Xilinx Axi Ethernet driver");
+MODULE_AUTHOR("Xilinx");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
new file mode 100644
index 000000000000..d70b6e79f6c0
--- /dev/null
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
@@ -0,0 +1,238 @@
+/*
+ * MDIO bus driver for the Xilinx Axi Ethernet device
+ *
+ * Copyright (c) 2009 Secret Lab Technologies, Ltd.
+ * Copyright (c) 2010 Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch>
+ * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch>
+ */
+
+#include <linux/of_address.h>
+#include <linux/of_mdio.h>
+#include <linux/jiffies.h>
+
+#include "xilinx_axienet.h"
+
+#define MAX_MDIO_FREQ 2500000 /* 2.5 MHz */
+#define DEFAULT_CLOCK_DIVISOR XAE_MDIO_DIV_DFT
+
+/* Wait till MDIO interface is ready to accept a new transaction.*/
+int axienet_mdio_wait_until_ready(struct axienet_local *lp)
+{
+ long end = jiffies + 2;
+ while (!(axienet_ior(lp, XAE_MDIO_MCR_OFFSET) &
+ XAE_MDIO_MCR_READY_MASK)) {
+ if (end - jiffies <= 0) {
+ WARN_ON(1);
+ return -ETIMEDOUT;
+ }
+ udelay(1);
+ }
+ return 0;
+}
+
+/**
+ * axienet_mdio_read - MDIO interface read function
+ * @bus: Pointer to mii bus structure
+ * @phy_id: Address of the PHY device
+ * @reg: PHY register to read
+ *
+ * returns: The register contents on success, -ETIMEDOUT on a timeout
+ *
+ * Reads the contents of the requested register from the requested PHY
+ * address by first writing the details into MCR register. After a while
+ * the register MRD is read to obtain the PHY register content.
+ */
+static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg)
+{
+ u32 rc;
+ int ret;
+ struct axienet_local *lp = bus->priv;
+
+ ret = axienet_mdio_wait_until_ready(lp);
+ if (ret < 0)
+ return ret;
+
+ axienet_iow(lp, XAE_MDIO_MCR_OFFSET,
+ (((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) &
+ XAE_MDIO_MCR_PHYAD_MASK) |
+ ((reg << XAE_MDIO_MCR_REGAD_SHIFT) &
+ XAE_MDIO_MCR_REGAD_MASK) |
+ XAE_MDIO_MCR_INITIATE_MASK |
+ XAE_MDIO_MCR_OP_READ_MASK));
+
+ ret = axienet_mdio_wait_until_ready(lp);
+ if (ret < 0)
+ return ret;
+
+ rc = axienet_ior(lp, XAE_MDIO_MRD_OFFSET) & 0x0000FFFF;
+
+ dev_dbg(lp->dev, "axienet_mdio_read(phy_id=%i, reg=%x) == %x\n",
+ phy_id, reg, rc);
+
+ return rc;
+}
+
+/**
+ * axienet_mdio_write - MDIO interface write function
+ * @bus: Pointer to mii bus structure
+ * @phy_id: Address of the PHY device
+ * @reg: PHY register to write to
+ * @val: Value to be written into the register
+ *
+ * returns: 0 on success, -ETIMEDOUT on a timeout
+ *
+ * Writes the value to the requested register by first writing the value
+ * into MWD register. The the MCR register is then appropriately setup
+ * to finish the write operation.
+ */
+static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
+ u16 val)
+{
+ int ret;
+ struct axienet_local *lp = bus->priv;
+
+ dev_dbg(lp->dev, "axienet_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
+ phy_id, reg, val);
+
+ ret = axienet_mdio_wait_until_ready(lp);
+ if (ret < 0)
+ return ret;
+
+ axienet_iow(lp, XAE_MDIO_MWD_OFFSET, (u32) val);
+ axienet_iow(lp, XAE_MDIO_MCR_OFFSET,
+ (((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) &
+ XAE_MDIO_MCR_PHYAD_MASK) |
+ ((reg << XAE_MDIO_MCR_REGAD_SHIFT) &
+ XAE_MDIO_MCR_REGAD_MASK) |
+ XAE_MDIO_MCR_INITIATE_MASK |
+ XAE_MDIO_MCR_OP_WRITE_MASK));
+
+ ret = axienet_mdio_wait_until_ready(lp);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+/**
+ * axienet_mdio_setup - MDIO setup function
+ * @lp: Pointer to axienet local data structure.
+ * @np: Pointer to device node
+ *
+ * returns: 0 on success, -ETIMEDOUT on a timeout, -ENOMEM when
+ * mdiobus_alloc (to allocate memory for mii bus structure) fails.
+ *
+ * Sets up the MDIO interface by initializing the MDIO clock and enabling the
+ * MDIO interface in hardware. Register the MDIO interface.
+ **/
+int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np)
+{
+ int ret;
+ u32 clk_div, host_clock;
+ u32 *property_p;
+ struct mii_bus *bus;
+ struct resource res;
+ struct device_node *np1;
+
+ /* clk_div can be calculated by deriving it from the equation:
+ * fMDIO = fHOST / ((1 + clk_div) * 2)
+ *
+ * Where fMDIO <= 2500000, so we get:
+ * fHOST / ((1 + clk_div) * 2) <= 2500000
+ *
+ * Then we get:
+ * 1 / ((1 + clk_div) * 2) <= (2500000 / fHOST)
+ *
+ * Then we get:
+ * 1 / (1 + clk_div) <= ((2500000 * 2) / fHOST)
+ *
+ * Then we get:
+ * 1 / (1 + clk_div) <= (5000000 / fHOST)
+ *
+ * So:
+ * (1 + clk_div) >= (fHOST / 5000000)
+ *
+ * And finally:
+ * clk_div >= (fHOST / 5000000) - 1
+ *
+ * fHOST can be read from the flattened device tree as property
+ * "clock-frequency" from the CPU
+ */
+
+ np1 = of_find_node_by_name(NULL, "cpu");
+ if (!np1) {
+ printk(KERN_WARNING "%s(): Could not find CPU device node.",
+ __func__);
+ printk(KERN_WARNING "Setting MDIO clock divisor to "
+ "default %d\n", DEFAULT_CLOCK_DIVISOR);
+ clk_div = DEFAULT_CLOCK_DIVISOR;
+ goto issue;
+ }
+ property_p = (u32 *) of_get_property(np1, "clock-frequency", NULL);
+ if (!property_p) {
+ printk(KERN_WARNING "%s(): Could not find CPU property: "
+ "clock-frequency.", __func__);
+ printk(KERN_WARNING "Setting MDIO clock divisor to "
+ "default %d\n", DEFAULT_CLOCK_DIVISOR);
+ clk_div = DEFAULT_CLOCK_DIVISOR;
+ goto issue;
+ }
+
+ host_clock = be32_to_cpup(property_p);
+ clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1;
+ /* If there is any remainder from the division of
+ * fHOST / (MAX_MDIO_FREQ * 2), then we need to add
+ * 1 to the clock divisor or we will surely be above 2.5 MHz */
+ if (host_clock % (MAX_MDIO_FREQ * 2))
+ clk_div++;
+
+ printk(KERN_DEBUG "%s(): Setting MDIO clock divisor to %u based "
+ "on %u Hz host clock.\n", __func__, clk_div, host_clock);
+
+ of_node_put(np1);
+issue:
+ axienet_iow(lp, XAE_MDIO_MC_OFFSET,
+ (((u32) clk_div) | XAE_MDIO_MC_MDIOEN_MASK));
+
+ ret = axienet_mdio_wait_until_ready(lp);
+ if (ret < 0)
+ return ret;
+
+ bus = mdiobus_alloc();
+ if (!bus)
+ return -ENOMEM;
+
+ np1 = of_get_parent(lp->phy_node);
+ of_address_to_resource(np1, 0, &res);
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
+ (unsigned long long) res.start);
+
+ bus->priv = lp;
+ bus->name = "Xilinx Axi Ethernet MDIO";
+ bus->read = axienet_mdio_read;
+ bus->write = axienet_mdio_write;
+ bus->parent = lp->dev;
+ bus->irq = lp->mdio_irqs; /* preallocated IRQ table */
+ lp->mii_bus = bus;
+
+ ret = of_mdiobus_register(bus, np1);
+ if (ret) {
+ mdiobus_free(bus);
+ return ret;
+ }
+ return 0;
+}
+
+/**
+ * axienet_mdio_teardown - MDIO remove function
+ * @lp: Pointer to axienet local data structure.
+ *
+ * Unregisters the MDIO and frees any associate memory for mii bus.
+ */
+void axienet_mdio_teardown(struct axienet_local *lp)
+{
+ mdiobus_unregister(lp->mii_bus);
+ kfree(lp->mii_bus->irq);
+ mdiobus_free(lp->mii_bus);
+ lp->mii_bus = NULL;
+}
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 79013e5731a5..77cfe5110318 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -613,7 +613,7 @@ static void xemaclite_rx_handler(struct net_device *dev)
u32 len;
len = ETH_FRAME_LEN + ETH_FCS_LEN;
- skb = dev_alloc_skb(len + ALIGNMENT);
+ skb = netdev_alloc_skb(dev, len + ALIGNMENT);
if (!skb) {
/* Couldn't get memory. */
dev->stats.rx_dropped++;
@@ -1136,10 +1136,8 @@ static int __devinit xemaclite_of_probe(struct platform_device *ofdev)
/* Create an ethernet device instance */
ndev = alloc_etherdev(sizeof(struct net_local));
- if (!ndev) {
- dev_err(dev, "Could not allocate network device\n");
+ if (!ndev)
return -ENOMEM;
- }
dev_set_drvdata(dev, ndev);
SET_NETDEV_DEV(ndev, &ofdev->dev);
diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c
index 33979c3ac943..5c69c6f93fb8 100644
--- a/drivers/net/ethernet/xircom/xirc2ps_cs.c
+++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c
@@ -1039,7 +1039,8 @@ xirc2ps_interrupt(int irq, void *dev_id)
pr_debug("rsr=%#02x packet_length=%u\n", rsr, pktlen);
- skb = dev_alloc_skb(pktlen+3); /* 1 extra so we can use insw */
+ /* 1 extra so we can use insw */
+ skb = netdev_alloc_skb(dev, pktlen + 3);
if (!skb) {
pr_notice("low memory, packet dropped (size=%u)\n", pktlen);
dev->stats.rx_dropped++;
diff --git a/drivers/net/ethernet/xscale/ixp2000/ixpdev.c b/drivers/net/ethernet/xscale/ixp2000/ixpdev.c
index e122493ab70e..45008377c8bf 100644
--- a/drivers/net/ethernet/xscale/ixp2000/ixpdev.c
+++ b/drivers/net/ethernet/xscale/ixp2000/ixpdev.c
@@ -398,11 +398,8 @@ int ixpdev_init(int __nds_count, struct net_device **__nds,
}
for (i = 0; i < nds_count; i++) {
- printk(KERN_INFO "%s: IXP2000 MSF ethernet (port %d), "
- "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x.\n", nds[i]->name, i,
- nds[i]->dev_addr[0], nds[i]->dev_addr[1],
- nds[i]->dev_addr[2], nds[i]->dev_addr[3],
- nds[i]->dev_addr[4], nds[i]->dev_addr[5]);
+ printk(KERN_INFO "%s: IXP2000 MSF ethernet (port %d), %pM.\n",
+ nds[i]->name, i, nds[i]->dev_addr);
}
return 0;