aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/3com/3c509.c123
-rw-r--r--drivers/net/ethernet/3com/typhoon.c3
-rw-r--r--drivers/net/ethernet/8390/Kconfig25
-rw-r--r--drivers/net/ethernet/8390/Makefile1
-rw-r--r--drivers/net/ethernet/8390/ax88796.c1
-rw-r--r--drivers/net/ethernet/8390/etherh.c1
-rw-r--r--drivers/net/ethernet/8390/ne2.c798
-rw-r--r--drivers/net/ethernet/8390/smc-mca.c575
-rw-r--r--drivers/net/ethernet/Kconfig1
-rw-r--r--drivers/net/ethernet/Makefile1
-rw-r--r--drivers/net/ethernet/adaptec/starfire.c54
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.c20
-rw-r--r--drivers/net/ethernet/amd/ariadne.c8
-rw-r--r--drivers/net/ethernet/amd/atarilance.c11
-rw-r--r--drivers/net/ethernet/amd/depca.c213
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c.h59
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c9
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.c569
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.h983
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c1007
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_main.c17
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c171
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.h17
-rw-r--r--drivers/net/ethernet/atheros/atlx/atlx.c15
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c46
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h45
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c474
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h383
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c38
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h268
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h219
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c733
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h4
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c1134
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h5
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c114
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h39
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c273
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h15
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c50
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.c61
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c142
-rw-r--r--drivers/net/ethernet/brocade/bna/bfi_reg.h6
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c320
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.h11
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_ethtool.c6
-rw-r--r--drivers/net/ethernet/cadence/at91_ether.c535
-rw-r--r--drivers/net/ethernet/cadence/at91_ether.h1
-rw-r--r--drivers/net/ethernet/cadence/macb.c1
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h23
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c235
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h11
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c22
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c62
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_regs.h53
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h15
-rw-r--r--drivers/net/ethernet/cirrus/cs89x0.c2221
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c34
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_pp.c2
-rw-r--r--drivers/net/ethernet/davicom/Kconfig2
-rw-r--r--drivers/net/ethernet/dec/ewrk3.c3
-rw-r--r--drivers/net/ethernet/dec/tulip/de2104x.c34
-rw-r--r--drivers/net/ethernet/dec/tulip/de4x5.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/dmfe.c301
-rw-r--r--drivers/net/ethernet/dec/tulip/tulip_core.c27
-rw-r--r--drivers/net/ethernet/dec/tulip/uli526x.c443
-rw-r--r--drivers/net/ethernet/dec/tulip/winbond-840.c17
-rw-r--r--drivers/net/ethernet/dec/tulip/xircom_cb.c280
-rw-r--r--drivers/net/ethernet/dlink/dl2k.c416
-rw-r--r--drivers/net/ethernet/dlink/dl2k.h19
-rw-r--r--drivers/net/ethernet/dlink/sundance.c12
-rw-r--r--drivers/net/ethernet/dnet.c1
-rw-r--r--drivers/net/ethernet/emulex/benet/Makefile2
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h92
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c205
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h102
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c326
-rw-r--r--drivers/net/ethernet/emulex/benet/be_hw.h80
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c583
-rw-r--r--drivers/net/ethernet/emulex/benet/be_roce.c182
-rw-r--r--drivers/net/ethernet/emulex/benet/be_roce.h75
-rw-r--r--drivers/net/ethernet/fealnx.c14
-rw-r--r--drivers/net/ethernet/freescale/fec.c1
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.c1
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c1
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c15
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h3
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c30
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ptp.c2
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth_ethtool.c1
-rw-r--r--drivers/net/ethernet/fujitsu/at1700.c120
-rw-r--r--drivers/net/ethernet/i825xx/3c523.c1312
-rw-r--r--drivers/net/ethernet/i825xx/3c523.h355
-rw-r--r--drivers/net/ethernet/i825xx/3c527.c1660
-rw-r--r--drivers/net/ethernet/i825xx/3c527.h81
-rw-r--r--drivers/net/ethernet/i825xx/Kconfig22
-rw-r--r--drivers/net/ethernet/i825xx/Makefile2
-rw-r--r--drivers/net/ethernet/i825xx/eexpress.c60
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_main.c2
-rw-r--r--drivers/net/ethernet/intel/Kconfig32
-rw-r--r--drivers/net/ethernet/intel/e100.c2
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c68
-rw-r--r--drivers/net/ethernet/intel/e1000e/80003es2lan.c21
-rw-r--r--drivers/net/ethernet/intel/e1000e/82571.c41
-rw-r--r--drivers/net/ethernet/intel/e1000e/defines.h8
-rw-r--r--drivers/net/ethernet/intel/e1000e/e1000.h51
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c88
-rw-r--r--drivers/net/ethernet/intel/e1000e/hw.h72
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c780
-rw-r--r--drivers/net/ethernet/intel/e1000e/mac.c12
-rw-r--r--drivers/net/ethernet/intel/e1000e/manage.c2
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c184
-rw-r--r--drivers/net/ethernet/intel/e1000e/param.c10
-rw-r--r--drivers/net/ethernet/intel/e1000e/phy.c115
-rw-r--r--drivers/net/ethernet/intel/igb/Makefile4
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.c276
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.h3
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_defines.h35
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_hw.h14
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_i210.c603
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_i210.h76
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.c1
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_nvm.c1
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_phy.c147
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_phy.h22
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_regs.h14
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h30
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c141
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c323
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ptp.c385
-rw-r--r--drivers/net/ethernet/intel/ixgbe/Makefile4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h68
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c92
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.c831
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.h19
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c69
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c104
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c134
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c124
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c35
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c449
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c20
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c900
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c13
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c245
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h97
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/defines.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ethtool.c18
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c30
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.c12
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c1
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c1
-rw-r--r--drivers/net/ethernet/marvell/sky2.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/Kconfig12
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/Makefile1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/alloc.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_cq.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c255
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c21
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_main.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c59
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_port.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_resources.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c95
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c32
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c49
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mcg.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h32
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h45
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mr.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/pd.c39
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c69
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c271
-rw-r--r--drivers/net/ethernet/micrel/ks8842.c2
-rw-r--r--drivers/net/ethernet/micrel/ks8851.c7
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c7
-rw-r--r--drivers/net/ethernet/natsemi/Kconfig20
-rw-r--r--drivers/net/ethernet/natsemi/Makefile1
-rw-r--r--drivers/net/ethernet/natsemi/natsemi.c67
-rw-r--r--drivers/net/ethernet/neterion/s2io.c14
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.c24
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.h15
-rw-r--r--drivers/net/ethernet/nvidia/forcedeth.c9
-rw-r--r--drivers/net/ethernet/nxp/lpc_eth.c77
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h3
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c89
-rw-r--r--drivers/net/ethernet/packetengines/hamachi.c11
-rw-r--r--drivers/net/ethernet/packetengines/yellowfin.c32
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac.c2
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic.h20
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c5
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c18
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h26
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c7
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c140
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h63
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c73
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c208
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h6
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c3
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c56
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_main.c2
-rw-r--r--drivers/net/ethernet/rdc/r6040.c76
-rw-r--r--drivers/net/ethernet/realtek/8139cp.c21
-rw-r--r--drivers/net/ethernet/realtek/8139too.c136
-rw-r--r--drivers/net/ethernet/realtek/r8169.c716
-rw-r--r--drivers/net/ethernet/renesas/Kconfig7
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c114
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.h5
-rw-r--r--drivers/net/ethernet/s6gmac.c6
-rw-r--r--drivers/net/ethernet/sfc/efx.c38
-rw-r--r--drivers/net/ethernet/sfc/ethtool.c37
-rw-r--r--drivers/net/ethernet/sfc/mcdi_phy.c76
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h8
-rw-r--r--drivers/net/ethernet/sfc/qt202x_phy.c33
-rw-r--r--drivers/net/ethernet/sfc/rx.c31
-rw-r--r--drivers/net/ethernet/silan/sc92031.c34
-rw-r--r--drivers/net/ethernet/sis/sis190.c26
-rw-r--r--drivers/net/ethernet/sis/sis900.c375
-rw-r--r--drivers/net/ethernet/smsc/epic100.c403
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.c1
-rw-r--r--drivers/net/ethernet/smsc/smsc9420.c48
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h22
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000.h14
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c15
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c46
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c14
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c8
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/enh_desc.c13
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/norm_desc.c13
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h50
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c163
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c36
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c18
-rw-r--r--drivers/net/ethernet/sun/niu.c2
-rw-r--r--drivers/net/ethernet/sun/sungem.c4
-rw-r--r--drivers/net/ethernet/sun/sunhme.c18
-rw-r--r--drivers/net/ethernet/sun/sunhme.h1
-rw-r--r--drivers/net/ethernet/sun/sunvnet.c2
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.c10
-rw-r--r--drivers/net/ethernet/ti/Kconfig2
-rw-r--r--drivers/net/ethernet/ti/davinci_cpdma.c13
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c1
-rw-r--r--drivers/net/ethernet/ti/tlan.c2
-rw-r--r--drivers/net/ethernet/tile/tilepro.c2
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.c8
-rw-r--r--drivers/net/ethernet/via/via-rhine.c12
-rw-r--r--drivers/net/ethernet/via/via-velocity.c9
-rw-r--r--drivers/net/ethernet/wiznet/Kconfig73
-rw-r--r--drivers/net/ethernet/wiznet/Makefile2
-rw-r--r--drivers/net/ethernet/wiznet/w5100.c808
-rw-r--r--drivers/net/ethernet/wiznet/w5300.c720
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c1
-rw-r--r--drivers/net/ethernet/xscale/Kconfig6
-rw-r--r--drivers/net/ethernet/xscale/Makefile1
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/Kconfig6
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/Makefile3
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/caleb.c136
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/caleb.h22
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/enp2611.c232
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.c212
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.h115
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.uc408
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.ucode130
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.uc272
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.ucode98
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixpdev.c437
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixpdev.h29
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/ixpdev_priv.h57
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/pm3386.c351
-rw-r--r--drivers/net/ethernet/xscale/ixp2000/pm3386.h29
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c29
283 files changed, 18580 insertions, 16348 deletions
diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c
index 41719da2e178..1a8eef2c3d58 100644
--- a/drivers/net/ethernet/3com/3c509.c
+++ b/drivers/net/ethernet/3com/3c509.c
@@ -69,7 +69,6 @@
#define TX_TIMEOUT (400*HZ/1000)
#include <linux/module.h>
-#include <linux/mca.h>
#include <linux/isa.h>
#include <linux/pnp.h>
#include <linux/string.h>
@@ -102,7 +101,7 @@ static int el3_debug = 2;
#endif
/* Used to do a global count of all the cards in the system. Must be
- * a global variable so that the mca/eisa probe routines can increment
+ * a global variable so that the eisa probe routines can increment
* it */
static int el3_cards = 0;
#define EL3_MAX_CARDS 8
@@ -163,7 +162,7 @@ enum RxFilter {
*/
#define SKB_QUEUE_SIZE 64
-enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA };
+enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_EISA };
struct el3_private {
spinlock_t lock;
@@ -505,41 +504,6 @@ static struct eisa_driver el3_eisa_driver = {
static int eisa_registered;
#endif
-#ifdef CONFIG_MCA
-static int el3_mca_probe(struct device *dev);
-
-static short el3_mca_adapter_ids[] __initdata = {
- 0x627c,
- 0x627d,
- 0x62db,
- 0x62f6,
- 0x62f7,
- 0x0000
-};
-
-static char *el3_mca_adapter_names[] __initdata = {
- "3Com 3c529 EtherLink III (10base2)",
- "3Com 3c529 EtherLink III (10baseT)",
- "3Com 3c529 EtherLink III (test mode)",
- "3Com 3c529 EtherLink III (TP or coax)",
- "3Com 3c529 EtherLink III (TP)",
- NULL
-};
-
-static struct mca_driver el3_mca_driver = {
- .id_table = el3_mca_adapter_ids,
- .driver = {
- .name = "3c529",
- .bus = &mca_bus_type,
- .probe = el3_mca_probe,
- .remove = __devexit_p(el3_device_remove),
- .suspend = el3_suspend,
- .resume = el3_resume,
- },
-};
-static int mca_registered;
-#endif /* CONFIG_MCA */
-
static const struct net_device_ops netdev_ops = {
.ndo_open = el3_open,
.ndo_stop = el3_close,
@@ -600,76 +564,6 @@ static void el3_common_remove (struct net_device *dev)
free_netdev (dev);
}
-#ifdef CONFIG_MCA
-static int __init el3_mca_probe(struct device *device)
-{
- /* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch,
- * heavily modified by Chris Beauregard
- * (cpbeaure@csclub.uwaterloo.ca) to support standard MCA
- * probing.
- *
- * redone for multi-card detection by ZP Gu (zpg@castle.net)
- * now works as a module */
-
- short i;
- int ioaddr, irq, if_port;
- __be16 phys_addr[3];
- struct net_device *dev = NULL;
- u_char pos4, pos5;
- struct mca_device *mdev = to_mca_device(device);
- int slot = mdev->slot;
- int err;
-
- pos4 = mca_device_read_stored_pos(mdev, 4);
- pos5 = mca_device_read_stored_pos(mdev, 5);
-
- ioaddr = ((short)((pos4&0xfc)|0x02)) << 8;
- irq = pos5 & 0x0f;
-
-
- pr_info("3c529: found %s at slot %d\n",
- el3_mca_adapter_names[mdev->index], slot + 1);
-
- /* claim the slot */
- strncpy(mdev->name, el3_mca_adapter_names[mdev->index],
- sizeof(mdev->name));
- mca_device_set_claim(mdev, 1);
-
- if_port = pos4 & 0x03;
-
- irq = mca_device_transform_irq(mdev, irq);
- ioaddr = mca_device_transform_ioport(mdev, ioaddr);
- if (el3_debug > 2) {
- pr_debug("3c529: irq %d ioaddr 0x%x ifport %d\n", irq, ioaddr, if_port);
- }
- EL3WINDOW(0);
- for (i = 0; i < 3; i++)
- phys_addr[i] = htons(read_eeprom(ioaddr, i));
-
- dev = alloc_etherdev(sizeof (struct el3_private));
- if (dev == NULL) {
- release_region(ioaddr, EL3_IO_EXTENT);
- return -ENOMEM;
- }
-
- netdev_boot_setup_check(dev);
-
- el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_MCA);
- dev_set_drvdata(device, dev);
- err = el3_common_init(dev);
-
- if (err) {
- dev_set_drvdata(device, NULL);
- free_netdev(dev);
- return -ENOMEM;
- }
-
- el3_devs[el3_cards++] = dev;
- return 0;
-}
-
-#endif /* CONFIG_MCA */
-
#ifdef CONFIG_EISA
static int __init el3_eisa_probe (struct device *device)
{
@@ -1547,11 +1441,6 @@ static int __init el3_init_module(void)
if (!ret)
eisa_registered = 1;
#endif
-#ifdef CONFIG_MCA
- ret = mca_register_driver(&el3_mca_driver);
- if (!ret)
- mca_registered = 1;
-#endif
#ifdef CONFIG_PNP
if (pnp_registered)
@@ -1563,10 +1452,6 @@ static int __init el3_init_module(void)
if (eisa_registered)
ret = 0;
#endif
-#ifdef CONFIG_MCA
- if (mca_registered)
- ret = 0;
-#endif
return ret;
}
@@ -1584,10 +1469,6 @@ static void __exit el3_cleanup_module(void)
if (eisa_registered)
eisa_driver_unregister(&el3_eisa_driver);
#endif
-#ifdef CONFIG_MCA
- if (mca_registered)
- mca_unregister_driver(&el3_mca_driver);
-#endif
}
module_init (el3_init_module);
diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index 1234a14b2b73..b15366635147 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -2549,8 +2549,7 @@ typhoon_init(void)
static void __exit
typhoon_cleanup(void)
{
- if (typhoon_fw)
- release_firmware(typhoon_fw);
+ release_firmware(typhoon_fw);
pci_unregister_driver(&typhoon_driver);
}
diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig
index e04ade444247..2e538676924d 100644
--- a/drivers/net/ethernet/8390/Kconfig
+++ b/drivers/net/ethernet/8390/Kconfig
@@ -60,6 +60,7 @@ config PCMCIA_AXNET
config AX88796
tristate "ASIX AX88796 NE2000 clone support"
depends on (ARM || MIPS || SUPERH)
+ select CRC32
select PHYLIB
select MDIO_BITBANG
---help---
@@ -181,18 +182,6 @@ config NE2000
To compile this driver as a module, choose M here. The module
will be called ne.
-config NE2_MCA
- tristate "NE/2 (ne2000 MCA version) support"
- depends on MCA_LEGACY
- select CRC32
- ---help---
- 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>.
-
- To compile this driver as a module, choose M here. The module
- will be called ne2.
-
config NE2K_PCI
tristate "PCI NE2000 and clones support (see help)"
depends on PCI
@@ -266,18 +255,6 @@ config STNIC
If unsure, say N.
-config ULTRAMCA
- tristate "SMC Ultra MCA support"
- depends on MCA
- select CRC32
- ---help---
- If you have a network (Ethernet) card of this type and are running
- an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here. The module
- will be called smc-mca.
-
config ULTRA
tristate "SMC Ultra support"
depends on ISA
diff --git a/drivers/net/ethernet/8390/Makefile b/drivers/net/ethernet/8390/Makefile
index 3337d7fb4344..d13790b7fd27 100644
--- a/drivers/net/ethernet/8390/Makefile
+++ b/drivers/net/ethernet/8390/Makefile
@@ -24,6 +24,5 @@ obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o 8390.o
obj-$(CONFIG_STNIC) += stnic.o 8390.o
obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
-obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
obj-$(CONFIG_WD80x3) += wd.o 8390.o
obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index 11476ca95e93..203ff9dccadb 100644
--- a/drivers/net/ethernet/8390/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -501,6 +501,7 @@ static const struct ethtool_ops ax_ethtool_ops = {
.get_settings = ax_get_settings,
.set_settings = ax_set_settings,
.get_link = ethtool_op_get_link,
+ .get_ts_info = ethtool_op_get_ts_info,
};
#ifdef CONFIG_AX88796_93CX6
diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c
index dbefd5658c14..8322c54972f3 100644
--- a/drivers/net/ethernet/8390/etherh.c
+++ b/drivers/net/ethernet/8390/etherh.c
@@ -635,6 +635,7 @@ static const struct ethtool_ops etherh_ethtool_ops = {
.get_settings = etherh_get_settings,
.set_settings = etherh_set_settings,
.get_drvinfo = etherh_get_drvinfo,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static const struct net_device_ops etherh_netdev_ops = {
diff --git a/drivers/net/ethernet/8390/ne2.c b/drivers/net/ethernet/8390/ne2.c
deleted file mode 100644
index ef85839f43d8..000000000000
--- a/drivers/net/ethernet/8390/ne2.c
+++ /dev/null
@@ -1,798 +0,0 @@
-/* ne2.c: A NE/2 Ethernet Driver for Linux. */
-/*
- Based on the NE2000 driver written by Donald Becker (1992-94).
- modified by Wim Dumon (Apr 1996)
-
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
- The author may be reached as wimpie@linux.cc.kuleuven.ac.be
-
- Currently supported: NE/2
- This patch was never tested on other MCA-ethernet adapters, but it
- might work. Just give it a try and let me know if you have problems.
- Also mail me if it really works, please!
-
- Changelog:
- Mon Feb 3 16:26:02 MET 1997
- - adapted the driver to work with the 2.1.25 kernel
- - multiple ne2 support (untested)
- - module support (untested)
-
- Fri Aug 28 00:18:36 CET 1998 (David Weinehall)
- - fixed a few minor typos
- - made the MODULE_PARM conditional (it only works with the v2.1.x kernels)
- - fixed the module support (Now it's working...)
-
- Mon Sep 7 19:01:44 CET 1998 (David Weinehall)
- - added support for Arco Electronics AE/2-card (experimental)
-
- Mon Sep 14 09:53:42 CET 1998 (David Weinehall)
- - added support for Compex ENET-16MC/P (experimental)
-
- Tue Sep 15 16:21:12 CET 1998 (David Weinehall, Magnus Jonsson, Tomas Ogren)
- - Miscellaneous bugfixes
-
- Tue Sep 19 16:21:12 CET 1998 (Magnus Jonsson)
- - Cleanup
-
- Wed Sep 23 14:33:34 CET 1998 (David Weinehall)
- - Restructuring and rewriting for v2.1.x compliance
-
- Wed Oct 14 17:19:21 CET 1998 (David Weinehall)
- - Added code that unregisters irq and proc-info
- - Version# bump
-
- Mon Nov 16 15:28:23 CET 1998 (Wim Dumon)
- - pass 'dev' as last parameter of request_irq in stead of 'NULL'
-
- Wed Feb 7 21:24:00 CET 2001 (Alfred Arnold)
- - added support for the D-Link DE-320CT
-
- * WARNING
- -------
- This is alpha-test software. It is not guaranteed to work. As a
- matter of fact, I'm quite sure there are *LOTS* of bugs in here. I
- would like to hear from you if you use this driver, even if it works.
- If it doesn't work, be sure to send me a mail with the problems !
-*/
-
-static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon <wimpie@kotnet.org>\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/mca-legacy.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include "8390.h"
-
-#define DRV_NAME "ne2"
-
-/* Some defines that people can play with if so inclined. */
-
-/* Do we perform extra sanity checks on stuff ? */
-/* #define NE_SANITY_CHECK */
-
-/* Do we implement the read before write bugfix ? */
-/* #define NE_RW_BUGFIX */
-
-/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
-/* #define PACKETBUF_MEMSIZE 0x40 */
-
-
-/* ---- No user-serviceable parts below ---- */
-
-#define NE_BASE (dev->base_addr)
-#define NE_CMD 0x00
-#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */
-#define NE_RESET 0x20 /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT 0x30
-
-#define NE1SM_START_PG 0x20 /* First page of TX buffer */
-#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
-#define NESM_START_PG 0x40 /* First page of TX buffer */
-#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
-
-/* From the .ADF file: */
-static unsigned int addresses[7] __initdata =
- {0x1000, 0x2020, 0x8020, 0xa0a0, 0xb0b0, 0xc0c0, 0xc3d0};
-static int irqs[4] __initdata = {3, 4, 5, 9};
-
-/* From the D-Link ADF file: */
-static unsigned int dlink_addresses[4] __initdata =
- {0x300, 0x320, 0x340, 0x360};
-static int dlink_irqs[8] __initdata = {3, 4, 5, 9, 10, 11, 14, 15};
-
-struct ne2_adapters_t {
- unsigned int id;
- char *name;
-};
-
-static struct ne2_adapters_t ne2_adapters[] __initdata = {
- { 0x6354, "Arco Ethernet Adapter AE/2" },
- { 0x70DE, "Compex ENET-16 MC/P" },
- { 0x7154, "Novell Ethernet Adapter NE/2" },
- { 0x56ea, "D-Link DE-320CT" },
- { 0x0000, NULL }
-};
-
-extern int netcard_probe(struct net_device *dev);
-
-static int ne2_probe1(struct net_device *dev, int slot);
-
-static void ne_reset_8390(struct net_device *dev);
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
- int ring_page);
-static void ne_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset);
-static void ne_block_output(struct net_device *dev, const int count,
- const unsigned char *buf, const int start_page);
-
-
-/*
- * special code to read the DE-320's MAC address EEPROM. In contrast to a
- * standard NE design, this is a serial EEPROM (93C46) that has to be read
- * bit by bit. The EEPROM cotrol port at base + 0x1e has the following
- * layout:
- *
- * Bit 0 = Data out (read from EEPROM)
- * Bit 1 = Data in (write to EEPROM)
- * Bit 2 = Clock
- * Bit 3 = Chip Select
- * Bit 7 = ~50 kHz clock for defined delays
- *
- */
-
-static void __init dlink_put_eeprom(unsigned char value, unsigned int addr)
-{
- int z;
- unsigned char v1, v2;
-
- /* write the value to the NIC EEPROM register */
-
- outb(value, addr + 0x1e);
-
- /* now wait the clock line to toggle twice. Effectively, we are
- waiting (at least) for one clock cycle */
-
- for (z = 0; z < 2; z++) {
- do {
- v1 = inb(addr + 0x1e);
- v2 = inb(addr + 0x1e);
- }
- while (!((v1 ^ v2) & 0x80));
- }
-}
-
-static void __init dlink_send_eeprom_bit(unsigned int bit, unsigned int addr)
-{
- /* shift data bit into correct position */
-
- bit = bit << 1;
-
- /* write value, keep clock line high for two cycles */
-
- dlink_put_eeprom(0x09 | bit, addr);
- dlink_put_eeprom(0x0d | bit, addr);
- dlink_put_eeprom(0x0d | bit, addr);
- dlink_put_eeprom(0x09 | bit, addr);
-}
-
-static void __init dlink_send_eeprom_word(unsigned int value, unsigned int len, unsigned int addr)
-{
- int z;
-
- /* adjust bits so that they are left-aligned in a 16-bit-word */
-
- value = value << (16 - len);
-
- /* shift bits out to the EEPROM */
-
- for (z = 0; z < len; z++) {
- dlink_send_eeprom_bit((value & 0x8000) >> 15, addr);
- value = value << 1;
- }
-}
-
-static unsigned int __init dlink_get_eeprom(unsigned int eeaddr, unsigned int addr)
-{
- int z;
- unsigned int value = 0;
-
- /* pull the CS line low for a moment. This resets the EEPROM-
- internal logic, and makes it ready for a new command. */
-
- dlink_put_eeprom(0x01, addr);
- dlink_put_eeprom(0x09, addr);
-
- /* send one start bit, read command (1 - 0), plus the address to
- the EEPROM */
-
- dlink_send_eeprom_word(0x0180 | (eeaddr & 0x3f), 9, addr);
-
- /* get the data word. We clock by sending 0s to the EEPROM, which
- get ignored during the read process */
-
- for (z = 0; z < 16; z++) {
- dlink_send_eeprom_bit(0, addr);
- value = (value << 1) | (inb(addr + 0x1e) & 0x01);
- }
-
- return value;
-}
-
-/*
- * Note that at boot, this probe only picks up one card at a time.
- */
-
-static int __init do_ne2_probe(struct net_device *dev)
-{
- static int current_mca_slot = -1;
- int i;
- int adapter_found = 0;
-
- /* Do not check any supplied i/o locations.
- POS registers usually don't fail :) */
-
- /* MCA cards have POS registers.
- Autodetecting MCA cards is extremely simple.
- Just search for the card. */
-
- for(i = 0; (ne2_adapters[i].name != NULL) && !adapter_found; i++) {
- current_mca_slot =
- mca_find_unused_adapter(ne2_adapters[i].id, 0);
-
- if((current_mca_slot != MCA_NOTFOUND) && !adapter_found) {
- int res;
- mca_set_adapter_name(current_mca_slot,
- ne2_adapters[i].name);
- mca_mark_as_used(current_mca_slot);
-
- res = ne2_probe1(dev, current_mca_slot);
- if (res)
- mca_mark_as_unused(current_mca_slot);
- return res;
- }
- }
- return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init ne2_probe(int unit)
-{
- struct net_device *dev = alloc_eip_netdev();
- int err;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
-
- err = do_ne2_probe(dev);
- if (err)
- goto out;
- return dev;
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-#endif
-
-static int ne2_procinfo(char *buf, int slot, struct net_device *dev)
-{
- int len=0;
-
- len += sprintf(buf+len, "The NE/2 Ethernet Adapter\n" );
- len += sprintf(buf+len, "Driver written by Wim Dumon ");
- len += sprintf(buf+len, "<wimpie@kotnet.org>\n");
- len += sprintf(buf+len, "Modified by ");
- len += sprintf(buf+len, "David Weinehall <tao@acc.umu.se>\n");
- len += sprintf(buf+len, "and by Magnus Jonsson <bigfoot@acc.umu.se>\n");
- len += sprintf(buf+len, "Based on the original NE2000 drivers\n" );
- len += sprintf(buf+len, "Base IO: %#x\n", (unsigned int)dev->base_addr);
- len += sprintf(buf+len, "IRQ : %d\n", dev->irq);
- len += sprintf(buf+len, "HW addr : %pM\n", dev->dev_addr);
-
- return len;
-}
-
-static int __init ne2_probe1(struct net_device *dev, int slot)
-{
- int i, base_addr, irq, retval;
- unsigned char POS;
- unsigned char SA_prom[32];
- const char *name = "NE/2";
- int start_page, stop_page;
- static unsigned version_printed;
-
- if (ei_debug && version_printed++ == 0)
- printk(version);
-
- printk("NE/2 ethercard found in slot %d:", slot);
-
- /* Read base IO and IRQ from the POS-registers */
- POS = mca_read_stored_pos(slot, 2);
- if(!(POS % 2)) {
- printk(" disabled.\n");
- return -ENODEV;
- }
-
- /* handle different POS register structure for D-Link card */
-
- if (mca_read_stored_pos(slot, 0) == 0xea) {
- base_addr = dlink_addresses[(POS >> 5) & 0x03];
- irq = dlink_irqs[(POS >> 2) & 0x07];
- }
- else {
- i = (POS & 0xE)>>1;
- /* printk("Halleluja sdog, als er na de pijl een 1 staat is 1 - 1 == 0"
- " en zou het moeten werken -> %d\n", i);
- The above line was for remote testing, thanx to sdog ... */
- base_addr = addresses[i - 1];
- irq = irqs[(POS & 0x60)>>5];
- }
-
- if (!request_region(base_addr, NE_IO_EXTENT, DRV_NAME))
- return -EBUSY;
-
-#ifdef DEBUG
- printk("POS info : pos 2 = %#x ; base = %#x ; irq = %ld\n", POS,
- base_addr, irq);
-#endif
-
-#ifndef CRYNWR_WAY
- /* Reset the card the way they do it in the Crynwr packet driver */
- for (i=0; i<8; i++)
- outb(0x0, base_addr + NE_RESET);
- inb(base_addr + NE_RESET);
- outb(0x21, base_addr + NE_CMD);
- if (inb(base_addr + NE_CMD) != 0x21) {
- printk("NE/2 adapter not responding\n");
- retval = -ENODEV;
- goto out;
- }
-
- /* In the crynwr sources they do a RAM-test here. I skip it. I suppose
- my RAM is okay. Suppose your memory is broken. Then this test
- should fail and you won't be able to use your card. But if I do not
- test, you won't be able to use your card, neither. So this test
- won't help you. */
-
-#else /* _I_ never tested it this way .. Go ahead and try ...*/
- /* Reset card. Who knows what dain-bramaged state it was left in. */
- {
- unsigned long reset_start_time = jiffies;
-
- /* DON'T change these to inb_p/outb_p or reset will fail on
- clones.. */
- outb(inb(base_addr + NE_RESET), base_addr + NE_RESET);
-
- while ((inb_p(base_addr + EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
- printk(" not found (no reset ack).\n");
- retval = -ENODEV;
- goto out;
- }
-
- outb_p(0xff, base_addr + EN0_ISR); /* Ack all intr. */
- }
-#endif
-
-
- /* Read the 16 bytes of station address PROM.
- We must first initialize registers, similar to
- NS8390p_init(eifdev, 0).
- We can't reliably read the SAPROM address without this.
- (I learned the hard way!). */
- {
- struct {
- unsigned char value, offset;
- } program_seq[] = {
- /* Select page 0 */
- {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD},
- {0x49, EN0_DCFG}, /* Set WORD-wide (0x49) access. */
- {0x00, EN0_RCNTLO}, /* Clear the count regs. */
- {0x00, EN0_RCNTHI},
- {0x00, EN0_IMR}, /* Mask completion irq. */
- {0xFF, EN0_ISR},
- {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
- {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
- {32, EN0_RCNTLO},
- {0x00, EN0_RCNTHI},
- {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
- {0x00, EN0_RSARHI},
- {E8390_RREAD+E8390_START, E8390_CMD},
- };
-
- for (i = 0; i < ARRAY_SIZE(program_seq); i++)
- outb_p(program_seq[i].value, base_addr +
- program_seq[i].offset);
-
- }
- for(i = 0; i < 6 /*sizeof(SA_prom)*/; i+=1) {
- SA_prom[i] = inb(base_addr + NE_DATAPORT);
- }
-
- /* I don't know whether the previous sequence includes the general
- board reset procedure, so better don't omit it and just overwrite
- the garbage read from a DE-320 with correct stuff. */
-
- if (mca_read_stored_pos(slot, 0) == 0xea) {
- unsigned int v;
-
- for (i = 0; i < 3; i++) {
- v = dlink_get_eeprom(i, base_addr);
- SA_prom[(i << 1) ] = v & 0xff;
- SA_prom[(i << 1) + 1] = (v >> 8) & 0xff;
- }
- }
-
- start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
-
- dev->irq=irq;
-
- /* Snarf the interrupt now. There's no point in waiting since we cannot
- share and the board will usually be enabled. */
- retval = request_irq(dev->irq, eip_interrupt, 0, DRV_NAME, dev);
- if (retval) {
- printk (" unable to get IRQ %d (irqval=%d).\n",
- dev->irq, retval);
- goto out;
- }
-
- dev->base_addr = base_addr;
-
- for (i = 0; i < ETH_ALEN; i++)
- dev->dev_addr[i] = SA_prom[i];
-
- printk(" %pM\n", dev->dev_addr);
-
- printk("%s: %s found at %#x, using IRQ %d.\n",
- dev->name, name, base_addr, dev->irq);
-
- mca_set_adapter_procfn(slot, (MCA_ProcFn) ne2_procinfo, dev);
-
- ei_status.name = name;
- ei_status.tx_start_page = start_page;
- ei_status.stop_page = stop_page;
- ei_status.word16 = (2 == 2);
-
- ei_status.rx_start_page = start_page + TX_PAGES;
-#ifdef PACKETBUF_MEMSIZE
- /* Allow the packet buffer size to be overridden by know-it-alls. */
- ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
- ei_status.reset_8390 = &ne_reset_8390;
- ei_status.block_input = &ne_block_input;
- ei_status.block_output = &ne_block_output;
- ei_status.get_8390_hdr = &ne_get_8390_hdr;
-
- ei_status.priv = slot;
-
- dev->netdev_ops = &eip_netdev_ops;
- NS8390p_init(dev, 0);
-
- retval = register_netdev(dev);
- if (retval)
- goto out1;
- return 0;
-out1:
- mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
- free_irq(dev->irq, dev);
-out:
- release_region(base_addr, NE_IO_EXTENT);
- return retval;
-}
-
-/* Hard reset the card. This used to pause for the same period that a
- 8390 reset command required, but that shouldn't be necessary. */
-static void ne_reset_8390(struct net_device *dev)
-{
- unsigned long reset_start_time = jiffies;
-
- if (ei_debug > 1)
- printk("resetting the 8390 t=%ld...", jiffies);
-
- /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
- outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
- ei_status.txing = 0;
- ei_status.dmaing = 0;
-
- /* This check _should_not_ be necessary, omit eventually. */
- while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
- printk("%s: ne_reset_8390() did not complete.\n",
- dev->name);
- break;
- }
- outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
- we don't need to be concerned with ring wrap as the header will be at
- the start of a page, so we optimize accordingly. */
-
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
- int ring_page)
-{
-
- int nic_base = dev->base_addr;
-
- /* This *shouldn't* happen.
- If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk("%s: DMAing conflict in ne_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
- return;
- }
-
- ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
- outb_p(0, nic_base + EN0_RCNTHI);
- outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
- outb_p(ring_page, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
- if (ei_status.word16)
- insw(NE_BASE + NE_DATAPORT, hdr,
- sizeof(struct e8390_pkt_hdr)>>1);
- else
- insb(NE_BASE + NE_DATAPORT, hdr,
- sizeof(struct e8390_pkt_hdr));
-
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
-
-/* Block input and output, similar to the Crynwr packet driver. If you
- are porting to a new ethercard, look at the packet driver source for
- hints. The NEx000 doesn't share the on-board packet memory -- you have
- to put the packet out through the "remote DMA" dataport using outb. */
-
-static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb,
- int ring_offset)
-{
-#ifdef NE_SANITY_CHECK
- int xfer_count = count;
-#endif
- int nic_base = dev->base_addr;
- char *buf = skb->data;
-
- /* This *shouldn't* happen.
- If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk("%s: DMAing conflict in ne_block_input "
- "[DMAstat:%d][irqlock:%d].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
- outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- if (ei_status.word16) {
- insw(NE_BASE + NE_DATAPORT,buf,count>>1);
- if (count & 0x01) {
- buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-#ifdef NE_SANITY_CHECK
- xfer_count++;
-#endif
- }
- } else {
- insb(NE_BASE + NE_DATAPORT, buf, count);
- }
-
-#ifdef NE_SANITY_CHECK
- /* This was for the ALPHA version only, but enough people have
- been encountering problems so it is still here. If you see
- this message you either 1) have a slightly incompatible clone
- or 2) have noise/speed problems with your bus. */
- if (ei_debug > 1) { /* DMA termination address check... */
- int addr, tries = 20;
- do {
- /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
- -- it's broken for Rx on some cards! */
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- addr = (high << 8) + low;
- if (((ring_offset + xfer_count) & 0xff) == low)
- break;
- } while (--tries > 0);
- if (tries <= 0)
- printk("%s: RX transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- dev->name, ring_offset + xfer_count, addr);
- }
-#endif
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
-
-static void ne_block_output(struct net_device *dev, int count,
- const unsigned char *buf, const int start_page)
-{
- int nic_base = NE_BASE;
- unsigned long dma_start;
-#ifdef NE_SANITY_CHECK
- int retries = 0;
-#endif
-
- /* Round the count up for word writes. Do we need to do this?
- What effect will an odd byte count have on the 8390?
- I should check someday. */
- if (ei_status.word16 && (count & 0x01))
- count++;
-
- /* This *shouldn't* happen.
- If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk("%s: DMAing conflict in ne_block_output."
- "[DMAstat:%d][irqlock:%d]\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-#ifdef NE_SANITY_CHECK
-retry:
-#endif
-
-#ifdef NE8390_RW_BUGFIX
- /* Handle the read-before-write bug the same way as the
- Crynwr packet driver -- the NatSemi method doesn't work.
- Actually this doesn't always work either, but if you have
- problems with your NEx000 this is better than nothing! */
- outb_p(0x42, nic_base + EN0_RCNTLO);
- outb_p(0x00, nic_base + EN0_RCNTHI);
- outb_p(0x42, nic_base + EN0_RSARLO);
- outb_p(0x00, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- /* Make certain that the dummy read has occurred. */
- SLOW_DOWN_IO;
- SLOW_DOWN_IO;
- SLOW_DOWN_IO;
-#endif
-
- outb_p(ENISR_RDC, nic_base + EN0_ISR);
-
- /* Now the normal output. */
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(0x00, nic_base + EN0_RSARLO);
- outb_p(start_page, nic_base + EN0_RSARHI);
-
- outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
- if (ei_status.word16) {
- outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
- } else {
- outsb(NE_BASE + NE_DATAPORT, buf, count);
- }
-
- dma_start = jiffies;
-
-#ifdef NE_SANITY_CHECK
- /* This was for the ALPHA version only, but enough people have
- been encountering problems so it is still here. */
-
- if (ei_debug > 1) { /* DMA termination address check... */
- int addr, tries = 20;
- do {
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- addr = (high << 8) + low;
- if ((start_page << 8) + count == addr)
- break;
- } while (--tries > 0);
- if (tries <= 0) {
- printk("%s: Tx packet transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- dev->name, (start_page << 8) + count, addr);
- if (retries++ == 0)
- goto retry;
- }
- }
-#endif
-
- while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
- if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
- printk("%s: timeout waiting for Tx RDC.\n", dev->name);
- ne_reset_8390(dev);
- NS8390p_init(dev, 1);
- break;
- }
-
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
-
-
-#ifdef MODULE
-#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
-static struct net_device *dev_ne[MAX_NE_CARDS];
-static int io[MAX_NE_CARDS];
-static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
-MODULE_LICENSE("GPL");
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(bad, int, NULL, 0);
-MODULE_PARM_DESC(io, "(ignored)");
-MODULE_PARM_DESC(irq, "(ignored)");
-MODULE_PARM_DESC(bad, "(ignored)");
-
-/* Module code fixed by David Weinehall */
-
-int __init init_module(void)
-{
- struct net_device *dev;
- int this_dev, found = 0;
-
- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- dev = alloc_eip_netdev();
- if (!dev)
- break;
- dev->irq = irq[this_dev];
- dev->mem_end = bad[this_dev];
- dev->base_addr = io[this_dev];
- if (do_ne2_probe(dev) == 0) {
- dev_ne[found++] = dev;
- continue;
- }
- free_netdev(dev);
- break;
- }
- if (found)
- return 0;
- printk(KERN_WARNING "ne2.c: No NE/2 card found\n");
- return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
- mca_mark_as_unused(ei_status.priv);
- mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
-}
-
-void __exit cleanup_module(void)
-{
- int this_dev;
-
- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = dev_ne[this_dev];
- if (dev) {
- unregister_netdev(dev);
- cleanup_card(dev);
- free_netdev(dev);
- }
- }
-}
-#endif /* MODULE */
diff --git a/drivers/net/ethernet/8390/smc-mca.c b/drivers/net/ethernet/8390/smc-mca.c
deleted file mode 100644
index 7a68590f2804..000000000000
--- a/drivers/net/ethernet/8390/smc-mca.c
+++ /dev/null
@@ -1,575 +0,0 @@
-/* smc-mca.c: A SMC Ultra ethernet driver for linux. */
-/*
- Most of this driver, except for ultramca_probe is nearly
- verbatim from smc-ultra.c by Donald Becker. The rest is
- written and copyright 1996 by David Weis, weisd3458@uni.edu
-
- This is a driver for the SMC Ultra and SMC EtherEZ ethercards.
-
- This driver uses the cards in the 8390-compatible, shared memory mode.
- Most of the run-time complexity is handled by the generic code in
- 8390.c.
-
- This driver enables the shared memory only when doing the actual data
- transfers to avoid a bug in early version of the card that corrupted
- data transferred by a AHA1542.
-
- This driver does not support the programmed-I/O data transfer mode of
- the EtherEZ. That support (if available) is smc-ez.c. Nor does it
- use the non-8390-compatible "Altego" mode. (No support currently planned.)
-
- Changelog:
-
- Paul Gortmaker : multiple card support for module users.
- David Weis : Micro Channel-ized it.
- Tom Sightler : Added support for IBM PS/2 Ethernet Adapter/A
- Christopher Turcksin : Changed MCA-probe so that multiple adapters are
- found correctly (Jul 16, 1997)
- Chris Beauregard : Tried to merge the two changes above (Dec 15, 1997)
- Tom Sightler : Fixed minor detection bug caused by above merge
- Tom Sightler : Added support for three more Western Digital
- MCA-adapters
- Tom Sightler : Added support for 2.2.x mca_find_unused_adapter
- Hartmut Schmidt : - Modified parameter detection to handle each
- card differently depending on a switch-list
- - 'card_ver' removed from the adapter list
- - Some minor bug fixes
-*/
-
-#include <linux/mca.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include <asm/io.h>
-
-#include "8390.h"
-
-#define DRV_NAME "smc-mca"
-
-static int ultramca_open(struct net_device *dev);
-static void ultramca_reset_8390(struct net_device *dev);
-static void ultramca_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr,
- int ring_page);
-static void ultramca_block_input(struct net_device *dev, int count,
- struct sk_buff *skb,
- int ring_offset);
-static void ultramca_block_output(struct net_device *dev, int count,
- const unsigned char *buf,
- const int start_page);
-static int ultramca_close_card(struct net_device *dev);
-
-#define START_PG 0x00 /* First page of TX buffer */
-
-#define ULTRA_CMDREG 0 /* Offset to ASIC command register. */
-#define ULTRA_RESET 0x80 /* Board reset, in ULTRA_CMDREG. */
-#define ULTRA_MEMENB 0x40 /* Enable the shared memory. */
-#define ULTRA_NIC_OFFSET 16 /* NIC register offset from the base_addr. */
-#define ULTRA_IO_EXTENT 32
-#define EN0_ERWCNT 0x08 /* Early receive warning count. */
-
-#define _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A 0
-#define _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A 1
-#define _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A 2
-#define _6fc1_WD_Starcard_PLUS_A_WD8003ST_A 3
-#define _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A 4
-#define _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A 5
-#define _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A 6
-#define _efe5_IBM_PS2_Adapter_A_for_Ethernet 7
-
-struct smc_mca_adapters_t {
- unsigned int id;
- char *name;
-};
-
-#define MAX_ULTRAMCA_CARDS 4 /* Max number of Ultra cards per module */
-
-static int ultra_io[MAX_ULTRAMCA_CARDS];
-static int ultra_irq[MAX_ULTRAMCA_CARDS];
-MODULE_LICENSE("GPL");
-
-module_param_array(ultra_io, int, NULL, 0);
-module_param_array(ultra_irq, int, NULL, 0);
-MODULE_PARM_DESC(ultra_io, "SMC Ultra/EtherEZ MCA I/O base address(es)");
-MODULE_PARM_DESC(ultra_irq, "SMC Ultra/EtherEZ MCA IRQ number(s)");
-
-static const struct {
- unsigned int base_addr;
-} addr_table[] = {
- { 0x0800 },
- { 0x1800 },
- { 0x2800 },
- { 0x3800 },
- { 0x4800 },
- { 0x5800 },
- { 0x6800 },
- { 0x7800 },
- { 0x8800 },
- { 0x9800 },
- { 0xa800 },
- { 0xb800 },
- { 0xc800 },
- { 0xd800 },
- { 0xe800 },
- { 0xf800 }
-};
-
-#define MEM_MASK 64
-
-static const struct {
- unsigned char mem_index;
- unsigned long mem_start;
- unsigned char num_pages;
-} mem_table[] = {
- { 16, 0x0c0000, 40 },
- { 18, 0x0c4000, 40 },
- { 20, 0x0c8000, 40 },
- { 22, 0x0cc000, 40 },
- { 24, 0x0d0000, 40 },
- { 26, 0x0d4000, 40 },
- { 28, 0x0d8000, 40 },
- { 30, 0x0dc000, 40 },
- {144, 0xfc0000, 40 },
- {148, 0xfc8000, 40 },
- {154, 0xfd0000, 40 },
- {156, 0xfd8000, 40 },
- { 0, 0x0c0000, 20 },
- { 1, 0x0c2000, 20 },
- { 2, 0x0c4000, 20 },
- { 3, 0x0c6000, 20 }
-};
-
-#define IRQ_MASK 243
-static const struct {
- unsigned char new_irq;
- unsigned char old_irq;
-} irq_table[] = {
- { 3, 3 },
- { 4, 4 },
- { 10, 10 },
- { 14, 15 }
-};
-
-static short smc_mca_adapter_ids[] __initdata = {
- 0x61c8,
- 0x61c9,
- 0x6fc0,
- 0x6fc1,
- 0x6fc2,
- 0xefd4,
- 0xefd5,
- 0xefe5,
- 0x0000
-};
-
-static char *smc_mca_adapter_names[] __initdata = {
- "SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)",
- "SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)",
- "WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)",
- "WD Starcard PLUS/A (WD8003ST/A)",
- "WD Ethercard PLUS 10T/A (WD8003W/A)",
- "IBM PS/2 Adapter/A for Ethernet UTP/AUI (WD8013WP/A)",
- "IBM PS/2 Adapter/A for Ethernet BNC/AUI (WD8013EP/A)",
- "IBM PS/2 Adapter/A for Ethernet",
- NULL
-};
-
-static int ultra_found = 0;
-
-
-static const struct net_device_ops ultramca_netdev_ops = {
- .ndo_open = ultramca_open,
- .ndo_stop = ultramca_close_card,
-
- .ndo_start_xmit = ei_start_xmit,
- .ndo_tx_timeout = ei_tx_timeout,
- .ndo_get_stats = ei_get_stats,
- .ndo_set_rx_mode = ei_set_multicast_list,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = ei_poll,
-#endif
-};
-
-static int __init ultramca_probe(struct device *gen_dev)
-{
- unsigned short ioaddr;
- struct net_device *dev;
- unsigned char reg4, num_pages;
- struct mca_device *mca_dev = to_mca_device(gen_dev);
- char slot = mca_dev->slot;
- unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff;
- int i, rc;
- int adapter = mca_dev->index;
- int tbase = 0;
- int tirq = 0;
- int base_addr = ultra_io[ultra_found];
- int irq = ultra_irq[ultra_found];
-
- if (base_addr || irq) {
- printk(KERN_INFO "Probing for SMC MCA adapter");
- if (base_addr) {
- printk(KERN_INFO " at I/O address 0x%04x%c",
- base_addr, irq ? ' ' : '\n');
- }
- if (irq) {
- printk(KERN_INFO "using irq %d\n", irq);
- }
- }
-
- tirq = 0;
- tbase = 0;
-
- /* If we're trying to match a specificied irq or io address,
- * we'll reject the adapter found unless it's the one we're
- * looking for */
-
- pos2 = mca_device_read_stored_pos(mca_dev, 2); /* io_addr */
- pos3 = mca_device_read_stored_pos(mca_dev, 3); /* shared mem */
- pos4 = mca_device_read_stored_pos(mca_dev, 4); /* ROM bios addr range */
- pos5 = mca_device_read_stored_pos(mca_dev, 5); /* irq, media and RIPL */
-
- /* Test the following conditions:
- * - If an irq parameter is supplied, compare it
- * with the irq of the adapter we found
- * - If a base_addr paramater is given, compare it
- * with the base_addr of the adapter we found
- * - Check that the irq and the base_addr of the
- * adapter we found is not already in use by
- * this driver
- */
-
- switch (mca_dev->index) {
- case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
- case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
- case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
- case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
- {
- tbase = addr_table[(pos2 & 0xf0) >> 4].base_addr;
- tirq = irq_table[(pos5 & 0xc) >> 2].new_irq;
- break;
- }
- case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
- case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
- case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
- case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
- {
- tbase = ((pos2 & 0x0fe) * 0x10);
- tirq = irq_table[(pos5 & 3)].old_irq;
- break;
- }
- }
-
- if(!tirq || !tbase ||
- (irq && irq != tirq) ||
- (base_addr && tbase != base_addr))
- /* FIXME: we're trying to force the ordering of the
- * devices here, there should be a way of getting this
- * to happen */
- return -ENXIO;
-
- /* Adapter found. */
- dev = alloc_ei_netdev();
- if(!dev)
- return -ENODEV;
-
- SET_NETDEV_DEV(dev, gen_dev);
- mca_device_set_name(mca_dev, smc_mca_adapter_names[adapter]);
- mca_device_set_claim(mca_dev, 1);
-
- printk(KERN_INFO "smc_mca: %s found in slot %d\n",
- smc_mca_adapter_names[adapter], slot + 1);
-
- ultra_found++;
-
- dev->base_addr = ioaddr = mca_device_transform_ioport(mca_dev, tbase);
- dev->irq = mca_device_transform_irq(mca_dev, tirq);
- dev->mem_start = 0;
- num_pages = 40;
-
- switch (adapter) { /* card-# in const array above [hs] */
- case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
- case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
- {
- for (i = 0; i < 16; i++) { /* taking 16 counts
- * up to 15 [hs] */
- if (mem_table[i].mem_index == (pos3 & ~MEM_MASK)) {
- dev->mem_start = (unsigned long)
- mca_device_transform_memory(mca_dev, (void *)mem_table[i].mem_start);
- num_pages = mem_table[i].num_pages;
- }
- }
- break;
- }
- case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
- case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
- case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
- case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
- {
- dev->mem_start = (unsigned long)
- mca_device_transform_memory(mca_dev, (void *)((pos3 & 0xfc) * 0x1000));
- num_pages = 0x40;
- break;
- }
- case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
- case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
- {
- /* courtesy of gamera@quartz.ocn.ne.jp, pos3 indicates
- * the index of the 0x2000 step.
- * beware different number of pages [hs]
- */
- dev->mem_start = (unsigned long)
- mca_device_transform_memory(mca_dev, (void *)(0xc0000 + (0x2000 * (pos3 & 0xf))));
- num_pages = 0x20 + (2 * (pos3 & 0x10));
- break;
- }
- }
-
- /* sanity check, shouldn't happen */
- if (dev->mem_start == 0) {
- rc = -ENODEV;
- goto err_unclaim;
- }
-
- if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) {
- rc = -ENODEV;
- goto err_unclaim;
- }
-
- reg4 = inb(ioaddr + 4) & 0x7f;
- outb(reg4, ioaddr + 4);
-
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = inb(ioaddr + 8 + i);
-
- printk(KERN_INFO "smc_mca[%d]: Parameters: %#3x, %pM",
- slot + 1, ioaddr, dev->dev_addr);
-
- /* Switch from the station address to the alternate register set
- * and read the useful registers there.
- */
-
- outb(0x80 | reg4, ioaddr + 4);
-
- /* Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot.
- */
-
- outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
-
- /* Switch back to the station address register set so that
- * the MS-DOS driver can find the card after a warm boot.
- */
-
- outb(reg4, ioaddr + 4);
-
- dev_set_drvdata(gen_dev, dev);
-
- /* The 8390 isn't at the base address, so fake the offset
- */
-
- dev->base_addr = ioaddr + ULTRA_NIC_OFFSET;
-
- ei_status.name = "SMC Ultra MCA";
- ei_status.word16 = 1;
- ei_status.tx_start_page = START_PG;
- ei_status.rx_start_page = START_PG + TX_PAGES;
- ei_status.stop_page = num_pages;
-
- ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG) * 256);
- if (!ei_status.mem) {
- rc = -ENOMEM;
- goto err_release_region;
- }
-
- dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG) * 256;
-
- printk(", IRQ %d memory %#lx-%#lx.\n",
- dev->irq, dev->mem_start, dev->mem_end - 1);
-
- ei_status.reset_8390 = &ultramca_reset_8390;
- ei_status.block_input = &ultramca_block_input;
- ei_status.block_output = &ultramca_block_output;
- ei_status.get_8390_hdr = &ultramca_get_8390_hdr;
-
- ei_status.priv = slot;
-
- dev->netdev_ops = &ultramca_netdev_ops;
-
- NS8390_init(dev, 0);
-
- rc = register_netdev(dev);
- if (rc)
- goto err_unmap;
-
- return 0;
-
-err_unmap:
- iounmap(ei_status.mem);
-err_release_region:
- release_region(ioaddr, ULTRA_IO_EXTENT);
-err_unclaim:
- mca_device_set_claim(mca_dev, 0);
- free_netdev(dev);
- return rc;
-}
-
-static int ultramca_open(struct net_device *dev)
-{
- int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
- int retval;
-
- if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)))
- return retval;
-
- outb(ULTRA_MEMENB, ioaddr); /* Enable memory */
- outb(0x80, ioaddr + 5); /* ??? */
- outb(0x01, ioaddr + 6); /* Enable interrupts and memory. */
- outb(0x04, ioaddr + 5); /* ??? */
-
- /* Set the early receive warning level in window 0 high enough not
- * to receive ERW interrupts.
- */
-
- /* outb_p(E8390_NODMA + E8390_PAGE0, dev->base_addr);
- * outb(0xff, dev->base_addr + EN0_ERWCNT);
- */
-
- ei_open(dev);
- return 0;
-}
-
-static void ultramca_reset_8390(struct net_device *dev)
-{
- int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
-
- outb(ULTRA_RESET, ioaddr);
- if (ei_debug > 1)
- printk("resetting Ultra, t=%ld...", jiffies);
- ei_status.txing = 0;
-
- outb(0x80, ioaddr + 5); /* ??? */
- outb(0x01, ioaddr + 6); /* Enable interrupts and memory. */
-
- if (ei_debug > 1)
- printk("reset done\n");
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
- * we don't need to be concerned with ring wrap as the header will be at
- * the start of a page, so we optimize accordingly.
- */
-
-static void ultramca_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
- void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG) << 8);
-
-#ifdef notdef
- /* Officially this is what we are doing, but the readl() is faster */
- memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-#else
- ((unsigned int*)hdr)[0] = readl(hdr_start);
-#endif
-}
-
-/* Block input and output are easy on shared memory ethercards, the only
- * complication is when the ring buffer wraps.
- */
-
-static void ultramca_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
- void __iomem *xfer_start = ei_status.mem + ring_offset - START_PG * 256;
-
- if (ring_offset + count > ei_status.stop_page * 256) {
- /* We must wrap the input move. */
- int semi_count = ei_status.stop_page * 256 - ring_offset;
- memcpy_fromio(skb->data, xfer_start, semi_count);
- count -= semi_count;
- memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
- } else {
- memcpy_fromio(skb->data, xfer_start, count);
- }
-
-}
-
-static void ultramca_block_output(struct net_device *dev, int count, const unsigned char *buf,
- int start_page)
-{
- void __iomem *shmem = ei_status.mem + ((start_page - START_PG) << 8);
-
- memcpy_toio(shmem, buf, count);
-}
-
-static int ultramca_close_card(struct net_device *dev)
-{
- int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
-
- netif_stop_queue(dev);
-
- if (ei_debug > 1)
- printk("%s: Shutting down ethercard.\n", dev->name);
-
- outb(0x00, ioaddr + 6); /* Disable interrupts. */
- free_irq(dev->irq, dev);
-
- NS8390_init(dev, 0);
- /* We should someday disable shared memory and change to 8-bit mode
- * "just in case"...
- */
-
- return 0;
-}
-
-static int ultramca_remove(struct device *gen_dev)
-{
- struct mca_device *mca_dev = to_mca_device(gen_dev);
- struct net_device *dev = dev_get_drvdata(gen_dev);
-
- if (dev) {
- /* NB: ultra_close_card() does free_irq */
- int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
-
- unregister_netdev(dev);
- mca_device_set_claim(mca_dev, 0);
- release_region(ioaddr, ULTRA_IO_EXTENT);
- iounmap(ei_status.mem);
- free_netdev(dev);
- }
- return 0;
-}
-
-
-static struct mca_driver ultra_driver = {
- .id_table = smc_mca_adapter_ids,
- .driver = {
- .name = "smc-mca",
- .bus = &mca_bus_type,
- .probe = ultramca_probe,
- .remove = ultramca_remove,
- }
-};
-
-static int __init ultramca_init_module(void)
-{
- if(!MCA_bus)
- return -ENXIO;
-
- mca_register_driver(&ultra_driver);
-
- return ultra_found ? 0 : -ENXIO;
-}
-
-static void __exit ultramca_cleanup_module(void)
-{
- mca_unregister_driver(&ultra_driver);
-}
-module_init(ultramca_init_module);
-module_exit(ultramca_cleanup_module);
-
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index c63a64cb6085..a11af5cc4844 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -174,6 +174,7 @@ source "drivers/net/ethernet/tile/Kconfig"
source "drivers/net/ethernet/toshiba/Kconfig"
source "drivers/net/ethernet/tundra/Kconfig"
source "drivers/net/ethernet/via/Kconfig"
+source "drivers/net/ethernet/wiznet/Kconfig"
source "drivers/net/ethernet/xilinx/Kconfig"
source "drivers/net/ethernet/xircom/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index 9676a5109d94..878ad32b93f2 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -73,5 +73,6 @@ obj-$(CONFIG_TILE_NET) += tile/
obj-$(CONFIG_NET_VENDOR_TOSHIBA) += toshiba/
obj-$(CONFIG_NET_VENDOR_TUNDRA) += tundra/
obj-$(CONFIG_NET_VENDOR_VIA) += via/
+obj-$(CONFIG_NET_VENDOR_WIZNET) += wiznet/
obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index d896816512ca..d920a529ba22 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -114,15 +114,6 @@ static int rx_copybreak /* = 0 */;
#define DMA_BURST_SIZE 128
#endif
-/* Used to pass the media type, etc.
- Both 'options[]' and 'full_duplex[]' exist for driver interoperability.
- The media type is usually passed in 'options[]'.
- These variables are deprecated, use ethtool instead. -Ion
-*/
-#define MAX_UNITS 8 /* More are supported, limit only on options */
-static int options[MAX_UNITS] = {0, };
-static int full_duplex[MAX_UNITS] = {0, };
-
/* Operational parameters that are set at compile time. */
/* The "native" ring sizes are either 256 or 2048.
@@ -192,8 +183,6 @@ module_param(debug, int, 0);
module_param(rx_copybreak, int, 0);
module_param(intr_latency, int, 0);
module_param(small_frames, int, 0);
-module_param_array(options, int, NULL, 0);
-module_param_array(full_duplex, int, NULL, 0);
module_param(enable_hw_cksum, int, 0);
MODULE_PARM_DESC(max_interrupt_work, "Maximum events handled per interrupt");
MODULE_PARM_DESC(mtu, "MTU (all boards)");
@@ -201,8 +190,6 @@ MODULE_PARM_DESC(debug, "Debug level (0-6)");
MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
MODULE_PARM_DESC(intr_latency, "Maximum interrupt latency, in microseconds");
MODULE_PARM_DESC(small_frames, "Maximum size of receive frames that bypass interrupt latency (0,64,128,256,512)");
-MODULE_PARM_DESC(options, "Deprecated: Bits 0-3: media type, bit 17: full duplex");
-MODULE_PARM_DESC(full_duplex, "Deprecated: Forced full-duplex setting (0/1)");
MODULE_PARM_DESC(enable_hw_cksum, "Enable/disable hardware cksum support (0/1)");
/*
@@ -657,10 +644,10 @@ static const struct net_device_ops netdev_ops = {
static int __devinit starfire_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
+ struct device *d = &pdev->dev;
struct netdev_private *np;
- int i, irq, option, chip_idx = ent->driver_data;
+ int i, irq, chip_idx = ent->driver_data;
struct net_device *dev;
- static int card_idx = -1;
long ioaddr;
void __iomem *base;
int drv_flags, io_size;
@@ -673,15 +660,13 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
printk(version);
#endif
- card_idx++;
-
if (pci_enable_device (pdev))
return -EIO;
ioaddr = pci_resource_start(pdev, 0);
io_size = pci_resource_len(pdev, 0);
if (!ioaddr || ((pci_resource_flags(pdev, 0) & IORESOURCE_MEM) == 0)) {
- printk(KERN_ERR DRV_NAME " %d: no PCI MEM resources, aborting\n", card_idx);
+ dev_err(d, "no PCI MEM resources, aborting\n");
return -ENODEV;
}
@@ -694,14 +679,14 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
irq = pdev->irq;
if (pci_request_regions (pdev, DRV_NAME)) {
- printk(KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", card_idx);
+ dev_err(d, "cannot reserve PCI resources, aborting\n");
goto err_out_free_netdev;
}
base = ioremap(ioaddr, io_size);
if (!base) {
- printk(KERN_ERR DRV_NAME " %d: cannot remap %#x @ %#lx, aborting\n",
- card_idx, io_size, ioaddr);
+ dev_err(d, "cannot remap %#x @ %#lx, aborting\n",
+ io_size, ioaddr);
goto err_out_free_res;
}
@@ -753,9 +738,6 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
/* wait a little longer */
udelay(1000);
- dev->base_addr = (unsigned long)base;
- dev->irq = irq;
-
np = netdev_priv(dev);
np->dev = dev;
np->base = base;
@@ -772,21 +754,6 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
drv_flags = netdrv_tbl[chip_idx].drv_flags;
- option = card_idx < MAX_UNITS ? options[card_idx] : 0;
- if (dev->mem_start)
- option = dev->mem_start;
-
- /* The lower four bits are the media type. */
- if (option & 0x200)
- np->mii_if.full_duplex = 1;
-
- if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
- np->mii_if.full_duplex = 1;
-
- if (np->mii_if.full_duplex)
- np->mii_if.force_media = 1;
- else
- np->mii_if.force_media = 0;
np->speed100 = 1;
/* timer resolution is 128 * 0.8us */
@@ -909,13 +876,14 @@ static int netdev_open(struct net_device *dev)
const __be32 *fw_rx_data, *fw_tx_data;
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->base;
+ const int irq = np->pci_dev->irq;
int i, retval;
size_t tx_size, rx_size;
size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
/* Do we ever need to reset the chip??? */
- retval = request_irq(dev->irq, intr_handler, IRQF_SHARED, dev->name, dev);
+ retval = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev);
if (retval)
return retval;
@@ -924,7 +892,7 @@ static int netdev_open(struct net_device *dev)
writel(1, ioaddr + PCIDeviceConfig);
if (debug > 1)
printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
- dev->name, dev->irq);
+ dev->name, irq);
/* Allocate the various queues. */
if (!np->queue_mem) {
@@ -935,7 +903,7 @@ static int netdev_open(struct net_device *dev)
np->queue_mem_size = tx_done_q_size + rx_done_q_size + tx_ring_size + rx_ring_size;
np->queue_mem = pci_alloc_consistent(np->pci_dev, np->queue_mem_size, &np->queue_mem_dma);
if (np->queue_mem == NULL) {
- free_irq(dev->irq, dev);
+ free_irq(irq, dev);
return -ENOMEM;
}
@@ -1962,7 +1930,7 @@ static int netdev_close(struct net_device *dev)
}
}
- free_irq(dev->irq, dev);
+ free_irq(np->pci_dev->irq, dev);
/* Free all the skbuffs in the Rx queue. */
for (i = 0; i < RX_RING_SIZE; i++) {
diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index ab4daeccdf98..f816426e1085 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -548,6 +548,25 @@ static int bfin_mac_ethtool_setwol(struct net_device *dev,
return 0;
}
+static int bfin_mac_ethtool_get_ts_info(struct net_device *dev,
+ struct ethtool_ts_info *info)
+{
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_SYS_HARDWARE;
+ info->phc_index = -1;
+ info->tx_types =
+ (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+ info->rx_filters =
+ (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
+ return 0;
+}
+
static const struct ethtool_ops bfin_mac_ethtool_ops = {
.get_settings = bfin_mac_ethtool_getsettings,
.set_settings = bfin_mac_ethtool_setsettings,
@@ -555,6 +574,7 @@ static const struct ethtool_ops bfin_mac_ethtool_ops = {
.get_drvinfo = bfin_mac_ethtool_getdrvinfo,
.get_wol = bfin_mac_ethtool_getwol,
.set_wol = bfin_mac_ethtool_setwol,
+ .get_ts_info = bfin_mac_ethtool_get_ts_info,
};
/**************************************************************************/
diff --git a/drivers/net/ethernet/amd/ariadne.c b/drivers/net/ethernet/amd/ariadne.c
index f4c228e4d76c..f2958df9a1e4 100644
--- a/drivers/net/ethernet/amd/ariadne.c
+++ b/drivers/net/ethernet/amd/ariadne.c
@@ -213,10 +213,10 @@ static int ariadne_rx(struct net_device *dev)
(const void *)priv->rx_buff[entry],
pkt_len);
skb->protocol = eth_type_trans(skb, dev);
- netdev_dbg(dev, "RX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+ netdev_dbg(dev, "RX pkt type 0x%04x from %pM to %pM data %p len %u\n",
((u_short *)skb->data)[6],
skb->data + 6, skb->data,
- (int)skb->data, (int)skb->len);
+ skb->data, skb->len);
netif_rx(skb);
dev->stats.rx_packets++;
@@ -566,10 +566,10 @@ static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
/* Fill in a Tx ring entry */
- netdev_dbg(dev, "TX pkt type 0x%04x from %pM to %pM data 0x%08x len %d\n",
+ netdev_dbg(dev, "TX pkt type 0x%04x from %pM to %pM data %p len %u\n",
((u_short *)skb->data)[6],
skb->data + 6, skb->data,
- (int)skb->data, (int)skb->len);
+ skb->data, skb->len);
local_irq_save(flags);
diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c
index 70ed79c46245..84219df72f51 100644
--- a/drivers/net/ethernet/amd/atarilance.c
+++ b/drivers/net/ethernet/amd/atarilance.c
@@ -558,21 +558,18 @@ static unsigned long __init lance_probe1( struct net_device *dev,
printk( "Lance: request for irq %d failed\n", IRQ_AUTO_5 );
return 0;
}
- dev->irq = (unsigned short)IRQ_AUTO_5;
+ dev->irq = IRQ_AUTO_5;
}
else {
- /* For VME-RieblCards, request a free VME int;
- * (This must be unsigned long, since dev->irq is short and the
- * IRQ_MACHSPEC bit would be cut off...)
- */
- unsigned long irq = atari_register_vme_int();
+ /* For VME-RieblCards, request a free VME int */
+ unsigned int irq = atari_register_vme_int();
if (!irq) {
printk( "Lance: request for VME interrupt failed\n" );
return 0;
}
if (request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO,
"Riebl-VME Ethernet", dev)) {
- printk( "Lance: request for irq %ld failed\n", irq );
+ printk( "Lance: request for irq %u failed\n", irq );
return 0;
}
dev->irq = irq;
diff --git a/drivers/net/ethernet/amd/depca.c b/drivers/net/ethernet/amd/depca.c
index 86dd95766a64..c771de71612a 100644
--- a/drivers/net/ethernet/amd/depca.c
+++ b/drivers/net/ethernet/amd/depca.c
@@ -155,23 +155,10 @@
2 depca's in a PC).
************************************************************************
- Support for MCA EtherWORKS cards added 11-3-98.
+ Support for MCA EtherWORKS cards added 11-3-98. (MCA since deleted)
Verified to work with up to 2 DE212 cards in a system (although not
fully stress-tested).
- Currently known bugs/limitations:
-
- Note: with the MCA stuff as a module, it trusts the MCA configuration,
- not the command line for IRQ and memory address. You can
- specify them if you want, but it will throw your values out.
- You still have to pass the IO address it was configured as
- though.
-
- ************************************************************************
- TO DO:
- ------
-
-
Revision History
----------------
@@ -261,10 +248,6 @@
#include <asm/io.h>
#include <asm/dma.h>
-#ifdef CONFIG_MCA
-#include <linux/mca.h>
-#endif
-
#ifdef CONFIG_EISA
#include <linux/eisa.h>
#endif
@@ -360,44 +343,6 @@ static struct eisa_driver depca_eisa_driver = {
};
#endif
-#ifdef CONFIG_MCA
-/*
-** Adapter ID for the MCA EtherWORKS DE210/212 adapter
-*/
-#define DE210_ID 0x628d
-#define DE212_ID 0x6def
-
-static short depca_mca_adapter_ids[] = {
- DE210_ID,
- DE212_ID,
- 0x0000
-};
-
-static char *depca_mca_adapter_name[] = {
- "DEC EtherWORKS MC Adapter (DE210)",
- "DEC EtherWORKS MC Adapter (DE212)",
- NULL
-};
-
-static enum depca_type depca_mca_adapter_type[] = {
- de210,
- de212,
- 0
-};
-
-static int depca_mca_probe (struct device *);
-
-static struct mca_driver depca_mca_driver = {
- .id_table = depca_mca_adapter_ids,
- .driver = {
- .name = depca_string,
- .bus = &mca_bus_type,
- .probe = depca_mca_probe,
- .remove = __devexit_p(depca_device_remove),
- },
-};
-#endif
-
static int depca_isa_probe (struct platform_device *);
static int __devexit depca_isa_remove(struct platform_device *pdev)
@@ -464,8 +409,7 @@ struct depca_private {
char adapter_name[DEPCA_STRLEN]; /* /proc/ioports string */
enum depca_type adapter; /* Adapter type */
enum {
- DEPCA_BUS_MCA = 1,
- DEPCA_BUS_ISA,
+ DEPCA_BUS_ISA = 1,
DEPCA_BUS_EISA,
} depca_bus; /* type of bus */
struct depca_init init_block; /* Shadow Initialization block */
@@ -624,12 +568,6 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device)
dev_name(device), depca_signature[lp->adapter], ioaddr);
switch (lp->depca_bus) {
-#ifdef CONFIG_MCA
- case DEPCA_BUS_MCA:
- printk(" (MCA slot %d)", to_mca_device(device)->slot + 1);
- break;
-#endif
-
#ifdef CONFIG_EISA
case DEPCA_BUS_EISA:
printk(" (EISA slot %d)", to_eisa_device(device)->slot);
@@ -661,10 +599,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device)
if (nicsr & BUF) {
nicsr &= ~BS; /* DEPCA RAM in top 32k */
netRAM -= 32;
-
- /* Only EISA/ISA needs start address to be re-computed */
- if (lp->depca_bus != DEPCA_BUS_MCA)
- mem_start += 0x8000;
+ mem_start += 0x8000;
}
if ((mem_len = (NUM_RX_DESC * (sizeof(struct depca_rx_desc) + RX_BUFF_SZ) + NUM_TX_DESC * (sizeof(struct depca_tx_desc) + TX_BUFF_SZ) + sizeof(struct depca_init)))
@@ -1079,7 +1014,8 @@ static int depca_rx(struct net_device *dev)
} else {
lp->pktStats.multicast++;
}
- } else if (compare_ether_addr(buf, dev->dev_addr) == 0) {
+ } else if (ether_addr_equal(buf,
+ dev->dev_addr)) {
lp->pktStats.unicast++;
}
@@ -1324,130 +1260,6 @@ static int __init depca_common_init (u_long ioaddr, struct net_device **devp)
return status;
}
-#ifdef CONFIG_MCA
-/*
-** Microchannel bus I/O device probe
-*/
-static int __init depca_mca_probe(struct device *device)
-{
- unsigned char pos[2];
- unsigned char where;
- unsigned long iobase, mem_start;
- int irq, err;
- struct mca_device *mdev = to_mca_device (device);
- struct net_device *dev;
- struct depca_private *lp;
-
- /*
- ** Search for the adapter. If an address has been given, search
- ** specifically for the card at that address. Otherwise find the
- ** first card in the system.
- */
-
- pos[0] = mca_device_read_stored_pos(mdev, 2);
- pos[1] = mca_device_read_stored_pos(mdev, 3);
-
- /*
- ** IO of card is handled by bits 1 and 2 of pos0.
- **
- ** bit2 bit1 IO
- ** 0 0 0x2c00
- ** 0 1 0x2c10
- ** 1 0 0x2c20
- ** 1 1 0x2c30
- */
- where = (pos[0] & 6) >> 1;
- iobase = 0x2c00 + (0x10 * where);
-
- /*
- ** Found the adapter we were looking for. Now start setting it up.
- **
- ** First work on decoding the IRQ. It's stored in the lower 4 bits
- ** of pos1. Bits are as follows (from the ADF file):
- **
- ** Bits
- ** 3 2 1 0 IRQ
- ** --------------------
- ** 0 0 1 0 5
- ** 0 0 0 1 9
- ** 0 1 0 0 10
- ** 1 0 0 0 11
- */
- where = pos[1] & 0x0f;
- switch (where) {
- case 1:
- irq = 9;
- break;
- case 2:
- irq = 5;
- break;
- case 4:
- irq = 10;
- break;
- case 8:
- irq = 11;
- break;
- default:
- printk("%s: mca_probe IRQ error. You should never get here (%d).\n", mdev->name, where);
- return -EINVAL;
- }
-
- /*
- ** Shared memory address of adapter is stored in bits 3-5 of pos0.
- ** They are mapped as follows:
- **
- ** Bit
- ** 5 4 3 Memory Addresses
- ** 0 0 0 C0000-CFFFF (64K)
- ** 1 0 0 C8000-CFFFF (32K)
- ** 0 0 1 D0000-DFFFF (64K)
- ** 1 0 1 D8000-DFFFF (32K)
- ** 0 1 0 E0000-EFFFF (64K)
- ** 1 1 0 E8000-EFFFF (32K)
- */
- where = (pos[0] & 0x18) >> 3;
- mem_start = 0xc0000 + (where * 0x10000);
- if (pos[0] & 0x20) {
- mem_start += 0x8000;
- }
-
- /* claim the slot */
- strncpy(mdev->name, depca_mca_adapter_name[mdev->index],
- sizeof(mdev->name));
- mca_device_set_claim(mdev, 1);
-
- /*
- ** Get everything allocated and initialized... (almost just
- ** like the ISA and EISA probes)
- */
- irq = mca_device_transform_irq(mdev, irq);
- iobase = mca_device_transform_ioport(mdev, iobase);
-
- if ((err = depca_common_init (iobase, &dev)))
- goto out_unclaim;
-
- dev->irq = irq;
- dev->base_addr = iobase;
- lp = netdev_priv(dev);
- lp->depca_bus = DEPCA_BUS_MCA;
- lp->adapter = depca_mca_adapter_type[mdev->index];
- lp->mem_start = mem_start;
-
- if ((err = depca_hw_init(dev, device)))
- goto out_free;
-
- return 0;
-
- out_free:
- free_netdev (dev);
- release_region (iobase, DEPCA_TOTAL_SIZE);
- out_unclaim:
- mca_device_set_claim(mdev, 0);
-
- return err;
-}
-#endif
-
/*
** ISA bus I/O device probe
*/
@@ -2058,15 +1870,10 @@ static int __init depca_module_init (void)
{
int err = 0;
-#ifdef CONFIG_MCA
- err = mca_register_driver(&depca_mca_driver);
- if (err)
- goto err;
-#endif
#ifdef CONFIG_EISA
err = eisa_driver_register(&depca_eisa_driver);
if (err)
- goto err_mca;
+ goto err_eisa;
#endif
err = platform_driver_register(&depca_isa_driver);
if (err)
@@ -2078,11 +1885,6 @@ static int __init depca_module_init (void)
err_eisa:
#ifdef CONFIG_EISA
eisa_driver_unregister(&depca_eisa_driver);
-err_mca:
-#endif
-#ifdef CONFIG_MCA
- mca_unregister_driver(&depca_mca_driver);
-err:
#endif
return err;
}
@@ -2090,9 +1892,6 @@ err:
static void __exit depca_module_exit (void)
{
int i;
-#ifdef CONFIG_MCA
- mca_unregister_driver (&depca_mca_driver);
-#endif
#ifdef CONFIG_EISA
eisa_driver_unregister (&depca_eisa_driver);
#endif
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h
index ca70e16b6e2c..b2bf324631dc 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h
@@ -74,8 +74,6 @@
#define AT_RX_BUF_SIZE (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)
#define MAX_JUMBO_FRAME_SIZE (6*1024)
-#define MAX_TSO_FRAME_SIZE (7*1024)
-#define MAX_TX_OFFLOAD_THRESH (9*1024)
#define AT_MAX_RECEIVE_QUEUE 4
#define AT_DEF_RECEIVE_QUEUE 1
@@ -100,7 +98,7 @@
#define ATL1C_ASPM_L0s_ENABLE 0x0001
#define ATL1C_ASPM_L1_ENABLE 0x0002
-#define AT_REGS_LEN (75 * sizeof(u32))
+#define AT_REGS_LEN (74 * sizeof(u32))
#define AT_EEPROM_LEN 512
#define ATL1C_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i]))
@@ -297,20 +295,6 @@ enum atl1c_dma_req_block {
atl1c_dma_req_4096 = 5
};
-enum atl1c_rss_mode {
- atl1c_rss_mode_disable = 0,
- atl1c_rss_sig_que = 1,
- atl1c_rss_mul_que_sig_int = 2,
- atl1c_rss_mul_que_mul_int = 4,
-};
-
-enum atl1c_rss_type {
- atl1c_rss_disable = 0,
- atl1c_rss_ipv4 = 1,
- atl1c_rss_ipv4_tcp = 2,
- atl1c_rss_ipv6 = 4,
- atl1c_rss_ipv6_tcp = 8
-};
enum atl1c_nic_type {
athr_l1c = 0,
@@ -388,7 +372,6 @@ struct atl1c_hw {
enum atl1c_dma_order dma_order;
enum atl1c_dma_rcb rcb_value;
enum atl1c_dma_req_block dmar_block;
- enum atl1c_dma_req_block dmaw_block;
u16 device_id;
u16 vendor_id;
@@ -399,8 +382,6 @@ struct atl1c_hw {
u16 phy_id2;
u32 intr_mask;
- u8 dmaw_dly_cnt;
- u8 dmar_dly_cnt;
u8 preamble_len;
u16 max_frame_size;
@@ -440,10 +421,6 @@ struct atl1c_hw {
#define ATL1C_FPGA_VERSION 0x8000
u16 link_cap_flags;
#define ATL1C_LINK_CAP_1000M 0x0001
- u16 cmb_tpd;
- u16 cmb_rrd;
- u16 cmb_rx_timer; /* 2us resolution */
- u16 cmb_tx_timer;
u32 smb_timer;
u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
@@ -451,9 +428,6 @@ struct atl1c_hw {
u16 tpd_thresh;
u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */
u8 rfd_burst;
- enum atl1c_rss_type rss_type;
- enum atl1c_rss_mode rss_mode;
- u8 rss_hash_bits;
u32 base_cpu;
u32 indirect_tab;
u8 mac_addr[ETH_ALEN];
@@ -462,12 +436,12 @@ struct atl1c_hw {
bool phy_configured;
bool re_autoneg;
bool emi_ca;
+ bool msi_lnkpatch; /* link patch for specific platforms */
};
/*
* atl1c_ring_header represents a single, contiguous block of DMA space
- * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
- * message blocks (cmb, smb) described below
+ * mapped for the three descriptor rings (tpd, rfd, rrd) described below
*/
struct atl1c_ring_header {
void *desc; /* virtual address */
@@ -541,16 +515,6 @@ struct atl1c_rrd_ring {
u16 next_to_clean;
};
-struct atl1c_cmb {
- void *cmb;
- dma_addr_t dma;
-};
-
-struct atl1c_smb {
- void *smb;
- dma_addr_t dma;
-};
-
/* board specific private data structure */
struct atl1c_adapter {
struct net_device *netdev;
@@ -586,11 +550,8 @@ struct atl1c_adapter {
/* All Descriptor memory */
struct atl1c_ring_header ring_header;
struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE];
- struct atl1c_rfd_ring rfd_ring[AT_MAX_RECEIVE_QUEUE];
- struct atl1c_rrd_ring rrd_ring[AT_MAX_RECEIVE_QUEUE];
- struct atl1c_cmb cmb;
- struct atl1c_smb smb;
- int num_rx_queues;
+ struct atl1c_rfd_ring rfd_ring;
+ struct atl1c_rrd_ring rrd_ring;
u32 bd_number; /* board number;*/
};
@@ -618,8 +579,14 @@ struct atl1c_adapter {
#define AT_WRITE_REGW(a, reg, value) (\
writew((value), ((a)->hw_addr + reg)))
-#define AT_READ_REGW(a, reg) (\
- readw((a)->hw_addr + reg))
+#define AT_READ_REGW(a, reg, pdata) do { \
+ if (unlikely((a)->hibernate)) { \
+ readw((a)->hw_addr + reg); \
+ *(u16 *)pdata = readw((a)->hw_addr + reg); \
+ } else { \
+ *(u16 *)pdata = readw((a)->hw_addr + reg); \
+ } \
+ } while (0)
#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \
writel((value), (((a)->hw_addr + reg) + ((offset) << 2))))
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
index 0a9326aa58b5..859ea844ba0f 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
@@ -141,8 +141,7 @@ static void atl1c_get_regs(struct net_device *netdev,
memset(p, 0, AT_REGS_LEN);
- regs->version = 0;
- AT_READ_REG(hw, REG_VPD_CAP, p++);
+ regs->version = 1;
AT_READ_REG(hw, REG_PM_CTRL, p++);
AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL, p++);
AT_READ_REG(hw, REG_TWSI_CTRL, p++);
@@ -154,7 +153,7 @@ static void atl1c_get_regs(struct net_device *netdev,
AT_READ_REG(hw, REG_LINK_CTRL, p++);
AT_READ_REG(hw, REG_IDLE_STATUS, p++);
AT_READ_REG(hw, REG_MDIO_CTRL, p++);
- AT_READ_REG(hw, REG_SERDES_LOCK, p++);
+ AT_READ_REG(hw, REG_SERDES, p++);
AT_READ_REG(hw, REG_MAC_CTRL, p++);
AT_READ_REG(hw, REG_MAC_IPG_IFG, p++);
AT_READ_REG(hw, REG_MAC_STA_ADDR, p++);
@@ -167,9 +166,9 @@ static void atl1c_get_regs(struct net_device *netdev,
AT_READ_REG(hw, REG_WOL_CTRL, p++);
atl1c_read_phy_reg(hw, MII_BMCR, &phy_data);
- regs_buff[73] = (u32) phy_data;
+ regs_buff[AT_REGS_LEN/sizeof(u32) - 2] = (u32) phy_data;
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
- regs_buff[74] = (u32) phy_data;
+ regs_buff[AT_REGS_LEN/sizeof(u32) - 1] = (u32) phy_data;
}
static int atl1c_get_eeprom_len(struct net_device *netdev)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index bd1667cbffa6..ff9c73859d45 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -43,7 +43,7 @@ int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
return 0;
}
-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr)
{
u32 value;
/*
@@ -51,35 +51,48 @@ void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
* 0: 6AF600DC 1: 000B
* low dword
*/
- value = (((u32)hw->mac_addr[2]) << 24) |
- (((u32)hw->mac_addr[3]) << 16) |
- (((u32)hw->mac_addr[4]) << 8) |
- (((u32)hw->mac_addr[5])) ;
+ value = mac_addr[2] << 24 |
+ mac_addr[3] << 16 |
+ mac_addr[4] << 8 |
+ mac_addr[5];
AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
/* hight dword */
- value = (((u32)hw->mac_addr[0]) << 8) |
- (((u32)hw->mac_addr[1])) ;
+ value = mac_addr[0] << 8 |
+ mac_addr[1];
AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
}
+/* read mac address from hardware register */
+static bool atl1c_read_current_addr(struct atl1c_hw *hw, u8 *eth_addr)
+{
+ u32 addr[2];
+
+ AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
+ AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
+
+ *(u32 *) &eth_addr[2] = htonl(addr[0]);
+ *(u16 *) &eth_addr[0] = htons((u16)addr[1]);
+
+ return is_valid_ether_addr(eth_addr);
+}
+
/*
* atl1c_get_permanent_address
* return 0 if get valid mac address,
*/
static int atl1c_get_permanent_address(struct atl1c_hw *hw)
{
- u32 addr[2];
u32 i;
u32 otp_ctrl_data;
u32 twsi_ctrl_data;
- u32 ltssm_ctrl_data;
- u32 wol_data;
- u8 eth_addr[ETH_ALEN];
u16 phy_data;
bool raise_vol = false;
+ /* MAC-address from BIOS is the 1st priority */
+ if (atl1c_read_current_addr(hw, hw->perm_mac_addr))
+ return 0;
+
/* init */
- addr[0] = addr[1] = 0;
AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
if (atl1c_check_eeprom_exist(hw)) {
if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) {
@@ -91,33 +104,17 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
msleep(1);
}
}
-
- if (hw->nic_type == athr_l2c_b ||
- hw->nic_type == athr_l2c_b2 ||
- hw->nic_type == athr_l1d) {
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data &= 0xFF7F;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data |= 0x8;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
+ /* raise voltage temporally for l2cb */
+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {
+ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data);
+ phy_data &= ~ANACTRL_HB_EN;
+ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data);
+ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);
+ phy_data |= VOLT_CTRL_SWLOWEST;
+ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);
udelay(20);
raise_vol = true;
}
- /* close open bit of ReadOnly*/
- AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &ltssm_ctrl_data);
- ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO;
- AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data);
-
- /* clear any WOL settings */
- AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
- AT_READ_REG(hw, REG_WOL_CTRL, &wol_data);
-
AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
@@ -138,37 +135,18 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
msleep(1);
}
if (raise_vol) {
- if (hw->nic_type == athr_l2c_b ||
- hw->nic_type == athr_l2c_b2 ||
- hw->nic_type == athr_l1d ||
- hw->nic_type == athr_l1d_2) {
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data |= 0x80;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
- goto out;
- phy_data &= 0xFFF7;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
- udelay(20);
- }
+ atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data);
+ phy_data |= ANACTRL_HB_EN;
+ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data);
+ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);
+ phy_data &= ~VOLT_CTRL_SWLOWEST;
+ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);
+ udelay(20);
}
- /* maybe MAC-address is from BIOS */
- AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
- AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
- *(u32 *) &eth_addr[2] = swab32(addr[0]);
- *(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
-
- if (is_valid_ether_addr(eth_addr)) {
- memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ if (atl1c_read_current_addr(hw, hw->perm_mac_addr))
return 0;
- }
-out:
return -1;
}
@@ -278,33 +256,158 @@ void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)
}
/*
- * Reads the value from a PHY register
- * hw - Struct containing variables accessed by shared code
- * reg_addr - address of the PHY register to read
+ * wait mdio module be idle
+ * return true: idle
+ * false: still busy
*/
-int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
+bool atl1c_wait_mdio_idle(struct atl1c_hw *hw)
{
u32 val;
int i;
- val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
- MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
- MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+ for (i = 0; i < MDIO_MAX_AC_TO; i++) {
+ AT_READ_REG(hw, REG_MDIO_CTRL, &val);
+ if (!(val & (MDIO_CTRL_BUSY | MDIO_CTRL_START)))
+ break;
+ udelay(10);
+ }
+
+ return i != MDIO_MAX_AC_TO;
+}
+
+void atl1c_stop_phy_polling(struct atl1c_hw *hw)
+{
+ if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
+ return;
+
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, 0);
+ atl1c_wait_mdio_idle(hw);
+}
+
+void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel)
+{
+ u32 val;
+
+ if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
+ return;
+ val = MDIO_CTRL_SPRES_PRMBL |
+ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
+ FIELDX(MDIO_CTRL_REG, 1) |
+ MDIO_CTRL_START |
+ MDIO_CTRL_OP_READ;
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+ atl1c_wait_mdio_idle(hw);
+ val |= MDIO_CTRL_AP_EN;
+ val &= ~MDIO_CTRL_START;
AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+ udelay(30);
+}
- for (i = 0; i < MDIO_WAIT_TIMES; i++) {
- udelay(2);
- AT_READ_REG(hw, REG_MDIO_CTRL, &val);
- if (!(val & (MDIO_START | MDIO_BUSY)))
- break;
+
+/*
+ * atl1c_read_phy_core
+ * core funtion to read register in PHY via MDIO control regsiter.
+ * ext: extension register (see IEEE 802.3)
+ * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)
+ * reg: reg to read
+ */
+int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
+ u16 reg, u16 *phy_data)
+{
+ u32 val;
+ u16 clk_sel = MDIO_CTRL_CLK_25_4;
+
+ atl1c_stop_phy_polling(hw);
+
+ *phy_data = 0;
+
+ /* only l2c_b2 & l1d_2 could use slow clock */
+ if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) &&
+ hw->hibernate)
+ clk_sel = MDIO_CTRL_CLK_25_128;
+ if (ext) {
+ val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);
+ AT_WRITE_REG(hw, REG_MDIO_EXTN, val);
+ val = MDIO_CTRL_SPRES_PRMBL |
+ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
+ MDIO_CTRL_START |
+ MDIO_CTRL_MODE_EXT |
+ MDIO_CTRL_OP_READ;
+ } else {
+ val = MDIO_CTRL_SPRES_PRMBL |
+ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
+ FIELDX(MDIO_CTRL_REG, reg) |
+ MDIO_CTRL_START |
+ MDIO_CTRL_OP_READ;
}
- if (!(val & (MDIO_START | MDIO_BUSY))) {
- *phy_data = (u16)val;
- return 0;
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+ if (!atl1c_wait_mdio_idle(hw))
+ return -1;
+
+ AT_READ_REG(hw, REG_MDIO_CTRL, &val);
+ *phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA);
+
+ atl1c_start_phy_polling(hw, clk_sel);
+
+ return 0;
+}
+
+/*
+ * atl1c_write_phy_core
+ * core funtion to write to register in PHY via MDIO control regsiter.
+ * ext: extension register (see IEEE 802.3)
+ * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)
+ * reg: reg to write
+ */
+int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
+ u16 reg, u16 phy_data)
+{
+ u32 val;
+ u16 clk_sel = MDIO_CTRL_CLK_25_4;
+
+ atl1c_stop_phy_polling(hw);
+
+
+ /* only l2c_b2 & l1d_2 could use slow clock */
+ if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) &&
+ hw->hibernate)
+ clk_sel = MDIO_CTRL_CLK_25_128;
+
+ if (ext) {
+ val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg);
+ AT_WRITE_REG(hw, REG_MDIO_EXTN, val);
+ val = MDIO_CTRL_SPRES_PRMBL |
+ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
+ FIELDX(MDIO_CTRL_DATA, phy_data) |
+ MDIO_CTRL_START |
+ MDIO_CTRL_MODE_EXT;
+ } else {
+ val = MDIO_CTRL_SPRES_PRMBL |
+ FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) |
+ FIELDX(MDIO_CTRL_DATA, phy_data) |
+ FIELDX(MDIO_CTRL_REG, reg) |
+ MDIO_CTRL_START;
}
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
- return -1;
+ if (!atl1c_wait_mdio_idle(hw))
+ return -1;
+
+ atl1c_start_phy_polling(hw, clk_sel);
+
+ return 0;
+}
+
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+ return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data);
}
/*
@@ -315,27 +418,47 @@ int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
*/
int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
{
- int i;
- u32 val;
+ return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data);
+}
- val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
- (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
- MDIO_SUP_PREAMBLE | MDIO_START |
- MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+/* read from PHY extension register */
+int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
+ u16 reg_addr, u16 *phy_data)
+{
+ return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data);
+}
- AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+/* write to PHY extension register */
+int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
+ u16 reg_addr, u16 phy_data)
+{
+ return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data);
+}
- for (i = 0; i < MDIO_WAIT_TIMES; i++) {
- udelay(2);
- AT_READ_REG(hw, REG_MDIO_CTRL, &val);
- if (!(val & (MDIO_START | MDIO_BUSY)))
- break;
- }
+int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+ int err;
- if (!(val & (MDIO_START | MDIO_BUSY)))
- return 0;
+ err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr);
+ if (unlikely(err))
+ return err;
+ else
+ err = atl1c_read_phy_reg(hw, MII_DBG_DATA, phy_data);
- return -1;
+ return err;
+}
+
+int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data)
+{
+ int err;
+
+ err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr);
+ if (unlikely(err))
+ return err;
+ else
+ err = atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data);
+
+ return err;
}
/*
@@ -380,119 +503,100 @@ static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
void atl1c_phy_disable(struct atl1c_hw *hw)
{
- AT_WRITE_REGW(hw, REG_GPHY_CTRL,
- GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
+ atl1c_power_saving(hw, 0);
}
-static void atl1c_phy_magic_data(struct atl1c_hw *hw)
-{
- u16 data;
-
- data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
- ((1 & ANA_INTERVAL_SEL_TIMER_MASK) <<
- ANA_INTERVAL_SEL_TIMER_SHIFT);
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18);
- atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
- data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG |
- ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL |
- ANA_SERDES_EN_LCKDT;
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5);
- atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
- data = (44 & ANA_LONG_CABLE_TH_100_MASK) |
- ((33 & ANA_SHORT_CABLE_TH_100_MASK) <<
- ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM |
- ANA_BP_SMALL_BW;
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54);
- atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
- data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) <<
- ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
- ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
- ANA_IECHO_ADJ_0_SHIFT);
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4);
- atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
- data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) <<
- ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE |
- ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M;
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0);
- atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
- if (hw->ctrl_flags & ATL1C_HIB_DISABLE) {
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
- return;
- data &= ~ANA_TOP_PS_EN;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
-
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11);
- if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
- return;
- data &= ~ANA_PS_HIB_EN;
- atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
- }
-}
int atl1c_phy_reset(struct atl1c_hw *hw)
{
struct atl1c_adapter *adapter = hw->adapter;
struct pci_dev *pdev = adapter->pdev;
u16 phy_data;
- u32 phy_ctrl_data = GPHY_CTRL_DEFAULT;
- u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN;
+ u32 phy_ctrl_data, lpi_ctrl;
int err;
- if (hw->ctrl_flags & ATL1C_HIB_DISABLE)
- phy_ctrl_data &= ~GPHY_CTRL_HIB_EN;
-
+ /* reset PHY core */
+ AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data);
+ phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_PHY_IDDQ |
+ GPHY_CTRL_GATE_25M_EN | GPHY_CTRL_PWDOWN_HW | GPHY_CTRL_CLS);
+ phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST;
+ if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE))
+ phy_ctrl_data |= (GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE);
+ else
+ phy_ctrl_data &= ~(GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE);
AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
AT_WRITE_FLUSH(hw);
- msleep(40);
- phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
- AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
+ udelay(10);
+ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data | GPHY_CTRL_EXT_RESET);
AT_WRITE_FLUSH(hw);
- msleep(10);
+ udelay(10 * GPHY_CTRL_EXT_RST_TO); /* delay 800us */
+ /* switch clock */
if (hw->nic_type == athr_l2c_b) {
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x0A);
- atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xDFFF);
+ atl1c_read_phy_dbg(hw, MIIDBG_CFGLPSPD, &phy_data);
+ atl1c_write_phy_dbg(hw, MIIDBG_CFGLPSPD,
+ phy_data & ~CFGLPSPD_RSTCNT_CLK125SW);
}
- if (hw->nic_type == athr_l2c_b ||
- hw->nic_type == athr_l2c_b2 ||
- hw->nic_type == athr_l1d ||
- hw->nic_type == athr_l1d_2) {
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
- atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
- atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7);
- msleep(20);
+ /* tx-half amplitude issue fix */
+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {
+ atl1c_read_phy_dbg(hw, MIIDBG_CABLE1TH_DET, &phy_data);
+ phy_data |= CABLE1TH_DET_EN;
+ atl1c_write_phy_dbg(hw, MIIDBG_CABLE1TH_DET, phy_data);
}
- if (hw->nic_type == athr_l1d) {
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
- atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D);
+
+ /* clear bit3 of dbgport 3B to lower voltage */
+ if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) {
+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) {
+ atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data);
+ phy_data &= ~VOLT_CTRL_SWLOWEST;
+ atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data);
+ }
+ /* power saving config */
+ phy_data =
+ hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ?
+ L1D_LEGCYPS_DEF : L1C_LEGCYPS_DEF;
+ atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, phy_data);
+ /* hib */
+ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,
+ SYSMODCTRL_IECHOADJ_DEF);
+ } else {
+ /* disable pws */
+ atl1c_read_phy_dbg(hw, MIIDBG_LEGCYPS, &phy_data);
+ atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS,
+ phy_data & ~LEGCYPS_EN);
+ /* disable hibernate */
+ atl1c_read_phy_dbg(hw, MIIDBG_HIBNEG, &phy_data);
+ atl1c_write_phy_dbg(hw, MIIDBG_HIBNEG,
+ phy_data & HIBNEG_PSHIB_EN);
}
- if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2
- || hw->nic_type == athr_l2c) {
- atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
- atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD);
+ /* disable AZ(EEE) by default */
+ if (hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ||
+ hw->nic_type == athr_l2c_b2) {
+ AT_READ_REG(hw, REG_LPI_CTRL, &lpi_ctrl);
+ AT_WRITE_REG(hw, REG_LPI_CTRL, lpi_ctrl & ~LPI_CTRL_EN);
+ atl1c_write_phy_ext(hw, MIIEXT_ANEG, MIIEXT_LOCAL_EEEADV, 0);
+ atl1c_write_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL3,
+ L2CB_CLDCTRL3);
}
- err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
+
+ /* other debug port to set */
+ atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, ANACTRL_DEF);
+ atl1c_write_phy_dbg(hw, MIIDBG_SRDSYSMOD, SRDSYSMOD_DEF);
+ atl1c_write_phy_dbg(hw, MIIDBG_TST10BTCFG, TST10BTCFG_DEF);
+ /* UNH-IOL test issue, set bit7 */
+ atl1c_write_phy_dbg(hw, MIIDBG_TST100BTCFG,
+ TST100BTCFG_DEF | TST100BTCFG_LITCH_EN);
+
+ /* set phy interrupt mask */
+ phy_data = IER_LINK_UP | IER_LINK_DOWN;
+ err = atl1c_write_phy_reg(hw, MII_IER, phy_data);
if (err) {
if (netif_msg_hw(adapter))
dev_err(&pdev->dev,
"Error enable PHY linkChange Interrupt\n");
return err;
}
- if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
- atl1c_phy_magic_data(hw);
return 0;
}
@@ -589,7 +693,8 @@ int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
return 0;
}
-int atl1c_phy_power_saving(struct atl1c_hw *hw)
+/* select one link mode to get lower power consumption */
+int atl1c_phy_to_ps_link(struct atl1c_hw *hw)
{
struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
struct pci_dev *pdev = adapter->pdev;
@@ -660,3 +765,101 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw)
return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
}
+
+int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc)
+{
+ struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
+ struct pci_dev *pdev = adapter->pdev;
+ u32 master_ctrl, mac_ctrl, phy_ctrl;
+ u32 wol_ctrl, speed;
+ u16 phy_data;
+
+ wol_ctrl = 0;
+ speed = adapter->link_speed == SPEED_1000 ?
+ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100;
+
+ AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl);
+ AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl);
+ AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl);
+
+ master_ctrl &= ~MASTER_CTRL_CLK_SEL_DIS;
+ mac_ctrl = FIELD_SETX(mac_ctrl, MAC_CTRL_SPEED, speed);
+ mac_ctrl &= ~(MAC_CTRL_DUPLX | MAC_CTRL_RX_EN | MAC_CTRL_TX_EN);
+ if (adapter->link_duplex == FULL_DUPLEX)
+ mac_ctrl |= MAC_CTRL_DUPLX;
+ phy_ctrl &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS);
+ phy_ctrl |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE |
+ GPHY_CTRL_HIB_EN;
+ if (!wufc) { /* without WoL */
+ master_ctrl |= MASTER_CTRL_CLK_SEL_DIS;
+ phy_ctrl |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW;
+ AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl);
+ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl);
+ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl);
+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+ hw->phy_configured = false; /* re-init PHY when resume */
+ return 0;
+ }
+ phy_ctrl |= GPHY_CTRL_EXT_RESET;
+ if (wufc & AT_WUFC_MAG) {
+ mac_ctrl |= MAC_CTRL_RX_EN | MAC_CTRL_BC_EN;
+ wol_ctrl |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+ if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V11)
+ wol_ctrl |= WOL_PATTERN_EN | WOL_PATTERN_PME_EN;
+ }
+ if (wufc & AT_WUFC_LNKC) {
+ wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
+ if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
+ dev_dbg(&pdev->dev, "%s: write phy MII_IER faild.\n",
+ atl1c_driver_name);
+ }
+ }
+ /* clear PHY interrupt */
+ atl1c_read_phy_reg(hw, MII_ISR, &phy_data);
+
+ dev_dbg(&pdev->dev, "%s: suspend MAC=%x,MASTER=%x,PHY=0x%x,WOL=%x\n",
+ atl1c_driver_name, mac_ctrl, master_ctrl, phy_ctrl, wol_ctrl);
+ AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl);
+ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl);
+ AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl);
+ AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl);
+
+ return 0;
+}
+
+
+/* configure phy after Link change Event */
+void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed)
+{
+ u16 phy_val;
+ bool adj_thresh = false;
+
+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 ||
+ hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2)
+ adj_thresh = true;
+
+ if (link_speed != SPEED_0) { /* link up */
+ /* az with brcm, half-amp */
+ if (hw->nic_type == athr_l1d_2) {
+ atl1c_read_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL6,
+ &phy_val);
+ phy_val = FIELD_GETX(phy_val, CLDCTRL6_CAB_LEN);
+ phy_val = phy_val > CLDCTRL6_CAB_LEN_SHORT ?
+ AZ_ANADECT_LONG : AZ_ANADECT_DEF;
+ atl1c_write_phy_dbg(hw, MIIDBG_AZ_ANADECT, phy_val);
+ }
+ /* threshold adjust */
+ if (adj_thresh && link_speed == SPEED_100 && hw->msi_lnkpatch) {
+ atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, L1D_MSE16DB_UP);
+ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,
+ L1D_SYSMODCTRL_IECHOADJ_DEF);
+ }
+ } else { /* link down */
+ if (adj_thresh && hw->msi_lnkpatch) {
+ atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL,
+ SYSMODCTRL_IECHOADJ_DEF);
+ atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB,
+ L1D_MSE16DB_DOWN);
+ }
+ }
+}
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index 655fc6c4a8a4..17d935bdde0a 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -25,12 +25,18 @@
#include <linux/types.h>
#include <linux/mii.h>
+#define FIELD_GETX(_x, _name) ((_x) >> (_name##_SHIFT) & (_name##_MASK))
+#define FIELD_SETX(_x, _name, _v) \
+(((_x) & ~((_name##_MASK) << (_name##_SHIFT))) |\
+(((_v) & (_name##_MASK)) << (_name##_SHIFT)))
+#define FIELDX(_name, _v) (((_v) & (_name##_MASK)) << (_name##_SHIFT))
+
struct atl1c_adapter;
struct atl1c_hw;
/* function prototype */
void atl1c_phy_disable(struct atl1c_hw *hw);
-void atl1c_hw_set_mac_addr(struct atl1c_hw *hw);
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr);
int atl1c_phy_reset(struct atl1c_hw *hw);
int atl1c_read_mac_addr(struct atl1c_hw *hw);
int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex);
@@ -42,47 +48,45 @@ bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value);
int atl1c_phy_init(struct atl1c_hw *hw);
int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
int atl1c_restart_autoneg(struct atl1c_hw *hw);
-int atl1c_phy_power_saving(struct atl1c_hw *hw);
+int atl1c_phy_to_ps_link(struct atl1c_hw *hw);
+int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc);
+bool atl1c_wait_mdio_idle(struct atl1c_hw *hw);
+void atl1c_stop_phy_polling(struct atl1c_hw *hw);
+void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel);
+int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
+ u16 reg, u16 *phy_data);
+int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev,
+ u16 reg, u16 phy_data);
+int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
+ u16 reg_addr, u16 *phy_data);
+int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
+ u16 reg_addr, u16 phy_data);
+int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data);
+int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data);
+void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed);
+
+/* hw-ids */
+#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062
+#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063
+#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */
+#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */
+#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */
+#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */
+#define L2CB_V10 0xc0
+#define L2CB_V11 0xc1
+
/* register definition */
#define REG_DEVICE_CAP 0x5C
#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7
#define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0
-#define REG_DEVICE_CTRL 0x60
-#define DEVICE_CTRL_MAX_PAYLOAD_MASK 0x7
-#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT 5
-#define DEVICE_CTRL_MAX_RREQ_SZ_MASK 0x7
-#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT 12
+#define DEVICE_CTRL_MAXRRS_MIN 2
#define REG_LINK_CTRL 0x68
#define LINK_CTRL_L0S_EN 0x01
#define LINK_CTRL_L1_EN 0x02
#define LINK_CTRL_EXT_SYNC 0x80
-#define REG_VPD_CAP 0x6C
-#define VPD_CAP_ID_MASK 0xff
-#define VPD_CAP_ID_SHIFT 0
-#define VPD_CAP_NEXT_PTR_MASK 0xFF
-#define VPD_CAP_NEXT_PTR_SHIFT 8
-#define VPD_CAP_VPD_ADDR_MASK 0x7FFF
-#define VPD_CAP_VPD_ADDR_SHIFT 16
-#define VPD_CAP_VPD_FLAG 0x80000000
-
-#define REG_VPD_DATA 0x70
-
-#define REG_PCIE_UC_SEVERITY 0x10C
-#define PCIE_UC_SERVRITY_TRN 0x00000001
-#define PCIE_UC_SERVRITY_DLP 0x00000010
-#define PCIE_UC_SERVRITY_PSN_TLP 0x00001000
-#define PCIE_UC_SERVRITY_FCP 0x00002000
-#define PCIE_UC_SERVRITY_CPL_TO 0x00004000
-#define PCIE_UC_SERVRITY_CA 0x00008000
-#define PCIE_UC_SERVRITY_UC 0x00010000
-#define PCIE_UC_SERVRITY_ROV 0x00020000
-#define PCIE_UC_SERVRITY_MLFP 0x00040000
-#define PCIE_UC_SERVRITY_ECRC 0x00080000
-#define PCIE_UC_SERVRITY_UR 0x00100000
-
#define REG_DEV_SERIALNUM_CTRL 0x200
#define REG_DEV_MAC_SEL_MASK 0x0 /* 0:EUI; 1:MAC */
#define REG_DEV_MAC_SEL_SHIFT 0
@@ -90,25 +94,17 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define REG_DEV_SERIAL_NUM_EN_SHIFT 1
#define REG_TWSI_CTRL 0x218
+#define TWSI_CTLR_FREQ_MASK 0x3UL
+#define TWSI_CTRL_FREQ_SHIFT 24
+#define TWSI_CTRL_FREQ_100K 0
+#define TWSI_CTRL_FREQ_200K 1
+#define TWSI_CTRL_FREQ_300K 2
+#define TWSI_CTRL_FREQ_400K 3
+#define TWSI_CTRL_LD_EXIST BIT(23)
+#define TWSI_CTRL_HW_LDSTAT BIT(12) /* 0:finish,1:in progress */
+#define TWSI_CTRL_SW_LDSTART BIT(11)
#define TWSI_CTRL_LD_OFFSET_MASK 0xFF
#define TWSI_CTRL_LD_OFFSET_SHIFT 0
-#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7
-#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8
-#define TWSI_CTRL_SW_LDSTART 0x800
-#define TWSI_CTRL_HW_LDSTART 0x1000
-#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x7F
-#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15
-#define TWSI_CTRL_LD_EXIST 0x400000
-#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3
-#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23
-#define TWSI_CTRL_FREQ_SEL_100K 0
-#define TWSI_CTRL_FREQ_SEL_200K 1
-#define TWSI_CTRL_FREQ_SEL_300K 2
-#define TWSI_CTRL_FREQ_SEL_400K 3
-#define TWSI_CTRL_SMB_SLV_ADDR
-#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3
-#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24
-
#define REG_PCIE_DEV_MISC_CTRL 0x21C
#define PCIE_DEV_MISC_EXT_PIPE 0x2
@@ -118,16 +114,23 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define PCIE_DEV_MISC_SERDES_SEL_DIN 0x10
#define REG_PCIE_PHYMISC 0x1000
-#define PCIE_PHYMISC_FORCE_RCV_DET 0x4
+#define PCIE_PHYMISC_FORCE_RCV_DET BIT(2)
+#define PCIE_PHYMISC_NFTS_MASK 0xFFUL
+#define PCIE_PHYMISC_NFTS_SHIFT 16
#define REG_PCIE_PHYMISC2 0x1004
-#define PCIE_PHYMISC2_SERDES_CDR_MASK 0x3
-#define PCIE_PHYMISC2_SERDES_CDR_SHIFT 16
-#define PCIE_PHYMISC2_SERDES_TH_MASK 0x3
-#define PCIE_PHYMISC2_SERDES_TH_SHIFT 18
+#define PCIE_PHYMISC2_L0S_TH_MASK 0x3UL
+#define PCIE_PHYMISC2_L0S_TH_SHIFT 18
+#define L2CB1_PCIE_PHYMISC2_L0S_TH 3
+#define PCIE_PHYMISC2_CDR_BW_MASK 0x3UL
+#define PCIE_PHYMISC2_CDR_BW_SHIFT 16
+#define L2CB1_PCIE_PHYMISC2_CDR_BW 3
#define REG_TWSI_DEBUG 0x1108
-#define TWSI_DEBUG_DEV_EXIST 0x20000000
+#define TWSI_DEBUG_DEV_EXIST BIT(29)
+
+#define REG_DMA_DBG 0x1114
+#define DMA_DBG_VENDOR_MSG BIT(0)
#define REG_EEPROM_CTRL 0x12C0
#define EEPROM_CTRL_DATA_HI_MASK 0xFFFF
@@ -140,56 +143,81 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define REG_EEPROM_DATA_LO 0x12C4
#define REG_OTP_CTRL 0x12F0
-#define OTP_CTRL_CLK_EN 0x0002
+#define OTP_CTRL_CLK_EN BIT(1)
#define REG_PM_CTRL 0x12F8
-#define PM_CTRL_SDES_EN 0x00000001
-#define PM_CTRL_RBER_EN 0x00000002
-#define PM_CTRL_CLK_REQ_EN 0x00000004
-#define PM_CTRL_ASPM_L1_EN 0x00000008
-#define PM_CTRL_SERDES_L1_EN 0x00000010
-#define PM_CTRL_SERDES_PLL_L1_EN 0x00000020
-#define PM_CTRL_SERDES_PD_EX_L1 0x00000040
-#define PM_CTRL_SERDES_BUDS_RX_L1_EN 0x00000080
-#define PM_CTRL_L0S_ENTRY_TIMER_MASK 0xF
-#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT 8
-#define PM_CTRL_ASPM_L0S_EN 0x00001000
-#define PM_CTRL_CLK_SWH_L1 0x00002000
-#define PM_CTRL_CLK_PWM_VER1_1 0x00004000
-#define PM_CTRL_RCVR_WT_TIMER 0x00008000
-#define PM_CTRL_L1_ENTRY_TIMER_MASK 0xF
-#define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16
-#define PM_CTRL_PM_REQ_TIMER_MASK 0xF
-#define PM_CTRL_PM_REQ_TIMER_SHIFT 20
-#define PM_CTRL_LCKDET_TIMER_MASK 0xF
+#define PM_CTRL_HOTRST BIT(31)
+#define PM_CTRL_MAC_ASPM_CHK BIT(30) /* L0s/L1 dis by MAC based on
+ * thrghput(setting in 15A0) */
+#define PM_CTRL_SA_DLY_EN BIT(29)
+#define PM_CTRL_L0S_BUFSRX_EN BIT(28)
+#define PM_CTRL_LCKDET_TIMER_MASK 0xFUL
#define PM_CTRL_LCKDET_TIMER_SHIFT 24
-#define PM_CTRL_EN_BUFS_RX_L0S 0x10000000
-#define PM_CTRL_SA_DLY_EN 0x20000000
-#define PM_CTRL_MAC_ASPM_CHK 0x40000000
-#define PM_CTRL_HOTRST 0x80000000
+#define PM_CTRL_LCKDET_TIMER_DEF 0xC
+#define PM_CTRL_PM_REQ_TIMER_MASK 0xFUL
+#define PM_CTRL_PM_REQ_TIMER_SHIFT 20 /* pm_request_l1 time > @
+ * ->L0s not L1 */
+#define PM_CTRL_PM_REQ_TO_DEF 0xF
+#define PMCTRL_TXL1_AFTER_L0S BIT(19) /* l1dv2.0+ */
+#define L1D_PMCTRL_L1_ENTRY_TM_MASK 7UL /* l1dv2.0+, 3bits */
+#define L1D_PMCTRL_L1_ENTRY_TM_SHIFT 16
+#define L1D_PMCTRL_L1_ENTRY_TM_DIS 0
+#define L1D_PMCTRL_L1_ENTRY_TM_2US 1
+#define L1D_PMCTRL_L1_ENTRY_TM_4US 2
+#define L1D_PMCTRL_L1_ENTRY_TM_8US 3
+#define L1D_PMCTRL_L1_ENTRY_TM_16US 4
+#define L1D_PMCTRL_L1_ENTRY_TM_24US 5
+#define L1D_PMCTRL_L1_ENTRY_TM_32US 6
+#define L1D_PMCTRL_L1_ENTRY_TM_63US 7
+#define PM_CTRL_L1_ENTRY_TIMER_MASK 0xFUL /* l1C 4bits */
+#define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16
+#define L2CB1_PM_CTRL_L1_ENTRY_TM 7
+#define L1C_PM_CTRL_L1_ENTRY_TM 0xF
+#define PM_CTRL_RCVR_WT_TIMER BIT(15) /* 1:1us, 0:2ms */
+#define PM_CTRL_CLK_PWM_VER1_1 BIT(14) /* 0:1.0a,1:1.1 */
+#define PM_CTRL_CLK_SWH_L1 BIT(13) /* en pcie clk sw in L1 */
+#define PM_CTRL_ASPM_L0S_EN BIT(12)
+#define PM_CTRL_RXL1_AFTER_L0S BIT(11) /* l1dv2.0+ */
+#define L1D_PMCTRL_L0S_TIMER_MASK 7UL /* l1d2.0+, 3bits*/
+#define L1D_PMCTRL_L0S_TIMER_SHIFT 8
+#define PM_CTRL_L0S_ENTRY_TIMER_MASK 0xFUL /* l1c, 4bits */
+#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT 8
+#define PM_CTRL_SERDES_BUFS_RX_L1_EN BIT(7)
+#define PM_CTRL_SERDES_PD_EX_L1 BIT(6) /* power down serdes rx */
+#define PM_CTRL_SERDES_PLL_L1_EN BIT(5)
+#define PM_CTRL_SERDES_L1_EN BIT(4)
+#define PM_CTRL_ASPM_L1_EN BIT(3)
+#define PM_CTRL_CLK_REQ_EN BIT(2)
+#define PM_CTRL_RBER_EN BIT(1)
+#define PM_CTRL_SPRSDWER_EN BIT(0)
#define REG_LTSSM_ID_CTRL 0x12FC
#define LTSSM_ID_EN_WRO 0x1000
+
+
/* Selene Master Control Register */
#define REG_MASTER_CTRL 0x1400
-#define MASTER_CTRL_SOFT_RST 0x1
-#define MASTER_CTRL_TEST_MODE_MASK 0x3
-#define MASTER_CTRL_TEST_MODE_SHIFT 2
-#define MASTER_CTRL_BERT_START 0x10
-#define MASTER_CTRL_OOB_DIS_OFF 0x40
-#define MASTER_CTRL_SA_TIMER_EN 0x80
-#define MASTER_CTRL_MTIMER_EN 0x100
-#define MASTER_CTRL_MANUAL_INT 0x200
-#define MASTER_CTRL_TX_ITIMER_EN 0x400
-#define MASTER_CTRL_RX_ITIMER_EN 0x800
-#define MASTER_CTRL_CLK_SEL_DIS 0x1000
-#define MASTER_CTRL_CLK_SWH_MODE 0x2000
-#define MASTER_CTRL_INT_RDCLR 0x4000
-#define MASTER_CTRL_REV_NUM_SHIFT 16
-#define MASTER_CTRL_REV_NUM_MASK 0xff
-#define MASTER_CTRL_DEV_ID_SHIFT 24
-#define MASTER_CTRL_DEV_ID_MASK 0x7f
-#define MASTER_CTRL_OTP_SEL 0x80000000
+#define MASTER_CTRL_OTP_SEL BIT(31)
+#define MASTER_DEV_NUM_MASK 0x7FUL
+#define MASTER_DEV_NUM_SHIFT 24
+#define MASTER_REV_NUM_MASK 0xFFUL
+#define MASTER_REV_NUM_SHIFT 16
+#define MASTER_CTRL_INT_RDCLR BIT(14)
+#define MASTER_CTRL_CLK_SEL_DIS BIT(12) /* 1:alwys sel pclk from
+ * serdes, not sw to 25M */
+#define MASTER_CTRL_RX_ITIMER_EN BIT(11) /* IRQ MODURATION FOR RX */
+#define MASTER_CTRL_TX_ITIMER_EN BIT(10) /* MODURATION FOR TX/RX */
+#define MASTER_CTRL_MANU_INT BIT(9) /* SOFT MANUAL INT */
+#define MASTER_CTRL_MANUTIMER_EN BIT(8)
+#define MASTER_CTRL_SA_TIMER_EN BIT(7) /* SYS ALIVE TIMER EN */
+#define MASTER_CTRL_OOB_DIS BIT(6) /* OUT OF BOX DIS */
+#define MASTER_CTRL_WAKEN_25M BIT(5) /* WAKE WO. PCIE CLK */
+#define MASTER_CTRL_BERT_START BIT(4)
+#define MASTER_PCIE_TSTMOD_MASK 3UL
+#define MASTER_PCIE_TSTMOD_SHIFT 2
+#define MASTER_PCIE_RST BIT(1)
+#define MASTER_CTRL_SOFT_RST BIT(0) /* RST MAC & DMA */
+#define DMA_MAC_RST_TO 50
/* Timer Initial Value Register */
#define REG_MANUAL_TIMER_INIT 0x1404
@@ -201,87 +229,85 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define IRQ_MODRT_RX_TIMER_SHIFT 16
#define REG_GPHY_CTRL 0x140C
-#define GPHY_CTRL_EXT_RESET 0x1
-#define GPHY_CTRL_RTL_MODE 0x2
-#define GPHY_CTRL_LED_MODE 0x4
-#define GPHY_CTRL_ANEG_NOW 0x8
-#define GPHY_CTRL_REV_ANEG 0x10
-#define GPHY_CTRL_GATE_25M_EN 0x20
-#define GPHY_CTRL_LPW_EXIT 0x40
-#define GPHY_CTRL_PHY_IDDQ 0x80
-#define GPHY_CTRL_PHY_IDDQ_DIS 0x100
-#define GPHY_CTRL_GIGA_DIS 0x200
-#define GPHY_CTRL_HIB_EN 0x400
-#define GPHY_CTRL_HIB_PULSE 0x800
-#define GPHY_CTRL_SEL_ANA_RST 0x1000
-#define GPHY_CTRL_PHY_PLL_ON 0x2000
-#define GPHY_CTRL_PWDOWN_HW 0x4000
-#define GPHY_CTRL_PHY_PLL_BYPASS 0x8000
-
-#define GPHY_CTRL_DEFAULT ( \
- GPHY_CTRL_SEL_ANA_RST |\
- GPHY_CTRL_HIB_PULSE |\
- GPHY_CTRL_HIB_EN)
-
-#define GPHY_CTRL_PW_WOL_DIS ( \
- GPHY_CTRL_SEL_ANA_RST |\
- GPHY_CTRL_HIB_PULSE |\
- GPHY_CTRL_HIB_EN |\
- GPHY_CTRL_PWDOWN_HW |\
- GPHY_CTRL_PHY_IDDQ)
-
-#define GPHY_CTRL_POWER_SAVING ( \
- GPHY_CTRL_SEL_ANA_RST |\
- GPHY_CTRL_HIB_EN |\
- GPHY_CTRL_HIB_PULSE |\
- GPHY_CTRL_PWDOWN_HW |\
- GPHY_CTRL_PHY_IDDQ)
+#define GPHY_CTRL_ADDR_MASK 0x1FUL
+#define GPHY_CTRL_ADDR_SHIFT 19
+#define GPHY_CTRL_BP_VLTGSW BIT(18)
+#define GPHY_CTRL_100AB_EN BIT(17)
+#define GPHY_CTRL_10AB_EN BIT(16)
+#define GPHY_CTRL_PHY_PLL_BYPASS BIT(15)
+#define GPHY_CTRL_PWDOWN_HW BIT(14) /* affect MAC&PHY, to low pw */
+#define GPHY_CTRL_PHY_PLL_ON BIT(13) /* 1:pll always on, 0:can sw */
+#define GPHY_CTRL_SEL_ANA_RST BIT(12)
+#define GPHY_CTRL_HIB_PULSE BIT(11)
+#define GPHY_CTRL_HIB_EN BIT(10)
+#define GPHY_CTRL_GIGA_DIS BIT(9)
+#define GPHY_CTRL_PHY_IDDQ_DIS BIT(8) /* pw on RST */
+#define GPHY_CTRL_PHY_IDDQ BIT(7) /* bit8 affect bit7 while rb */
+#define GPHY_CTRL_LPW_EXIT BIT(6)
+#define GPHY_CTRL_GATE_25M_EN BIT(5)
+#define GPHY_CTRL_REV_ANEG BIT(4)
+#define GPHY_CTRL_ANEG_NOW BIT(3)
+#define GPHY_CTRL_LED_MODE BIT(2)
+#define GPHY_CTRL_RTL_MODE BIT(1)
+#define GPHY_CTRL_EXT_RESET BIT(0) /* 1:out of DSP RST status */
+#define GPHY_CTRL_EXT_RST_TO 80 /* 800us atmost */
+#define GPHY_CTRL_CLS (\
+ GPHY_CTRL_LED_MODE |\
+ GPHY_CTRL_100AB_EN |\
+ GPHY_CTRL_PHY_PLL_ON)
+
/* Block IDLE Status Register */
-#define REG_IDLE_STATUS 0x1410
-#define IDLE_STATUS_MASK 0x00FF
-#define IDLE_STATUS_RXMAC_NO_IDLE 0x1
-#define IDLE_STATUS_TXMAC_NO_IDLE 0x2
-#define IDLE_STATUS_RXQ_NO_IDLE 0x4
-#define IDLE_STATUS_TXQ_NO_IDLE 0x8
-#define IDLE_STATUS_DMAR_NO_IDLE 0x10
-#define IDLE_STATUS_DMAW_NO_IDLE 0x20
-#define IDLE_STATUS_SMB_NO_IDLE 0x40
-#define IDLE_STATUS_CMB_NO_IDLE 0x80
+#define REG_IDLE_STATUS 0x1410
+#define IDLE_STATUS_SFORCE_MASK 0xFUL
+#define IDLE_STATUS_SFORCE_SHIFT 14
+#define IDLE_STATUS_CALIB_DONE BIT(13)
+#define IDLE_STATUS_CALIB_RES_MASK 0x1FUL
+#define IDLE_STATUS_CALIB_RES_SHIFT 8
+#define IDLE_STATUS_CALIBERR_MASK 0xFUL
+#define IDLE_STATUS_CALIBERR_SHIFT 4
+#define IDLE_STATUS_TXQ_BUSY BIT(3)
+#define IDLE_STATUS_RXQ_BUSY BIT(2)
+#define IDLE_STATUS_TXMAC_BUSY BIT(1)
+#define IDLE_STATUS_RXMAC_BUSY BIT(0)
+#define IDLE_STATUS_MASK (\
+ IDLE_STATUS_TXQ_BUSY |\
+ IDLE_STATUS_RXQ_BUSY |\
+ IDLE_STATUS_TXMAC_BUSY |\
+ IDLE_STATUS_RXMAC_BUSY)
/* MDIO Control Register */
#define REG_MDIO_CTRL 0x1414
-#define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit
- * control data to write to PHY
- * MII management register */
-#define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit
- * status data that was read
- * from the PHY MII management register */
-#define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */
-#define MDIO_REG_ADDR_SHIFT 16
-#define MDIO_RW 0x200000 /* 1: read, 0: write */
-#define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */
-#define MDIO_START 0x800000 /* Write 1 to initiate the MDIO
- * master. And this bit is self
- * cleared after one cycle */
-#define MDIO_CLK_SEL_SHIFT 24
-#define MDIO_CLK_25_4 0
-#define MDIO_CLK_25_6 2
-#define MDIO_CLK_25_8 3
-#define MDIO_CLK_25_10 4
-#define MDIO_CLK_25_14 5
-#define MDIO_CLK_25_20 6
-#define MDIO_CLK_25_28 7
-#define MDIO_BUSY 0x8000000
-#define MDIO_AP_EN 0x10000000
-#define MDIO_WAIT_TIMES 10
-
-/* MII PHY Status Register */
-#define REG_PHY_STATUS 0x1418
-#define PHY_GENERAL_STATUS_MASK 0xFFFF
-#define PHY_STATUS_RECV_ENABLE 0x0001
-#define PHY_OE_PWSP_STATUS_MASK 0x07FF
-#define PHY_OE_PWSP_STATUS_SHIFT 16
-#define PHY_STATUS_LPW_STATE 0x80000000
+#define MDIO_CTRL_MODE_EXT BIT(30)
+#define MDIO_CTRL_POST_READ BIT(29)
+#define MDIO_CTRL_AP_EN BIT(28)
+#define MDIO_CTRL_BUSY BIT(27)
+#define MDIO_CTRL_CLK_SEL_MASK 0x7UL
+#define MDIO_CTRL_CLK_SEL_SHIFT 24
+#define MDIO_CTRL_CLK_25_4 0 /* 25MHz divide 4 */
+#define MDIO_CTRL_CLK_25_6 2
+#define MDIO_CTRL_CLK_25_8 3
+#define MDIO_CTRL_CLK_25_10 4
+#define MDIO_CTRL_CLK_25_32 5
+#define MDIO_CTRL_CLK_25_64 6
+#define MDIO_CTRL_CLK_25_128 7
+#define MDIO_CTRL_START BIT(23)
+#define MDIO_CTRL_SPRES_PRMBL BIT(22)
+#define MDIO_CTRL_OP_READ BIT(21) /* 1:read, 0:write */
+#define MDIO_CTRL_REG_MASK 0x1FUL
+#define MDIO_CTRL_REG_SHIFT 16
+#define MDIO_CTRL_DATA_MASK 0xFFFFUL
+#define MDIO_CTRL_DATA_SHIFT 0
+#define MDIO_MAX_AC_TO 120 /* 1.2ms timeout for slow clk */
+
+/* for extension reg access */
+#define REG_MDIO_EXTN 0x1448
+#define MDIO_EXTN_PORTAD_MASK 0x1FUL
+#define MDIO_EXTN_PORTAD_SHIFT 21
+#define MDIO_EXTN_DEVAD_MASK 0x1FUL
+#define MDIO_EXTN_DEVAD_SHIFT 16
+#define MDIO_EXTN_REG_MASK 0xFFFFUL
+#define MDIO_EXTN_REG_SHIFT 0
+
/* BIST Control and Status Register0 (for the Packet Memory) */
#define REG_BIST0_CTRL 0x141c
#define BIST0_NOW 0x1
@@ -299,50 +325,81 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define BIST1_FUSE_FLAG 0x4
/* SerDes Lock Detect Control and Status Register */
-#define REG_SERDES_LOCK 0x1424
-#define SERDES_LOCK_DETECT 0x1 /* SerDes lock detected. This signal
- * comes from Analog SerDes */
-#define SERDES_LOCK_DETECT_EN 0x2 /* 1: Enable SerDes Lock detect function */
-#define SERDES_LOCK_STS_SELFB_PLL_SHIFT 0xE
-#define SERDES_LOCK_STS_SELFB_PLL_MASK 0x3
-#define SERDES_OVCLK_18_25 0x0
-#define SERDES_OVCLK_12_18 0x1
-#define SERDES_OVCLK_0_4 0x2
-#define SERDES_OVCLK_4_12 0x3
-#define SERDES_MAC_CLK_SLOWDOWN 0x20000
-#define SERDES_PYH_CLK_SLOWDOWN 0x40000
+#define REG_SERDES 0x1424
+#define SERDES_PHY_CLK_SLOWDOWN BIT(18)
+#define SERDES_MAC_CLK_SLOWDOWN BIT(17)
+#define SERDES_SELFB_PLL_MASK 0x3UL
+#define SERDES_SELFB_PLL_SHIFT 14
+#define SERDES_PHYCLK_SEL_GTX BIT(13) /* 1:gtx_clk, 0:25M */
+#define SERDES_PCIECLK_SEL_SRDS BIT(12) /* 1:serdes,0:25M */
+#define SERDES_BUFS_RX_EN BIT(11)
+#define SERDES_PD_RX BIT(10)
+#define SERDES_PLL_EN BIT(9)
+#define SERDES_EN BIT(8)
+#define SERDES_SELFB_PLL_SEL_CSR BIT(6) /* 0:state-machine,1:csr */
+#define SERDES_SELFB_PLL_CSR_MASK 0x3UL
+#define SERDES_SELFB_PLL_CSR_SHIFT 4
+#define SERDES_SELFB_PLL_CSR_4 3 /* 4-12% OV-CLK */
+#define SERDES_SELFB_PLL_CSR_0 2 /* 0-4% OV-CLK */
+#define SERDES_SELFB_PLL_CSR_12 1 /* 12-18% OV-CLK */
+#define SERDES_SELFB_PLL_CSR_18 0 /* 18-25% OV-CLK */
+#define SERDES_VCO_SLOW BIT(3)
+#define SERDES_VCO_FAST BIT(2)
+#define SERDES_LOCK_DETECT_EN BIT(1)
+#define SERDES_LOCK_DETECT BIT(0)
+
+#define REG_LPI_DECISN_TIMER 0x143C
+#define L2CB_LPI_DESISN_TIMER 0x7D00
+
+#define REG_LPI_CTRL 0x1440
+#define LPI_CTRL_CHK_DA BIT(31)
+#define LPI_CTRL_ENH_TO_MASK 0x1FFFUL
+#define LPI_CTRL_ENH_TO_SHIFT 12
+#define LPI_CTRL_ENH_TH_MASK 0x1FUL
+#define LPI_CTRL_ENH_TH_SHIFT 6
+#define LPI_CTRL_ENH_EN BIT(5)
+#define LPI_CTRL_CHK_RX BIT(4)
+#define LPI_CTRL_CHK_STATE BIT(3)
+#define LPI_CTRL_GMII BIT(2)
+#define LPI_CTRL_TO_PHY BIT(1)
+#define LPI_CTRL_EN BIT(0)
+
+#define REG_LPI_WAIT 0x1444
+#define LPI_WAIT_TIMER_MASK 0xFFFFUL
+#define LPI_WAIT_TIMER_SHIFT 0
/* MAC Control Register */
#define REG_MAC_CTRL 0x1480
-#define MAC_CTRL_TX_EN 0x1
-#define MAC_CTRL_RX_EN 0x2
-#define MAC_CTRL_TX_FLOW 0x4
-#define MAC_CTRL_RX_FLOW 0x8
-#define MAC_CTRL_LOOPBACK 0x10
-#define MAC_CTRL_DUPLX 0x20
-#define MAC_CTRL_ADD_CRC 0x40
-#define MAC_CTRL_PAD 0x80
-#define MAC_CTRL_LENCHK 0x100
-#define MAC_CTRL_HUGE_EN 0x200
-#define MAC_CTRL_PRMLEN_SHIFT 10
-#define MAC_CTRL_PRMLEN_MASK 0xf
-#define MAC_CTRL_RMV_VLAN 0x4000
-#define MAC_CTRL_PROMIS_EN 0x8000
-#define MAC_CTRL_TX_PAUSE 0x10000
-#define MAC_CTRL_SCNT 0x20000
-#define MAC_CTRL_SRST_TX 0x40000
-#define MAC_CTRL_TX_SIMURST 0x80000
-#define MAC_CTRL_SPEED_SHIFT 20
-#define MAC_CTRL_SPEED_MASK 0x3
-#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000
-#define MAC_CTRL_TX_HUGE 0x800000
-#define MAC_CTRL_RX_CHKSUM_EN 0x1000000
-#define MAC_CTRL_MC_ALL_EN 0x2000000
-#define MAC_CTRL_BC_EN 0x4000000
-#define MAC_CTRL_DBG 0x8000000
-#define MAC_CTRL_SINGLE_PAUSE_EN 0x10000000
-#define MAC_CTRL_HASH_ALG_CRC32 0x20000000
-#define MAC_CTRL_SPEED_MODE_SW 0x40000000
+#define MAC_CTRL_SPEED_MODE_SW BIT(30) /* 0:phy,1:sw */
+#define MAC_CTRL_HASH_ALG_CRC32 BIT(29) /* 1:legacy,0:lw_5b */
+#define MAC_CTRL_SINGLE_PAUSE_EN BIT(28)
+#define MAC_CTRL_DBG BIT(27)
+#define MAC_CTRL_BC_EN BIT(26)
+#define MAC_CTRL_MC_ALL_EN BIT(25)
+#define MAC_CTRL_RX_CHKSUM_EN BIT(24)
+#define MAC_CTRL_TX_HUGE BIT(23)
+#define MAC_CTRL_DBG_TX_BKPRESURE BIT(22)
+#define MAC_CTRL_SPEED_MASK 3UL
+#define MAC_CTRL_SPEED_SHIFT 20
+#define MAC_CTRL_SPEED_10_100 1
+#define MAC_CTRL_SPEED_1000 2
+#define MAC_CTRL_TX_SIMURST BIT(19)
+#define MAC_CTRL_SCNT BIT(17)
+#define MAC_CTRL_TX_PAUSE BIT(16)
+#define MAC_CTRL_PROMIS_EN BIT(15)
+#define MAC_CTRL_RMV_VLAN BIT(14)
+#define MAC_CTRL_PRMLEN_MASK 0xFUL
+#define MAC_CTRL_PRMLEN_SHIFT 10
+#define MAC_CTRL_HUGE_EN BIT(9)
+#define MAC_CTRL_LENCHK BIT(8)
+#define MAC_CTRL_PAD BIT(7)
+#define MAC_CTRL_ADD_CRC BIT(6)
+#define MAC_CTRL_DUPLX BIT(5)
+#define MAC_CTRL_LOOPBACK BIT(4)
+#define MAC_CTRL_RX_FLOW BIT(3)
+#define MAC_CTRL_TX_FLOW BIT(2)
+#define MAC_CTRL_RX_EN BIT(1)
+#define MAC_CTRL_TX_EN BIT(0)
/* MAC IPG/IFG Control Register */
#define REG_MAC_IPG_IFG 0x1484
@@ -386,34 +443,53 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
/* Wake-On-Lan control register */
#define REG_WOL_CTRL 0x14a0
-#define WOL_PATTERN_EN 0x00000001
-#define WOL_PATTERN_PME_EN 0x00000002
-#define WOL_MAGIC_EN 0x00000004
-#define WOL_MAGIC_PME_EN 0x00000008
-#define WOL_LINK_CHG_EN 0x00000010
-#define WOL_LINK_CHG_PME_EN 0x00000020
-#define WOL_PATTERN_ST 0x00000100
-#define WOL_MAGIC_ST 0x00000200
-#define WOL_LINKCHG_ST 0x00000400
-#define WOL_CLK_SWITCH_EN 0x00008000
-#define WOL_PT0_EN 0x00010000
-#define WOL_PT1_EN 0x00020000
-#define WOL_PT2_EN 0x00040000
-#define WOL_PT3_EN 0x00080000
-#define WOL_PT4_EN 0x00100000
-#define WOL_PT5_EN 0x00200000
-#define WOL_PT6_EN 0x00400000
+#define WOL_PT7_MATCH BIT(31)
+#define WOL_PT6_MATCH BIT(30)
+#define WOL_PT5_MATCH BIT(29)
+#define WOL_PT4_MATCH BIT(28)
+#define WOL_PT3_MATCH BIT(27)
+#define WOL_PT2_MATCH BIT(26)
+#define WOL_PT1_MATCH BIT(25)
+#define WOL_PT0_MATCH BIT(24)
+#define WOL_PT7_EN BIT(23)
+#define WOL_PT6_EN BIT(22)
+#define WOL_PT5_EN BIT(21)
+#define WOL_PT4_EN BIT(20)
+#define WOL_PT3_EN BIT(19)
+#define WOL_PT2_EN BIT(18)
+#define WOL_PT1_EN BIT(17)
+#define WOL_PT0_EN BIT(16)
+#define WOL_LNKCHG_ST BIT(10)
+#define WOL_MAGIC_ST BIT(9)
+#define WOL_PATTERN_ST BIT(8)
+#define WOL_OOB_EN BIT(6)
+#define WOL_LINK_CHG_PME_EN BIT(5)
+#define WOL_LINK_CHG_EN BIT(4)
+#define WOL_MAGIC_PME_EN BIT(3)
+#define WOL_MAGIC_EN BIT(2)
+#define WOL_PATTERN_PME_EN BIT(1)
+#define WOL_PATTERN_EN BIT(0)
/* WOL Length ( 2 DWORD ) */
-#define REG_WOL_PATTERN_LEN 0x14a4
-#define WOL_PT_LEN_MASK 0x7f
-#define WOL_PT0_LEN_SHIFT 0
-#define WOL_PT1_LEN_SHIFT 8
-#define WOL_PT2_LEN_SHIFT 16
-#define WOL_PT3_LEN_SHIFT 24
-#define WOL_PT4_LEN_SHIFT 0
-#define WOL_PT5_LEN_SHIFT 8
-#define WOL_PT6_LEN_SHIFT 16
+#define REG_WOL_PTLEN1 0x14A4
+#define WOL_PTLEN1_3_MASK 0xFFUL
+#define WOL_PTLEN1_3_SHIFT 24
+#define WOL_PTLEN1_2_MASK 0xFFUL
+#define WOL_PTLEN1_2_SHIFT 16
+#define WOL_PTLEN1_1_MASK 0xFFUL
+#define WOL_PTLEN1_1_SHIFT 8
+#define WOL_PTLEN1_0_MASK 0xFFUL
+#define WOL_PTLEN1_0_SHIFT 0
+
+#define REG_WOL_PTLEN2 0x14A8
+#define WOL_PTLEN2_7_MASK 0xFFUL
+#define WOL_PTLEN2_7_SHIFT 24
+#define WOL_PTLEN2_6_MASK 0xFFUL
+#define WOL_PTLEN2_6_SHIFT 16
+#define WOL_PTLEN2_5_MASK 0xFFUL
+#define WOL_PTLEN2_5_SHIFT 8
+#define WOL_PTLEN2_4_MASK 0xFFUL
+#define WOL_PTLEN2_4_SHIFT 0
/* Internal SRAM Partition Register */
#define RFDX_HEAD_ADDR_MASK 0x03FF
@@ -458,66 +534,50 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
*/
#define REG_RX_BASE_ADDR_HI 0x1540
#define REG_TX_BASE_ADDR_HI 0x1544
-#define REG_SMB_BASE_ADDR_HI 0x1548
-#define REG_SMB_BASE_ADDR_LO 0x154C
#define REG_RFD0_HEAD_ADDR_LO 0x1550
-#define REG_RFD1_HEAD_ADDR_LO 0x1554
-#define REG_RFD2_HEAD_ADDR_LO 0x1558
-#define REG_RFD3_HEAD_ADDR_LO 0x155C
#define REG_RFD_RING_SIZE 0x1560
#define RFD_RING_SIZE_MASK 0x0FFF
#define REG_RX_BUF_SIZE 0x1564
#define RX_BUF_SIZE_MASK 0xFFFF
#define REG_RRD0_HEAD_ADDR_LO 0x1568
-#define REG_RRD1_HEAD_ADDR_LO 0x156C
-#define REG_RRD2_HEAD_ADDR_LO 0x1570
-#define REG_RRD3_HEAD_ADDR_LO 0x1574
#define REG_RRD_RING_SIZE 0x1578
#define RRD_RING_SIZE_MASK 0x0FFF
-#define REG_HTPD_HEAD_ADDR_LO 0x157C
-#define REG_NTPD_HEAD_ADDR_LO 0x1580
+#define REG_TPD_PRI1_ADDR_LO 0x157C
+#define REG_TPD_PRI0_ADDR_LO 0x1580
#define REG_TPD_RING_SIZE 0x1584
#define TPD_RING_SIZE_MASK 0xFFFF
-#define REG_CMB_BASE_ADDR_LO 0x1588
-
-/* RSS about */
-#define REG_RSS_KEY0 0x14B0
-#define REG_RSS_KEY1 0x14B4
-#define REG_RSS_KEY2 0x14B8
-#define REG_RSS_KEY3 0x14BC
-#define REG_RSS_KEY4 0x14C0
-#define REG_RSS_KEY5 0x14C4
-#define REG_RSS_KEY6 0x14C8
-#define REG_RSS_KEY7 0x14CC
-#define REG_RSS_KEY8 0x14D0
-#define REG_RSS_KEY9 0x14D4
-#define REG_IDT_TABLE0 0x14E0
-#define REG_IDT_TABLE1 0x14E4
-#define REG_IDT_TABLE2 0x14E8
-#define REG_IDT_TABLE3 0x14EC
-#define REG_IDT_TABLE4 0x14F0
-#define REG_IDT_TABLE5 0x14F4
-#define REG_IDT_TABLE6 0x14F8
-#define REG_IDT_TABLE7 0x14FC
-#define REG_IDT_TABLE REG_IDT_TABLE0
-#define REG_RSS_HASH_VALUE 0x15B0
-#define REG_RSS_HASH_FLAG 0x15B4
-#define REG_BASE_CPU_NUMBER 0x15B8
/* TXQ Control Register */
-#define REG_TXQ_CTRL 0x1590
-#define TXQ_NUM_TPD_BURST_MASK 0xF
-#define TXQ_NUM_TPD_BURST_SHIFT 0
-#define TXQ_CTRL_IP_OPTION_EN 0x10
-#define TXQ_CTRL_EN 0x20
-#define TXQ_CTRL_ENH_MODE 0x40
-#define TXQ_CTRL_LS_8023_EN 0x80
-#define TXQ_TXF_BURST_NUM_SHIFT 16
-#define TXQ_TXF_BURST_NUM_MASK 0xFFFF
+#define REG_TXQ_CTRL 0x1590
+#define TXQ_TXF_BURST_NUM_MASK 0xFFFFUL
+#define TXQ_TXF_BURST_NUM_SHIFT 16
+#define L1C_TXQ_TXF_BURST_PREF 0x200
+#define L2CB_TXQ_TXF_BURST_PREF 0x40
+#define TXQ_CTRL_PEDING_CLR BIT(8)
+#define TXQ_CTRL_LS_8023_EN BIT(7)
+#define TXQ_CTRL_ENH_MODE BIT(6)
+#define TXQ_CTRL_EN BIT(5)
+#define TXQ_CTRL_IP_OPTION_EN BIT(4)
+#define TXQ_NUM_TPD_BURST_MASK 0xFUL
+#define TXQ_NUM_TPD_BURST_SHIFT 0
+#define TXQ_NUM_TPD_BURST_DEF 5
+#define TXQ_CFGV (\
+ FIELDX(TXQ_NUM_TPD_BURST, TXQ_NUM_TPD_BURST_DEF) |\
+ TXQ_CTRL_ENH_MODE |\
+ TXQ_CTRL_LS_8023_EN |\
+ TXQ_CTRL_IP_OPTION_EN)
+#define L1C_TXQ_CFGV (\
+ TXQ_CFGV |\
+ FIELDX(TXQ_TXF_BURST_NUM, L1C_TXQ_TXF_BURST_PREF))
+#define L2CB_TXQ_CFGV (\
+ TXQ_CFGV |\
+ FIELDX(TXQ_TXF_BURST_NUM, L2CB_TXQ_TXF_BURST_PREF))
+
/* Jumbo packet Threshold for task offload */
#define REG_TX_TSO_OFFLOAD_THRESH 0x1594 /* In 8-bytes */
#define TX_TSO_OFFLOAD_THRESH_MASK 0x07FF
+#define MAX_TSO_FRAME_SIZE (7*1024)
#define REG_TXF_WATER_MARK 0x1598 /* In 8-bytes */
#define TXF_WATER_MARK_MASK 0x0FFF
@@ -537,26 +597,21 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define ASPM_THRUPUT_LIMIT_NO 0x00
#define ASPM_THRUPUT_LIMIT_1M 0x01
#define ASPM_THRUPUT_LIMIT_10M 0x02
-#define ASPM_THRUPUT_LIMIT_100M 0x04
-#define RXQ1_CTRL_EN 0x10
-#define RXQ2_CTRL_EN 0x20
-#define RXQ3_CTRL_EN 0x40
-#define IPV6_CHKSUM_CTRL_EN 0x80
-#define RSS_HASH_BITS_MASK 0x00FF
-#define RSS_HASH_BITS_SHIFT 8
-#define RSS_HASH_IPV4 0x10000
-#define RSS_HASH_IPV4_TCP 0x20000
-#define RSS_HASH_IPV6 0x40000
-#define RSS_HASH_IPV6_TCP 0x80000
+#define ASPM_THRUPUT_LIMIT_100M 0x03
+#define IPV6_CHKSUM_CTRL_EN BIT(7)
#define RXQ_RFD_BURST_NUM_MASK 0x003F
#define RXQ_RFD_BURST_NUM_SHIFT 20
-#define RSS_MODE_MASK 0x0003
+#define RXQ_NUM_RFD_PREF_DEF 8
+#define RSS_MODE_MASK 3UL
#define RSS_MODE_SHIFT 26
-#define RSS_NIP_QUEUE_SEL_MASK 0x1
-#define RSS_NIP_QUEUE_SEL_SHIFT 28
-#define RRS_HASH_CTRL_EN 0x20000000
-#define RX_CUT_THRU_EN 0x40000000
-#define RXQ_CTRL_EN 0x80000000
+#define RSS_MODE_DIS 0
+#define RSS_MODE_SQSI 1
+#define RSS_MODE_MQSI 2
+#define RSS_MODE_MQMI 3
+#define RSS_NIP_QUEUE_SEL BIT(28) /* 0:q0, 1:table */
+#define RRS_HASH_CTRL_EN BIT(29)
+#define RX_CUT_THRU_EN BIT(30)
+#define RXQ_CTRL_EN BIT(31)
#define REG_RFD_FREE_THRESH 0x15A4
#define RFD_FREE_THRESH_MASK 0x003F
@@ -577,57 +632,45 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define RXD_DMA_DOWN_TIMER_SHIFT 16
/* DMA Engine Control Register */
-#define REG_DMA_CTRL 0x15C0
-#define DMA_CTRL_DMAR_IN_ORDER 0x1
-#define DMA_CTRL_DMAR_ENH_ORDER 0x2
-#define DMA_CTRL_DMAR_OUT_ORDER 0x4
-#define DMA_CTRL_RCB_VALUE 0x8
-#define DMA_CTRL_DMAR_BURST_LEN_MASK 0x0007
-#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4
-#define DMA_CTRL_DMAW_BURST_LEN_MASK 0x0007
-#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7
-#define DMA_CTRL_DMAR_REQ_PRI 0x400
-#define DMA_CTRL_DMAR_DLY_CNT_MASK 0x001F
-#define DMA_CTRL_DMAR_DLY_CNT_SHIFT 11
-#define DMA_CTRL_DMAW_DLY_CNT_MASK 0x000F
-#define DMA_CTRL_DMAW_DLY_CNT_SHIFT 16
-#define DMA_CTRL_CMB_EN 0x100000
-#define DMA_CTRL_SMB_EN 0x200000
-#define DMA_CTRL_CMB_NOW 0x400000
-#define MAC_CTRL_SMB_DIS 0x1000000
-#define DMA_CTRL_SMB_NOW 0x80000000
-
-/* CMB/SMB Control Register */
+#define REG_DMA_CTRL 0x15C0
+#define DMA_CTRL_SMB_NOW BIT(31)
+#define DMA_CTRL_WPEND_CLR BIT(30)
+#define DMA_CTRL_RPEND_CLR BIT(29)
+#define DMA_CTRL_WDLY_CNT_MASK 0xFUL
+#define DMA_CTRL_WDLY_CNT_SHIFT 16
+#define DMA_CTRL_WDLY_CNT_DEF 4
+#define DMA_CTRL_RDLY_CNT_MASK 0x1FUL
+#define DMA_CTRL_RDLY_CNT_SHIFT 11
+#define DMA_CTRL_RDLY_CNT_DEF 15
+#define DMA_CTRL_RREQ_PRI_DATA BIT(10) /* 0:tpd, 1:data */
+#define DMA_CTRL_WREQ_BLEN_MASK 7UL
+#define DMA_CTRL_WREQ_BLEN_SHIFT 7
+#define DMA_CTRL_RREQ_BLEN_MASK 7UL
+#define DMA_CTRL_RREQ_BLEN_SHIFT 4
+#define L1C_CTRL_DMA_RCB_LEN128 BIT(3) /* 0:64bytes,1:128bytes */
+#define DMA_CTRL_RORDER_MODE_MASK 7UL
+#define DMA_CTRL_RORDER_MODE_SHIFT 0
+#define DMA_CTRL_RORDER_MODE_OUT 4
+#define DMA_CTRL_RORDER_MODE_ENHANCE 2
+#define DMA_CTRL_RORDER_MODE_IN 1
+
+/* INT-triggle/SMB Control Register */
#define REG_SMB_STAT_TIMER 0x15C4 /* 2us resolution */
#define SMB_STAT_TIMER_MASK 0xFFFFFF
-#define REG_CMB_TPD_THRESH 0x15C8
-#define CMB_TPD_THRESH_MASK 0xFFFF
-#define REG_CMB_TX_TIMER 0x15CC /* 2us resolution */
-#define CMB_TX_TIMER_MASK 0xFFFF
+#define REG_TINT_TPD_THRESH 0x15C8 /* tpd th to trig intrrupt */
/* Mail box */
#define MB_RFDX_PROD_IDX_MASK 0xFFFF
#define REG_MB_RFD0_PROD_IDX 0x15E0
-#define REG_MB_RFD1_PROD_IDX 0x15E4
-#define REG_MB_RFD2_PROD_IDX 0x15E8
-#define REG_MB_RFD3_PROD_IDX 0x15EC
-#define MB_PRIO_PROD_IDX_MASK 0xFFFF
-#define REG_MB_PRIO_PROD_IDX 0x15F0
-#define MB_HTPD_PROD_IDX_SHIFT 0
-#define MB_NTPD_PROD_IDX_SHIFT 16
-
-#define MB_PRIO_CONS_IDX_MASK 0xFFFF
-#define REG_MB_PRIO_CONS_IDX 0x15F4
-#define MB_HTPD_CONS_IDX_SHIFT 0
-#define MB_NTPD_CONS_IDX_SHIFT 16
+#define REG_TPD_PRI1_PIDX 0x15F0 /* 16bit,hi-tpd producer idx */
+#define REG_TPD_PRI0_PIDX 0x15F2 /* 16bit,lo-tpd producer idx */
+#define REG_TPD_PRI1_CIDX 0x15F4 /* 16bit,hi-tpd consumer idx */
+#define REG_TPD_PRI0_CIDX 0x15F6 /* 16bit,lo-tpd consumer idx */
#define REG_MB_RFD01_CONS_IDX 0x15F8
#define MB_RFD0_CONS_IDX_MASK 0x0000FFFF
#define MB_RFD1_CONS_IDX_MASK 0xFFFF0000
-#define REG_MB_RFD23_CONS_IDX 0x15FC
-#define MB_RFD2_CONS_IDX_MASK 0x0000FFFF
-#define MB_RFD3_CONS_IDX_MASK 0xFFFF0000
/* Interrupt Status Register */
#define REG_ISR 0x1600
@@ -705,13 +748,6 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define REG_INT_RETRIG_TIMER 0x1608
#define INT_RETRIG_TIMER_MASK 0xFFFF
-#define REG_HDS_CTRL 0x160C
-#define HDS_CTRL_EN 0x0001
-#define HDS_CTRL_BACKFILLSIZE_SHIFT 8
-#define HDS_CTRL_BACKFILLSIZE_MASK 0x0FFF
-#define HDS_CTRL_MAX_HDRSIZE_SHIFT 20
-#define HDS_CTRL_MAC_HDRSIZE_MASK 0x0FFF
-
#define REG_MAC_RX_STATUS_BIN 0x1700
#define REG_MAC_RX_STATUS_END 0x175c
#define REG_MAC_TX_STATUS_BIN 0x1760
@@ -796,73 +832,188 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
#define MII_DBG_ADDR 0x1D
#define MII_DBG_DATA 0x1E
-#define MII_ANA_CTRL_0 0x0
-#define ANA_RESTART_CAL 0x0001
-#define ANA_MANUL_SWICH_ON_SHIFT 0x1
-#define ANA_MANUL_SWICH_ON_MASK 0xF
-#define ANA_MAN_ENABLE 0x0020
-#define ANA_SEL_HSP 0x0040
-#define ANA_EN_HB 0x0080
-#define ANA_EN_HBIAS 0x0100
-#define ANA_OEN_125M 0x0200
-#define ANA_EN_LCKDT 0x0400
-#define ANA_LCKDT_PHY 0x0800
-#define ANA_AFE_MODE 0x1000
-#define ANA_VCO_SLOW 0x2000
-#define ANA_VCO_FAST 0x4000
-#define ANA_SEL_CLK125M_DSP 0x8000
-
-#define MII_ANA_CTRL_4 0x4
-#define ANA_IECHO_ADJ_MASK 0xF
-#define ANA_IECHO_ADJ_3_SHIFT 0
-#define ANA_IECHO_ADJ_2_SHIFT 4
-#define ANA_IECHO_ADJ_1_SHIFT 8
-#define ANA_IECHO_ADJ_0_SHIFT 12
-
-#define MII_ANA_CTRL_5 0x5
-#define ANA_SERDES_CDR_BW_SHIFT 0
-#define ANA_SERDES_CDR_BW_MASK 0x3
-#define ANA_MS_PAD_DBG 0x0004
-#define ANA_SPEEDUP_DBG 0x0008
-#define ANA_SERDES_TH_LOS_SHIFT 4
-#define ANA_SERDES_TH_LOS_MASK 0x3
-#define ANA_SERDES_EN_DEEM 0x0040
-#define ANA_SERDES_TXELECIDLE 0x0080
-#define ANA_SERDES_BEACON 0x0100
-#define ANA_SERDES_HALFTXDR 0x0200
-#define ANA_SERDES_SEL_HSP 0x0400
-#define ANA_SERDES_EN_PLL 0x0800
-#define ANA_SERDES_EN 0x1000
-#define ANA_SERDES_EN_LCKDT 0x2000
-
-#define MII_ANA_CTRL_11 0xB
-#define ANA_PS_HIB_EN 0x8000
-
-#define MII_ANA_CTRL_18 0x12
-#define ANA_TEST_MODE_10BT_01SHIFT 0
-#define ANA_TEST_MODE_10BT_01MASK 0x3
-#define ANA_LOOP_SEL_10BT 0x0004
-#define ANA_RGMII_MODE_SW 0x0008
-#define ANA_EN_LONGECABLE 0x0010
-#define ANA_TEST_MODE_10BT_2 0x0020
-#define ANA_EN_10BT_IDLE 0x0400
-#define ANA_EN_MASK_TB 0x0800
-#define ANA_TRIGGER_SEL_TIMER_SHIFT 12
-#define ANA_TRIGGER_SEL_TIMER_MASK 0x3
-#define ANA_INTERVAL_SEL_TIMER_SHIFT 14
-#define ANA_INTERVAL_SEL_TIMER_MASK 0x3
-
-#define MII_ANA_CTRL_41 0x29
-#define ANA_TOP_PS_EN 0x8000
-
-#define MII_ANA_CTRL_54 0x36
-#define ANA_LONG_CABLE_TH_100_SHIFT 0
-#define ANA_LONG_CABLE_TH_100_MASK 0x3F
-#define ANA_DESERVED 0x0040
-#define ANA_EN_LIT_CH 0x0080
-#define ANA_SHORT_CABLE_TH_100_SHIFT 8
-#define ANA_SHORT_CABLE_TH_100_MASK 0x3F
-#define ANA_BP_BAD_LINK_ACCUM 0x4000
-#define ANA_BP_SMALL_BW 0x8000
+/***************************** debug port *************************************/
+
+#define MIIDBG_ANACTRL 0x00
+#define ANACTRL_CLK125M_DELAY_EN 0x8000
+#define ANACTRL_VCO_FAST 0x4000
+#define ANACTRL_VCO_SLOW 0x2000
+#define ANACTRL_AFE_MODE_EN 0x1000
+#define ANACTRL_LCKDET_PHY 0x800
+#define ANACTRL_LCKDET_EN 0x400
+#define ANACTRL_OEN_125M 0x200
+#define ANACTRL_HBIAS_EN 0x100
+#define ANACTRL_HB_EN 0x80
+#define ANACTRL_SEL_HSP 0x40
+#define ANACTRL_CLASSA_EN 0x20
+#define ANACTRL_MANUSWON_SWR_MASK 3U
+#define ANACTRL_MANUSWON_SWR_SHIFT 2
+#define ANACTRL_MANUSWON_SWR_2V 0
+#define ANACTRL_MANUSWON_SWR_1P9V 1
+#define ANACTRL_MANUSWON_SWR_1P8V 2
+#define ANACTRL_MANUSWON_SWR_1P7V 3
+#define ANACTRL_MANUSWON_BW3_4M 0x2
+#define ANACTRL_RESTART_CAL 0x1
+#define ANACTRL_DEF 0x02EF
+
+#define MIIDBG_SYSMODCTRL 0x04
+#define SYSMODCTRL_IECHOADJ_PFMH_PHY 0x8000
+#define SYSMODCTRL_IECHOADJ_BIASGEN 0x4000
+#define SYSMODCTRL_IECHOADJ_PFML_PHY 0x2000
+#define SYSMODCTRL_IECHOADJ_PS_MASK 3U
+#define SYSMODCTRL_IECHOADJ_PS_SHIFT 10
+#define SYSMODCTRL_IECHOADJ_PS_40 3
+#define SYSMODCTRL_IECHOADJ_PS_20 2
+#define SYSMODCTRL_IECHOADJ_PS_0 1
+#define SYSMODCTRL_IECHOADJ_10BT_100MV 0x40 /* 1:100mv, 0:200mv */
+#define SYSMODCTRL_IECHOADJ_HLFAP_MASK 3U
+#define SYSMODCTRL_IECHOADJ_HLFAP_SHIFT 4
+#define SYSMODCTRL_IECHOADJ_VDFULBW 0x8
+#define SYSMODCTRL_IECHOADJ_VDBIASHLF 0x4
+#define SYSMODCTRL_IECHOADJ_VDAMPHLF 0x2
+#define SYSMODCTRL_IECHOADJ_VDLANSW 0x1
+#define SYSMODCTRL_IECHOADJ_DEF 0x88BB /* ???? */
+
+/* for l1d & l2cb */
+#define SYSMODCTRL_IECHOADJ_CUR_ADD 0x8000
+#define SYSMODCTRL_IECHOADJ_CUR_MASK 7U
+#define SYSMODCTRL_IECHOADJ_CUR_SHIFT 12
+#define SYSMODCTRL_IECHOADJ_VOL_MASK 0xFU
+#define SYSMODCTRL_IECHOADJ_VOL_SHIFT 8
+#define SYSMODCTRL_IECHOADJ_VOL_17ALL 3
+#define SYSMODCTRL_IECHOADJ_VOL_100M15 1
+#define SYSMODCTRL_IECHOADJ_VOL_10M17 0
+#define SYSMODCTRL_IECHOADJ_BIAS1_MASK 0xFU
+#define SYSMODCTRL_IECHOADJ_BIAS1_SHIFT 4
+#define SYSMODCTRL_IECHOADJ_BIAS2_MASK 0xFU
+#define SYSMODCTRL_IECHOADJ_BIAS2_SHIFT 0
+#define L1D_SYSMODCTRL_IECHOADJ_DEF 0x4FBB
+
+#define MIIDBG_SRDSYSMOD 0x05
+#define SRDSYSMOD_LCKDET_EN 0x2000
+#define SRDSYSMOD_PLL_EN 0x800
+#define SRDSYSMOD_SEL_HSP 0x400
+#define SRDSYSMOD_HLFTXDR 0x200
+#define SRDSYSMOD_TXCLK_DELAY_EN 0x100
+#define SRDSYSMOD_TXELECIDLE 0x80
+#define SRDSYSMOD_DEEMP_EN 0x40
+#define SRDSYSMOD_MS_PAD 0x4
+#define SRDSYSMOD_CDR_ADC_VLTG 0x2
+#define SRDSYSMOD_CDR_DAC_1MA 0x1
+#define SRDSYSMOD_DEF 0x2C46
+
+#define MIIDBG_CFGLPSPD 0x0A
+#define CFGLPSPD_RSTCNT_MASK 3U
+#define CFGLPSPD_RSTCNT_SHIFT 14
+#define CFGLPSPD_RSTCNT_CLK125SW 0x2000
+
+#define MIIDBG_HIBNEG 0x0B
+#define HIBNEG_PSHIB_EN 0x8000
+#define HIBNEG_WAKE_BOTH 0x4000
+#define HIBNEG_ONOFF_ANACHG_SUDEN 0x2000
+#define HIBNEG_HIB_PULSE 0x1000
+#define HIBNEG_GATE_25M_EN 0x800
+#define HIBNEG_RST_80U 0x400
+#define HIBNEG_RST_TIMER_MASK 3U
+#define HIBNEG_RST_TIMER_SHIFT 8
+#define HIBNEG_GTX_CLK_DELAY_MASK 3U
+#define HIBNEG_GTX_CLK_DELAY_SHIFT 5
+#define HIBNEG_BYPSS_BRKTIMER 0x10
+#define HIBNEG_DEF 0xBC40
+
+#define MIIDBG_TST10BTCFG 0x12
+#define TST10BTCFG_INTV_TIMER_MASK 3U
+#define TST10BTCFG_INTV_TIMER_SHIFT 14
+#define TST10BTCFG_TRIGER_TIMER_MASK 3U
+#define TST10BTCFG_TRIGER_TIMER_SHIFT 12
+#define TST10BTCFG_DIV_MAN_MLT3_EN 0x800
+#define TST10BTCFG_OFF_DAC_IDLE 0x400
+#define TST10BTCFG_LPBK_DEEP 0x4 /* 1:deep,0:shallow */
+#define TST10BTCFG_DEF 0x4C04
+
+#define MIIDBG_AZ_ANADECT 0x15
+#define AZ_ANADECT_10BTRX_TH 0x8000
+#define AZ_ANADECT_BOTH_01CHNL 0x4000
+#define AZ_ANADECT_INTV_MASK 0x3FU
+#define AZ_ANADECT_INTV_SHIFT 8
+#define AZ_ANADECT_THRESH_MASK 0xFU
+#define AZ_ANADECT_THRESH_SHIFT 4
+#define AZ_ANADECT_CHNL_MASK 0xFU
+#define AZ_ANADECT_CHNL_SHIFT 0
+#define AZ_ANADECT_DEF 0x3220
+#define AZ_ANADECT_LONG 0xb210
+
+#define MIIDBG_MSE16DB 0x18 /* l1d */
+#define L1D_MSE16DB_UP 0x05EA
+#define L1D_MSE16DB_DOWN 0x02EA
+
+#define MIIDBG_LEGCYPS 0x29
+#define LEGCYPS_EN 0x8000
+#define LEGCYPS_DAC_AMP1000_MASK 7U
+#define LEGCYPS_DAC_AMP1000_SHIFT 12
+#define LEGCYPS_DAC_AMP100_MASK 7U
+#define LEGCYPS_DAC_AMP100_SHIFT 9
+#define LEGCYPS_DAC_AMP10_MASK 7U
+#define LEGCYPS_DAC_AMP10_SHIFT 6
+#define LEGCYPS_UNPLUG_TIMER_MASK 7U
+#define LEGCYPS_UNPLUG_TIMER_SHIFT 3
+#define LEGCYPS_UNPLUG_DECT_EN 0x4
+#define LEGCYPS_ECNC_PS_EN 0x1
+#define L1D_LEGCYPS_DEF 0x129D
+#define L1C_LEGCYPS_DEF 0x36DD
+
+#define MIIDBG_TST100BTCFG 0x36
+#define TST100BTCFG_NORMAL_BW_EN 0x8000
+#define TST100BTCFG_BADLNK_BYPASS 0x4000
+#define TST100BTCFG_SHORTCABL_TH_MASK 0x3FU
+#define TST100BTCFG_SHORTCABL_TH_SHIFT 8
+#define TST100BTCFG_LITCH_EN 0x80
+#define TST100BTCFG_VLT_SW 0x40
+#define TST100BTCFG_LONGCABL_TH_MASK 0x3FU
+#define TST100BTCFG_LONGCABL_TH_SHIFT 0
+#define TST100BTCFG_DEF 0xE12C
+
+#define MIIDBG_VOLT_CTRL 0x3B /* only for l2cb 1 & 2 */
+#define VOLT_CTRL_CABLE1TH_MASK 0x1FFU
+#define VOLT_CTRL_CABLE1TH_SHIFT 7
+#define VOLT_CTRL_AMPCTRL_MASK 3U
+#define VOLT_CTRL_AMPCTRL_SHIFT 5
+#define VOLT_CTRL_SW_BYPASS 0x10
+#define VOLT_CTRL_SWLOWEST 0x8
+#define VOLT_CTRL_DACAMP10_MASK 7U
+#define VOLT_CTRL_DACAMP10_SHIFT 0
+
+#define MIIDBG_CABLE1TH_DET 0x3E
+#define CABLE1TH_DET_EN 0x8000
+
+
+/******* dev 3 *********/
+#define MIIEXT_PCS 3
+
+#define MIIEXT_CLDCTRL3 0x8003
+#define CLDCTRL3_BP_CABLE1TH_DET_GT 0x8000
+#define CLDCTRL3_AZ_DISAMP 0x1000
+#define L2CB_CLDCTRL3 0x4D19
+#define L1D_CLDCTRL3 0xDD19
+
+#define MIIEXT_CLDCTRL6 0x8006
+#define CLDCTRL6_CAB_LEN_MASK 0x1FFU
+#define CLDCTRL6_CAB_LEN_SHIFT 0
+#define CLDCTRL6_CAB_LEN_SHORT 0x50
+
+/********* dev 7 **********/
+#define MIIEXT_ANEG 7
+
+#define MIIEXT_LOCAL_EEEADV 0x3C
+#define LOCAL_EEEADV_1000BT 0x4
+#define LOCAL_EEEADV_100BT 0x2
+
+#define MIIEXT_REMOTE_EEEADV 0x3D
+#define REMOTE_EEEADV_1000BT 0x4
+#define REMOTE_EEEADV_100BT 0x2
+
+#define MIIEXT_EEE_ANEG 0x8000
+#define EEE_ANEG_1000M 0x4
+#define EEE_ANEG_100M 0x2
#endif /*_ATL1C_HW_H_*/
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 1ef0c9275dee..9cc15701101b 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -24,14 +24,6 @@
#define ATL1C_DRV_VERSION "1.0.1.0-NAPI"
char atl1c_driver_name[] = "atl1c";
char atl1c_driver_version[] = ATL1C_DRV_VERSION;
-#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062
-#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063
-#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */
-#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */
-#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */
-#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */
-#define L2CB_V10 0xc0
-#define L2CB_V11 0xc1
/*
* atl1c_pci_tbl - PCI Device ID Table
@@ -54,70 +46,72 @@ static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = {
};
MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl);
-MODULE_AUTHOR("Jie Yang <jie.yang@atheros.com>");
-MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver");
+MODULE_AUTHOR("Jie Yang");
+MODULE_AUTHOR("Qualcomm Atheros Inc., <nic-devel@qualcomm.com>");
+MODULE_DESCRIPTION("Qualcom Atheros 100/1000M Ethernet Network Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(ATL1C_DRV_VERSION);
static int atl1c_stop_mac(struct atl1c_hw *hw);
-static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw);
-static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw);
static void atl1c_disable_l0s_l1(struct atl1c_hw *hw);
-static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup);
-static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter);
-static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
+static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed);
+static void atl1c_start_mac(struct atl1c_adapter *adapter);
+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter,
int *work_done, int work_to_do);
static int atl1c_up(struct atl1c_adapter *adapter);
static void atl1c_down(struct atl1c_adapter *adapter);
+static int atl1c_reset_mac(struct atl1c_hw *hw);
+static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter);
+static int atl1c_configure(struct atl1c_adapter *adapter);
+static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter);
static const u16 atl1c_pay_load_size[] = {
128, 256, 512, 1024, 2048, 4096,
};
-static const u16 atl1c_rfd_prod_idx_regs[AT_MAX_RECEIVE_QUEUE] =
-{
- REG_MB_RFD0_PROD_IDX,
- REG_MB_RFD1_PROD_IDX,
- REG_MB_RFD2_PROD_IDX,
- REG_MB_RFD3_PROD_IDX
-};
-
-static const u16 atl1c_rfd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
-{
- REG_RFD0_HEAD_ADDR_LO,
- REG_RFD1_HEAD_ADDR_LO,
- REG_RFD2_HEAD_ADDR_LO,
- REG_RFD3_HEAD_ADDR_LO
-};
-
-static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
-{
- REG_RRD0_HEAD_ADDR_LO,
- REG_RRD1_HEAD_ADDR_LO,
- REG_RRD2_HEAD_ADDR_LO,
- REG_RRD3_HEAD_ADDR_LO
-};
static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
static void atl1c_pcie_patch(struct atl1c_hw *hw)
{
- u32 data;
+ u32 mst_data, data;
- AT_READ_REG(hw, REG_PCIE_PHYMISC, &data);
- data |= PCIE_PHYMISC_FORCE_RCV_DET;
- AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data);
+ /* pclk sel could switch to 25M */
+ AT_READ_REG(hw, REG_MASTER_CTRL, &mst_data);
+ mst_data &= ~MASTER_CTRL_CLK_SEL_DIS;
+ AT_WRITE_REG(hw, REG_MASTER_CTRL, mst_data);
+ /* WoL/PCIE related settings */
+ if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) {
+ AT_READ_REG(hw, REG_PCIE_PHYMISC, &data);
+ data |= PCIE_PHYMISC_FORCE_RCV_DET;
+ AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data);
+ } else { /* new dev set bit5 of MASTER */
+ if (!(mst_data & MASTER_CTRL_WAKEN_25M))
+ AT_WRITE_REG(hw, REG_MASTER_CTRL,
+ mst_data | MASTER_CTRL_WAKEN_25M);
+ }
+ /* aspm/PCIE setting only for l2cb 1.0 */
if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) {
AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data);
-
- data &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK <<
- PCIE_PHYMISC2_SERDES_CDR_SHIFT);
- data |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT;
- data &= ~(PCIE_PHYMISC2_SERDES_TH_MASK <<
- PCIE_PHYMISC2_SERDES_TH_SHIFT);
- data |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT;
+ data = FIELD_SETX(data, PCIE_PHYMISC2_CDR_BW,
+ L2CB1_PCIE_PHYMISC2_CDR_BW);
+ data = FIELD_SETX(data, PCIE_PHYMISC2_L0S_TH,
+ L2CB1_PCIE_PHYMISC2_L0S_TH);
AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data);
+ /* extend L1 sync timer */
+ AT_READ_REG(hw, REG_LINK_CTRL, &data);
+ data |= LINK_CTRL_EXT_SYNC;
+ AT_WRITE_REG(hw, REG_LINK_CTRL, data);
+ }
+ /* l2cb 1.x & l1d 1.x */
+ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d) {
+ AT_READ_REG(hw, REG_PM_CTRL, &data);
+ data |= PM_CTRL_L0S_BUFSRX_EN;
+ AT_WRITE_REG(hw, REG_PM_CTRL, data);
+ /* clear vendor msg */
+ AT_READ_REG(hw, REG_DMA_DBG, &data);
+ AT_WRITE_REG(hw, REG_DMA_DBG, data & ~DMA_DBG_VENDOR_MSG);
}
}
@@ -130,6 +124,7 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
u32 data;
u32 pci_cmd;
struct pci_dev *pdev = hw->adapter->pdev;
+ int pos;
AT_READ_REG(hw, PCI_COMMAND, &pci_cmd);
pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
@@ -142,14 +137,23 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
*/
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
+ /* wol sts read-clear */
+ AT_READ_REG(hw, REG_WOL_CTRL, &data);
+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
/*
* Mask some pcie error bits
*/
- AT_READ_REG(hw, REG_PCIE_UC_SEVERITY, &data);
- data &= ~PCIE_UC_SERVRITY_DLP;
- data &= ~PCIE_UC_SERVRITY_FCP;
- AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data);
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
+ pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data);
+ data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
+ pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
+ /* clear error status */
+ pci_write_config_word(pdev, pci_pcie_cap(pdev) + PCI_EXP_DEVSTA,
+ PCI_EXP_DEVSTA_NFED |
+ PCI_EXP_DEVSTA_FED |
+ PCI_EXP_DEVSTA_CED |
+ PCI_EXP_DEVSTA_URD);
AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &data);
data &= ~LTSSM_ID_EN_WRO;
@@ -158,11 +162,6 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
atl1c_pcie_patch(hw);
if (flag & ATL1C_PCIE_L0S_L1_DISABLE)
atl1c_disable_l0s_l1(hw);
- if (flag & ATL1C_PCIE_PHY_RESET)
- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
- else
- AT_WRITE_REG(hw, REG_GPHY_CTRL,
- GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET);
msleep(5);
}
@@ -207,14 +206,14 @@ static inline void atl1c_irq_reset(struct atl1c_adapter *adapter)
* atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads
* of the idle status register until the device is actually idle
*/
-static u32 atl1c_wait_until_idle(struct atl1c_hw *hw)
+static u32 atl1c_wait_until_idle(struct atl1c_hw *hw, u32 modu_ctrl)
{
int timeout;
u32 data;
for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
AT_READ_REG(hw, REG_IDLE_STATUS, &data);
- if ((data & IDLE_STATUS_MASK) == 0)
+ if ((data & modu_ctrl) == 0)
return 0;
msleep(1);
}
@@ -261,15 +260,16 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)
if ((phy_data & BMSR_LSTATUS) == 0) {
/* link down */
- hw->hibernate = true;
- if (atl1c_stop_mac(hw) != 0)
- if (netif_msg_hw(adapter))
- dev_warn(&pdev->dev, "stop mac failed\n");
- atl1c_set_aspm(hw, false);
netif_carrier_off(netdev);
netif_stop_queue(netdev);
- atl1c_phy_reset(hw);
- atl1c_phy_init(&adapter->hw);
+ hw->hibernate = true;
+ if (atl1c_reset_mac(hw) != 0)
+ if (netif_msg_hw(adapter))
+ dev_warn(&pdev->dev, "reset mac failed\n");
+ atl1c_set_aspm(hw, SPEED_0);
+ atl1c_post_phy_linkchg(hw, SPEED_0);
+ atl1c_reset_dma_ring(adapter);
+ atl1c_configure(adapter);
} else {
/* Link Up */
hw->hibernate = false;
@@ -283,10 +283,9 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)
adapter->link_duplex != duplex) {
adapter->link_speed = speed;
adapter->link_duplex = duplex;
- atl1c_set_aspm(hw, true);
- atl1c_enable_tx_ctrl(hw);
- atl1c_enable_rx_ctrl(hw);
- atl1c_setup_mac_ctrl(adapter);
+ atl1c_set_aspm(hw, speed);
+ atl1c_post_phy_linkchg(hw, speed);
+ atl1c_start_mac(adapter);
if (netif_msg_link(adapter))
dev_info(&pdev->dev,
"%s: %s NIC Link is Up<%d Mbps %s>\n",
@@ -337,6 +336,9 @@ static void atl1c_common_task(struct work_struct *work)
adapter = container_of(work, struct atl1c_adapter, common_task);
netdev = adapter->netdev;
+ if (test_bit(__AT_DOWN, &adapter->flags))
+ return;
+
if (test_and_clear_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event)) {
netif_device_detach(netdev);
atl1c_down(adapter);
@@ -345,8 +347,11 @@ static void atl1c_common_task(struct work_struct *work)
}
if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE,
- &adapter->work_event))
+ &adapter->work_event)) {
+ atl1c_irq_disable(adapter);
atl1c_check_link_status(adapter);
+ atl1c_irq_enable(adapter);
+ }
}
@@ -470,7 +475,7 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p)
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);
+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr);
return 0;
}
@@ -523,11 +528,16 @@ static int atl1c_set_features(struct net_device *netdev,
static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
+ struct atl1c_hw *hw = &adapter->hw;
int old_mtu = netdev->mtu;
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
- if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
- (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+ /* Fast Ethernet controller doesn't support jumbo packet */
+ if (((hw->nic_type == athr_l2c ||
+ hw->nic_type == athr_l2c_b ||
+ hw->nic_type == athr_l2c_b2) && new_mtu > ETH_DATA_LEN) ||
+ max_frame < ETH_ZLEN + ETH_FCS_LEN ||
+ max_frame > MAX_JUMBO_FRAME_SIZE) {
if (netif_msg_link(adapter))
dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
return -EINVAL;
@@ -543,14 +553,6 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
netdev_update_features(netdev);
atl1c_up(adapter);
clear_bit(__AT_RESETTING, &adapter->flags);
- if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
- u32 phy_data;
-
- AT_READ_REG(&adapter->hw, 0x1414, &phy_data);
- phy_data |= 0x10000000;
- AT_WRITE_REG(&adapter->hw, 0x1414, phy_data);
- }
-
}
return 0;
}
@@ -563,7 +565,7 @@ static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num)
struct atl1c_adapter *adapter = netdev_priv(netdev);
u16 result;
- atl1c_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
+ atl1c_read_phy_reg(&adapter->hw, reg_num, &result);
return result;
}
@@ -572,7 +574,7 @@ static void atl1c_mdio_write(struct net_device *netdev, int phy_id,
{
struct atl1c_adapter *adapter = netdev_priv(netdev);
- atl1c_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
+ atl1c_write_phy_reg(&adapter->hw, reg_num, val);
}
/*
@@ -687,21 +689,15 @@ static void atl1c_set_mac_type(struct atl1c_hw *hw)
static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
{
- u32 phy_status_data;
u32 link_ctrl_data;
atl1c_set_mac_type(hw);
- AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data);
AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE |
ATL1C_TXQ_MODE_ENHANCE;
- if (link_ctrl_data & LINK_CTRL_L0S_EN)
- hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT;
- if (link_ctrl_data & LINK_CTRL_L1_EN)
- hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT;
- if (link_ctrl_data & LINK_CTRL_EXT_SYNC)
- hw->ctrl_flags |= ATL1C_LINK_EXT_SYNC;
+ hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT |
+ ATL1C_ASPM_L1_SUPPORT;
hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON;
if (hw->nic_type == athr_l1c ||
@@ -710,6 +706,55 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
hw->link_cap_flags |= ATL1C_LINK_CAP_1000M;
return 0;
}
+
+struct atl1c_platform_patch {
+ u16 pci_did;
+ u8 pci_revid;
+ u16 subsystem_vid;
+ u16 subsystem_did;
+ u32 patch_flag;
+#define ATL1C_LINK_PATCH 0x1
+};
+static const struct atl1c_platform_patch plats[] __devinitdata = {
+{0x2060, 0xC1, 0x1019, 0x8152, 0x1},
+{0x2060, 0xC1, 0x1019, 0x2060, 0x1},
+{0x2060, 0xC1, 0x1019, 0xE000, 0x1},
+{0x2062, 0xC0, 0x1019, 0x8152, 0x1},
+{0x2062, 0xC0, 0x1019, 0x2062, 0x1},
+{0x2062, 0xC0, 0x1458, 0xE000, 0x1},
+{0x2062, 0xC1, 0x1019, 0x8152, 0x1},
+{0x2062, 0xC1, 0x1019, 0x2062, 0x1},
+{0x2062, 0xC1, 0x1458, 0xE000, 0x1},
+{0x2062, 0xC1, 0x1565, 0x2802, 0x1},
+{0x2062, 0xC1, 0x1565, 0x2801, 0x1},
+{0x1073, 0xC0, 0x1019, 0x8151, 0x1},
+{0x1073, 0xC0, 0x1019, 0x1073, 0x1},
+{0x1073, 0xC0, 0x1458, 0xE000, 0x1},
+{0x1083, 0xC0, 0x1458, 0xE000, 0x1},
+{0x1083, 0xC0, 0x1019, 0x8151, 0x1},
+{0x1083, 0xC0, 0x1019, 0x1083, 0x1},
+{0x1083, 0xC0, 0x1462, 0x7680, 0x1},
+{0x1083, 0xC0, 0x1565, 0x2803, 0x1},
+{0},
+};
+
+static void __devinit atl1c_patch_assign(struct atl1c_hw *hw)
+{
+ int i = 0;
+
+ hw->msi_lnkpatch = false;
+
+ while (plats[i].pci_did != 0) {
+ if (plats[i].pci_did == hw->device_id &&
+ plats[i].pci_revid == hw->revision_id &&
+ plats[i].subsystem_vid == hw->subsystem_vendor_id &&
+ plats[i].subsystem_did == hw->subsystem_id) {
+ if (plats[i].patch_flag & ATL1C_LINK_PATCH)
+ hw->msi_lnkpatch = true;
+ }
+ i++;
+ }
+}
/*
* atl1c_sw_init - Initialize general software structures (struct atl1c_adapter)
* @adapter: board private structure to initialize
@@ -729,9 +774,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
device_set_wakeup_enable(&pdev->dev, false);
adapter->link_speed = SPEED_0;
adapter->link_duplex = FULL_DUPLEX;
- adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE;
adapter->tpd_ring[0].count = 1024;
- adapter->rfd_ring[0].count = 512;
+ adapter->rfd_ring.count = 512;
hw->vendor_id = pdev->vendor;
hw->device_id = pdev->device;
@@ -746,26 +790,18 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
dev_err(&pdev->dev, "set mac function pointers failed\n");
return -1;
}
+ atl1c_patch_assign(hw);
+
hw->intr_mask = IMR_NORMAL_MASK;
hw->phy_configured = false;
hw->preamble_len = 7;
hw->max_frame_size = adapter->netdev->mtu;
- if (adapter->num_rx_queues < 2) {
- hw->rss_type = atl1c_rss_disable;
- hw->rss_mode = atl1c_rss_mode_disable;
- } else {
- hw->rss_type = atl1c_rss_ipv4;
- hw->rss_mode = atl1c_rss_mul_que_mul_int;
- hw->rss_hash_bits = 16;
- }
hw->autoneg_advertised = ADVERTISED_Autoneg;
hw->indirect_tab = 0xE4E4E4E4;
hw->base_cpu = 0;
hw->ict = 50000; /* 100ms */
hw->smb_timer = 200000; /* 400ms */
- hw->cmb_tpd = 4;
- hw->cmb_tx_timer = 1; /* 2 us */
hw->rx_imt = 200;
hw->tx_imt = 1000;
@@ -773,9 +809,6 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
hw->rfd_burst = 8;
hw->dma_order = atl1c_dma_ord_out;
hw->dmar_block = atl1c_dma_req_1024;
- hw->dmaw_block = atl1c_dma_req_1024;
- hw->dmar_dly_cnt = 15;
- hw->dmaw_dly_cnt = 4;
if (atl1c_alloc_queues(adapter)) {
dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
@@ -851,24 +884,22 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter,
*/
static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter)
{
- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct atl1c_buffer *buffer_info;
struct pci_dev *pdev = adapter->pdev;
- int i, j;
+ int j;
- for (i = 0; i < adapter->num_rx_queues; i++) {
- for (j = 0; j < rfd_ring[i].count; j++) {
- buffer_info = &rfd_ring[i].buffer_info[j];
- atl1c_clean_buffer(pdev, buffer_info, 0);
- }
- /* zero out the descriptor ring */
- memset(rfd_ring[i].desc, 0, rfd_ring[i].size);
- rfd_ring[i].next_to_clean = 0;
- rfd_ring[i].next_to_use = 0;
- rrd_ring[i].next_to_use = 0;
- rrd_ring[i].next_to_clean = 0;
+ for (j = 0; j < rfd_ring->count; j++) {
+ buffer_info = &rfd_ring->buffer_info[j];
+ atl1c_clean_buffer(pdev, buffer_info, 0);
}
+ /* zero out the descriptor ring */
+ memset(rfd_ring->desc, 0, rfd_ring->size);
+ rfd_ring->next_to_clean = 0;
+ rfd_ring->next_to_use = 0;
+ rrd_ring->next_to_use = 0;
+ rrd_ring->next_to_clean = 0;
}
/*
@@ -877,8 +908,8 @@ static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter)
static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter)
{
struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct atl1c_buffer *buffer_info;
int i, j;
@@ -890,15 +921,13 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter)
ATL1C_SET_BUFFER_STATE(&buffer_info[i],
ATL1C_BUFFER_FREE);
}
- for (i = 0; i < adapter->num_rx_queues; i++) {
- rfd_ring[i].next_to_use = 0;
- rfd_ring[i].next_to_clean = 0;
- rrd_ring[i].next_to_use = 0;
- rrd_ring[i].next_to_clean = 0;
- for (j = 0; j < rfd_ring[i].count; j++) {
- buffer_info = &rfd_ring[i].buffer_info[j];
- ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE);
- }
+ rfd_ring->next_to_use = 0;
+ rfd_ring->next_to_clean = 0;
+ rrd_ring->next_to_use = 0;
+ rrd_ring->next_to_clean = 0;
+ for (j = 0; j < rfd_ring->count; j++) {
+ buffer_info = &rfd_ring->buffer_info[j];
+ ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE);
}
}
@@ -935,27 +964,23 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
- struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
- struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct atl1c_ring_header *ring_header = &adapter->ring_header;
- int num_rx_queues = adapter->num_rx_queues;
int size;
int i;
int count = 0;
int rx_desc_count = 0;
u32 offset = 0;
- rrd_ring[0].count = rfd_ring[0].count;
+ rrd_ring->count = rfd_ring->count;
for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++)
tpd_ring[i].count = tpd_ring[0].count;
- for (i = 1; i < adapter->num_rx_queues; i++)
- rfd_ring[i].count = rrd_ring[i].count = rfd_ring[0].count;
-
/* 2 tpd queue, one high priority queue,
* another normal priority queue */
size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 +
- rfd_ring->count * num_rx_queues);
+ rfd_ring->count);
tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
if (unlikely(!tpd_ring->buffer_info)) {
dev_err(&pdev->dev, "kzalloc failed, size = %d\n",
@@ -968,12 +993,11 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
count += tpd_ring[i].count;
}
- for (i = 0; i < num_rx_queues; i++) {
- rfd_ring[i].buffer_info =
- (struct atl1c_buffer *) (tpd_ring->buffer_info + count);
- count += rfd_ring[i].count;
- rx_desc_count += rfd_ring[i].count;
- }
+ rfd_ring->buffer_info =
+ (struct atl1c_buffer *) (tpd_ring->buffer_info + count);
+ count += rfd_ring->count;
+ rx_desc_count += rfd_ring->count;
+
/*
* real ring DMA buffer
* each ring/block may need up to 8 bytes for alignment, hence the
@@ -983,8 +1007,7 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 +
sizeof(struct atl1c_rx_free_desc) * rx_desc_count +
sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
- sizeof(struct atl1c_hw_stats) +
- 8 * 4 + 8 * 2 * num_rx_queues;
+ 8 * 4;
ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
&ring_header->dma);
@@ -1005,25 +1028,18 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
offset += roundup(tpd_ring[i].size, 8);
}
/* init RFD ring */
- for (i = 0; i < num_rx_queues; i++) {
- rfd_ring[i].dma = ring_header->dma + offset;
- rfd_ring[i].desc = (u8 *) ring_header->desc + offset;
- rfd_ring[i].size = sizeof(struct atl1c_rx_free_desc) *
- rfd_ring[i].count;
- offset += roundup(rfd_ring[i].size, 8);
- }
+ rfd_ring->dma = ring_header->dma + offset;
+ rfd_ring->desc = (u8 *) ring_header->desc + offset;
+ rfd_ring->size = sizeof(struct atl1c_rx_free_desc) * rfd_ring->count;
+ offset += roundup(rfd_ring->size, 8);
/* init RRD ring */
- for (i = 0; i < num_rx_queues; i++) {
- rrd_ring[i].dma = ring_header->dma + offset;
- rrd_ring[i].desc = (u8 *) ring_header->desc + offset;
- rrd_ring[i].size = sizeof(struct atl1c_recv_ret_status) *
- rrd_ring[i].count;
- offset += roundup(rrd_ring[i].size, 8);
- }
+ rrd_ring->dma = ring_header->dma + offset;
+ rrd_ring->desc = (u8 *) ring_header->desc + offset;
+ rrd_ring->size = sizeof(struct atl1c_recv_ret_status) *
+ rrd_ring->count;
+ offset += roundup(rrd_ring->size, 8);
- adapter->smb.dma = ring_header->dma + offset;
- adapter->smb.smb = (u8 *)ring_header->desc + offset;
return 0;
err_nomem:
@@ -1034,26 +1050,20 @@ err_nomem:
static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
{
struct atl1c_hw *hw = &adapter->hw;
- struct atl1c_rfd_ring *rfd_ring = (struct atl1c_rfd_ring *)
- adapter->rfd_ring;
- struct atl1c_rrd_ring *rrd_ring = (struct atl1c_rrd_ring *)
- adapter->rrd_ring;
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *)
adapter->tpd_ring;
- struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb;
- struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb;
- int i;
- u32 data;
/* TPD */
AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI,
(u32)((tpd_ring[atl1c_trans_normal].dma &
AT_DMA_HI_ADDR_MASK) >> 32));
/* just enable normal priority TX queue */
- AT_WRITE_REG(hw, REG_NTPD_HEAD_ADDR_LO,
+ AT_WRITE_REG(hw, REG_TPD_PRI0_ADDR_LO,
(u32)(tpd_ring[atl1c_trans_normal].dma &
AT_DMA_LO_ADDR_MASK));
- AT_WRITE_REG(hw, REG_HTPD_HEAD_ADDR_LO,
+ AT_WRITE_REG(hw, REG_TPD_PRI1_ADDR_LO,
(u32)(tpd_ring[atl1c_trans_high].dma &
AT_DMA_LO_ADDR_MASK));
AT_WRITE_REG(hw, REG_TPD_RING_SIZE,
@@ -1062,31 +1072,21 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
/* RFD */
AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI,
- (u32)((rfd_ring[0].dma & AT_DMA_HI_ADDR_MASK) >> 32));
- for (i = 0; i < adapter->num_rx_queues; i++)
- AT_WRITE_REG(hw, atl1c_rfd_addr_lo_regs[i],
- (u32)(rfd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
+ (u32)((rfd_ring->dma & AT_DMA_HI_ADDR_MASK) >> 32));
+ AT_WRITE_REG(hw, REG_RFD0_HEAD_ADDR_LO,
+ (u32)(rfd_ring->dma & AT_DMA_LO_ADDR_MASK));
AT_WRITE_REG(hw, REG_RFD_RING_SIZE,
- rfd_ring[0].count & RFD_RING_SIZE_MASK);
+ rfd_ring->count & RFD_RING_SIZE_MASK);
AT_WRITE_REG(hw, REG_RX_BUF_SIZE,
adapter->rx_buffer_len & RX_BUF_SIZE_MASK);
/* RRD */
- for (i = 0; i < adapter->num_rx_queues; i++)
- AT_WRITE_REG(hw, atl1c_rrd_addr_lo_regs[i],
- (u32)(rrd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
+ AT_WRITE_REG(hw, REG_RRD0_HEAD_ADDR_LO,
+ (u32)(rrd_ring->dma & AT_DMA_LO_ADDR_MASK));
AT_WRITE_REG(hw, REG_RRD_RING_SIZE,
- (rrd_ring[0].count & RRD_RING_SIZE_MASK));
+ (rrd_ring->count & RRD_RING_SIZE_MASK));
- /* CMB */
- AT_WRITE_REG(hw, REG_CMB_BASE_ADDR_LO, cmb->dma & AT_DMA_LO_ADDR_MASK);
-
- /* SMB */
- AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_HI,
- (u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32));
- AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO,
- (u32)(smb->dma & AT_DMA_LO_ADDR_MASK));
if (hw->nic_type == athr_l2c_b) {
AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L);
AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L);
@@ -1097,13 +1097,6 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0); /* TX watermark, to enter l1 state.*/
AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0); /* RXD threshold.*/
}
- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d_2) {
- /* Power Saving for L2c_B */
- AT_READ_REG(hw, REG_SERDES_LOCK, &data);
- data |= SERDES_MAC_CLK_SLOWDOWN;
- data |= SERDES_PYH_CLK_SLOWDOWN;
- AT_WRITE_REG(hw, REG_SERDES_LOCK, data);
- }
/* Load all of base address above */
AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
}
@@ -1111,32 +1104,26 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
static void atl1c_configure_tx(struct atl1c_adapter *adapter)
{
struct atl1c_hw *hw = &adapter->hw;
- u32 dev_ctrl_data;
- u32 max_pay_load;
+ int max_pay_load;
u16 tx_offload_thresh;
u32 txq_ctrl_data;
- u32 max_pay_load_data;
- tx_offload_thresh = MAX_TX_OFFLOAD_THRESH;
+ tx_offload_thresh = MAX_TSO_FRAME_SIZE;
AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH,
(tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK);
- AT_READ_REG(hw, REG_DEVICE_CTRL, &dev_ctrl_data);
- max_pay_load = (dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT) &
- DEVICE_CTRL_MAX_PAYLOAD_MASK;
- hw->dmaw_block = min_t(u32, max_pay_load, hw->dmaw_block);
- max_pay_load = (dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT) &
- DEVICE_CTRL_MAX_RREQ_SZ_MASK;
+ max_pay_load = pcie_get_readrq(adapter->pdev) >> 8;
hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block);
-
- txq_ctrl_data = (hw->tpd_burst & TXQ_NUM_TPD_BURST_MASK) <<
- TXQ_NUM_TPD_BURST_SHIFT;
- if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE)
- txq_ctrl_data |= TXQ_CTRL_ENH_MODE;
- max_pay_load_data = (atl1c_pay_load_size[hw->dmar_block] &
- TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT;
- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2)
- max_pay_load_data >>= 1;
- txq_ctrl_data |= max_pay_load_data;
+ /*
+ * if BIOS had changed the dam-read-max-length to an invalid value,
+ * restore it to default value
+ */
+ if (hw->dmar_block < DEVICE_CTRL_MAXRRS_MIN) {
+ pcie_set_readrq(adapter->pdev, 128 << DEVICE_CTRL_MAXRRS_MIN);
+ hw->dmar_block = DEVICE_CTRL_MAXRRS_MIN;
+ }
+ txq_ctrl_data =
+ hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 ?
+ L2CB_TXQ_CFGV : L1C_TXQ_CFGV;
AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data);
}
@@ -1151,34 +1138,13 @@ static void atl1c_configure_rx(struct atl1c_adapter *adapter)
if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM)
rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN;
- if (hw->rss_type == atl1c_rss_ipv4)
- rxq_ctrl_data |= RSS_HASH_IPV4;
- if (hw->rss_type == atl1c_rss_ipv4_tcp)
- rxq_ctrl_data |= RSS_HASH_IPV4_TCP;
- if (hw->rss_type == atl1c_rss_ipv6)
- rxq_ctrl_data |= RSS_HASH_IPV6;
- if (hw->rss_type == atl1c_rss_ipv6_tcp)
- rxq_ctrl_data |= RSS_HASH_IPV6_TCP;
- if (hw->rss_type != atl1c_rss_disable)
- rxq_ctrl_data |= RRS_HASH_CTRL_EN;
-
- rxq_ctrl_data |= (hw->rss_mode & RSS_MODE_MASK) <<
- RSS_MODE_SHIFT;
- rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) <<
- RSS_HASH_BITS_SHIFT;
- if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON)
- rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_1M &
- ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT;
- AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
-}
-
-static void atl1c_configure_rss(struct atl1c_adapter *adapter)
-{
- struct atl1c_hw *hw = &adapter->hw;
+ /* aspm for gigabit */
+ if (hw->nic_type != athr_l1d_2 && (hw->device_id & 1) != 0)
+ rxq_ctrl_data = FIELD_SETX(rxq_ctrl_data, ASPM_THRUPUT_LIMIT,
+ ASPM_THRUPUT_LIMIT_100M);
- AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab);
- AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu);
+ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
}
static void atl1c_configure_dma(struct atl1c_adapter *adapter)
@@ -1186,36 +1152,11 @@ static void atl1c_configure_dma(struct atl1c_adapter *adapter)
struct atl1c_hw *hw = &adapter->hw;
u32 dma_ctrl_data;
- dma_ctrl_data = DMA_CTRL_DMAR_REQ_PRI;
- if (hw->ctrl_flags & ATL1C_CMB_ENABLE)
- dma_ctrl_data |= DMA_CTRL_CMB_EN;
- if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
- dma_ctrl_data |= DMA_CTRL_SMB_EN;
- else
- dma_ctrl_data |= MAC_CTRL_SMB_DIS;
-
- switch (hw->dma_order) {
- case atl1c_dma_ord_in:
- dma_ctrl_data |= DMA_CTRL_DMAR_IN_ORDER;
- break;
- case atl1c_dma_ord_enh:
- dma_ctrl_data |= DMA_CTRL_DMAR_ENH_ORDER;
- break;
- case atl1c_dma_ord_out:
- dma_ctrl_data |= DMA_CTRL_DMAR_OUT_ORDER;
- break;
- default:
- break;
- }
-
- dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
- << DMA_CTRL_DMAR_BURST_LEN_SHIFT;
- dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
- << DMA_CTRL_DMAW_BURST_LEN_SHIFT;
- dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK)
- << DMA_CTRL_DMAR_DLY_CNT_SHIFT;
- dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK)
- << DMA_CTRL_DMAW_DLY_CNT_SHIFT;
+ dma_ctrl_data = FIELDX(DMA_CTRL_RORDER_MODE, DMA_CTRL_RORDER_MODE_OUT) |
+ DMA_CTRL_RREQ_PRI_DATA |
+ FIELDX(DMA_CTRL_RREQ_BLEN, hw->dmar_block) |
+ FIELDX(DMA_CTRL_WDLY_CNT, DMA_CTRL_WDLY_CNT_DEF) |
+ FIELDX(DMA_CTRL_RDLY_CNT, DMA_CTRL_RDLY_CNT_DEF);
AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data);
}
@@ -1230,52 +1171,53 @@ static int atl1c_stop_mac(struct atl1c_hw *hw)
u32 data;
AT_READ_REG(hw, REG_RXQ_CTRL, &data);
- data &= ~(RXQ1_CTRL_EN | RXQ2_CTRL_EN |
- RXQ3_CTRL_EN | RXQ_CTRL_EN);
+ data &= ~RXQ_CTRL_EN;
AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
AT_READ_REG(hw, REG_TXQ_CTRL, &data);
data &= ~TXQ_CTRL_EN;
- AT_WRITE_REG(hw, REG_TWSI_CTRL, data);
+ AT_WRITE_REG(hw, REG_TXQ_CTRL, data);
- atl1c_wait_until_idle(hw);
+ atl1c_wait_until_idle(hw, IDLE_STATUS_RXQ_BUSY | IDLE_STATUS_TXQ_BUSY);
AT_READ_REG(hw, REG_MAC_CTRL, &data);
data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN);
AT_WRITE_REG(hw, REG_MAC_CTRL, data);
- return (int)atl1c_wait_until_idle(hw);
-}
-
-static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw)
-{
- u32 data;
-
- AT_READ_REG(hw, REG_RXQ_CTRL, &data);
- switch (hw->adapter->num_rx_queues) {
- case 4:
- data |= (RXQ3_CTRL_EN | RXQ2_CTRL_EN | RXQ1_CTRL_EN);
- break;
- case 3:
- data |= (RXQ2_CTRL_EN | RXQ1_CTRL_EN);
- break;
- case 2:
- data |= RXQ1_CTRL_EN;
- break;
- default:
- break;
- }
- data |= RXQ_CTRL_EN;
- AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
+ return (int)atl1c_wait_until_idle(hw,
+ IDLE_STATUS_TXMAC_BUSY | IDLE_STATUS_RXMAC_BUSY);
}
-static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw)
+static void atl1c_start_mac(struct atl1c_adapter *adapter)
{
- u32 data;
+ struct atl1c_hw *hw = &adapter->hw;
+ u32 mac, txq, rxq;
+
+ hw->mac_duplex = adapter->link_duplex == FULL_DUPLEX ? true : false;
+ hw->mac_speed = adapter->link_speed == SPEED_1000 ?
+ atl1c_mac_speed_1000 : atl1c_mac_speed_10_100;
+
+ AT_READ_REG(hw, REG_TXQ_CTRL, &txq);
+ AT_READ_REG(hw, REG_RXQ_CTRL, &rxq);
+ AT_READ_REG(hw, REG_MAC_CTRL, &mac);
+
+ txq |= TXQ_CTRL_EN;
+ rxq |= RXQ_CTRL_EN;
+ mac |= MAC_CTRL_TX_EN | MAC_CTRL_TX_FLOW |
+ MAC_CTRL_RX_EN | MAC_CTRL_RX_FLOW |
+ MAC_CTRL_ADD_CRC | MAC_CTRL_PAD |
+ MAC_CTRL_BC_EN | MAC_CTRL_SINGLE_PAUSE_EN |
+ MAC_CTRL_HASH_ALG_CRC32;
+ if (hw->mac_duplex)
+ mac |= MAC_CTRL_DUPLX;
+ else
+ mac &= ~MAC_CTRL_DUPLX;
+ mac = FIELD_SETX(mac, MAC_CTRL_SPEED, hw->mac_speed);
+ mac = FIELD_SETX(mac, MAC_CTRL_PRMLEN, hw->preamble_len);
- AT_READ_REG(hw, REG_TXQ_CTRL, &data);
- data |= TXQ_CTRL_EN;
- AT_WRITE_REG(hw, REG_TXQ_CTRL, data);
+ AT_WRITE_REG(hw, REG_TXQ_CTRL, txq);
+ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq);
+ AT_WRITE_REG(hw, REG_MAC_CTRL, mac);
}
/*
@@ -1287,10 +1229,7 @@ static int atl1c_reset_mac(struct atl1c_hw *hw)
{
struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
struct pci_dev *pdev = adapter->pdev;
- u32 master_ctrl_data = 0;
-
- AT_WRITE_REG(hw, REG_IMR, 0);
- AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT);
+ u32 ctrl_data = 0;
atl1c_stop_mac(hw);
/*
@@ -1299,194 +1238,148 @@ static int atl1c_reset_mac(struct atl1c_hw *hw)
* the current PCI configuration. The global reset bit is self-
* clearing, and should clear within a microsecond.
*/
- AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
- master_ctrl_data |= MASTER_CTRL_OOB_DIS_OFF;
- AT_WRITE_REGW(hw, REG_MASTER_CTRL, ((master_ctrl_data | MASTER_CTRL_SOFT_RST)
- & 0xFFFF));
+ AT_READ_REG(hw, REG_MASTER_CTRL, &ctrl_data);
+ ctrl_data |= MASTER_CTRL_OOB_DIS;
+ AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data | MASTER_CTRL_SOFT_RST);
AT_WRITE_FLUSH(hw);
msleep(10);
/* Wait at least 10ms for All module to be Idle */
- if (atl1c_wait_until_idle(hw)) {
+ if (atl1c_wait_until_idle(hw, IDLE_STATUS_MASK)) {
dev_err(&pdev->dev,
"MAC state machine can't be idle since"
" disabled for 10ms second\n");
return -1;
}
+ AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data);
+
+ /* driver control speed/duplex */
+ AT_READ_REG(hw, REG_MAC_CTRL, &ctrl_data);
+ AT_WRITE_REG(hw, REG_MAC_CTRL, ctrl_data | MAC_CTRL_SPEED_MODE_SW);
+
+ /* clk switch setting */
+ AT_READ_REG(hw, REG_SERDES, &ctrl_data);
+ switch (hw->nic_type) {
+ case athr_l2c_b:
+ ctrl_data &= ~(SERDES_PHY_CLK_SLOWDOWN |
+ SERDES_MAC_CLK_SLOWDOWN);
+ AT_WRITE_REG(hw, REG_SERDES, ctrl_data);
+ break;
+ case athr_l2c_b2:
+ case athr_l1d_2:
+ ctrl_data |= SERDES_PHY_CLK_SLOWDOWN | SERDES_MAC_CLK_SLOWDOWN;
+ AT_WRITE_REG(hw, REG_SERDES, ctrl_data);
+ break;
+ default:
+ break;
+ }
+
return 0;
}
static void atl1c_disable_l0s_l1(struct atl1c_hw *hw)
{
- u32 pm_ctrl_data;
+ u16 ctrl_flags = hw->ctrl_flags;
- AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
- PM_CTRL_L1_ENTRY_TIMER_SHIFT);
- pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
- pm_ctrl_data &= ~PM_CTRL_MAC_ASPM_CHK;
- pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
-
- pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN;
- pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN;
- pm_ctrl_data |= PM_CTRL_SERDES_L1_EN;
- AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
+ hw->ctrl_flags &= ~(ATL1C_ASPM_L0S_SUPPORT | ATL1C_ASPM_L1_SUPPORT);
+ atl1c_set_aspm(hw, SPEED_0);
+ hw->ctrl_flags = ctrl_flags;
}
/*
* Set ASPM state.
* Enable/disable L0s/L1 depend on link state.
*/
-static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
+static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed)
{
u32 pm_ctrl_data;
- u32 link_ctrl_data;
- u32 link_l1_timer = 0xF;
+ u32 link_l1_timer;
AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
- AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
+ pm_ctrl_data &= ~(PM_CTRL_ASPM_L1_EN |
+ PM_CTRL_ASPM_L0S_EN |
+ PM_CTRL_MAC_ASPM_CHK);
+ /* L1 timer */
+ if (hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
+ pm_ctrl_data &= ~PMCTRL_TXL1_AFTER_L0S;
+ link_l1_timer =
+ link_speed == SPEED_1000 || link_speed == SPEED_100 ?
+ L1D_PMCTRL_L1_ENTRY_TM_16US : 1;
+ pm_ctrl_data = FIELD_SETX(pm_ctrl_data,
+ L1D_PMCTRL_L1_ENTRY_TM, link_l1_timer);
+ } else {
+ link_l1_timer = hw->nic_type == athr_l2c_b ?
+ L2CB1_PM_CTRL_L1_ENTRY_TM : L1C_PM_CTRL_L1_ENTRY_TM;
+ if (link_speed != SPEED_1000 && link_speed != SPEED_100)
+ link_l1_timer = 1;
+ pm_ctrl_data = FIELD_SETX(pm_ctrl_data,
+ PM_CTRL_L1_ENTRY_TIMER, link_l1_timer);
+ }
- pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
- PM_CTRL_L1_ENTRY_TIMER_SHIFT);
- pm_ctrl_data &= ~(PM_CTRL_LCKDET_TIMER_MASK <<
- PM_CTRL_LCKDET_TIMER_SHIFT);
- pm_ctrl_data |= AT_LCKDET_TIMER << PM_CTRL_LCKDET_TIMER_SHIFT;
+ /* L0S/L1 enable */
+ if ((hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) && link_speed != SPEED_0)
+ pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN | PM_CTRL_MAC_ASPM_CHK;
+ if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT)
+ pm_ctrl_data |= PM_CTRL_ASPM_L1_EN | PM_CTRL_MAC_ASPM_CHK;
+ /* l2cb & l1d & l2cb2 & l1d2 */
if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d ||
- hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
- link_ctrl_data &= ~LINK_CTRL_EXT_SYNC;
- if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) {
- if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10)
- link_ctrl_data |= LINK_CTRL_EXT_SYNC;
- }
-
- AT_WRITE_REG(hw, REG_LINK_CTRL, link_ctrl_data);
-
- pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER;
- pm_ctrl_data &= ~(PM_CTRL_PM_REQ_TIMER_MASK <<
- PM_CTRL_PM_REQ_TIMER_SHIFT);
- pm_ctrl_data |= AT_ASPM_L1_TIMER <<
- PM_CTRL_PM_REQ_TIMER_SHIFT;
- pm_ctrl_data &= ~PM_CTRL_SA_DLY_EN;
- pm_ctrl_data &= ~PM_CTRL_HOTRST;
- pm_ctrl_data |= 1 << PM_CTRL_L1_ENTRY_TIMER_SHIFT;
- pm_ctrl_data |= PM_CTRL_SERDES_PD_EX_L1;
- }
- pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK;
- if (linkup) {
- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
- if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT)
- pm_ctrl_data |= PM_CTRL_ASPM_L1_EN;
- if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT)
- pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN;
-
- if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d ||
- hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
- if (hw->nic_type == athr_l2c_b)
- if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE))
- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
- pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN;
- pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
- pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN;
- pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
- if (hw->adapter->link_speed == SPEED_100 ||
- hw->adapter->link_speed == SPEED_1000) {
- pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
- PM_CTRL_L1_ENTRY_TIMER_SHIFT);
- if (hw->nic_type == athr_l2c_b)
- link_l1_timer = 7;
- else if (hw->nic_type == athr_l2c_b2 ||
- hw->nic_type == athr_l1d_2)
- link_l1_timer = 4;
- pm_ctrl_data |= link_l1_timer <<
- PM_CTRL_L1_ENTRY_TIMER_SHIFT;
- }
- } else {
- pm_ctrl_data |= PM_CTRL_SERDES_L1_EN;
- pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN;
- pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN;
- pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
+ hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
+ pm_ctrl_data = FIELD_SETX(pm_ctrl_data,
+ PM_CTRL_PM_REQ_TIMER, PM_CTRL_PM_REQ_TO_DEF);
+ pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER |
+ PM_CTRL_SERDES_PD_EX_L1 |
+ PM_CTRL_CLK_SWH_L1;
+ pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN |
+ PM_CTRL_SERDES_PLL_L1_EN |
+ PM_CTRL_SERDES_BUFS_RX_L1_EN |
+ PM_CTRL_SA_DLY_EN |
+ PM_CTRL_HOTRST);
+ /* disable l0s if link down or l2cb */
+ if (link_speed == SPEED_0 || hw->nic_type == athr_l2c_b)
pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
-
+ } else { /* l1c */
+ pm_ctrl_data =
+ FIELD_SETX(pm_ctrl_data, PM_CTRL_L1_ENTRY_TIMER, 0);
+ if (link_speed != SPEED_0) {
+ pm_ctrl_data |= PM_CTRL_SERDES_L1_EN |
+ PM_CTRL_SERDES_PLL_L1_EN |
+ PM_CTRL_SERDES_BUFS_RX_L1_EN;
+ pm_ctrl_data &= ~(PM_CTRL_SERDES_PD_EX_L1 |
+ PM_CTRL_CLK_SWH_L1 |
+ PM_CTRL_ASPM_L0S_EN |
+ PM_CTRL_ASPM_L1_EN);
+ } else { /* link down */
+ pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
+ pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN |
+ PM_CTRL_SERDES_PLL_L1_EN |
+ PM_CTRL_SERDES_BUFS_RX_L1_EN |
+ PM_CTRL_ASPM_L0S_EN);
}
- } else {
- pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN;
- pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
- pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
- pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
-
- if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT)
- pm_ctrl_data |= PM_CTRL_ASPM_L1_EN;
- else
- pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
}
AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
return;
}
-static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
-{
- struct atl1c_hw *hw = &adapter->hw;
- struct net_device *netdev = adapter->netdev;
- u32 mac_ctrl_data;
-
- mac_ctrl_data = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
- mac_ctrl_data |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
-
- if (adapter->link_duplex == FULL_DUPLEX) {
- hw->mac_duplex = true;
- mac_ctrl_data |= MAC_CTRL_DUPLX;
- }
-
- if (adapter->link_speed == SPEED_1000)
- hw->mac_speed = atl1c_mac_speed_1000;
- else
- hw->mac_speed = atl1c_mac_speed_10_100;
-
- mac_ctrl_data |= (hw->mac_speed & MAC_CTRL_SPEED_MASK) <<
- MAC_CTRL_SPEED_SHIFT;
-
- mac_ctrl_data |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
- mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) <<
- MAC_CTRL_PRMLEN_SHIFT);
-
- __atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
-
- mac_ctrl_data |= MAC_CTRL_BC_EN;
- if (netdev->flags & IFF_PROMISC)
- mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
- if (netdev->flags & IFF_ALLMULTI)
- mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
-
- mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN;
- if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2 ||
- hw->nic_type == athr_l1d_2) {
- mac_ctrl_data |= MAC_CTRL_SPEED_MODE_SW;
- mac_ctrl_data |= MAC_CTRL_HASH_ALG_CRC32;
- }
- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-}
-
/*
* atl1c_configure - Configure Transmit&Receive Unit after Reset
* @adapter: board private structure
*
* Configure the Tx /Rx unit of the MAC after a reset.
*/
-static int atl1c_configure(struct atl1c_adapter *adapter)
+static int atl1c_configure_mac(struct atl1c_adapter *adapter)
{
struct atl1c_hw *hw = &adapter->hw;
u32 master_ctrl_data = 0;
u32 intr_modrt_data;
u32 data;
+ AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
+ master_ctrl_data &= ~(MASTER_CTRL_TX_ITIMER_EN |
+ MASTER_CTRL_RX_ITIMER_EN |
+ MASTER_CTRL_INT_RDCLR);
/* clear interrupt status */
AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF);
/* Clear any WOL status */
@@ -1525,30 +1418,39 @@ static int atl1c_configure(struct atl1c_adapter *adapter)
master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN;
AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
- if (hw->ctrl_flags & ATL1C_CMB_ENABLE) {
- AT_WRITE_REG(hw, REG_CMB_TPD_THRESH,
- hw->cmb_tpd & CMB_TPD_THRESH_MASK);
- AT_WRITE_REG(hw, REG_CMB_TX_TIMER,
- hw->cmb_tx_timer & CMB_TX_TIMER_MASK);
- }
+ AT_WRITE_REG(hw, REG_SMB_STAT_TIMER,
+ hw->smb_timer & SMB_STAT_TIMER_MASK);
- if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
- AT_WRITE_REG(hw, REG_SMB_STAT_TIMER,
- hw->smb_timer & SMB_STAT_TIMER_MASK);
/* set MTU */
AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN +
VLAN_HLEN + ETH_FCS_LEN);
- /* HDS, disable */
- AT_WRITE_REG(hw, REG_HDS_CTRL, 0);
atl1c_configure_tx(adapter);
atl1c_configure_rx(adapter);
- atl1c_configure_rss(adapter);
atl1c_configure_dma(adapter);
return 0;
}
+static int atl1c_configure(struct atl1c_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int num;
+
+ atl1c_init_ring_ptrs(adapter);
+ atl1c_set_multi(netdev);
+ atl1c_restore_vlan(adapter);
+
+ num = atl1c_alloc_rx_buffer(adapter);
+ if (unlikely(num == 0))
+ return -ENOMEM;
+
+ if (atl1c_configure_mac(adapter))
+ return -EIO;
+
+ return 0;
+}
+
static void atl1c_update_hw_stats(struct atl1c_adapter *adapter)
{
u16 hw_reg_addr = 0;
@@ -1635,16 +1537,11 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter,
struct pci_dev *pdev = adapter->pdev;
u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
u16 hw_next_to_clean;
- u16 shift;
- u32 data;
+ u16 reg;
- if (type == atl1c_trans_high)
- shift = MB_HTPD_CONS_IDX_SHIFT;
- else
- shift = MB_NTPD_CONS_IDX_SHIFT;
+ reg = type == atl1c_trans_high ? REG_TPD_PRI1_CIDX : REG_TPD_PRI0_CIDX;
- AT_READ_REG(&adapter->hw, REG_MB_PRIO_CONS_IDX, &data);
- hw_next_to_clean = (data >> shift) & MB_PRIO_PROD_IDX_MASK;
+ AT_READ_REGW(&adapter->hw, reg, &hw_next_to_clean);
while (next_to_clean != hw_next_to_clean) {
buffer_info = &tpd_ring->buffer_info[next_to_clean];
@@ -1746,9 +1643,9 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter,
skb_checksum_none_assert(skb);
}
-static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid)
+static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter)
{
- struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[ringid];
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
struct pci_dev *pdev = adapter->pdev;
struct atl1c_buffer *buffer_info, *next_info;
struct sk_buff *skb;
@@ -1800,7 +1697,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid
/* TODO: update mailbox here */
wmb();
rfd_ring->next_to_use = rfd_next_to_use;
- AT_WRITE_REG(&adapter->hw, atl1c_rfd_prod_idx_regs[ringid],
+ AT_WRITE_REG(&adapter->hw, REG_MB_RFD0_PROD_IDX,
rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK);
}
@@ -1839,7 +1736,7 @@ static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring,
rfd_ring->next_to_clean = rfd_index;
}
-static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter,
int *work_done, int work_to_do)
{
u16 rfd_num, rfd_index;
@@ -1847,8 +1744,8 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
u16 length;
struct pci_dev *pdev = adapter->pdev;
struct net_device *netdev = adapter->netdev;
- struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[que];
- struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[que];
+ struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct sk_buff *skb;
struct atl1c_recv_ret_status *rrs;
struct atl1c_buffer *buffer_info;
@@ -1914,7 +1811,7 @@ rrs_checked:
count++;
}
if (count)
- atl1c_alloc_rx_buffer(adapter, que);
+ atl1c_alloc_rx_buffer(adapter);
}
/*
@@ -1931,7 +1828,7 @@ static int atl1c_clean(struct napi_struct *napi, int budget)
if (!netif_carrier_ok(adapter->netdev))
goto quit_polling;
/* just enable one RXQ */
- atl1c_clean_rx_irq(adapter, 0, &work_done, budget);
+ atl1c_clean_rx_irq(adapter, &work_done, budget);
if (work_done < budget) {
quit_polling:
@@ -2206,23 +2103,10 @@ static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb,
struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type)
{
struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
- u32 prod_data;
+ u16 reg;
- AT_READ_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, &prod_data);
- switch (type) {
- case atl1c_trans_high:
- prod_data &= 0xFFFF0000;
- prod_data |= tpd_ring->next_to_use & 0xFFFF;
- break;
- case atl1c_trans_normal:
- prod_data &= 0x0000FFFF;
- prod_data |= (tpd_ring->next_to_use & 0xFFFF) << 16;
- break;
- default:
- break;
- }
- wmb();
- AT_WRITE_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, prod_data);
+ reg = type == atl1c_trans_high ? REG_TPD_PRI1_PIDX : REG_TPD_PRI0_PIDX;
+ AT_WRITE_REGW(&adapter->hw, reg, tpd_ring->next_to_use);
}
static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
@@ -2307,8 +2191,7 @@ static int atl1c_request_irq(struct atl1c_adapter *adapter)
"Unable to allocate MSI interrupt Error: %d\n",
err);
adapter->have_msi = false;
- } else
- netdev->irq = pdev->irq;
+ }
if (!adapter->have_msi)
flags |= IRQF_SHARED;
@@ -2328,44 +2211,38 @@ static int atl1c_request_irq(struct atl1c_adapter *adapter)
return err;
}
+
+static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter)
+{
+ /* release tx-pending skbs and reset tx/rx ring index */
+ atl1c_clean_tx_ring(adapter, atl1c_trans_normal);
+ atl1c_clean_tx_ring(adapter, atl1c_trans_high);
+ atl1c_clean_rx_ring(adapter);
+}
+
static int atl1c_up(struct atl1c_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- int num;
int err;
- int i;
netif_carrier_off(netdev);
- atl1c_init_ring_ptrs(adapter);
- atl1c_set_multi(netdev);
- atl1c_restore_vlan(adapter);
- for (i = 0; i < adapter->num_rx_queues; i++) {
- num = atl1c_alloc_rx_buffer(adapter, i);
- if (unlikely(num == 0)) {
- err = -ENOMEM;
- goto err_alloc_rx;
- }
- }
-
- if (atl1c_configure(adapter)) {
- err = -EIO;
+ err = atl1c_configure(adapter);
+ if (unlikely(err))
goto err_up;
- }
err = atl1c_request_irq(adapter);
if (unlikely(err))
goto err_up;
+ atl1c_check_link_status(adapter);
clear_bit(__AT_DOWN, &adapter->flags);
napi_enable(&adapter->napi);
atl1c_irq_enable(adapter);
- atl1c_check_link_status(adapter);
netif_start_queue(netdev);
return err;
err_up:
-err_alloc_rx:
atl1c_clean_rx_ring(adapter);
return err;
}
@@ -2383,15 +2260,15 @@ static void atl1c_down(struct atl1c_adapter *adapter)
napi_disable(&adapter->napi);
atl1c_irq_disable(adapter);
atl1c_free_irq(adapter);
+ /* disable ASPM if device inactive */
+ atl1c_disable_l0s_l1(&adapter->hw);
/* reset MAC to disable all RX/TX */
atl1c_reset_mac(&adapter->hw);
msleep(1);
adapter->link_speed = SPEED_0;
adapter->link_duplex = -1;
- atl1c_clean_tx_ring(adapter, atl1c_trans_normal);
- atl1c_clean_tx_ring(adapter, atl1c_trans_high);
- atl1c_clean_rx_ring(adapter);
+ atl1c_reset_dma_ring(adapter);
}
/*
@@ -2424,13 +2301,6 @@ static int atl1c_open(struct net_device *netdev)
if (unlikely(err))
goto err_up;
- if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
- u32 phy_data;
-
- AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data);
- phy_data |= MDIO_AP_EN;
- AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data);
- }
return 0;
err_up:
@@ -2456,6 +2326,8 @@ static int atl1c_close(struct net_device *netdev)
struct atl1c_adapter *adapter = netdev_priv(netdev);
WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+ set_bit(__AT_DOWN, &adapter->flags);
+ cancel_work_sync(&adapter->common_task);
atl1c_down(adapter);
atl1c_free_ring_resources(adapter);
return 0;
@@ -2467,10 +2339,6 @@ static int atl1c_suspend(struct device *dev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct atl1c_adapter *adapter = netdev_priv(netdev);
struct atl1c_hw *hw = &adapter->hw;
- u32 mac_ctrl_data = 0;
- u32 master_ctrl_data = 0;
- u32 wol_ctrl_data = 0;
- u16 mii_intr_status_data = 0;
u32 wufc = adapter->wol;
atl1c_disable_l0s_l1(hw);
@@ -2481,75 +2349,10 @@ static int atl1c_suspend(struct device *dev)
netif_device_detach(netdev);
if (wufc)
- if (atl1c_phy_power_saving(hw) != 0)
+ if (atl1c_phy_to_ps_link(hw) != 0)
dev_dbg(&pdev->dev, "phy power saving failed");
- AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
- AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
-
- master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
- mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT);
- mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
- MAC_CTRL_PRMLEN_MASK) <<
- MAC_CTRL_PRMLEN_SHIFT);
- mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT);
- mac_ctrl_data &= ~MAC_CTRL_DUPLX;
-
- if (wufc) {
- mac_ctrl_data |= MAC_CTRL_RX_EN;
- if (adapter->link_speed == SPEED_1000 ||
- adapter->link_speed == SPEED_0) {
- mac_ctrl_data |= atl1c_mac_speed_1000 <<
- MAC_CTRL_SPEED_SHIFT;
- mac_ctrl_data |= MAC_CTRL_DUPLX;
- } else
- mac_ctrl_data |= atl1c_mac_speed_10_100 <<
- MAC_CTRL_SPEED_SHIFT;
-
- if (adapter->link_duplex == DUPLEX_FULL)
- mac_ctrl_data |= MAC_CTRL_DUPLX;
-
- /* turn on magic packet wol */
- if (wufc & AT_WUFC_MAG)
- wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
-
- if (wufc & AT_WUFC_LNKC) {
- wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
- /* only link up can wake up */
- if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
- dev_dbg(&pdev->dev, "%s: read write phy "
- "register failed.\n",
- atl1c_driver_name);
- }
- }
- /* clear phy interrupt */
- atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data);
- /* Config MAC Ctrl register */
- __atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
-
- /* magic packet maybe Broadcast&multicast&Unicast frame */
- if (wufc & AT_WUFC_MAG)
- mac_ctrl_data |= MAC_CTRL_BC_EN;
-
- dev_dbg(&pdev->dev,
- "%s: suspend MAC=0x%x\n",
- atl1c_driver_name, mac_ctrl_data);
- AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
- AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
-
- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
- GPHY_CTRL_EXT_RESET);
- } else {
- AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING);
- master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS;
- mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
- mac_ctrl_data |= MAC_CTRL_DUPLX;
- AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
- AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
- AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
- hw->phy_configured = false; /* re-init PHY when resume */
- }
+ atl1c_power_saving(hw, wufc);
return 0;
}
@@ -2562,8 +2365,7 @@ static int atl1c_resume(struct device *dev)
struct atl1c_adapter *adapter = netdev_priv(netdev);
AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
- atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
- ATL1C_PCIE_PHY_RESET);
+ atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE);
atl1c_phy_reset(&adapter->hw);
atl1c_reset_mac(&adapter->hw);
@@ -2616,7 +2418,6 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
SET_NETDEV_DEV(netdev, &pdev->dev);
pci_set_drvdata(pdev, netdev);
- netdev->irq = pdev->irq;
netdev->netdev_ops = &atl1c_netdev_ops;
netdev->watchdog_timeo = AT_TX_WATCHDOG;
atl1c_set_ethtool_ops(netdev);
@@ -2706,14 +2507,13 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
dev_err(&pdev->dev, "cannot map device registers\n");
goto err_ioremap;
}
- netdev->base_addr = (unsigned long)adapter->hw.hw_addr;
/* init mii data */
adapter->mii.dev = netdev;
adapter->mii.mdio_read = atl1c_mdio_read;
adapter->mii.mdio_write = atl1c_mdio_write;
adapter->mii.phy_id_mask = 0x1f;
- adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
+ adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK;
netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64);
setup_timer(&adapter->phy_config_timer, atl1c_phy_config,
(unsigned long)adapter);
@@ -2723,8 +2523,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
dev_err(&pdev->dev, "net device private data init failed\n");
goto err_sw_init;
}
- atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
- ATL1C_PCIE_PHY_RESET);
+ atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE);
/* Init GPHY as early as possible due to power saving issue */
atl1c_phy_reset(&adapter->hw);
@@ -2752,7 +2551,7 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
dev_dbg(&pdev->dev, "mac address : %pM\n",
adapter->hw.mac_addr);
- atl1c_hw_set_mac_addr(&adapter->hw);
+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr);
INIT_WORK(&adapter->common_task, atl1c_common_task);
adapter->work_event = 0;
err = register_netdev(netdev);
@@ -2796,6 +2595,8 @@ static void __devexit atl1c_remove(struct pci_dev *pdev)
struct atl1c_adapter *adapter = netdev_priv(netdev);
unregister_netdev(netdev);
+ /* restore permanent address */
+ atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.perm_mac_addr);
atl1c_phy_disable(&adapter->hw);
iounmap(adapter->hw.hw_addr);
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 93ff2b231284..1220e511ced6 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -1883,27 +1883,24 @@ static int atl1e_request_irq(struct atl1e_adapter *adapter)
int err = 0;
adapter->have_msi = true;
- err = pci_enable_msi(adapter->pdev);
+ err = pci_enable_msi(pdev);
if (err) {
- netdev_dbg(adapter->netdev,
+ netdev_dbg(netdev,
"Unable to allocate MSI interrupt Error: %d\n", err);
adapter->have_msi = false;
- } else
- netdev->irq = pdev->irq;
-
+ }
if (!adapter->have_msi)
flags |= IRQF_SHARED;
- err = request_irq(adapter->pdev->irq, atl1e_intr, flags,
- netdev->name, netdev);
+ err = request_irq(pdev->irq, atl1e_intr, flags, netdev->name, netdev);
if (err) {
netdev_dbg(adapter->netdev,
"Unable to allocate interrupt Error: %d\n", err);
if (adapter->have_msi)
- pci_disable_msi(adapter->pdev);
+ pci_disable_msi(pdev);
return err;
}
- netdev_dbg(adapter->netdev, "atl1e_request_irq OK\n");
+ netdev_dbg(netdev, "atl1e_request_irq OK\n");
return err;
}
@@ -2233,7 +2230,6 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
SET_NETDEV_DEV(netdev, &pdev->dev);
pci_set_drvdata(pdev, netdev);
- netdev->irq = pdev->irq;
netdev->netdev_ops = &atl1e_netdev_ops;
netdev->watchdog_timeo = AT_TX_WATCHDOG;
@@ -2319,7 +2315,6 @@ static int __devinit atl1e_probe(struct pci_dev *pdev,
netdev_err(netdev, "cannot map device registers\n");
goto err_ioremap;
}
- netdev->base_addr = (unsigned long)adapter->hw.hw_addr;
/* init mii data */
adapter->mii.dev = netdev;
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index c926857e8205..5d10884e5080 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -266,7 +266,7 @@ static s32 atl1_reset_hw(struct atl1_hw *hw)
* interrupts & Clear any pending interrupt events
*/
/*
- * iowrite32(0, hw->hw_addr + REG_IMR);
+ * atlx_irq_disable(adapter);
* iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
*/
@@ -1917,7 +1917,7 @@ next:
return num_alloc;
}
-static void atl1_intr_rx(struct atl1_adapter *adapter)
+static int atl1_intr_rx(struct atl1_adapter *adapter, int budget)
{
int i, count;
u16 length;
@@ -1933,7 +1933,7 @@ static void atl1_intr_rx(struct atl1_adapter *adapter)
rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
- while (1) {
+ while (count < budget) {
rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
i = 1;
if (likely(rrd->xsz.valid)) { /* packet valid */
@@ -2032,7 +2032,7 @@ rrd_ok:
__vlan_hwaccel_put_tag(skb, vlan_tag);
}
- netif_rx(skb);
+ netif_receive_skb(skb);
/* let protocol layer free skb */
buffer_info->skb = NULL;
@@ -2065,14 +2065,17 @@ rrd_ok:
iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
spin_unlock(&adapter->mb_lock);
}
+
+ return count;
}
-static void atl1_intr_tx(struct atl1_adapter *adapter)
+static int atl1_intr_tx(struct atl1_adapter *adapter)
{
struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
struct atl1_buffer *buffer_info;
u16 sw_tpd_next_to_clean;
u16 cmb_tpd_next_to_clean;
+ int count = 0;
sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
@@ -2092,12 +2095,16 @@ static void atl1_intr_tx(struct atl1_adapter *adapter)
if (++sw_tpd_next_to_clean == tpd_ring->count)
sw_tpd_next_to_clean = 0;
+
+ count++;
}
atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
if (netif_queue_stopped(adapter->netdev) &&
netif_carrier_ok(adapter->netdev))
netif_wake_queue(adapter->netdev);
+
+ return count;
}
static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
@@ -2439,6 +2446,49 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+static int atl1_rings_clean(struct napi_struct *napi, int budget)
+{
+ struct atl1_adapter *adapter = container_of(napi, struct atl1_adapter, napi);
+ int work_done = atl1_intr_rx(adapter, budget);
+
+ if (atl1_intr_tx(adapter))
+ work_done = budget;
+
+ /* Let's come again to process some more packets */
+ if (work_done >= budget)
+ return work_done;
+
+ napi_complete(napi);
+ /* re-enable Interrupt */
+ if (likely(adapter->int_enabled))
+ atlx_imr_set(adapter, IMR_NORMAL_MASK);
+ return work_done;
+}
+
+static inline int atl1_sched_rings_clean(struct atl1_adapter* adapter)
+{
+ if (!napi_schedule_prep(&adapter->napi))
+ /* It is possible in case even the RX/TX ints are disabled via IMR
+ * register the ISR bits are set anyway (but do not produce IRQ).
+ * To handle such situation the napi functions used to check is
+ * something scheduled or not.
+ */
+ return 0;
+
+ __napi_schedule(&adapter->napi);
+
+ /*
+ * Disable RX/TX ints via IMR register if it is
+ * allowed. NAPI handler must reenable them in same
+ * way.
+ */
+ if (!adapter->int_enabled)
+ return 1;
+
+ atlx_imr_set(adapter, IMR_NORXTX_MASK);
+ return 1;
+}
+
/*
* atl1_intr - Interrupt Handler
* @irq: interrupt number
@@ -2449,78 +2499,74 @@ static irqreturn_t atl1_intr(int irq, void *data)
{
struct atl1_adapter *adapter = netdev_priv(data);
u32 status;
- int max_ints = 10;
status = adapter->cmb.cmb->int_stats;
if (!status)
return IRQ_NONE;
- do {
- /* clear CMB interrupt status at once */
- adapter->cmb.cmb->int_stats = 0;
-
- if (status & ISR_GPHY) /* clear phy status */
- atlx_clear_phy_int(adapter);
+ /* clear CMB interrupt status at once,
+ * but leave rx/tx interrupt status in case it should be dropped
+ * only if rx/tx processing queued. In other case interrupt
+ * can be lost.
+ */
+ adapter->cmb.cmb->int_stats = status & (ISR_CMB_TX | ISR_CMB_RX);
- /* clear ISR status, and Enable CMB DMA/Disable Interrupt */
- iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
+ if (status & ISR_GPHY) /* clear phy status */
+ atlx_clear_phy_int(adapter);
- /* check if SMB intr */
- if (status & ISR_SMB)
- atl1_inc_smb(adapter);
+ /* clear ISR status, and Enable CMB DMA/Disable Interrupt */
+ iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
- /* check if PCIE PHY Link down */
- if (status & ISR_PHY_LINKDOWN) {
- if (netif_msg_intr(adapter))
- dev_printk(KERN_DEBUG, &adapter->pdev->dev,
- "pcie phy link down %x\n", status);
- if (netif_running(adapter->netdev)) { /* reset MAC */
- iowrite32(0, adapter->hw.hw_addr + REG_IMR);
- schedule_work(&adapter->reset_dev_task);
- return IRQ_HANDLED;
- }
- }
+ /* check if SMB intr */
+ if (status & ISR_SMB)
+ atl1_inc_smb(adapter);
- /* check if DMA read/write error ? */
- if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
- if (netif_msg_intr(adapter))
- dev_printk(KERN_DEBUG, &adapter->pdev->dev,
- "pcie DMA r/w error (status = 0x%x)\n",
- status);
- iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+ /* check if PCIE PHY Link down */
+ if (status & ISR_PHY_LINKDOWN) {
+ if (netif_msg_intr(adapter))
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "pcie phy link down %x\n", status);
+ if (netif_running(adapter->netdev)) { /* reset MAC */
+ atlx_irq_disable(adapter);
schedule_work(&adapter->reset_dev_task);
return IRQ_HANDLED;
}
+ }
- /* link event */
- if (status & ISR_GPHY) {
- adapter->soft_stats.tx_carrier_errors++;
- atl1_check_for_link(adapter);
- }
+ /* check if DMA read/write error ? */
+ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+ if (netif_msg_intr(adapter))
+ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+ "pcie DMA r/w error (status = 0x%x)\n",
+ status);
+ atlx_irq_disable(adapter);
+ schedule_work(&adapter->reset_dev_task);
+ return IRQ_HANDLED;
+ }
- /* transmit event */
- if (status & ISR_CMB_TX)
- atl1_intr_tx(adapter);
-
- /* rx exception */
- if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
- ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
- ISR_HOST_RRD_OV | ISR_CMB_RX))) {
- if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
- ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
- ISR_HOST_RRD_OV))
- if (netif_msg_intr(adapter))
- dev_printk(KERN_DEBUG,
- &adapter->pdev->dev,
- "rx exception, ISR = 0x%x\n",
- status);
- atl1_intr_rx(adapter);
- }
+ /* link event */
+ if (status & ISR_GPHY) {
+ adapter->soft_stats.tx_carrier_errors++;
+ atl1_check_for_link(adapter);
+ }
- if (--max_ints < 0)
- break;
+ /* transmit or receive event */
+ if (status & (ISR_CMB_TX | ISR_CMB_RX) &&
+ atl1_sched_rings_clean(adapter))
+ adapter->cmb.cmb->int_stats = adapter->cmb.cmb->int_stats &
+ ~(ISR_CMB_TX | ISR_CMB_RX);
- } while ((status = adapter->cmb.cmb->int_stats));
+ /* rx exception */
+ if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+ ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+ ISR_HOST_RRD_OV))) {
+ if (netif_msg_intr(adapter))
+ dev_printk(KERN_DEBUG,
+ &adapter->pdev->dev,
+ "rx exception, ISR = 0x%x\n",
+ status);
+ atl1_sched_rings_clean(adapter);
+ }
/* re-enable Interrupt */
iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
@@ -2599,6 +2645,7 @@ static s32 atl1_up(struct atl1_adapter *adapter)
if (unlikely(err))
goto err_up;
+ napi_enable(&adapter->napi);
atlx_irq_enable(adapter);
atl1_check_link(adapter);
netif_start_queue(netdev);
@@ -2615,6 +2662,7 @@ static void atl1_down(struct atl1_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ napi_disable(&adapter->napi);
netif_stop_queue(netdev);
del_timer_sync(&adapter->phy_config_timer);
adapter->phy_timer_pending = false;
@@ -2971,6 +3019,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
netdev->netdev_ops = &atl1_netdev_ops;
netdev->watchdog_timeo = 5 * HZ;
+ netif_napi_add(netdev, &adapter->napi, atl1_rings_clean, 64);
netdev->ethtool_ops = &atl1_ethtool_ops;
adapter->bd_number = cards_found;
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.h b/drivers/net/ethernet/atheros/atlx/atl1.h
index e04bf4d71e46..3bf79a56220d 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.h
+++ b/drivers/net/ethernet/atheros/atlx/atl1.h
@@ -275,13 +275,17 @@ static u32 atl1_check_link(struct atl1_adapter *adapter);
#define ISR_DIS_SMB 0x20000000
#define ISR_DIS_DMA 0x40000000
-/* Normal Interrupt mask */
-#define IMR_NORMAL_MASK (\
+/* Normal Interrupt mask without RX/TX enabled */
+#define IMR_NORXTX_MASK (\
ISR_SMB |\
ISR_GPHY |\
ISR_PHY_LINKDOWN|\
ISR_DMAR_TO_RST |\
- ISR_DMAW_TO_RST |\
+ ISR_DMAW_TO_RST)
+
+/* Normal Interrupt mask */
+#define IMR_NORMAL_MASK (\
+ IMR_NORXTX_MASK |\
ISR_CMB_TX |\
ISR_CMB_RX)
@@ -758,6 +762,7 @@ struct atl1_adapter {
u16 link_speed;
u16 link_duplex;
spinlock_t lock;
+ struct napi_struct napi;
struct work_struct reset_dev_task;
struct work_struct link_chg_task;
@@ -781,6 +786,12 @@ struct atl1_adapter {
u16 ict; /* interrupt clear timer (2us resolution */
struct mii_if_info mii; /* MII interface info */
+ /*
+ * Use this value to check is napi handler allowed to
+ * enable ints or not
+ */
+ bool int_enabled;
+
u32 bd_number; /* board number */
bool pci_using_64;
struct atl1_hw hw;
diff --git a/drivers/net/ethernet/atheros/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c
index c9e9dc57986c..b4f3aa49a7fc 100644
--- a/drivers/net/ethernet/atheros/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
@@ -155,14 +155,21 @@ static void atlx_set_multi(struct net_device *netdev)
}
}
+static inline void atlx_imr_set(struct atlx_adapter *adapter,
+ unsigned int imr)
+{
+ iowrite32(imr, adapter->hw.hw_addr + REG_IMR);
+ ioread32(adapter->hw.hw_addr + REG_IMR);
+}
+
/*
* atlx_irq_enable - Enable default interrupt generation settings
* @adapter: board private structure
*/
static void atlx_irq_enable(struct atlx_adapter *adapter)
{
- iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
- ioread32(adapter->hw.hw_addr + REG_IMR);
+ atlx_imr_set(adapter, IMR_NORMAL_MASK);
+ adapter->int_enabled = true;
}
/*
@@ -171,8 +178,8 @@ static void atlx_irq_enable(struct atlx_adapter *adapter)
*/
static void atlx_irq_disable(struct atlx_adapter *adapter)
{
- iowrite32(0, adapter->hw.hw_addr + REG_IMR);
- ioread32(adapter->hw.hw_addr + REG_IMR);
+ adapter->int_enabled = false;
+ atlx_imr_set(adapter, 0);
synchronize_irq(adapter->pdev->irq);
}
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 8297e2868736..ac7b74488531 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -3006,7 +3006,7 @@ error:
dma_unmap_single(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size,
PCI_DMA_FROMDEVICE);
- skb = build_skb(data);
+ skb = build_skb(data, 0);
if (!skb) {
kfree(data);
goto error;
@@ -7343,8 +7343,7 @@ static struct {
{ "rx_fw_discards" },
};
-#define BNX2_NUM_STATS (sizeof(bnx2_stats_str_arr)/\
- sizeof(bnx2_stats_str_arr[0]))
+#define BNX2_NUM_STATS ARRAY_SIZE(bnx2_stats_str_arr)
#define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
@@ -7976,7 +7975,6 @@ static int __devinit
bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
{
struct bnx2 *bp;
- unsigned long mem_len;
int rc, i, j;
u32 reg;
u64 dma_mask, persist_dma_mask;
@@ -8036,13 +8034,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
#endif
INIT_WORK(&bp->reset_task, bnx2_reset_task);
- dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
- mem_len = MB_GET_CID_ADDR(TX_TSS_CID + TX_MAX_TSS_RINGS + 1);
- dev->mem_end = dev->mem_start + mem_len;
- dev->irq = pdev->irq;
-
- bp->regview = ioremap_nocache(dev->base_addr, mem_len);
-
+ bp->regview = pci_iomap(pdev, 0, MB_GET_CID_ADDR(TX_TSS_CID +
+ TX_MAX_TSS_RINGS + 1));
if (!bp->regview) {
dev_err(&pdev->dev, "Cannot map register space, aborting\n");
rc = -ENOMEM;
@@ -8346,10 +8339,8 @@ err_out_unmap:
bp->flags &= ~BNX2_FLAG_AER_ENABLED;
}
- if (bp->regview) {
- iounmap(bp->regview);
- bp->regview = NULL;
- }
+ pci_iounmap(pdev, bp->regview);
+ bp->regview = NULL;
err_out_release:
pci_release_regions(pdev);
@@ -8432,7 +8423,7 @@ static int __devinit
bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int version_printed = 0;
- struct net_device *dev = NULL;
+ struct net_device *dev;
struct bnx2 *bp;
int rc;
char str[40];
@@ -8442,15 +8433,12 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* dev zeroed in init_etherdev */
dev = alloc_etherdev_mq(sizeof(*bp), TX_MAX_RINGS);
-
if (!dev)
return -ENOMEM;
rc = bnx2_init_board(pdev, dev);
- if (rc < 0) {
- free_netdev(dev);
- return rc;
- }
+ if (rc < 0)
+ goto err_free;
dev->netdev_ops = &bnx2_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
@@ -8480,22 +8468,21 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto error;
}
- netdev_info(dev, "%s (%c%d) %s found at mem %lx, IRQ %d, node addr %pM\n",
- board_info[ent->driver_data].name,
+ netdev_info(dev, "%s (%c%d) %s found at mem %lx, IRQ %d, "
+ "node addr %pM\n", board_info[ent->driver_data].name,
((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
((CHIP_ID(bp) & 0x0ff0) >> 4),
- bnx2_bus_string(bp, str),
- dev->base_addr,
- bp->pdev->irq, dev->dev_addr);
+ bnx2_bus_string(bp, str), (long)pci_resource_start(pdev, 0),
+ pdev->irq, dev->dev_addr);
return 0;
error:
- if (bp->regview)
- iounmap(bp->regview);
+ iounmap(bp->regview);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
+err_free:
free_netdev(dev);
return rc;
}
@@ -8511,8 +8498,7 @@ bnx2_remove_one(struct pci_dev *pdev)
del_timer_sync(&bp->timer);
cancel_work_sync(&bp->reset_task);
- if (bp->regview)
- iounmap(bp->regview);
+ pci_iounmap(bp->pdev, bp->regview);
kfree(bp->temp_stats_blk);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 2c9ee552dffc..e30e2a2f354c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -23,13 +23,17 @@
* (you will need to reboot afterwards) */
/* #define BNX2X_STOP_ON_ERROR */
-#define DRV_MODULE_VERSION "1.72.10-0"
-#define DRV_MODULE_RELDATE "2012/02/20"
+#define DRV_MODULE_VERSION "1.72.50-0"
+#define DRV_MODULE_RELDATE "2012/04/23"
#define BNX2X_BC_VER 0x040200
#if defined(CONFIG_DCB)
#define BCM_DCBNL
#endif
+
+
+#include "bnx2x_hsi.h"
+
#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
#define BCM_CNIC 1
#include "../cnic_if.h"
@@ -345,7 +349,6 @@ 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
@@ -815,6 +818,8 @@ struct bnx2x_common {
#define CHIP_NUM_57800_MF 0x16a5
#define CHIP_NUM_57810 0x168e
#define CHIP_NUM_57810_MF 0x16ae
+#define CHIP_NUM_57811 0x163d
+#define CHIP_NUM_57811_MF 0x163e
#define CHIP_NUM_57840 0x168d
#define CHIP_NUM_57840_MF 0x16ab
#define CHIP_IS_E1(bp) (CHIP_NUM(bp) == CHIP_NUM_57710)
@@ -826,6 +831,8 @@ struct bnx2x_common {
#define CHIP_IS_57800_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57800_MF)
#define CHIP_IS_57810(bp) (CHIP_NUM(bp) == CHIP_NUM_57810)
#define CHIP_IS_57810_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57810_MF)
+#define CHIP_IS_57811(bp) (CHIP_NUM(bp) == CHIP_NUM_57811)
+#define CHIP_IS_57811_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57811_MF)
#define CHIP_IS_57840(bp) (CHIP_NUM(bp) == CHIP_NUM_57840)
#define CHIP_IS_57840_MF(bp) (CHIP_NUM(bp) == CHIP_NUM_57840_MF)
#define CHIP_IS_E1H(bp) (CHIP_IS_57711(bp) || \
@@ -836,6 +843,8 @@ struct bnx2x_common {
CHIP_IS_57800_MF(bp) || \
CHIP_IS_57810(bp) || \
CHIP_IS_57810_MF(bp) || \
+ CHIP_IS_57811(bp) || \
+ CHIP_IS_57811_MF(bp) || \
CHIP_IS_57840(bp) || \
CHIP_IS_57840_MF(bp))
#define CHIP_IS_E1x(bp) (CHIP_IS_E1((bp)) || CHIP_IS_E1H((bp)))
@@ -1053,6 +1062,13 @@ struct bnx2x_slowpath {
struct flow_control_configuration pfc_config;
} func_rdata;
+ /* afex ramrod can not be a part of func_rdata union because these
+ * events might arrive in parallel to other events from func_rdata.
+ * Therefore, if they would have been defined in the same union,
+ * data can get corrupted.
+ */
+ struct afex_vif_list_ramrod_data func_afex_rdata;
+
/* used by dmae command executer */
struct dmae_command dmae[MAX_DMAE_C];
@@ -1169,6 +1185,7 @@ struct bnx2x_fw_stats_data {
enum {
BNX2X_SP_RTNL_SETUP_TC,
BNX2X_SP_RTNL_TX_TIMEOUT,
+ BNX2X_SP_RTNL_AFEX_F_UPDATE,
BNX2X_SP_RTNL_FAN_FAILURE,
};
@@ -1222,7 +1239,6 @@ struct bnx2x {
#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)
@@ -1300,6 +1316,7 @@ struct bnx2x {
#define NO_ISCSI_FLAG (1 << 14)
#define NO_FCOE_FLAG (1 << 15)
#define BC_SUPPORTS_PFC_STATS (1 << 17)
+#define USING_SINGLE_MSIX_FLAG (1 << 20)
#define NO_ISCSI(bp) ((bp)->flags & NO_ISCSI_FLAG)
#define NO_ISCSI_OOO(bp) ((bp)->flags & NO_ISCSI_OOO_FLAG)
@@ -1329,21 +1346,20 @@ struct bnx2x {
struct bnx2x_common common;
struct bnx2x_port port;
- struct cmng_struct_per_port cmng;
- u32 vn_weight_sum;
+ struct cmng_init cmng;
+
u32 mf_config[E1HVN_MAX];
- u32 mf2_config[E2_FUNC_MAX];
+ u32 mf_ext_config;
u32 path_has_ovlan; /* E3 */
u16 mf_ov;
u8 mf_mode;
#define IS_MF(bp) (bp->mf_mode != 0)
#define IS_MF_SI(bp) (bp->mf_mode == MULTI_FUNCTION_SI)
#define IS_MF_SD(bp) (bp->mf_mode == MULTI_FUNCTION_SD)
+#define IS_MF_AFEX(bp) (bp->mf_mode == MULTI_FUNCTION_AFEX)
u8 wol;
- bool gro_check;
-
int rx_ring_size;
u16 tx_quick_cons_trip_int;
@@ -1371,7 +1387,6 @@ struct bnx2x {
#define BNX2X_STATE_DIAG 0xe000
#define BNX2X_STATE_ERROR 0xf000
- int multi_mode;
#define BNX2X_MAX_PRIORITY 8
#define BNX2X_MAX_ENTRIES_PER_PRI 16
#define BNX2X_MAX_COS 3
@@ -1582,6 +1597,9 @@ struct bnx2x {
struct dcbx_features dcbx_remote_feat;
u32 dcbx_remote_flags;
#endif
+ /* AFEX: store default vlan used */
+ int afex_def_vlan_tag;
+ enum mf_cfg_afex_vlan_mode afex_vlan_mode;
u32 pending_max;
/* multiple tx classes of service */
@@ -2138,9 +2156,16 @@ void bnx2x_notify_link_changed(struct bnx2x *bp);
#define IS_MF_ISCSI_SD(bp) (IS_MF_SD(bp) && BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp))
#define IS_MF_FCOE_SD(bp) (IS_MF_SD(bp) && BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp))
+#define BNX2X_MF_EXT_PROTOCOL_FCOE(bp) ((bp)->mf_ext_config & \
+ MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD)
+
+#define IS_MF_FCOE_AFEX(bp) (IS_MF_AFEX(bp) && BNX2X_MF_EXT_PROTOCOL_FCOE(bp))
#define IS_MF_STORAGE_SD(bp) (IS_MF_SD(bp) && \
(BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) || \
BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp)))
+#else
+#define IS_MF_FCOE_AFEX(bp) false
#endif
+
#endif /* bnx2x.h */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 4b054812713a..ad0743bf4bde 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -23,7 +23,6 @@
#include <linux/ip.h>
#include <net/ipv6.h>
#include <net/ip6_checksum.h>
-#include <linux/firmware.h>
#include <linux/prefetch.h>
#include "bnx2x_cmn.h"
#include "bnx2x_init.h"
@@ -329,16 +328,6 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
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;
}
@@ -369,8 +358,8 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
* Approximate value of the MSS for this aggregation calculated using
* the first packet of it.
*/
-static inline u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags,
- u16 len_on_bd)
+static u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags,
+ u16 len_on_bd)
{
/*
* TPA arrgregation won't have either IP options or TCP options
@@ -396,6 +385,36 @@ static inline u16 bnx2x_set_lro_mss(struct bnx2x *bp, u16 parsing_flags,
return len_on_bd - hdrs_len;
}
+static int bnx2x_alloc_rx_sge(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, u16 index)
+{
+ struct page *page = alloc_pages(GFP_ATOMIC, PAGES_PER_SGE_SHIFT);
+ struct sw_rx_page *sw_buf = &fp->rx_page_ring[index];
+ struct eth_rx_sge *sge = &fp->rx_sge_ring[index];
+ dma_addr_t mapping;
+
+ if (unlikely(page == NULL)) {
+ BNX2X_ERR("Can't alloc sge\n");
+ return -ENOMEM;
+ }
+
+ mapping = dma_map_page(&bp->pdev->dev, page, 0,
+ SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+ __free_pages(page, PAGES_PER_SGE_SHIFT);
+ BNX2X_ERR("Can't map sge\n");
+ return -ENOMEM;
+ }
+
+ sw_buf->page = page;
+ dma_unmap_addr_set(sw_buf, mapping, mapping);
+
+ sge->addr_hi = cpu_to_le32(U64_HI(mapping));
+ sge->addr_lo = cpu_to_le32(U64_LO(mapping));
+
+ return 0;
+}
+
static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
struct bnx2x_agg_info *tpa_info,
u16 pages,
@@ -494,11 +513,11 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
return 0;
}
-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)
+static 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 sw_rx_bd *rx_buf = &tpa_info->first_buf;
u8 pad = tpa_info->placement_offset;
@@ -524,7 +543,7 @@ static inline void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(rx_buf, mapping),
fp->rx_buf_size, DMA_FROM_DEVICE);
if (likely(new_data))
- skb = build_skb(data);
+ skb = build_skb(data, 0);
if (likely(skb)) {
#ifdef BNX2X_STOP_ON_ERROR
@@ -568,6 +587,36 @@ drop:
fp->eth_q_stats.rx_skb_alloc_failed++;
}
+static int bnx2x_alloc_rx_data(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, u16 index)
+{
+ u8 *data;
+ struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[index];
+ struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index];
+ dma_addr_t mapping;
+
+ data = kmalloc(fp->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC);
+ if (unlikely(data == NULL))
+ return -ENOMEM;
+
+ mapping = dma_map_single(&bp->pdev->dev, data + NET_SKB_PAD,
+ fp->rx_buf_size,
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
+ kfree(data);
+ BNX2X_ERR("Can't map rx data\n");
+ return -ENOMEM;
+ }
+
+ rx_buf->data = data;
+ dma_unmap_addr_set(rx_buf, mapping, mapping);
+
+ rx_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
+ rx_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
+
+ return 0;
+}
+
int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
{
@@ -732,7 +781,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
dma_unmap_addr(rx_buf, mapping),
fp->rx_buf_size,
DMA_FROM_DEVICE);
- skb = build_skb(data);
+ skb = build_skb(data, 0);
if (unlikely(!skb)) {
kfree(data);
fp->eth_q_stats.rx_skb_alloc_failed++;
@@ -881,8 +930,8 @@ u16 bnx2x_get_mf_speed(struct bnx2x *bp)
*
* It uses a none-atomic bit operations because is called under the mutex.
*/
-static inline void bnx2x_fill_report_data(struct bnx2x *bp,
- struct bnx2x_link_report_data *data)
+static void bnx2x_fill_report_data(struct bnx2x *bp,
+ struct bnx2x_link_report_data *data)
{
u16 line_speed = bnx2x_get_mf_speed(bp);
@@ -1000,6 +1049,47 @@ void __bnx2x_link_report(struct bnx2x *bp)
}
}
+static void bnx2x_set_next_page_sgl(struct bnx2x_fastpath *fp)
+{
+ int i;
+
+ for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
+ struct eth_rx_sge *sge;
+
+ sge = &fp->rx_sge_ring[RX_SGE_CNT * i - 2];
+ sge->addr_hi =
+ cpu_to_le32(U64_HI(fp->rx_sge_mapping +
+ BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
+
+ sge->addr_lo =
+ cpu_to_le32(U64_LO(fp->rx_sge_mapping +
+ BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
+ }
+}
+
+static void bnx2x_free_tpa_pool(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp, int last)
+{
+ int i;
+
+ for (i = 0; i < last; i++) {
+ struct bnx2x_agg_info *tpa_info = &fp->tpa_info[i];
+ struct sw_rx_bd *first_buf = &tpa_info->first_buf;
+ u8 *data = first_buf->data;
+
+ if (data == NULL) {
+ DP(NETIF_MSG_IFDOWN, "tpa bin %d empty on free\n", i);
+ continue;
+ }
+ if (tpa_info->tpa_state == BNX2X_TPA_START)
+ dma_unmap_single(&bp->pdev->dev,
+ dma_unmap_addr(first_buf, mapping),
+ fp->rx_buf_size, DMA_FROM_DEVICE);
+ kfree(data);
+ first_buf->data = NULL;
+ }
+}
+
void bnx2x_init_rx_rings(struct bnx2x *bp)
{
int func = BP_FUNC(bp);
@@ -1212,16 +1302,15 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp, int nvecs)
void bnx2x_free_irq(struct bnx2x *bp)
{
- if (bp->flags & USING_MSIX_FLAG)
+ if (bp->flags & USING_MSIX_FLAG &&
+ !(bp->flags & USING_SINGLE_MSIX_FLAG))
bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) +
CNIC_PRESENT + 1);
- else if (bp->flags & USING_MSI_FLAG)
- free_irq(bp->pdev->irq, bp->dev);
else
- free_irq(bp->pdev->irq, bp->dev);
+ free_irq(bp->dev->irq, bp->dev);
}
-int bnx2x_enable_msix(struct bnx2x *bp)
+int __devinit bnx2x_enable_msix(struct bnx2x *bp)
{
int msix_vec = 0, i, rc, req_cnt;
@@ -1261,8 +1350,8 @@ int bnx2x_enable_msix(struct bnx2x *bp)
rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], rc);
if (rc) {
- BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc);
- return rc;
+ BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc);
+ goto no_msix;
}
/*
* decrease number of queues by number of unallocated entries
@@ -1270,18 +1359,34 @@ int bnx2x_enable_msix(struct bnx2x *bp)
bp->num_queues -= diff;
BNX2X_DEV_INFO("New queue configuration set: %d\n",
- bp->num_queues);
- } else if (rc) {
- /* fall to INTx if not enough memory */
- if (rc == -ENOMEM)
- bp->flags |= DISABLE_MSI_FLAG;
+ bp->num_queues);
+ } else if (rc > 0) {
+ /* Get by with single vector */
+ rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], 1);
+ if (rc) {
+ BNX2X_DEV_INFO("Single MSI-X is not attainable rc %d\n",
+ rc);
+ goto no_msix;
+ }
+
+ BNX2X_DEV_INFO("Using single MSI-X vector\n");
+ bp->flags |= USING_SINGLE_MSIX_FLAG;
+
+ } else if (rc < 0) {
BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc);
- return rc;
+ goto no_msix;
}
bp->flags |= USING_MSIX_FLAG;
return 0;
+
+no_msix:
+ /* fall to INTx if not enough memory */
+ if (rc == -ENOMEM)
+ bp->flags |= DISABLE_MSI_FLAG;
+
+ return rc;
}
static int bnx2x_req_msix_irqs(struct bnx2x *bp)
@@ -1343,22 +1448,26 @@ int bnx2x_enable_msi(struct bnx2x *bp)
static int bnx2x_req_irq(struct bnx2x *bp)
{
unsigned long flags;
- int rc;
+ unsigned int irq;
- if (bp->flags & USING_MSI_FLAG)
+ if (bp->flags & (USING_MSI_FLAG | USING_MSIX_FLAG))
flags = 0;
else
flags = IRQF_SHARED;
- rc = request_irq(bp->pdev->irq, bnx2x_interrupt, flags,
- bp->dev->name, bp->dev);
- return rc;
+ if (bp->flags & USING_MSIX_FLAG)
+ irq = bp->msix_table[0].vector;
+ else
+ irq = bp->pdev->irq;
+
+ return request_irq(irq, bnx2x_interrupt, flags, bp->dev->name, bp->dev);
}
-static inline int bnx2x_setup_irqs(struct bnx2x *bp)
+static int bnx2x_setup_irqs(struct bnx2x *bp)
{
int rc = 0;
- if (bp->flags & USING_MSIX_FLAG) {
+ if (bp->flags & USING_MSIX_FLAG &&
+ !(bp->flags & USING_SINGLE_MSIX_FLAG)) {
rc = bnx2x_req_msix_irqs(bp);
if (rc)
return rc;
@@ -1371,15 +1480,20 @@ static inline int bnx2x_setup_irqs(struct bnx2x *bp)
}
if (bp->flags & USING_MSI_FLAG) {
bp->dev->irq = bp->pdev->irq;
- netdev_info(bp->dev, "using MSI IRQ %d\n",
- bp->pdev->irq);
+ netdev_info(bp->dev, "using MSI IRQ %d\n",
+ bp->dev->irq);
+ }
+ if (bp->flags & USING_MSIX_FLAG) {
+ bp->dev->irq = bp->msix_table[0].vector;
+ netdev_info(bp->dev, "using MSIX IRQ %d\n",
+ bp->dev->irq);
}
}
return 0;
}
-static inline void bnx2x_napi_enable(struct bnx2x *bp)
+static void bnx2x_napi_enable(struct bnx2x *bp)
{
int i;
@@ -1387,7 +1501,7 @@ static inline void bnx2x_napi_enable(struct bnx2x *bp)
napi_enable(&bnx2x_fp(bp, i, napi));
}
-static inline void bnx2x_napi_disable(struct bnx2x *bp)
+static void bnx2x_napi_disable(struct bnx2x *bp)
{
int i;
@@ -1437,24 +1551,15 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp));
}
+
void bnx2x_set_num_queues(struct bnx2x *bp)
{
- switch (bp->multi_mode) {
- case ETH_RSS_MODE_DISABLED:
- bp->num_queues = 1;
- break;
- case ETH_RSS_MODE_REGULAR:
- bp->num_queues = bnx2x_calc_num_queues(bp);
- break;
-
- default:
- bp->num_queues = 1;
- break;
- }
+ /* RSS queues */
+ bp->num_queues = bnx2x_calc_num_queues(bp);
#ifdef BCM_CNIC
- /* override in STORAGE SD mode */
- if (IS_MF_STORAGE_SD(bp))
+ /* override in STORAGE SD modes */
+ if (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))
bp->num_queues = 1;
#endif
/* Add special queues */
@@ -1483,7 +1588,7 @@ void bnx2x_set_num_queues(struct bnx2x *bp)
* bnx2x_setup_tc() takes care of the proper TC mappings so that __skb_tx_hash()
* will return a proper Tx index if TC is enabled (netdev->num_tc > 0).
*/
-static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
+static int bnx2x_set_real_num_queues(struct bnx2x *bp)
{
int rc, tx, rx;
@@ -1515,7 +1620,7 @@ static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
return rc;
}
-static inline void bnx2x_set_rx_buf_size(struct bnx2x *bp)
+static void bnx2x_set_rx_buf_size(struct bnx2x *bp)
{
int i;
@@ -1543,22 +1648,19 @@ static inline void bnx2x_set_rx_buf_size(struct bnx2x *bp)
}
}
-static inline int bnx2x_init_rss_pf(struct bnx2x *bp)
+static int bnx2x_init_rss_pf(struct bnx2x *bp)
{
int i;
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
- /*
- * Prepare the inital contents fo the indirection table if RSS is
+ /* Prepare the initial contents fo the indirection table if RSS is
* enabled
*/
- if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
- for (i = 0; i < sizeof(ind_table); i++)
- ind_table[i] =
- bp->fp->cl_id +
- ethtool_rxfh_indir_default(i, num_eth_queues);
- }
+ for (i = 0; i < sizeof(ind_table); i++)
+ ind_table[i] =
+ bp->fp->cl_id +
+ ethtool_rxfh_indir_default(i, num_eth_queues);
/*
* For 57710 and 57711 SEARCHER configuration (rss_keys) is
@@ -1568,11 +1670,12 @@ static inline int bnx2x_init_rss_pf(struct bnx2x *bp)
* For 57712 and newer on the other hand it's a per-function
* configuration.
*/
- return bnx2x_config_rss_pf(bp, ind_table,
- bp->port.pmf || !CHIP_IS_E1x(bp));
+ return bnx2x_config_rss_eth(bp, ind_table,
+ bp->port.pmf || !CHIP_IS_E1x(bp));
}
-int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash)
+int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
+ u8 *ind_table, bool config_hash)
{
struct bnx2x_config_rss_params params = {NULL};
int i;
@@ -1584,58 +1687,35 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash)
* bp->multi_mode = ETH_RSS_MODE_DISABLED;
*/
- params.rss_obj = &bp->rss_conf_obj;
+ params.rss_obj = rss_obj;
__set_bit(RAMROD_COMP_WAIT, &params.ramrod_flags);
- /* RSS mode */
- switch (bp->multi_mode) {
- case ETH_RSS_MODE_DISABLED:
- __set_bit(BNX2X_RSS_MODE_DISABLED, &params.rss_flags);
- break;
- case ETH_RSS_MODE_REGULAR:
- __set_bit(BNX2X_RSS_MODE_REGULAR, &params.rss_flags);
- break;
- case ETH_RSS_MODE_VLAN_PRI:
- __set_bit(BNX2X_RSS_MODE_VLAN_PRI, &params.rss_flags);
- break;
- case ETH_RSS_MODE_E1HOV_PRI:
- __set_bit(BNX2X_RSS_MODE_E1HOV_PRI, &params.rss_flags);
- break;
- case ETH_RSS_MODE_IP_DSCP:
- __set_bit(BNX2X_RSS_MODE_IP_DSCP, &params.rss_flags);
- break;
- default:
- BNX2X_ERR("Unknown multi_mode: %d\n", bp->multi_mode);
- return -EINVAL;
- }
+ __set_bit(BNX2X_RSS_MODE_REGULAR, &params.rss_flags);
- /* If RSS is enabled */
- if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
- /* RSS configuration */
- __set_bit(BNX2X_RSS_IPV4, &params.rss_flags);
- __set_bit(BNX2X_RSS_IPV4_TCP, &params.rss_flags);
- __set_bit(BNX2X_RSS_IPV6, &params.rss_flags);
- __set_bit(BNX2X_RSS_IPV6_TCP, &params.rss_flags);
+ /* RSS configuration */
+ __set_bit(BNX2X_RSS_IPV4, &params.rss_flags);
+ __set_bit(BNX2X_RSS_IPV4_TCP, &params.rss_flags);
+ __set_bit(BNX2X_RSS_IPV6, &params.rss_flags);
+ __set_bit(BNX2X_RSS_IPV6_TCP, &params.rss_flags);
- /* Hash bits */
- params.rss_result_mask = MULTI_MASK;
+ /* Hash bits */
+ params.rss_result_mask = MULTI_MASK;
- memcpy(params.ind_table, ind_table, sizeof(params.ind_table));
+ memcpy(params.ind_table, ind_table, sizeof(params.ind_table));
- if (config_hash) {
- /* RSS keys */
- for (i = 0; i < sizeof(params.rss_key) / 4; i++)
- params.rss_key[i] = random32();
+ if (config_hash) {
+ /* RSS keys */
+ for (i = 0; i < sizeof(params.rss_key) / 4; i++)
+ params.rss_key[i] = random32();
- __set_bit(BNX2X_RSS_SET_SRCH, &params.rss_flags);
- }
+ __set_bit(BNX2X_RSS_SET_SRCH, &params.rss_flags);
}
return bnx2x_config_rss(bp, &params);
}
-static inline int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
+static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
{
struct bnx2x_func_state_params func_params = {NULL};
@@ -1744,6 +1824,87 @@ bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err)
return true;
}
+/**
+ * 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 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
+}
+
+
/* must be called with rtnl_lock */
int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
{
@@ -1911,8 +2072,14 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
SHMEM2_WR(bp, dcc_support,
(SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV |
SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV));
+ if (SHMEM2_HAS(bp, afex_driver_support))
+ SHMEM2_WR(bp, afex_driver_support,
+ SHMEM_AFEX_SUPPORTED_VERSION_ONE);
}
+ /* Set AFEX default VLAN tag to an invalid value */
+ bp->afex_def_vlan_tag = -1;
+
bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
rc = bnx2x_func_start(bp);
if (rc) {
@@ -2968,6 +3135,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_sent_queue(txq, skb->len);
+ skb_tx_timestamp(skb);
+
txdata->tx_pkt_prod++;
/*
* Make sure that the BD data is updated before updating the producer
@@ -3084,7 +3253,8 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p)
}
#ifdef BCM_CNIC
- if (IS_MF_STORAGE_SD(bp) && !is_zero_ether_addr(addr->sa_data)) {
+ if ((IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)) &&
+ !is_zero_ether_addr(addr->sa_data)) {
BNX2X_ERR("Can't configure non-zero address on iSCSI or FCoE functions in MF-SD mode\n");
return -EINVAL;
}
@@ -3181,7 +3351,7 @@ void bnx2x_free_fp_mem(struct bnx2x *bp)
bnx2x_free_fp_mem_at(bp, i);
}
-static inline void set_sb_shortcuts(struct bnx2x *bp, int index)
+static void set_sb_shortcuts(struct bnx2x *bp, int index)
{
union host_hc_status_block status_blk = bnx2x_fp(bp, index, status_blk);
if (!CHIP_IS_E1x(bp)) {
@@ -3197,6 +3367,63 @@ static inline void set_sb_shortcuts(struct bnx2x *bp, int index)
}
}
+/* Returns the number of actually allocated BDs */
+static int bnx2x_alloc_rx_bds(struct bnx2x_fastpath *fp,
+ int rx_ring_size)
+{
+ struct bnx2x *bp = fp->bp;
+ u16 ring_prod, cqe_ring_prod;
+ int i, failure_cnt = 0;
+
+ fp->rx_comp_cons = 0;
+ cqe_ring_prod = ring_prod = 0;
+
+ /* This routine is called only during fo init so
+ * fp->eth_q_stats.rx_skb_alloc_failed = 0
+ */
+ for (i = 0; i < rx_ring_size; i++) {
+ if (bnx2x_alloc_rx_data(bp, fp, ring_prod) < 0) {
+ failure_cnt++;
+ continue;
+ }
+ ring_prod = NEXT_RX_IDX(ring_prod);
+ cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod);
+ WARN_ON(ring_prod <= (i - failure_cnt));
+ }
+
+ if (failure_cnt)
+ BNX2X_ERR("was only able to allocate %d rx skbs on queue[%d]\n",
+ i - failure_cnt, fp->index);
+
+ fp->rx_bd_prod = ring_prod;
+ /* Limit the CQE producer by the CQE ring size */
+ fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT,
+ cqe_ring_prod);
+ fp->rx_pkt = fp->rx_calls = 0;
+
+ fp->eth_q_stats.rx_skb_alloc_failed += failure_cnt;
+
+ return i - failure_cnt;
+}
+
+static void bnx2x_set_next_page_rx_cq(struct bnx2x_fastpath *fp)
+{
+ int i;
+
+ for (i = 1; i <= NUM_RCQ_RINGS; i++) {
+ struct eth_rx_cqe_next_page *nextpg;
+
+ nextpg = (struct eth_rx_cqe_next_page *)
+ &fp->rx_comp_ring[RCQ_DESC_CNT * i - 1];
+ nextpg->addr_hi =
+ cpu_to_le32(U64_HI(fp->rx_comp_mapping +
+ BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
+ nextpg->addr_lo =
+ cpu_to_le32(U64_LO(fp->rx_comp_mapping +
+ BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
+ }
+}
+
static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
{
union host_hc_status_block *sb;
@@ -3206,7 +3433,8 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
int rx_ring_size = 0;
#ifdef BCM_CNIC
- if (!bp->rx_ring_size && IS_MF_STORAGE_SD(bp)) {
+ if (!bp->rx_ring_size &&
+ (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) {
rx_ring_size = MIN_RX_SIZE_NONTPA;
bp->rx_ring_size = rx_ring_size;
} else
@@ -3528,8 +3756,6 @@ 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);
}
@@ -3687,9 +3913,9 @@ void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
CDU_REGION_NUMBER_XCM_AG, ETH_CONNECTION_TYPE);
}
-static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
- u8 fw_sb_id, u8 sb_index,
- u8 ticks)
+static void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
+ u8 fw_sb_id, u8 sb_index,
+ u8 ticks)
{
u32 addr = BAR_CSTRORM_INTMEM +
@@ -3700,9 +3926,9 @@ static inline void storm_memset_hc_timeout(struct bnx2x *bp, u8 port,
port, fw_sb_id, sb_index, ticks);
}
-static inline void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
- u16 fw_sb_id, u8 sb_index,
- u8 disable)
+static void storm_memset_hc_disable(struct bnx2x *bp, u8 port,
+ u16 fw_sb_id, u8 sb_index,
+ u8 disable)
{
u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
u32 addr = BAR_CSTRORM_INTMEM +
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 5c27454d2ec2..7cd99b75347a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -86,13 +86,15 @@ u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode);
void bnx2x_send_unload_done(struct bnx2x *bp);
/**
- * bnx2x_config_rss_pf - configure RSS parameters.
+ * bnx2x_config_rss_pf - configure RSS parameters in a PF.
*
* @bp: driver handle
+ * @rss_obj RSS object to use
* @ind_table: indirection table to configure
* @config_hash: re-configure RSS hash keys configuration
*/
-int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash);
+int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
+ u8 *ind_table, bool config_hash);
/**
* bnx2x__init_func_obj - init function object
@@ -485,7 +487,7 @@ void bnx2x_netif_start(struct bnx2x *bp);
* fills msix_table, requests vectors, updates num_queues
* according to number of available vectors.
*/
-int bnx2x_enable_msix(struct bnx2x *bp);
+int __devinit bnx2x_enable_msix(struct bnx2x *bp);
/**
* bnx2x_enable_msi - request msi mode from OS, updated internals accordingly
@@ -610,53 +612,6 @@ static inline void bnx2x_igu_ack_sb_gen(struct bnx2x *bp, u8 igu_sb_id,
barrier();
}
-static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func,
- u8 idu_sb_id, bool is_Pf)
-{
- u32 data, ctl, cnt = 100;
- u32 igu_addr_data = IGU_REG_COMMAND_REG_32LSB_DATA;
- 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 ? 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 */
- if (CHIP_INT_MODE_IS_BC(bp))
- return;
-
- data = (IGU_USE_REGISTER_cstorm_type_0_sb_cleanup
- << IGU_REGULAR_CLEANUP_TYPE_SHIFT) |
- IGU_REGULAR_CLEANUP_SET |
- IGU_REGULAR_BCLEANUP;
-
- ctl = addr_encode << IGU_CTRL_REG_ADDRESS_SHIFT |
- func_encode << IGU_CTRL_REG_FID_SHIFT |
- IGU_CTRL_CMD_TYPE_WR << IGU_CTRL_REG_TYPE_SHIFT;
-
- DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
- data, igu_addr_data);
- REG_WR(bp, igu_addr_data, data);
- mmiowb();
- barrier();
- DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
- ctl, igu_addr_ctl);
- REG_WR(bp, igu_addr_ctl, ctl);
- mmiowb();
- barrier();
-
- /* wait for clean up to finish */
- while (!(REG_RD(bp, igu_addr_ack) & sb_bit) && --cnt)
- msleep(20);
-
-
- if (!(REG_RD(bp, igu_addr_ack) & sb_bit)) {
- DP(NETIF_MSG_HW,
- "Unable to finish IGU cleanup: idu_sb_id %d offset %d bit %d (cnt %d)\n",
- idu_sb_id, idu_sb_id/32, idu_sb_id%32, cnt);
- }
-}
-
static inline void bnx2x_hc_ack_sb(struct bnx2x *bp, u8 sb_id,
u8 storm, u16 index, u8 op, u8 update)
{
@@ -843,7 +798,7 @@ static inline void bnx2x_disable_msi(struct bnx2x *bp)
{
if (bp->flags & USING_MSIX_FLAG) {
pci_disable_msix(bp->pdev);
- bp->flags &= ~USING_MSIX_FLAG;
+ bp->flags &= ~(USING_MSIX_FLAG | USING_SINGLE_MSIX_FLAG);
} else if (bp->flags & USING_MSI_FLAG) {
pci_disable_msi(bp->pdev);
bp->flags &= ~USING_MSI_FLAG;
@@ -883,66 +838,6 @@ static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp)
bnx2x_clear_sge_mask_next_elems(fp);
}
-static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp,
- struct bnx2x_fastpath *fp, u16 index)
-{
- struct page *page = alloc_pages(GFP_ATOMIC, PAGES_PER_SGE_SHIFT);
- struct sw_rx_page *sw_buf = &fp->rx_page_ring[index];
- struct eth_rx_sge *sge = &fp->rx_sge_ring[index];
- dma_addr_t mapping;
-
- if (unlikely(page == NULL)) {
- BNX2X_ERR("Can't alloc sge\n");
- return -ENOMEM;
- }
-
- mapping = dma_map_page(&bp->pdev->dev, page, 0,
- SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
- __free_pages(page, PAGES_PER_SGE_SHIFT);
- BNX2X_ERR("Can't map sge\n");
- return -ENOMEM;
- }
-
- sw_buf->page = page;
- dma_unmap_addr_set(sw_buf, mapping, mapping);
-
- sge->addr_hi = cpu_to_le32(U64_HI(mapping));
- sge->addr_lo = cpu_to_le32(U64_LO(mapping));
-
- return 0;
-}
-
-static inline int bnx2x_alloc_rx_data(struct bnx2x *bp,
- struct bnx2x_fastpath *fp, u16 index)
-{
- u8 *data;
- struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[index];
- struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index];
- dma_addr_t mapping;
-
- data = kmalloc(fp->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC);
- if (unlikely(data == NULL))
- return -ENOMEM;
-
- mapping = dma_map_single(&bp->pdev->dev, data + NET_SKB_PAD,
- fp->rx_buf_size,
- DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
- kfree(data);
- BNX2X_ERR("Can't map rx data\n");
- return -ENOMEM;
- }
-
- rx_buf->data = data;
- dma_unmap_addr_set(rx_buf, mapping, mapping);
-
- rx_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
- rx_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
-
- return 0;
-}
-
/* note that we are not allocating a new buffer,
* we are just moving one from cons to prod
* we are not creating a new mapping,
@@ -964,6 +859,19 @@ static inline void bnx2x_reuse_rx_data(struct bnx2x_fastpath *fp,
/************************* Init ******************************************/
+/* returns func by VN for current port */
+static inline int func_by_vn(struct bnx2x *bp, int vn)
+{
+ return 2 * vn + BP_PORT(bp);
+}
+
+static inline int bnx2x_config_rss_eth(struct bnx2x *bp, u8 *ind_table,
+ bool config_hash)
+{
+ return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, ind_table,
+ config_hash);
+}
+
/**
* bnx2x_func_start - init function
*
@@ -1027,66 +935,6 @@ static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
bnx2x_free_rx_sge(bp, fp, i);
}
-static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
- struct bnx2x_fastpath *fp, int last)
-{
- int i;
-
- for (i = 0; i < last; i++) {
- struct bnx2x_agg_info *tpa_info = &fp->tpa_info[i];
- struct sw_rx_bd *first_buf = &tpa_info->first_buf;
- u8 *data = first_buf->data;
-
- if (data == NULL) {
- DP(NETIF_MSG_IFDOWN, "tpa bin %d empty on free\n", i);
- continue;
- }
- if (tpa_info->tpa_state == BNX2X_TPA_START)
- dma_unmap_single(&bp->pdev->dev,
- dma_unmap_addr(first_buf, mapping),
- fp->rx_buf_size, DMA_FROM_DEVICE);
- kfree(data);
- first_buf->data = NULL;
- }
-}
-
-static inline void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata)
-{
- int i;
-
- for (i = 1; i <= NUM_TX_RINGS; i++) {
- struct eth_tx_next_bd *tx_next_bd =
- &txdata->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
-
- tx_next_bd->addr_hi =
- cpu_to_le32(U64_HI(txdata->tx_desc_mapping +
- BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
- tx_next_bd->addr_lo =
- cpu_to_le32(U64_LO(txdata->tx_desc_mapping +
- BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
- }
-
- SET_FLAG(txdata->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
- txdata->tx_db.data.zero_fill1 = 0;
- txdata->tx_db.data.prod = 0;
-
- txdata->tx_pkt_prod = 0;
- txdata->tx_pkt_cons = 0;
- txdata->tx_bd_prod = 0;
- txdata->tx_bd_cons = 0;
- txdata->tx_pkt = 0;
-}
-
-static inline void bnx2x_init_tx_rings(struct bnx2x *bp)
-{
- int i;
- u8 cos;
-
- for_each_tx_queue(bp, i)
- for_each_cos_in_tx_queue(&bp->fp[i], cos)
- bnx2x_init_tx_ring_one(&bp->fp[i].txdata[cos]);
-}
-
static inline void bnx2x_set_next_page_rx_bd(struct bnx2x_fastpath *fp)
{
int i;
@@ -1104,80 +952,6 @@ static inline void bnx2x_set_next_page_rx_bd(struct bnx2x_fastpath *fp)
}
}
-static inline void bnx2x_set_next_page_sgl(struct bnx2x_fastpath *fp)
-{
- int i;
-
- for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
- struct eth_rx_sge *sge;
-
- sge = &fp->rx_sge_ring[RX_SGE_CNT * i - 2];
- sge->addr_hi =
- cpu_to_le32(U64_HI(fp->rx_sge_mapping +
- BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
-
- sge->addr_lo =
- cpu_to_le32(U64_LO(fp->rx_sge_mapping +
- BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
- }
-}
-
-static inline void bnx2x_set_next_page_rx_cq(struct bnx2x_fastpath *fp)
-{
- int i;
- for (i = 1; i <= NUM_RCQ_RINGS; i++) {
- struct eth_rx_cqe_next_page *nextpg;
-
- nextpg = (struct eth_rx_cqe_next_page *)
- &fp->rx_comp_ring[RCQ_DESC_CNT * i - 1];
- nextpg->addr_hi =
- cpu_to_le32(U64_HI(fp->rx_comp_mapping +
- BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
- nextpg->addr_lo =
- cpu_to_le32(U64_LO(fp->rx_comp_mapping +
- BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
- }
-}
-
-/* Returns the number of actually allocated BDs */
-static inline int bnx2x_alloc_rx_bds(struct bnx2x_fastpath *fp,
- int rx_ring_size)
-{
- struct bnx2x *bp = fp->bp;
- u16 ring_prod, cqe_ring_prod;
- int i, failure_cnt = 0;
-
- fp->rx_comp_cons = 0;
- cqe_ring_prod = ring_prod = 0;
-
- /* This routine is called only during fo init so
- * fp->eth_q_stats.rx_skb_alloc_failed = 0
- */
- for (i = 0; i < rx_ring_size; i++) {
- if (bnx2x_alloc_rx_data(bp, fp, ring_prod) < 0) {
- failure_cnt++;
- continue;
- }
- ring_prod = NEXT_RX_IDX(ring_prod);
- cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod);
- WARN_ON(ring_prod <= (i - failure_cnt));
- }
-
- if (failure_cnt)
- BNX2X_ERR("was only able to allocate %d rx skbs on queue[%d]\n",
- i - failure_cnt, fp->index);
-
- fp->rx_bd_prod = ring_prod;
- /* Limit the CQE producer by the CQE ring size */
- fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT,
- cqe_ring_prod);
- fp->rx_pkt = fp->rx_calls = 0;
-
- fp->eth_q_stats.rx_skb_alloc_failed += failure_cnt;
-
- return i - failure_cnt;
-}
-
/* Statistics ID are global per chip/path, while Client IDs for E1x are per
* port.
*/
@@ -1406,30 +1180,6 @@ static inline void __storm_memset_struct(struct bnx2x *bp,
REG_WR(bp, addr + (i * 4), data[i]);
}
-static inline void storm_memset_func_cfg(struct bnx2x *bp,
- struct tstorm_eth_function_common_config *tcfg,
- u16 abs_fid)
-{
- size_t size = sizeof(struct tstorm_eth_function_common_config);
-
- u32 addr = BAR_TSTRORM_INTMEM +
- TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
-
- __storm_memset_struct(bp, addr, size, (u32 *)tcfg);
-}
-
-static inline void storm_memset_cmng(struct bnx2x *bp,
- struct cmng_struct_per_port *cmng,
- u8 port)
-{
- size_t size = sizeof(struct cmng_struct_per_port);
-
- u32 addr = BAR_XSTRORM_INTMEM +
- XSTORM_CMNG_PER_PORT_VARS_OFFSET(port);
-
- __storm_memset_struct(bp, addr, size, (u32 *)cmng);
-}
-
/**
* bnx2x_wait_sp_comp - wait for the outstanding SP commands.
*
@@ -1512,93 +1262,6 @@ static inline bool bnx2x_mtu_allows_gro(int mtu)
*/
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
-}
-
#ifdef BCM_CNIC
/**
* bnx2x_get_iscsi_info - update iSCSI params according to licensing info.
@@ -1608,11 +1271,6 @@ static inline void bnx2x_bz_fp(struct bnx2x *bp, int index)
*/
void bnx2x_get_iscsi_info(struct bnx2x *bp);
#endif
-/* returns func by VN for current port */
-static inline int func_by_vn(struct bnx2x *bp, int vn)
-{
- return 2 * vn + BP_PORT(bp);
-}
/**
* bnx2x_link_sync_notify - send notification to other functions.
@@ -1667,7 +1325,8 @@ static inline bool bnx2x_is_valid_ether_addr(struct bnx2x *bp, u8 *addr)
if (is_valid_ether_addr(addr))
return true;
#ifdef BCM_CNIC
- if (is_zero_ether_addr(addr) && IS_MF_STORAGE_SD(bp))
+ if (is_zero_ether_addr(addr) &&
+ (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)))
return true;
#endif
return false;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 2cc0a1703970..ddc18ee5c5ae 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -22,13 +22,10 @@
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/crc32.h>
-
-
#include "bnx2x.h"
#include "bnx2x_cmn.h"
#include "bnx2x_dump.h"
#include "bnx2x_init.h"
-#include "bnx2x_sp.h"
/* Note: in the format strings below %s is replaced by the queue-name which is
* either its index or 'fcoe' for the fcoe queue. Make sure the format string
@@ -595,8 +592,8 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
#define IS_E3_ONLINE(info) (((info) & RI_E3_ONLINE) == RI_E3_ONLINE)
#define IS_E3B0_ONLINE(info) (((info) & RI_E3B0_ONLINE) == RI_E3B0_ONLINE)
-static inline bool bnx2x_is_reg_online(struct bnx2x *bp,
- const struct reg_addr *reg_info)
+static bool bnx2x_is_reg_online(struct bnx2x *bp,
+ const struct reg_addr *reg_info)
{
if (CHIP_IS_E1(bp))
return IS_E1_ONLINE(reg_info->info);
@@ -613,7 +610,7 @@ static inline bool bnx2x_is_reg_online(struct bnx2x *bp,
}
/******* Paged registers info selectors ********/
-static inline const u32 *__bnx2x_get_page_addr_ar(struct bnx2x *bp)
+static const u32 *__bnx2x_get_page_addr_ar(struct bnx2x *bp)
{
if (CHIP_IS_E2(bp))
return page_vals_e2;
@@ -623,7 +620,7 @@ static inline const u32 *__bnx2x_get_page_addr_ar(struct bnx2x *bp)
return NULL;
}
-static inline u32 __bnx2x_get_page_reg_num(struct bnx2x *bp)
+static u32 __bnx2x_get_page_reg_num(struct bnx2x *bp)
{
if (CHIP_IS_E2(bp))
return PAGE_MODE_VALUES_E2;
@@ -633,7 +630,7 @@ static inline u32 __bnx2x_get_page_reg_num(struct bnx2x *bp)
return 0;
}
-static inline const u32 *__bnx2x_get_page_write_ar(struct bnx2x *bp)
+static const u32 *__bnx2x_get_page_write_ar(struct bnx2x *bp)
{
if (CHIP_IS_E2(bp))
return page_write_regs_e2;
@@ -643,7 +640,7 @@ static inline const u32 *__bnx2x_get_page_write_ar(struct bnx2x *bp)
return NULL;
}
-static inline u32 __bnx2x_get_page_write_num(struct bnx2x *bp)
+static u32 __bnx2x_get_page_write_num(struct bnx2x *bp)
{
if (CHIP_IS_E2(bp))
return PAGE_WRITE_REGS_E2;
@@ -653,7 +650,7 @@ static inline u32 __bnx2x_get_page_write_num(struct bnx2x *bp)
return 0;
}
-static inline const struct reg_addr *__bnx2x_get_page_read_ar(struct bnx2x *bp)
+static const struct reg_addr *__bnx2x_get_page_read_ar(struct bnx2x *bp)
{
if (CHIP_IS_E2(bp))
return page_read_regs_e2;
@@ -663,7 +660,7 @@ static inline const struct reg_addr *__bnx2x_get_page_read_ar(struct bnx2x *bp)
return NULL;
}
-static inline u32 __bnx2x_get_page_read_num(struct bnx2x *bp)
+static u32 __bnx2x_get_page_read_num(struct bnx2x *bp)
{
if (CHIP_IS_E2(bp))
return PAGE_READ_REGS_E2;
@@ -673,7 +670,7 @@ static inline u32 __bnx2x_get_page_read_num(struct bnx2x *bp)
return 0;
}
-static inline int __bnx2x_get_regs_len(struct bnx2x *bp)
+static int __bnx2x_get_regs_len(struct bnx2x *bp)
{
int num_pages = __bnx2x_get_page_reg_num(bp);
int page_write_num = __bnx2x_get_page_write_num(bp);
@@ -718,7 +715,7 @@ static int bnx2x_get_regs_len(struct net_device *dev)
* ("read address"). There may be more than one write address per "page" and
* more than one read address per write address.
*/
-static inline void bnx2x_read_pages_regs(struct bnx2x *bp, u32 *p)
+static void bnx2x_read_pages_regs(struct bnx2x *bp, u32 *p)
{
u32 i, j, k, n;
/* addresses of the paged registers */
@@ -747,7 +744,7 @@ static inline void bnx2x_read_pages_regs(struct bnx2x *bp, u32 *p)
}
}
-static inline void __bnx2x_get_regs(struct bnx2x *bp, u32 *p)
+static void __bnx2x_get_regs(struct bnx2x *bp, u32 *p)
{
u32 i, j;
@@ -1433,7 +1430,7 @@ static void bnx2x_get_ringparam(struct net_device *dev,
else
ering->rx_pending = MAX_RX_AVAIL;
- ering->tx_max_pending = MAX_TX_AVAIL;
+ ering->tx_max_pending = IS_MF_FCOE_AFEX(bp) ? 0 : MAX_TX_AVAIL;
ering->tx_pending = bp->tx_ring_size;
}
@@ -1451,7 +1448,7 @@ static int bnx2x_set_ringparam(struct net_device *dev,
if ((ering->rx_pending > MAX_RX_AVAIL) ||
(ering->rx_pending < (bp->disable_tpa ? MIN_RX_SIZE_NONTPA :
MIN_RX_SIZE_TPA)) ||
- (ering->tx_pending > MAX_TX_AVAIL) ||
+ (ering->tx_pending > (IS_MF_FCOE_AFEX(bp) ? 0 : MAX_TX_AVAIL)) ||
(ering->tx_pending <= MAX_SKB_FRAGS + 4)) {
DP(BNX2X_MSG_ETHTOOL, "Command parameters not supported\n");
return -EINVAL;
@@ -2212,7 +2209,7 @@ static void bnx2x_self_test(struct net_device *dev,
/* ethtool statistics are displayed for all regular ethernet queues and the
* fcoe L2 queue if not disabled
*/
-static inline int bnx2x_num_stat_queues(struct bnx2x *bp)
+static int bnx2x_num_stat_queues(struct bnx2x *bp)
{
return BNX2X_NUM_ETH_QUEUES(bp);
}
@@ -2396,10 +2393,7 @@ static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev)
{
- struct bnx2x *bp = netdev_priv(dev);
-
- return (bp->multi_mode == ETH_RSS_MODE_DISABLED ?
- 0 : T_ETH_INDIRECTION_TABLE_SIZE);
+ return T_ETH_INDIRECTION_TABLE_SIZE;
}
static int bnx2x_get_rxfh_indir(struct net_device *dev, u32 *indir)
@@ -2445,7 +2439,7 @@ static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir)
ind_table[i] = indir[i] + bp->fp->cl_id;
}
- return bnx2x_config_rss_pf(bp, ind_table, false);
+ return bnx2x_config_rss_eth(bp, ind_table, false);
}
static const struct ethtool_ops bnx2x_ethtool_ops = {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
index b9b263323436..426f77aa721a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
@@ -387,7 +387,7 @@
#define STATS_QUERY_CMD_COUNT 16
-#define NIV_LIST_TABLE_SIZE 4096
+#define AFEX_LIST_TABLE_SIZE 4096
#define INVALID_VNIC_ID 0xFF
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
index dbff5915b81a..a440a8ba85f2 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
@@ -833,6 +833,7 @@ struct shared_feat_cfg { /* NVRAM Offset */
#define SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF 0x00000100
#define SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4 0x00000200
#define SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT 0x00000300
+ #define SHARED_FEAT_CFG_FORCE_SF_MODE_AFEX_MODE 0x00000400
/* The interval in seconds between sending LLDP packets. Set to zero
to disable the feature */
@@ -1235,6 +1236,8 @@ struct drv_func_mb {
#define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL 0x00050006
#define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL 0xa1000000
#define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL 0x00050234
+ #define DRV_MSG_CODE_VRFY_AFEX_SUPPORTED 0xa2000000
+ #define REQ_BC_VER_4_VRFY_AFEX_SUPPORTED 0x00070002
#define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED 0x00070014
#define REQ_BC_VER_4_PFC_STATS_SUPPORTED 0x00070201
@@ -1242,6 +1245,13 @@ struct drv_func_mb {
#define DRV_MSG_CODE_DCBX_PMF_DRV_OK 0xb2000000
#define DRV_MSG_CODE_VF_DISABLED_DONE 0xc0000000
+
+ #define DRV_MSG_CODE_AFEX_DRIVER_SETMAC 0xd0000000
+ #define DRV_MSG_CODE_AFEX_LISTGET_ACK 0xd1000000
+ #define DRV_MSG_CODE_AFEX_LISTSET_ACK 0xd2000000
+ #define DRV_MSG_CODE_AFEX_STATSGET_ACK 0xd3000000
+ #define DRV_MSG_CODE_AFEX_VIFSET_ACK 0xd4000000
+
#define DRV_MSG_CODE_DRV_INFO_ACK 0xd8000000
#define DRV_MSG_CODE_DRV_INFO_NACK 0xd9000000
@@ -1299,6 +1309,14 @@ struct drv_func_mb {
#define FW_MSG_CODE_VRFY_OPT_MDL_INVLD_IMG 0xa0200000
#define FW_MSG_CODE_VRFY_OPT_MDL_UNAPPROVED 0xa0300000
#define FW_MSG_CODE_VF_DISABLED_DONE 0xb0000000
+ #define FW_MSG_CODE_HW_SET_INVALID_IMAGE 0xb0100000
+
+ #define FW_MSG_CODE_AFEX_DRIVER_SETMAC_DONE 0xd0100000
+ #define FW_MSG_CODE_AFEX_LISTGET_ACK 0xd1100000
+ #define FW_MSG_CODE_AFEX_LISTSET_ACK 0xd2100000
+ #define FW_MSG_CODE_AFEX_STATSGET_ACK 0xd3100000
+ #define FW_MSG_CODE_AFEX_VIFSET_ACK 0xd4100000
+
#define FW_MSG_CODE_DRV_INFO_ACK 0xd8100000
#define FW_MSG_CODE_DRV_INFO_NACK 0xd9100000
@@ -1357,6 +1375,12 @@ struct drv_func_mb {
#define DRV_STATUS_DCBX_EVENT_MASK 0x000f0000
#define DRV_STATUS_DCBX_NEGOTIATION_RESULTS 0x00010000
+ #define DRV_STATUS_AFEX_EVENT_MASK 0x03f00000
+ #define DRV_STATUS_AFEX_LISTGET_REQ 0x00100000
+ #define DRV_STATUS_AFEX_LISTSET_REQ 0x00200000
+ #define DRV_STATUS_AFEX_STATSGET_REQ 0x00400000
+ #define DRV_STATUS_AFEX_VIFSET_REQ 0x00800000
+
#define DRV_STATUS_DRV_INFO_REQ 0x04000000
u32 virt_mac_upper;
@@ -1448,7 +1472,26 @@ struct func_mf_cfg {
#define FUNC_MF_CFG_E1HOV_TAG_SHIFT 0
#define FUNC_MF_CFG_E1HOV_TAG_DEFAULT FUNC_MF_CFG_E1HOV_TAG_MASK
- u32 reserved[2];
+ /* afex default VLAN ID - 12 bits */
+ #define FUNC_MF_CFG_AFEX_VLAN_MASK 0x0fff0000
+ #define FUNC_MF_CFG_AFEX_VLAN_SHIFT 16
+
+ u32 afex_config;
+ #define FUNC_MF_CFG_AFEX_COS_FILTER_MASK 0x000000ff
+ #define FUNC_MF_CFG_AFEX_COS_FILTER_SHIFT 0
+ #define FUNC_MF_CFG_AFEX_MBA_ENABLED_MASK 0x0000ff00
+ #define FUNC_MF_CFG_AFEX_MBA_ENABLED_SHIFT 8
+ #define FUNC_MF_CFG_AFEX_MBA_ENABLED_VAL 0x00000100
+ #define FUNC_MF_CFG_AFEX_VLAN_MODE_MASK 0x000f0000
+ #define FUNC_MF_CFG_AFEX_VLAN_MODE_SHIFT 16
+
+ u32 reserved;
+};
+
+enum mf_cfg_afex_vlan_mode {
+ FUNC_MF_CFG_AFEX_VLAN_TRUNK_MODE = 0,
+ FUNC_MF_CFG_AFEX_VLAN_ACCESS_MODE,
+ FUNC_MF_CFG_AFEX_VLAN_TRUNK_TAG_NATIVE_MODE
};
/* This structure is not applicable and should not be accessed on 57711 */
@@ -1945,18 +1988,29 @@ struct shmem2_region {
u32 nvm_retain_bitmap_addr; /* 0x0070 */
- u32 reserved1; /* 0x0074 */
+ /* afex support of that driver */
+ u32 afex_driver_support; /* 0x0074 */
+ #define SHMEM_AFEX_VERSION_MASK 0x100f
+ #define SHMEM_AFEX_SUPPORTED_VERSION_ONE 0x1001
+ #define SHMEM_AFEX_REDUCED_DRV_LOADED 0x8000
- u32 reserved2[E2_FUNC_MAX];
+ /* driver receives addr in scratchpad to which it should respond */
+ u32 afex_scratchpad_addr_to_write[E2_FUNC_MAX];
- u32 reserved3[E2_FUNC_MAX];/* 0x0088 */
- u32 reserved4[E2_FUNC_MAX];/* 0x0098 */
+ /* generic params from MCP to driver (value depends on the msg sent
+ * to driver
+ */
+ u32 afex_param1_to_driver[E2_FUNC_MAX]; /* 0x0088 */
+ u32 afex_param2_to_driver[E2_FUNC_MAX]; /* 0x0098 */
u32 swim_base_addr; /* 0x0108 */
u32 swim_funcs;
u32 swim_main_cb;
- u32 reserved5[2];
+ /* bitmap notifying which VIF profiles stored in nvram are enabled by
+ * switch
+ */
+ u32 afex_profiles_enabled[2];
/* generic flags controlled by the driver */
u32 drv_flags;
@@ -2696,10 +2750,51 @@ union drv_info_to_mcp {
struct fcoe_stats_info fcoe_stat;
struct iscsi_stats_info iscsi_stat;
};
+
+/* stats collected for afex.
+ * NOTE: structure is exactly as expected to be received by the switch.
+ * order must remain exactly as is unless protocol changes !
+ */
+struct afex_stats {
+ u32 tx_unicast_frames_hi;
+ u32 tx_unicast_frames_lo;
+ u32 tx_unicast_bytes_hi;
+ u32 tx_unicast_bytes_lo;
+ u32 tx_multicast_frames_hi;
+ u32 tx_multicast_frames_lo;
+ u32 tx_multicast_bytes_hi;
+ u32 tx_multicast_bytes_lo;
+ u32 tx_broadcast_frames_hi;
+ u32 tx_broadcast_frames_lo;
+ u32 tx_broadcast_bytes_hi;
+ u32 tx_broadcast_bytes_lo;
+ u32 tx_frames_discarded_hi;
+ u32 tx_frames_discarded_lo;
+ u32 tx_frames_dropped_hi;
+ u32 tx_frames_dropped_lo;
+
+ u32 rx_unicast_frames_hi;
+ u32 rx_unicast_frames_lo;
+ u32 rx_unicast_bytes_hi;
+ u32 rx_unicast_bytes_lo;
+ u32 rx_multicast_frames_hi;
+ u32 rx_multicast_frames_lo;
+ u32 rx_multicast_bytes_hi;
+ u32 rx_multicast_bytes_lo;
+ u32 rx_broadcast_frames_hi;
+ u32 rx_broadcast_frames_lo;
+ u32 rx_broadcast_bytes_hi;
+ u32 rx_broadcast_bytes_lo;
+ u32 rx_frames_discarded_hi;
+ u32 rx_frames_discarded_lo;
+ u32 rx_frames_dropped_hi;
+ u32 rx_frames_dropped_lo;
+};
+
#define BCM_5710_FW_MAJOR_VERSION 7
#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_REVISION_VERSION 51
+#define BCM_5710_FW_ENGINEERING_VERSION 0
#define BCM_5710_FW_COMPILE_FLAGS 1
@@ -3389,7 +3484,7 @@ struct client_init_tx_data {
#define CLIENT_INIT_TX_DATA_RESERVED1 (0xFFF<<4)
#define CLIENT_INIT_TX_DATA_RESERVED1_SHIFT 4
u8 default_vlan_flg;
- u8 reserved2;
+ u8 force_default_pri_flg;
__le32 reserved3;
};
@@ -4375,8 +4470,21 @@ struct fcoe_statistics_params {
/*
+ * The data afex vif list ramrod need
+ */
+struct afex_vif_list_ramrod_data {
+ u8 afex_vif_list_command;
+ u8 func_bit_map;
+ __le16 vif_list_index;
+ u8 func_to_clear;
+ u8 echo;
+ __le16 reserved1;
+};
+
+
+/*
* cfc delete event data
-*/
+ */
struct cfc_del_event_data {
u32 cid;
u32 reserved0;
@@ -4448,6 +4556,65 @@ struct cmng_struct_per_port {
struct cmng_flags_per_port flags;
};
+/*
+ * a single rate shaping counter. can be used as protocol or vnic counter
+ */
+struct rate_shaping_counter {
+ u32 quota;
+#if defined(__BIG_ENDIAN)
+ u16 __reserved0;
+ u16 rate;
+#elif defined(__LITTLE_ENDIAN)
+ u16 rate;
+ u16 __reserved0;
+#endif
+};
+
+/*
+ * per-vnic rate shaping variables
+ */
+struct rate_shaping_vars_per_vn {
+ struct rate_shaping_counter vn_counter;
+};
+
+/*
+ * per-vnic fairness variables
+ */
+struct fairness_vars_per_vn {
+ u32 cos_credit_delta[MAX_COS_NUMBER];
+ u32 vn_credit_delta;
+ u32 __reserved0;
+};
+
+/*
+ * cmng port init state
+ */
+struct cmng_vnic {
+ struct rate_shaping_vars_per_vn vnic_max_rate[4];
+ struct fairness_vars_per_vn vnic_min_rate[4];
+};
+
+/*
+ * cmng port init state
+ */
+struct cmng_init {
+ struct cmng_struct_per_port port;
+ struct cmng_vnic vnic;
+};
+
+
+/*
+ * driver parameters for congestion management init, all rates are in Mbps
+ */
+struct cmng_init_input {
+ u32 port_rate;
+ u16 vnic_min_rate[4];
+ u16 vnic_max_rate[4];
+ u16 cos_min_rate[MAX_COS_NUMBER];
+ u16 cos_to_pause_mask[MAX_COS_NUMBER];
+ struct cmng_flags_per_port flags;
+};
+
/*
* Protocol-common command ID for slow path elements
@@ -4462,7 +4629,7 @@ enum common_spqe_cmd_id {
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_AFEX_VIF_LISTS,
MAX_COMMON_SPQE_CMD_ID
};
@@ -4670,6 +4837,17 @@ struct malicious_vf_event_data {
};
/*
+ * vif list event data
+ */
+struct vif_list_event_data {
+ u8 func_bit_map;
+ u8 echo;
+ __le16 reserved0;
+ __le32 reserved1;
+ __le32 reserved2;
+};
+
+/*
* union for all event ring message types
*/
union event_data {
@@ -4678,6 +4856,7 @@ union event_data {
struct cfc_del_event_data cfc_del_event;
struct vf_flr_event_data vf_flr_event;
struct malicious_vf_event_data malicious_vf_event;
+ struct vif_list_event_data vif_list_event;
};
@@ -4743,7 +4922,7 @@ enum event_ring_opcode {
EVENT_RING_OPCODE_FORWARD_SETUP,
EVENT_RING_OPCODE_RSS_UPDATE_RULES,
EVENT_RING_OPCODE_FUNCTION_UPDATE,
- EVENT_RING_OPCODE_RESERVED1,
+ EVENT_RING_OPCODE_AFEX_VIF_LISTS,
EVENT_RING_OPCODE_SET_MAC,
EVENT_RING_OPCODE_CLASSIFICATION_RULES,
EVENT_RING_OPCODE_FILTERS_RULES,
@@ -4763,16 +4942,6 @@ enum fairness_mode {
/*
- * per-vnic fairness variables
- */
-struct fairness_vars_per_vn {
- u32 cos_credit_delta[MAX_COS_NUMBER];
- u32 vn_credit_delta;
- u32 __reserved0;
-};
-
-
-/*
* Priority and cos
*/
struct priority_cos {
@@ -4800,12 +4969,27 @@ struct flow_control_configuration {
struct function_start_data {
__le16 function_mode;
__le16 sd_vlan_tag;
- u16 reserved;
+ __le16 vif_id;
u8 path_id;
u8 network_cos_mode;
};
+struct function_update_data {
+ u8 vif_id_change_flg;
+ u8 afex_default_vlan_change_flg;
+ u8 allowed_priorities_change_flg;
+ u8 network_cos_mode_change_flg;
+ __le16 vif_id;
+ __le16 afex_default_vlan;
+ u8 allowed_priorities;
+ u8 network_cos_mode;
+ u8 lb_mode_en;
+ u8 reserved0;
+ __le32 reserved1;
+};
+
+
/*
* FW version stored in the Xstorm RAM
*/
@@ -5003,7 +5187,7 @@ enum mf_mode {
SINGLE_FUNCTION,
MULTI_FUNCTION_SD,
MULTI_FUNCTION_SI,
- MULTI_FUNCTION_RESERVED,
+ MULTI_FUNCTION_AFEX,
MAX_MF_MODE
};
@@ -5128,6 +5312,7 @@ union protocol_common_specific_data {
u8 protocol_data[8];
struct regpair phy_address;
struct regpair mac_config_addr;
+ struct afex_vif_list_ramrod_data afex_vif_list_data;
};
/*
@@ -5140,29 +5325,6 @@ struct protocol_common_spe {
/*
- * a single rate shaping counter. can be used as protocol or vnic counter
- */
-struct rate_shaping_counter {
- u32 quota;
-#if defined(__BIG_ENDIAN)
- u16 __reserved0;
- u16 rate;
-#elif defined(__LITTLE_ENDIAN)
- u16 rate;
- u16 __reserved0;
-#endif
-};
-
-
-/*
- * per-vnic rate shaping variables
- */
-struct rate_shaping_vars_per_vn {
- struct rate_shaping_counter vn_counter;
-};
-
-
-/*
* The send queue element
*/
struct slow_path_element {
@@ -5330,6 +5492,18 @@ enum vf_pf_channel_state {
/*
+ * vif_list_rule_kind
+ */
+enum vif_list_rule_kind {
+ VIF_LIST_RULE_SET,
+ VIF_LIST_RULE_GET,
+ VIF_LIST_RULE_CLEAR_ALL,
+ VIF_LIST_RULE_CLEAR_FUNC,
+ MAX_VIF_LIST_RULE_KIND
+};
+
+
+/*
* zone A per-queue data
*/
struct xstorm_queue_zone_data {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
index 29f5c3cca31a..559c396d45cc 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
@@ -125,7 +125,7 @@ enum {
MODE_MF = 0x00000100,
MODE_MF_SD = 0x00000200,
MODE_MF_SI = 0x00000400,
- MODE_MF_NIV = 0x00000800,
+ MODE_MF_AFEX = 0x00000800,
MODE_E3_A0 = 0x00001000,
MODE_E3_B0 = 0x00002000,
MODE_COS3 = 0x00004000,
@@ -241,7 +241,8 @@ static inline void bnx2x_map_q_cos(struct bnx2x *bp, u32 q_num, u32 new_cos)
REG_WR(bp, reg_addr, reg_bit_map | q_bit_map);
/* set/clear queue bit in command-queue bit map
- (E2/E3A0 only, valid COS values are 0/1) */
+ * (E2/E3A0 only, valid COS values are 0/1)
+ */
if (!(INIT_MODE_FLAGS(bp) & MODE_E3_B0)) {
reg_addr = BNX2X_Q_CMDQ_REG_ADDR(pf_q_num);
reg_bit_map = REG_RD(bp, reg_addr);
@@ -277,7 +278,215 @@ static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode,
}
-/* Returns the index of start or end of a specific block stage in ops array*/
+/* congestion managment port init api description
+ * the api works as follows:
+ * the driver should pass the cmng_init_input struct, the port_init function
+ * will prepare the required internal ram structure which will be passed back
+ * to the driver (cmng_init) that will write it into the internal ram.
+ *
+ * IMPORTANT REMARKS:
+ * 1. the cmng_init struct does not represent the contiguous internal ram
+ * structure. the driver should use the XSTORM_CMNG_PERPORT_VARS_OFFSET
+ * offset in order to write the port sub struct and the
+ * PFID_FROM_PORT_AND_VNIC offset for writing the vnic sub struct (in other
+ * words - don't use memcpy!).
+ * 2. although the cmng_init struct is filled for the maximal vnic number
+ * possible, the driver should only write the valid vnics into the internal
+ * ram according to the appropriate port mode.
+ */
+#define BITS_TO_BYTES(x) ((x)/8)
+
+/* CMNG constants, as derived from system spec calculations */
+
+/* default MIN rate in case VNIC min rate is configured to zero- 100Mbps */
+#define DEF_MIN_RATE 100
+
+/* resolution of the rate shaping timer - 400 usec */
+#define RS_PERIODIC_TIMEOUT_USEC 400
+
+/* number of bytes in single QM arbitration cycle -
+ * coefficient for calculating the fairness timer
+ */
+#define QM_ARB_BYTES 160000
+
+/* resolution of Min algorithm 1:100 */
+#define MIN_RES 100
+
+/* how many bytes above threshold for
+ * the minimal credit of Min algorithm
+ */
+#define MIN_ABOVE_THRESH 32768
+
+/* Fairness algorithm integration time coefficient -
+ * for calculating the actual Tfair
+ */
+#define T_FAIR_COEF ((MIN_ABOVE_THRESH + QM_ARB_BYTES) * 8 * MIN_RES)
+
+/* Memory of fairness algorithm - 2 cycles */
+#define FAIR_MEM 2
+#define SAFC_TIMEOUT_USEC 52
+
+#define SDM_TICKS 4
+
+
+static inline void bnx2x_init_max(const struct cmng_init_input *input_data,
+ u32 r_param, struct cmng_init *ram_data)
+{
+ u32 vnic;
+ struct cmng_vnic *vdata = &ram_data->vnic;
+ struct cmng_struct_per_port *pdata = &ram_data->port;
+ /* rate shaping per-port variables
+ * 100 micro seconds in SDM ticks = 25
+ * since each tick is 4 microSeconds
+ */
+
+ pdata->rs_vars.rs_periodic_timeout =
+ RS_PERIODIC_TIMEOUT_USEC / SDM_TICKS;
+
+ /* this is the threshold below which no timer arming will occur.
+ * 1.25 coefficient is for the threshold to be a little bigger
+ * then the real time to compensate for timer in-accuracy
+ */
+ pdata->rs_vars.rs_threshold =
+ (5 * RS_PERIODIC_TIMEOUT_USEC * r_param)/4;
+
+ /* rate shaping per-vnic variables */
+ for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++) {
+ /* global vnic counter */
+ vdata->vnic_max_rate[vnic].vn_counter.rate =
+ input_data->vnic_max_rate[vnic];
+ /* maximal Mbps for this vnic
+ * the quota in each timer period - number of bytes
+ * transmitted in this period
+ */
+ vdata->vnic_max_rate[vnic].vn_counter.quota =
+ RS_PERIODIC_TIMEOUT_USEC *
+ (u32)vdata->vnic_max_rate[vnic].vn_counter.rate / 8;
+ }
+
+}
+
+static inline void bnx2x_init_min(const struct cmng_init_input *input_data,
+ u32 r_param, struct cmng_init *ram_data)
+{
+ u32 vnic, fair_periodic_timeout_usec, vnicWeightSum, tFair;
+ struct cmng_vnic *vdata = &ram_data->vnic;
+ struct cmng_struct_per_port *pdata = &ram_data->port;
+
+ /* this is the resolution of the fairness timer */
+ fair_periodic_timeout_usec = QM_ARB_BYTES / r_param;
+
+ /* fairness per-port variables
+ * for 10G it is 1000usec. for 1G it is 10000usec.
+ */
+ tFair = T_FAIR_COEF / input_data->port_rate;
+
+ /* this is the threshold below which we won't arm the timer anymore */
+ pdata->fair_vars.fair_threshold = QM_ARB_BYTES;
+
+ /* we multiply by 1e3/8 to get bytes/msec. We don't want the credits
+ * to pass a credit of the T_FAIR*FAIR_MEM (algorithm resolution)
+ */
+ pdata->fair_vars.upper_bound = r_param * tFair * FAIR_MEM;
+
+ /* since each tick is 4 microSeconds */
+ pdata->fair_vars.fairness_timeout =
+ fair_periodic_timeout_usec / SDM_TICKS;
+
+ /* calculate sum of weights */
+ vnicWeightSum = 0;
+
+ for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++)
+ vnicWeightSum += input_data->vnic_min_rate[vnic];
+
+ /* global vnic counter */
+ if (vnicWeightSum > 0) {
+ /* fairness per-vnic variables */
+ for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++) {
+ /* this is the credit for each period of the fairness
+ * algorithm - number of bytes in T_FAIR (this vnic
+ * share of the port rate)
+ */
+ vdata->vnic_min_rate[vnic].vn_credit_delta =
+ (u32)input_data->vnic_min_rate[vnic] * 100 *
+ (T_FAIR_COEF / (8 * 100 * vnicWeightSum));
+ if (vdata->vnic_min_rate[vnic].vn_credit_delta <
+ pdata->fair_vars.fair_threshold +
+ MIN_ABOVE_THRESH) {
+ vdata->vnic_min_rate[vnic].vn_credit_delta =
+ pdata->fair_vars.fair_threshold +
+ MIN_ABOVE_THRESH;
+ }
+ }
+ }
+}
+
+static inline void bnx2x_init_fw_wrr(const struct cmng_init_input *input_data,
+ u32 r_param, struct cmng_init *ram_data)
+{
+ u32 vnic, cos;
+ u32 cosWeightSum = 0;
+ struct cmng_vnic *vdata = &ram_data->vnic;
+ struct cmng_struct_per_port *pdata = &ram_data->port;
+
+ for (cos = 0; cos < MAX_COS_NUMBER; cos++)
+ cosWeightSum += input_data->cos_min_rate[cos];
+
+ if (cosWeightSum > 0) {
+
+ for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++) {
+ /* Since cos and vnic shouldn't work together the rate
+ * to divide between the coses is the port rate.
+ */
+ u32 *ccd = vdata->vnic_min_rate[vnic].cos_credit_delta;
+ for (cos = 0; cos < MAX_COS_NUMBER; cos++) {
+ /* this is the credit for each period of
+ * the fairness algorithm - number of bytes
+ * in T_FAIR (this cos share of the vnic rate)
+ */
+ ccd[cos] =
+ (u32)input_data->cos_min_rate[cos] * 100 *
+ (T_FAIR_COEF / (8 * 100 * cosWeightSum));
+ if (ccd[cos] < pdata->fair_vars.fair_threshold
+ + MIN_ABOVE_THRESH) {
+ ccd[cos] =
+ pdata->fair_vars.fair_threshold +
+ MIN_ABOVE_THRESH;
+ }
+ }
+ }
+ }
+}
+
+static inline void bnx2x_init_safc(const struct cmng_init_input *input_data,
+ struct cmng_init *ram_data)
+{
+ /* in microSeconds */
+ ram_data->port.safc_vars.safc_timeout_usec = SAFC_TIMEOUT_USEC;
+}
+
+/* Congestion management port init */
+static inline void bnx2x_init_cmng(const struct cmng_init_input *input_data,
+ struct cmng_init *ram_data)
+{
+ u32 r_param;
+ memset(ram_data, 0, sizeof(struct cmng_init));
+
+ ram_data->port.flags = input_data->flags;
+
+ /* number of bytes transmitted in a rate of 10Gbps
+ * in one usec = 1.25KB.
+ */
+ r_param = BITS_TO_BYTES(input_data->port_rate);
+ bnx2x_init_max(input_data, r_param, ram_data);
+ bnx2x_init_min(input_data, r_param, ram_data);
+ bnx2x_init_fw_wrr(input_data, r_param, ram_data);
+ bnx2x_init_safc(input_data, ram_data);
+}
+
+
+
+/* Returns the index of start or end of a specific block stage in ops array */
#define BLOCK_OPS_IDX(block, stage, end) \
(2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
@@ -499,9 +708,7 @@ static inline void bnx2x_disable_blocks_parity(struct bnx2x *bp)
bnx2x_set_mcp_parity(bp, false);
}
-/**
- * Clear the parity error status registers.
- */
+/* Clear the parity error status registers. */
static inline void bnx2x_clear_blocks_parity(struct bnx2x *bp)
{
int i;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 64392ec410a3..a3fb7215cd89 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -138,7 +138,6 @@
-/* */
#define SFP_EEPROM_CON_TYPE_ADDR 0x2
#define SFP_EEPROM_CON_TYPE_VAL_LC 0x7
#define SFP_EEPROM_CON_TYPE_VAL_COPPER 0x21
@@ -404,8 +403,7 @@ static void bnx2x_ets_e2e3a0_disabled(struct link_params *params)
DP(NETIF_MSG_LINK, "ETS E2E3 disabled configuration\n");
- /*
- * mapping between entry priority to client number (0,1,2 -debug and
+ /* mapping between entry priority to client number (0,1,2 -debug and
* management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
* 3bits client num.
* PRI4 | PRI3 | PRI2 | PRI1 | PRI0
@@ -413,8 +411,7 @@ static void bnx2x_ets_e2e3a0_disabled(struct link_params *params)
*/
REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, 0x4688);
- /*
- * Bitmap of 5bits length. Each bit specifies whether the entry behaves
+ /* Bitmap of 5bits length. Each bit specifies whether the entry behaves
* as strict. Bits 0,1,2 - debug and management entries, 3 -
* COS0 entry, 4 - COS1 entry.
* COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
@@ -425,13 +422,11 @@ static void bnx2x_ets_e2e3a0_disabled(struct link_params *params)
REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
/* defines which entries (clients) are subjected to WFQ arbitration */
REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
- /*
- * For strict priority entries defines the number of consecutive
+ /* For strict priority entries defines the number of consecutive
* slots for the highest priority.
*/
REG_WR(bp, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
- /*
- * mapping between the CREDIT_WEIGHT registers and actual client
+ /* mapping between the CREDIT_WEIGHT registers and actual client
* numbers
*/
REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0);
@@ -443,8 +438,7 @@ static void bnx2x_ets_e2e3a0_disabled(struct link_params *params)
REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, 0);
/* ETS mode disable */
REG_WR(bp, PBF_REG_ETS_ENABLED, 0);
- /*
- * If ETS mode is enabled (there is no strict priority) defines a WFQ
+ /* If ETS mode is enabled (there is no strict priority) defines a WFQ
* weight for COS0/COS1.
*/
REG_WR(bp, PBF_REG_COS0_WEIGHT, 0x2710);
@@ -471,10 +465,9 @@ static u32 bnx2x_ets_get_min_w_val_nig(const struct link_vars *vars)
min_w_val = ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS;
} else
min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
- /**
- * If the link isn't up (static configuration for example ) The
- * link will be according to 20GBPS.
- */
+ /* If the link isn't up (static configuration for example ) The
+ * link will be according to 20GBPS.
+ */
return min_w_val;
}
/******************************************************************************
@@ -538,8 +531,7 @@ static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params,
struct bnx2x *bp = params->bp;
const u8 port = params->port;
const u32 min_w_val = bnx2x_ets_get_min_w_val_nig(vars);
- /**
- * mapping between entry priority to client number (0,1,2 -debug and
+ /* Mapping between entry priority to client number (0,1,2 -debug and
* management clients, 3 - COS0 client, 4 - COS1, ... 8 -
* COS5)(HIGHEST) 4bits client num.TODO_ETS - Should be done by
* reset value or init tool
@@ -551,18 +543,14 @@ static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params,
REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB, 0x76543210);
REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB, 0x8);
}
- /**
- * For strict priority entries defines the number of consecutive
- * slots for the highest priority.
- */
- /* TODO_ETS - Should be done by reset value or init tool */
+ /* For strict priority entries defines the number of consecutive
+ * slots for the highest priority.
+ */
REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS :
NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
- /**
- * mapping between the CREDIT_WEIGHT registers and actual client
+ /* Mapping between the CREDIT_WEIGHT registers and actual client
* numbers
*/
- /* TODO_ETS - Should be done by reset value or init tool */
if (port) {
/*Port 1 has 6 COS*/
REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB, 0x210543);
@@ -574,8 +562,7 @@ static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params,
REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x5);
}
- /**
- * Bitmap of 5bits length. Each bit specifies whether the entry behaves
+ /* Bitmap of 5bits length. Each bit specifies whether the entry behaves
* as strict. Bits 0,1,2 - debug and management entries, 3 -
* COS0 entry, 4 - COS1 entry.
* COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
@@ -590,13 +577,12 @@ static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params,
REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
- /**
- * Please notice the register address are note continuous and a
- * for here is note appropriate.In 2 port mode port0 only COS0-5
- * can be used. DEBUG1,DEBUG1,MGMT are never used for WFQ* In 4
- * port mode port1 only COS0-2 can be used. DEBUG1,DEBUG1,MGMT
- * are never used for WFQ
- */
+ /* Please notice the register address are note continuous and a
+ * for here is note appropriate.In 2 port mode port0 only COS0-5
+ * can be used. DEBUG1,DEBUG1,MGMT are never used for WFQ* In 4
+ * port mode port1 only COS0-2 can be used. DEBUG1,DEBUG1,MGMT
+ * are never used for WFQ
+ */
REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0x0);
REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
@@ -633,10 +619,9 @@ static void bnx2x_ets_e3b0_set_credit_upper_bound_pbf(
u32 base_upper_bound = 0;
u8 max_cos = 0;
u8 i = 0;
- /**
- * In 2 port mode port0 has COS0-5 that can be used for WFQ.In 4
- * port mode port1 has COS0-2 that can be used for WFQ.
- */
+ /* In 2 port mode port0 has COS0-5 that can be used for WFQ.In 4
+ * port mode port1 has COS0-2 that can be used for WFQ.
+ */
if (!port) {
base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P0;
max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
@@ -666,8 +651,7 @@ static void bnx2x_ets_e3b0_pbf_disabled(const struct link_params *params)
u32 base_weight = 0;
u8 max_cos = 0;
- /**
- * mapping between entry priority to client number 0 - COS0
+ /* Mapping between entry priority to client number 0 - COS0
* client, 2 - COS1, ... 5 - COS5)(HIGHEST) 4bits client num.
* TODO_ETS - Should be done by reset value or init tool
*/
@@ -695,10 +679,9 @@ static void bnx2x_ets_e3b0_pbf_disabled(const struct link_params *params)
REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0 , 0);
- /**
- * In 2 port mode port0 has COS0-5 that can be used for WFQ.
- * In 4 port mode port1 has COS0-2 that can be used for WFQ.
- */
+ /* In 2 port mode port0 has COS0-5 that can be used for WFQ.
+ * In 4 port mode port1 has COS0-2 that can be used for WFQ.
+ */
if (!port) {
base_weight = PBF_REG_COS0_WEIGHT_P0;
max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
@@ -738,7 +721,7 @@ static int bnx2x_ets_e3b0_disabled(const struct link_params *params,
/******************************************************************************
* Description:
* Disable will return basicly the values to init values.
-*.
+*
******************************************************************************/
int bnx2x_ets_disabled(struct link_params *params,
struct link_vars *vars)
@@ -867,7 +850,7 @@ static int bnx2x_ets_e3b0_set_cos_bw(struct bnx2x *bp,
/******************************************************************************
* Description:
* Calculate the total BW.A value of 0 isn't legal.
-*.
+*
******************************************************************************/
static int bnx2x_ets_e3b0_get_total_bw(
const struct link_params *params,
@@ -879,7 +862,6 @@ static int bnx2x_ets_e3b0_get_total_bw(
u8 is_bw_cos_exist = 0;
*total_bw = 0 ;
-
/* Calculate total BW requested */
for (cos_idx = 0; cos_idx < ets_params->num_of_cos; cos_idx++) {
if (ets_params->cos[cos_idx].state == bnx2x_cos_state_bw) {
@@ -887,10 +869,9 @@ static int bnx2x_ets_e3b0_get_total_bw(
if (!ets_params->cos[cos_idx].params.bw_params.bw) {
DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config BW"
"was set to 0\n");
- /*
- * This is to prevent a state when ramrods
+ /* This is to prevent a state when ramrods
* can't be sent
- */
+ */
ets_params->cos[cos_idx].params.bw_params.bw
= 1;
}
@@ -908,8 +889,7 @@ static int bnx2x_ets_e3b0_get_total_bw(
}
DP(NETIF_MSG_LINK,
"bnx2x_ets_E3B0_config total BW should be 100\n");
- /*
- * We can handle a case whre the BW isn't 100 this can happen
+ /* We can handle a case whre the BW isn't 100 this can happen
* if the TC are joined.
*/
}
@@ -919,7 +899,7 @@ static int bnx2x_ets_e3b0_get_total_bw(
/******************************************************************************
* Description:
* Invalidate all the sp_pri_to_cos.
-*.
+*
******************************************************************************/
static void bnx2x_ets_e3b0_sp_pri_to_cos_init(u8 *sp_pri_to_cos)
{
@@ -931,7 +911,7 @@ static void bnx2x_ets_e3b0_sp_pri_to_cos_init(u8 *sp_pri_to_cos)
* Description:
* Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
* according to sp_pri_to_cos.
-*.
+*
******************************************************************************/
static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
u8 *sp_pri_to_cos, const u8 pri,
@@ -964,7 +944,7 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
* Description:
* Returns the correct value according to COS and priority in
* the sp_pri_cli register.
-*.
+*
******************************************************************************/
static u64 bnx2x_e3b0_sp_get_pri_cli_reg(const u8 cos, const u8 cos_offset,
const u8 pri_set,
@@ -981,7 +961,7 @@ static u64 bnx2x_e3b0_sp_get_pri_cli_reg(const u8 cos, const u8 cos_offset,
* Description:
* Returns the correct value according to COS and priority in the
* sp_pri_cli register for NIG.
-*.
+*
******************************************************************************/
static u64 bnx2x_e3b0_sp_get_pri_cli_reg_nig(const u8 cos, const u8 pri_set)
{
@@ -997,7 +977,7 @@ static u64 bnx2x_e3b0_sp_get_pri_cli_reg_nig(const u8 cos, const u8 pri_set)
* Description:
* Returns the correct value according to COS and priority in the
* sp_pri_cli register for PBF.
-*.
+*
******************************************************************************/
static u64 bnx2x_e3b0_sp_get_pri_cli_reg_pbf(const u8 cos, const u8 pri_set)
{
@@ -1013,7 +993,7 @@ static u64 bnx2x_e3b0_sp_get_pri_cli_reg_pbf(const u8 cos, const u8 pri_set)
* Description:
* Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
* according to sp_pri_to_cos.(which COS has higher priority)
-*.
+*
******************************************************************************/
static int bnx2x_ets_e3b0_sp_set_pri_cli_reg(const struct link_params *params,
u8 *sp_pri_to_cos)
@@ -1149,8 +1129,7 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
return -EINVAL;
}
- /*
- * Upper bound is set according to current link speed (min_w_val
+ /* Upper bound is set according to current link speed (min_w_val
* should be the same for upper bound and COS credit val).
*/
bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val_nig);
@@ -1160,8 +1139,7 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
for (cos_entry = 0; cos_entry < ets_params->num_of_cos; cos_entry++) {
if (bnx2x_cos_state_bw == ets_params->cos[cos_entry].state) {
cos_bw_bitmap |= (1 << cos_entry);
- /*
- * The function also sets the BW in HW(not the mappin
+ /* The function also sets the BW in HW(not the mappin
* yet)
*/
bnx2x_status = bnx2x_ets_e3b0_set_cos_bw(
@@ -1217,14 +1195,12 @@ static void bnx2x_ets_bw_limit_common(const struct link_params *params)
/* ETS disabled configuration */
struct bnx2x *bp = params->bp;
DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
- /*
- * defines which entries (clients) are subjected to WFQ arbitration
+ /* Defines which entries (clients) are subjected to WFQ arbitration
* COS0 0x8
* COS1 0x10
*/
REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0x18);
- /*
- * mapping between the ARB_CREDIT_WEIGHT registers and actual
+ /* Mapping between the ARB_CREDIT_WEIGHT registers and actual
* client numbers (WEIGHT_0 does not actually have to represent
* client 0)
* PRI4 | PRI3 | PRI2 | PRI1 | PRI0
@@ -1242,8 +1218,7 @@ static void bnx2x_ets_bw_limit_common(const struct link_params *params)
/* Defines the number of consecutive slots for the strict priority */
REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
- /*
- * Bitmap of 5bits length. Each bit specifies whether the entry behaves
+ /* Bitmap of 5bits length. Each bit specifies whether the entry behaves
* as strict. Bits 0,1,2 - debug and management entries, 3 - COS0
* entry, 4 - COS1 entry.
* COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
@@ -1298,8 +1273,7 @@ int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
u32 val = 0;
DP(NETIF_MSG_LINK, "ETS enabled strict configuration\n");
- /*
- * Bitmap of 5bits length. Each bit specifies whether the entry behaves
+ /* Bitmap of 5bits length. Each bit specifies whether the entry behaves
* as strict. Bits 0,1,2 - debug and management entries,
* 3 - COS0 entry, 4 - COS1 entry.
* COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
@@ -1307,8 +1281,7 @@ int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
* MCP and debug are strict
*/
REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1F);
- /*
- * For strict priority entries defines the number of consecutive slots
+ /* For strict priority entries defines the number of consecutive slots
* for the highest priority.
*/
REG_WR(bp, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
@@ -1320,8 +1293,7 @@ int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
/* Defines the number of consecutive slots for the strict priority */
REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, strict_cos);
- /*
- * mapping between entry priority to client number (0,1,2 -debug and
+ /* Mapping between entry priority to client number (0,1,2 -debug and
* management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
* 3bits client num.
* PRI4 | PRI3 | PRI2 | PRI1 | PRI0
@@ -1356,15 +1328,12 @@ static void bnx2x_update_pfc_xmac(struct link_params *params,
if (!(params->feature_config_flags &
FEATURE_CONFIG_PFC_ENABLED)) {
- /*
- * RX flow control - Process pause frame in receive direction
+ /* RX flow control - Process pause frame in receive direction
*/
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
pause_val |= XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN;
- /*
- * TX flow control - Send pause packet when buffer is full
- */
+ /* TX flow control - Send pause packet when buffer is full */
if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
pause_val |= XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN;
} else {/* PFC support */
@@ -1457,8 +1426,7 @@ void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
{
u32 mode, emac_base;
- /**
- * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
+ /* Set clause 45 mode, slow down the MDIO clock to 2.5MHz
* (a value of 49==0x31) and make sure that the AUTO poll is off
*/
@@ -1578,15 +1546,6 @@ static void bnx2x_umac_enable(struct link_params *params,
DP(NETIF_MSG_LINK, "enabling UMAC\n");
- /**
- * This register determines on which events the MAC will assert
- * error on the i/f to the NIG along w/ EOP.
- */
-
- /**
- * BD REG_WR(bp, NIG_REG_P0_MAC_RSV_ERR_MASK +
- * params->port*0x14, 0xfffff.
- */
/* This register opens the gate for the UMAC despite its name */
REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
@@ -1649,8 +1608,7 @@ static void bnx2x_umac_enable(struct link_params *params,
val |= UMAC_COMMAND_CONFIG_REG_LOOP_ENA;
REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
- /*
- * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
+ /* Maximum Frame Length (RW). Defines a 14-Bit maximum frame
* length used by the MAC receive logic to check frames.
*/
REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
@@ -1666,8 +1624,7 @@ static void bnx2x_xmac_init(struct link_params *params, u32 max_speed)
struct bnx2x *bp = params->bp;
u32 is_port4mode = bnx2x_is_4_port_mode(bp);
- /*
- * In 4-port mode, need to set the mode only once, so if XMAC is
+ /* In 4-port mode, need to set the mode only once, so if XMAC is
* already out of reset, it means the mode has already been set,
* and it must not* reset the XMAC again, since it controls both
* ports of the path
@@ -1691,13 +1648,13 @@ static void bnx2x_xmac_init(struct link_params *params, u32 max_speed)
if (is_port4mode) {
DP(NETIF_MSG_LINK, "Init XMAC to 2 ports x 10G per path\n");
- /* Set the number of ports on the system side to up to 2 */
+ /* Set the number of ports on the system side to up to 2 */
REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 1);
/* Set the number of ports on the Warp Core to 10G */
REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
} else {
- /* Set the number of ports on the system side to 1 */
+ /* Set the number of ports on the system side to 1 */
REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 0);
if (max_speed == SPEED_10000) {
DP(NETIF_MSG_LINK,
@@ -1729,8 +1686,7 @@ static void bnx2x_xmac_disable(struct link_params *params)
if (REG_RD(bp, MISC_REG_RESET_REG_2) &
MISC_REGISTERS_RESET_REG_2_XMAC) {
- /*
- * Send an indication to change the state in the NIG back to XON
+ /* Send an indication to change the state in the NIG back to XON
* Clearing this bit enables the next set of this bit to get
* rising edge
*/
@@ -1755,13 +1711,11 @@ static int bnx2x_xmac_enable(struct link_params *params,
bnx2x_xmac_init(params, vars->line_speed);
- /*
- * This register determines on which events the MAC will assert
+ /* This register determines on which events the MAC will assert
* error on the i/f to the NIG along w/ EOP.
*/
- /*
- * This register tells the NIG whether to send traffic to UMAC
+ /* This register tells the NIG whether to send traffic to UMAC
* or XMAC
*/
REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0);
@@ -1863,8 +1817,7 @@ static int bnx2x_emac_enable(struct link_params *params,
val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
- /*
- * Setting this bit causes MAC control frames (except for pause
+ /* Setting this bit causes MAC control frames (except for pause
* frames) to be passed on for processing. This setting has no
* affect on the operation of the pause frames. This bit effects
* all packets regardless of RX Parser packet sorting logic.
@@ -1963,8 +1916,7 @@ static void bnx2x_update_pfc_bmac2(struct link_params *params,
struct link_vars *vars,
u8 is_lb)
{
- /*
- * Set rx control: Strip CRC and enable BigMAC to relay
+ /* Set rx control: Strip CRC and enable BigMAC to relay
* control packets to the system as well
*/
u32 wb_data[2];
@@ -2016,8 +1968,7 @@ static void bnx2x_update_pfc_bmac2(struct link_params *params,
REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL, wb_data, 2);
- /*
- * Set Time (based unit is 512 bit time) between automatic
+ /* Set Time (based unit is 512 bit time) between automatic
* re-sending of PP packets amd enable automatic re-send of
* Per-Priroity Packet as long as pp_gen is asserted and
* pp_disable is low.
@@ -2086,7 +2037,7 @@ static int bnx2x_pfc_brb_get_config_params(
config_val->default_class1.full_xon = 0;
if (CHIP_IS_E2(bp)) {
- /* class0 defaults */
+ /* Class0 defaults */
config_val->default_class0.pause_xoff =
DEFAULT0_E2_BRB_MAC_PAUSE_XOFF_THR;
config_val->default_class0.pause_xon =
@@ -2095,7 +2046,7 @@ static int bnx2x_pfc_brb_get_config_params(
DEFAULT0_E2_BRB_MAC_FULL_XOFF_THR;
config_val->default_class0.full_xon =
DEFAULT0_E2_BRB_MAC_FULL_XON_THR;
- /* pause able*/
+ /* Pause able*/
config_val->pauseable_th.pause_xoff =
PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
config_val->pauseable_th.pause_xon =
@@ -2114,7 +2065,7 @@ static int bnx2x_pfc_brb_get_config_params(
config_val->non_pauseable_th.full_xon =
PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE;
} else if (CHIP_IS_E3A0(bp)) {
- /* class0 defaults */
+ /* Class0 defaults */
config_val->default_class0.pause_xoff =
DEFAULT0_E3A0_BRB_MAC_PAUSE_XOFF_THR;
config_val->default_class0.pause_xon =
@@ -2123,7 +2074,7 @@ static int bnx2x_pfc_brb_get_config_params(
DEFAULT0_E3A0_BRB_MAC_FULL_XOFF_THR;
config_val->default_class0.full_xon =
DEFAULT0_E3A0_BRB_MAC_FULL_XON_THR;
- /* pause able */
+ /* Pause able */
config_val->pauseable_th.pause_xoff =
PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
config_val->pauseable_th.pause_xon =
@@ -2142,7 +2093,7 @@ static int bnx2x_pfc_brb_get_config_params(
config_val->non_pauseable_th.full_xon =
PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE;
} else if (CHIP_IS_E3B0(bp)) {
- /* class0 defaults */
+ /* Class0 defaults */
config_val->default_class0.pause_xoff =
DEFAULT0_E3B0_BRB_MAC_PAUSE_XOFF_THR;
config_val->default_class0.pause_xon =
@@ -2305,27 +2256,23 @@ static int bnx2x_update_pfc_brb(struct link_params *params,
reg_th_config = &config_val.non_pauseable_th;
} else
reg_th_config = &config_val.default_class0;
- /*
- * The number of free blocks below which the pause signal to class 0
+ /* The number of free blocks below which the pause signal to class 0
* of MAC #n is asserted. n=0,1
*/
REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XOFF_THRESHOLD_1 :
BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 ,
reg_th_config->pause_xoff);
- /*
- * The number of free blocks above which the pause signal to class 0
+ /* The number of free blocks above which the pause signal to class 0
* of MAC #n is de-asserted. n=0,1
*/
REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XON_THRESHOLD_1 :
BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , reg_th_config->pause_xon);
- /*
- * The number of free blocks below which the full signal to class 0
+ /* The number of free blocks below which the full signal to class 0
* of MAC #n is asserted. n=0,1
*/
REG_WR(bp, (port) ? BRB1_REG_FULL_0_XOFF_THRESHOLD_1 :
BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , reg_th_config->full_xoff);
- /*
- * The number of free blocks above which the full signal to class 0
+ /* The number of free blocks above which the full signal to class 0
* of MAC #n is de-asserted. n=0,1
*/
REG_WR(bp, (port) ? BRB1_REG_FULL_0_XON_THRESHOLD_1 :
@@ -2339,30 +2286,26 @@ static int bnx2x_update_pfc_brb(struct link_params *params,
reg_th_config = &config_val.non_pauseable_th;
} else
reg_th_config = &config_val.default_class1;
- /*
- * The number of free blocks below which the pause signal to
+ /* The number of free blocks below which the pause signal to
* class 1 of MAC #n is asserted. n=0,1
*/
REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 :
BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0,
reg_th_config->pause_xoff);
- /*
- * The number of free blocks above which the pause signal to
+ /* The number of free blocks above which the pause signal to
* class 1 of MAC #n is de-asserted. n=0,1
*/
REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XON_THRESHOLD_1 :
BRB1_REG_PAUSE_1_XON_THRESHOLD_0,
reg_th_config->pause_xon);
- /*
- * The number of free blocks below which the full signal to
+ /* The number of free blocks below which the full signal to
* class 1 of MAC #n is asserted. n=0,1
*/
REG_WR(bp, (port) ? BRB1_REG_FULL_1_XOFF_THRESHOLD_1 :
BRB1_REG_FULL_1_XOFF_THRESHOLD_0,
reg_th_config->full_xoff);
- /*
- * The number of free blocks above which the full signal to
+ /* The number of free blocks above which the full signal to
* class 1 of MAC #n is de-asserted. n=0,1
*/
REG_WR(bp, (port) ? BRB1_REG_FULL_1_XON_THRESHOLD_1 :
@@ -2379,49 +2322,41 @@ static int bnx2x_update_pfc_brb(struct link_params *params,
REG_WR(bp, BRB1_REG_PER_CLASS_GUARANTY_MODE,
e3b0_val.per_class_guaranty_mode);
- /*
- * The hysteresis on the guarantied buffer space for the Lb
+ /* The hysteresis on the guarantied buffer space for the Lb
* port before signaling XON.
*/
REG_WR(bp, BRB1_REG_LB_GUARANTIED_HYST,
e3b0_val.lb_guarantied_hyst);
- /*
- * The number of free blocks below which the full signal to the
+ /* The number of free blocks below which the full signal to the
* LB port is asserted.
*/
REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD,
e3b0_val.full_lb_xoff_th);
- /*
- * The number of free blocks above which the full signal to the
+ /* The number of free blocks above which the full signal to the
* LB port is de-asserted.
*/
REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD,
e3b0_val.full_lb_xon_threshold);
- /*
- * The number of blocks guarantied for the MAC #n port. n=0,1
+ /* The number of blocks guarantied for the MAC #n port. n=0,1
*/
- /* The number of blocks guarantied for the LB port.*/
+ /* The number of blocks guarantied for the LB port. */
REG_WR(bp, BRB1_REG_LB_GUARANTIED,
e3b0_val.lb_guarantied);
- /*
- * The number of blocks guarantied for the MAC #n port.
- */
+ /* The number of blocks guarantied for the MAC #n port. */
REG_WR(bp, BRB1_REG_MAC_GUARANTIED_0,
2 * e3b0_val.mac_0_class_t_guarantied);
REG_WR(bp, BRB1_REG_MAC_GUARANTIED_1,
2 * e3b0_val.mac_1_class_t_guarantied);
- /*
- * The number of blocks guarantied for class #t in MAC0. t=0,1
+ /* The number of blocks guarantied for class #t in MAC0. t=0,1
*/
REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED,
e3b0_val.mac_0_class_t_guarantied);
REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED,
e3b0_val.mac_0_class_t_guarantied);
- /*
- * The hysteresis on the guarantied buffer space for class in
+ /* The hysteresis on the guarantied buffer space for class in
* MAC0. t=0,1
*/
REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST,
@@ -2429,15 +2364,13 @@ static int bnx2x_update_pfc_brb(struct link_params *params,
REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST,
e3b0_val.mac_0_class_t_guarantied_hyst);
- /*
- * The number of blocks guarantied for class #t in MAC1.t=0,1
+ /* The number of blocks guarantied for class #t in MAC1.t=0,1
*/
REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED,
e3b0_val.mac_1_class_t_guarantied);
REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED,
e3b0_val.mac_1_class_t_guarantied);
- /*
- * The hysteresis on the guarantied buffer space for class #t
+ /* The hysteresis on the guarantied buffer space for class #t
* in MAC1. t=0,1
*/
REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST,
@@ -2520,15 +2453,13 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
FEATURE_CONFIG_PFC_ENABLED;
DP(NETIF_MSG_LINK, "updating pfc nig parameters\n");
- /*
- * When NIG_LLH0_XCM_MASK_REG_LLHX_XCM_MASK_BCN bit is set
+ /* When NIG_LLH0_XCM_MASK_REG_LLHX_XCM_MASK_BCN bit is set
* MAC control frames (that are not pause packets)
* will be forwarded to the XCM.
*/
xcm_mask = REG_RD(bp, port ? NIG_REG_LLH1_XCM_MASK :
NIG_REG_LLH0_XCM_MASK);
- /*
- * nig params will override non PFC params, since it's possible to
+ /* NIG params will override non PFC params, since it's possible to
* do transition from PFC to SAFC
*/
if (set_pfc) {
@@ -2548,7 +2479,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
llfc_out_en = nig_params->llfc_out_en;
llfc_enable = nig_params->llfc_enable;
pause_enable = nig_params->pause_enable;
- } else /*defaul non PFC mode - PAUSE */
+ } else /* Default non PFC mode - PAUSE */
pause_enable = 1;
xcm_mask |= (port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
@@ -2608,8 +2539,7 @@ int bnx2x_update_pfc(struct link_params *params,
struct link_vars *vars,
struct bnx2x_nig_brb_pfc_port_params *pfc_params)
{
- /*
- * The PFC and pause are orthogonal to one another, meaning when
+ /* The PFC and pause are orthogonal to one another, meaning when
* PFC is enabled, the pause are disabled, and when PFC is
* disabled, pause are set according to the pause result.
*/
@@ -3148,7 +3078,6 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
EMAC_MDIO_STATUS_10MB);
/* address */
-
tmp = ((phy->addr << 21) | (devad << 16) | reg |
EMAC_MDIO_COMM_COMMAND_ADDRESS |
EMAC_MDIO_COMM_START_BUSY);
@@ -3337,8 +3266,7 @@ int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
u8 devad, u16 reg, u16 *ret_val)
{
u8 phy_index;
- /*
- * Probe for the phy according to the given phy_addr, and execute
+ /* Probe for the phy according to the given phy_addr, and execute
* the read request on it
*/
for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
@@ -3355,8 +3283,7 @@ int bnx2x_phy_write(struct link_params *params, u8 phy_addr,
u8 devad, u16 reg, u16 val)
{
u8 phy_index;
- /*
- * Probe for the phy according to the given phy_addr, and execute
+ /* Probe for the phy according to the given phy_addr, and execute
* the write request on it
*/
for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
@@ -3382,7 +3309,7 @@ static u8 bnx2x_get_warpcore_lane(struct bnx2x_phy *phy,
if (bnx2x_is_4_port_mode(bp)) {
u32 port_swap, port_swap_ovr;
- /*figure out path swap value */
+ /* Figure out path swap value */
path_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PATH_SWAP_OVWR);
if (path_swap_ovr & 0x1)
path_swap = (path_swap_ovr & 0x2);
@@ -3392,7 +3319,7 @@ static u8 bnx2x_get_warpcore_lane(struct bnx2x_phy *phy,
if (path_swap)
path = path ^ 1;
- /*figure out port swap value */
+ /* Figure out port swap value */
port_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PORT_SWAP_OVWR);
if (port_swap_ovr & 0x1)
port_swap = (port_swap_ovr & 0x2);
@@ -3405,7 +3332,7 @@ static u8 bnx2x_get_warpcore_lane(struct bnx2x_phy *phy,
lane = (port<<1) + path;
} else { /* two port mode - no port swap */
- /*figure out path swap value */
+ /* Figure out path swap value */
path_swap_ovr =
REG_RD(bp, MISC_REG_TWO_PORT_PATH_SWAP_OVWR);
if (path_swap_ovr & 0x1) {
@@ -3437,8 +3364,7 @@ static void bnx2x_set_aer_mmd(struct link_params *params,
if (USES_WARPCORE(bp)) {
aer_val = bnx2x_get_warpcore_lane(phy, params);
- /*
- * In Dual-lane mode, two lanes are joined together,
+ /* In Dual-lane mode, two lanes are joined together,
* so in order to configure them, the AER broadcast method is
* used here.
* 0x200 is the broadcast address for lanes 0,1
@@ -3518,8 +3444,7 @@ static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
{
struct bnx2x *bp = params->bp;
*ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
- /**
- * resolve pause mode and advertisement Please refer to Table
+ /* Resolve pause mode and advertisement Please refer to Table
* 28B-3 of the 802.3ab-1999 spec
*/
@@ -3642,6 +3567,7 @@ static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
if (pause_result & (1<<1))
vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
+
}
static void bnx2x_ext_phy_update_adv_fc(struct bnx2x_phy *phy,
@@ -3698,6 +3624,7 @@ static void bnx2x_ext_phy_update_adv_fc(struct bnx2x_phy *phy,
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)
@@ -3819,9 +3746,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
/* Advertise pause */
bnx2x_ext_phy_set_pause(params, phy, vars);
-
- /*
- * Set KR Autoneg Work-Around flag for Warpcore version older than D108
+ /* Set KR Autoneg Work-Around flag for Warpcore version older than D108
*/
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_UC_INFO_B1_VERSION, &val16);
@@ -3829,7 +3754,6 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "Enable AN KR work-around\n");
vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
}
-
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_DIGITAL5_MISC7, &val16);
@@ -3903,7 +3827,7 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0xB);
- /*Enable encoded forced speed */
+ /* Enable encoded forced speed */
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x30);
@@ -4265,8 +4189,7 @@ static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
PORT_HW_CFG_E3_MOD_ABS_MASK) >>
PORT_HW_CFG_E3_MOD_ABS_SHIFT;
- /*
- * Should not happen. This function called upon interrupt
+ /* Should not happen. This function called upon interrupt
* triggered by GPIO ( since EPIO can only generate interrupts
* to MCP).
* So if this function was called and none of the GPIOs was set,
@@ -4366,7 +4289,7 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
"link up, rx_tx_asic_rst 0x%x\n",
vars->rx_tx_asic_rst);
} else {
- /*reset the lane to see if link comes up.*/
+ /* Reset the lane to see if link comes up.*/
bnx2x_warpcore_reset_lane(bp, phy, 1);
bnx2x_warpcore_reset_lane(bp, phy, 0);
@@ -4387,7 +4310,6 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
} /*params->rx_tx_asic_rst*/
}
-
static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars)
@@ -4545,7 +4467,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
/* Update those 1-copy registers */
CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
MDIO_AER_BLOCK_AER_REG, 0);
- /* Enable 1G MDIO (1-copy) */
+ /* Enable 1G MDIO (1-copy) */
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
&val16);
@@ -4624,43 +4546,43 @@ void bnx2x_sync_link(struct link_params *params,
vars->duplex = DUPLEX_FULL;
switch (vars->link_status &
LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
- case LINK_10THD:
- vars->duplex = DUPLEX_HALF;
- /* fall thru */
- case LINK_10TFD:
- vars->line_speed = SPEED_10;
- break;
+ case LINK_10THD:
+ vars->duplex = DUPLEX_HALF;
+ /* Fall thru */
+ case LINK_10TFD:
+ vars->line_speed = SPEED_10;
+ break;
- case LINK_100TXHD:
- vars->duplex = DUPLEX_HALF;
- /* fall thru */
- case LINK_100T4:
- case LINK_100TXFD:
- vars->line_speed = SPEED_100;
- break;
+ case LINK_100TXHD:
+ vars->duplex = DUPLEX_HALF;
+ /* Fall thru */
+ case LINK_100T4:
+ case LINK_100TXFD:
+ vars->line_speed = SPEED_100;
+ break;
- case LINK_1000THD:
- vars->duplex = DUPLEX_HALF;
- /* fall thru */
- case LINK_1000TFD:
- vars->line_speed = SPEED_1000;
- break;
+ case LINK_1000THD:
+ vars->duplex = DUPLEX_HALF;
+ /* Fall thru */
+ case LINK_1000TFD:
+ vars->line_speed = SPEED_1000;
+ break;
- case LINK_2500THD:
- vars->duplex = DUPLEX_HALF;
- /* fall thru */
- case LINK_2500TFD:
- vars->line_speed = SPEED_2500;
- break;
+ case LINK_2500THD:
+ vars->duplex = DUPLEX_HALF;
+ /* Fall thru */
+ case LINK_2500TFD:
+ vars->line_speed = SPEED_2500;
+ break;
- case LINK_10GTFD:
- vars->line_speed = SPEED_10000;
- break;
- case LINK_20GTFD:
- vars->line_speed = SPEED_20000;
- break;
- default:
- break;
+ case LINK_10GTFD:
+ vars->line_speed = SPEED_10000;
+ break;
+ case LINK_20GTFD:
+ vars->line_speed = SPEED_20000;
+ break;
+ default:
+ break;
}
vars->flow_ctrl = 0;
if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
@@ -4835,9 +4757,8 @@ static void bnx2x_set_swap_lanes(struct link_params *params,
struct bnx2x_phy *phy)
{
struct bnx2x *bp = params->bp;
- /*
- * Each two bits represents a lane number:
- * No swap is 0123 => 0x1b no need to enable the swap
+ /* Each two bits represents a lane number:
+ * No swap is 0123 => 0x1b no need to enable the swap
*/
u16 rx_lane_swap, tx_lane_swap;
@@ -5051,8 +4972,7 @@ static void bnx2x_program_serdes(struct bnx2x_phy *phy,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
- /*
- * program speed
+ /* Program speed
* - needed only if the speed is greater than 1G (2.5G or 10G)
*/
CL22_RD_OVER_CL45(bp, phy,
@@ -5087,8 +5007,6 @@ static void bnx2x_set_brcm_cl37_advertisement(struct bnx2x_phy *phy,
struct bnx2x *bp = params->bp;
u16 val = 0;
- /* configure the 48 bits for BAM AN */
-
/* set extended capabilities */
if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
val |= MDIO_OVER_1G_UP1_2_5G;
@@ -5234,11 +5152,8 @@ static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
}
}
-
-/*
- * link management
+/* Link management
*/
-
static int bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
struct link_params *params)
{
@@ -5383,8 +5298,7 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
"ustat_val(0x8371) = 0x%x\n", ustat_val);
return;
}
- /*
- * Step 3: Check CL37 Message Pages received to indicate LP
+ /* Step 3: Check CL37 Message Pages received to indicate LP
* supports only CL37
*/
CL22_RD_OVER_CL45(bp, phy,
@@ -5401,8 +5315,7 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
cl37_fsm_received);
return;
}
- /*
- * The combined cl37/cl73 fsm state information indicating that
+ /* The combined cl37/cl73 fsm state information indicating that
* we are connected to a device which does not support cl73, but
* does support cl37 BAM. In this case we disable cl73 and
* restart cl37 auto-neg
@@ -5973,8 +5886,7 @@ static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port,
{
u32 latch_status = 0;
- /*
- * Disable the MI INT ( external phy int ) by writing 1 to the
+ /* Disable the MI INT ( external phy int ) by writing 1 to the
* status register. Link down indication is high-active-signal,
* so in this case we need to write the status to clear the XOR
*/
@@ -6009,8 +5921,7 @@ static void bnx2x_link_int_ack(struct link_params *params,
struct bnx2x *bp = params->bp;
u8 port = params->port;
u32 mask;
- /*
- * First reset all status we assume only one line will be
+ /* First reset all status we assume only one line will be
* change at a time
*/
bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
@@ -6024,8 +5935,7 @@ static void bnx2x_link_int_ack(struct link_params *params,
if (is_10g_plus)
mask = NIG_STATUS_XGXS0_LINK10G;
else if (params->switch_cfg == SWITCH_CFG_10G) {
- /*
- * Disable the link interrupt by writing 1 to
+ /* Disable the link interrupt by writing 1 to
* the relevant lane in the status register
*/
u32 ser_lane =
@@ -6227,8 +6137,7 @@ int bnx2x_set_led(struct link_params *params,
break;
case LED_MODE_OPER:
- /*
- * For all other phys, OPER mode is same as ON, so in case
+ /* For all other phys, OPER mode is same as ON, so in case
* link is down, do nothing
*/
if (!vars->link_up)
@@ -6239,9 +6148,7 @@ int bnx2x_set_led(struct link_params *params,
(params->phy[EXT_PHY1].type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722)) &&
CHIP_IS_E2(bp) && params->num_phys == 2) {
- /*
- * This is a work-around for E2+8727 Configurations
- */
+ /* This is a work-around for E2+8727 Configurations */
if (mode == LED_MODE_ON ||
speed == SPEED_10000){
REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
@@ -6250,8 +6157,7 @@ int bnx2x_set_led(struct link_params *params,
tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
EMAC_WR(bp, EMAC_REG_EMAC_LED,
(tmp | EMAC_LED_OVERRIDE));
- /*
- * return here without enabling traffic
+ /* Return here without enabling traffic
* LED blink and setting rate in ON mode.
* In oper mode, enabling LED blink
* and setting rate is needed.
@@ -6260,8 +6166,7 @@ int bnx2x_set_led(struct link_params *params,
return rc;
}
} else if (SINGLE_MEDIA_DIRECT(params)) {
- /*
- * This is a work-around for HW issue found when link
+ /* This is a work-around for HW issue found when link
* is up in CL73
*/
if ((!CHIP_IS_E3(bp)) ||
@@ -6310,10 +6215,7 @@ int bnx2x_set_led(struct link_params *params,
(speed == SPEED_1000) ||
(speed == SPEED_100) ||
(speed == SPEED_10))) {
- /*
- * On Everest 1 Ax chip versions for speeds less than
- * 10G LED scheme is different
- */
+ /* For speeds less than 10G LED scheme is different */
REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
+ port*4, 1);
REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
@@ -6333,8 +6235,7 @@ int bnx2x_set_led(struct link_params *params,
}
-/*
- * This function comes to reflect the actual link state read DIRECTLY from the
+/* This function comes to reflect the actual link state read DIRECTLY from the
* HW
*/
int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
@@ -6422,16 +6323,14 @@ static int bnx2x_link_initialize(struct link_params *params,
int rc = 0;
u8 phy_index, non_ext_phy;
struct bnx2x *bp = params->bp;
- /*
- * In case of external phy existence, the line speed would be the
+ /* In case of external phy existence, the line speed would be the
* line speed linked up by the external phy. In case it is direct
* only, then the line_speed during initialization will be
* equal to the req_line_speed
*/
vars->line_speed = params->phy[INT_PHY].req_line_speed;
- /*
- * Initialize the internal phy in case this is a direct board
+ /* Initialize the internal phy in case this is a direct board
* (no external phys), or this board has external phy which requires
* to first.
*/
@@ -6463,8 +6362,7 @@ static int bnx2x_link_initialize(struct link_params *params,
} else {
for (phy_index = EXT_PHY1; phy_index < params->num_phys;
phy_index++) {
- /*
- * No need to initialize second phy in case of first
+ /* No need to initialize second phy in case of first
* phy only selection. In case of second phy, we do
* need to initialize the first phy, since they are
* connected.
@@ -6492,7 +6390,6 @@ static int bnx2x_link_initialize(struct link_params *params,
NIG_STATUS_XGXS0_LINK_STATUS |
NIG_STATUS_SERDES0_LINK_STATUS |
NIG_MASK_MI_INT));
- bnx2x_update_mng(params, vars->link_status);
return rc;
}
@@ -6577,7 +6474,7 @@ static int bnx2x_update_link_up(struct link_params *params,
u8 link_10g)
{
struct bnx2x *bp = params->bp;
- u8 port = params->port;
+ u8 phy_idx, port = params->port;
int rc = 0;
vars->link_status |= (LINK_STATUS_LINK_UP |
@@ -6641,11 +6538,18 @@ static int bnx2x_update_link_up(struct link_params *params,
/* update shared memory */
bnx2x_update_mng(params, vars->link_status);
+
+ /* Check remote fault */
+ for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
+ if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
+ bnx2x_check_half_open_conn(params, vars, 0);
+ break;
+ }
+ }
msleep(20);
return rc;
}
-/*
- * The bnx2x_link_update function should be called upon link
+/* The bnx2x_link_update function should be called upon link
* interrupt.
* Link is considered up as follows:
* - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs
@@ -6702,8 +6606,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
if (!CHIP_IS_E3(bp))
REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
- /*
- * Step 1:
+ /* Step 1:
* Check external link change only for external phys, and apply
* priority selection between them in case the link on both phys
* is up. Note that instead of the common vars, a temporary
@@ -6734,23 +6637,20 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
switch (bnx2x_phy_selection(params)) {
case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
- /*
- * In this option, the first PHY makes sure to pass the
+ /* In this option, the first PHY makes sure to pass the
* traffic through itself only.
* Its not clear how to reset the link on the second phy
*/
active_external_phy = EXT_PHY1;
break;
case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
- /*
- * In this option, the first PHY makes sure to pass the
+ /* In this option, the first PHY makes sure to pass the
* traffic through the second PHY.
*/
active_external_phy = EXT_PHY2;
break;
default:
- /*
- * Link indication on both PHYs with the following cases
+ /* Link indication on both PHYs with the following cases
* is invalid:
* - FIRST_PHY means that second phy wasn't initialized,
* hence its link is expected to be down
@@ -6767,8 +6667,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
}
}
prev_line_speed = vars->line_speed;
- /*
- * Step 2:
+ /* Step 2:
* Read the status of the internal phy. In case of
* DIRECT_SINGLE_MEDIA board, this link is the external link,
* otherwise this is the link between the 577xx and the first
@@ -6778,8 +6677,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
params->phy[INT_PHY].read_status(
&params->phy[INT_PHY],
params, vars);
- /*
- * The INT_PHY flow control reside in the vars. This include the
+ /* The INT_PHY flow control reside in the vars. This include the
* case where the speed or flow control are not set to AUTO.
* Otherwise, the active external phy flow control result is set
* to the vars. The ext_phy_line_speed is needed to check if the
@@ -6788,14 +6686,12 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
*/
if (active_external_phy > INT_PHY) {
vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl;
- /*
- * Link speed is taken from the XGXS. AN and FC result from
+ /* Link speed is taken from the XGXS. AN and FC result from
* the external phy.
*/
vars->link_status |= phy_vars[active_external_phy].link_status;
- /*
- * if active_external_phy is first PHY and link is up - disable
+ /* if active_external_phy is first PHY and link is up - disable
* disable TX on second external PHY
*/
if (active_external_phy == EXT_PHY1) {
@@ -6832,8 +6728,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x,"
" ext_phy_line_speed = %d\n", vars->flow_ctrl,
vars->link_status, ext_phy_line_speed);
- /*
- * Upon link speed change set the NIG into drain mode. Comes to
+ /* Upon link speed change set the NIG into drain mode. Comes to
* deals with possible FIFO glitch due to clk change when speed
* is decreased without link down indicator
*/
@@ -6858,8 +6753,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
bnx2x_link_int_ack(params, vars, link_10g_plus);
- /*
- * In case external phy link is up, and internal link is down
+ /* In case external phy link is up, and internal link is down
* (not initialized yet probably after link initialization, it
* needs to be initialized.
* Note that after link down-up as result of cable plug, the xgxs
@@ -6887,8 +6781,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
vars);
}
}
- /*
- * Link is up only if both local phy and external phy (in case of
+ /* Link is up only if both local phy and external phy (in case of
* non-direct board) are up and no fault detected on active PHY.
*/
vars->link_up = (vars->phy_link_up &&
@@ -6907,6 +6800,10 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
else
rc = bnx2x_update_link_down(params, vars);
+ /* Update MCP link status was changed */
+ if (params->feature_config_flags & FEATURE_CONFIG_BC_SUPPORTS_AFEX)
+ bnx2x_fw_command(bp, DRV_MSG_CODE_LINK_STATUS_CHANGED, 0);
+
return rc;
}
@@ -7120,8 +7017,7 @@ static int bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
}
/* XAUI workaround in 8073 A0: */
- /*
- * After loading the boot ROM and restarting Autoneg, poll
+ /* After loading the boot ROM and restarting Autoneg, poll
* Dev1, Reg $C820:
*/
@@ -7130,8 +7026,7 @@ static int bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
&val);
- /*
- * If bit [14] = 0 or bit [13] = 0, continue on with
+ /* If bit [14] = 0 or bit [13] = 0, continue on with
* system initialization (XAUI work-around not required, as
* these bits indicate 2.5G or 1G link up).
*/
@@ -7140,8 +7035,7 @@ static int bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
return 0;
} else if (!(val & (1<<15))) {
DP(NETIF_MSG_LINK, "bit 15 went off\n");
- /*
- * If bit 15 is 0, then poll Dev1, Reg $C841 until it's
+ /* If bit 15 is 0, then poll Dev1, Reg $C841 until it's
* MSB (bit15) goes to 1 (indicating that the XAUI
* workaround has completed), then continue on with
* system initialization.
@@ -7291,8 +7185,7 @@ static int bnx2x_8073_config_init(struct bnx2x_phy *phy,
val = (1<<7);
} else if (phy->req_line_speed == SPEED_2500) {
val = (1<<5);
- /*
- * Note that 2.5G works only when used with 1G
+ /* Note that 2.5G works only when used with 1G
* advertisement
*/
} else
@@ -7343,8 +7236,7 @@ static int bnx2x_8073_config_init(struct bnx2x_phy *phy,
/* Add support for CL37 (passive mode) III */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
- /*
- * The SNR will improve about 2db by changing BW and FEE main
+ /* The SNR will improve about 2db by changing BW and FEE main
* tap. Rest commands are executed after link is up
* Change FFE main cursor to 5 in EDC register
*/
@@ -7431,8 +7323,7 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
link_up = (((val1 & 4) == 4) || (an1000_status & (1<<1)));
if (link_up && bnx2x_8073_is_snr_needed(bp, phy)) {
- /*
- * The SNR will improve about 2dbby changing the BW and FEE main
+ /* The SNR will improve about 2dbby changing the BW and FEE main
* tap. The 1st write to change FFE main tap is set before
* restart AN. Change PLL Bandwidth in EDC register
*/
@@ -7479,8 +7370,7 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
bnx2x_cl45_read(bp, phy,
MDIO_XS_DEVAD,
MDIO_XS_REG_8073_RX_CTRL_PCIE, &val1);
- /*
- * Set bit 3 to invert Rx in 1G mode and clear this bit
+ /* Set bit 3 to invert Rx in 1G mode and clear this bit
* when it`s in 10G mode.
*/
if (vars->line_speed == SPEED_1000) {
@@ -7602,8 +7492,7 @@ static void bnx2x_set_disable_pmd_transmit(struct link_params *params,
u8 pmd_dis)
{
struct bnx2x *bp = params->bp;
- /*
- * Disable transmitter only for bootcodes which can enable it afterwards
+ /* Disable transmitter only for bootcodes which can enable it afterwards
* (for D3 link)
*/
if (pmd_dis) {
@@ -7780,9 +7669,6 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
u32 data_array[4];
u16 addr32;
struct bnx2x *bp = params->bp;
- /*DP(NETIF_MSG_LINK, "bnx2x_direct_read_sfp_module_eeprom:"
- " addr %d, cnt %d\n",
- addr, byte_cnt);*/
if (byte_cnt > 16) {
DP(NETIF_MSG_LINK,
"Reading from eeprom is limited to 16 bytes\n");
@@ -7847,8 +7733,7 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
0x8002);
- /*
- * Wait appropriate time for two-wire command to finish before
+ /* Wait appropriate time for two-wire command to finish before
* polling the status register
*/
msleep(1);
@@ -7941,8 +7826,7 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
{
u8 copper_module_type;
phy->media_type = ETH_PHY_DA_TWINAX;
- /*
- * Check if its active cable (includes SFP+ module)
+ /* Check if its active cable (includes SFP+ module)
* of passive cable
*/
if (bnx2x_read_sfp_module_eeprom(phy,
@@ -8019,8 +7903,7 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "EDC mode is set to 0x%x\n", *edc_mode);
return 0;
}
-/*
- * This function read the relevant field from the module (SFP+), and verify it
+/* This function read the relevant field from the module (SFP+), and verify it
* is compliant with this board
*/
static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
@@ -8102,8 +7985,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
u8 val;
struct bnx2x *bp = params->bp;
u16 timeout;
- /*
- * Initialization time after hot-plug may take up to 300ms for
+ /* Initialization time after hot-plug may take up to 300ms for
* some phys type ( e.g. JDSU )
*/
@@ -8125,8 +8007,7 @@ static void bnx2x_8727_power_module(struct bnx2x *bp,
u8 is_power_up) {
/* Make sure GPIOs are not using for LED mode */
u16 val;
- /*
- * In the GPIO register, bit 4 is use to determine if the GPIOs are
+ /* In the GPIO register, bit 4 is use to determine if the GPIOs are
* operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
* output
* Bits 0-1 determine the GPIOs value for OUTPUT in case bit 4 val is 0
@@ -8142,8 +8023,7 @@ static void bnx2x_8727_power_module(struct bnx2x *bp,
if (is_power_up)
val = (1<<4);
else
- /*
- * Set GPIO control to OUTPUT, and set the power bit
+ /* Set GPIO control to OUTPUT, and set the power bit
* to according to the is_power_up
*/
val = (1<<1);
@@ -8177,8 +8057,7 @@ static int bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
DP(NETIF_MSG_LINK, "Setting LRM MODE\n");
- /*
- * Changing to LRM mode takes quite few seconds. So do it only
+ /* Changing to LRM mode takes quite few seconds. So do it only
* if current mode is limiting (default is LRM)
*/
if (cur_limiting_mode != EDC_MODE_LIMITING)
@@ -8313,8 +8192,7 @@ static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
struct bnx2x *bp = params->bp;
DP(NETIF_MSG_LINK, "Setting SFP+ module fault LED to %d\n", gpio_mode);
if (CHIP_IS_E3(bp)) {
- /*
- * Low ==> if SFP+ module is supported otherwise
+ /* Low ==> if SFP+ module is supported otherwise
* High ==> if SFP+ module is not on the approved vendor list
*/
bnx2x_set_e3_module_fault_led(params, gpio_mode);
@@ -8339,8 +8217,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params,
return;
DP(NETIF_MSG_LINK, "Setting SFP+ module power to %d using pin cfg %d\n",
power, pin_cfg);
- /*
- * Low ==> corresponding SFP+ module is powered
+ /* Low ==> corresponding SFP+ module is powered
* high ==> the SFP+ module is powered down
*/
bnx2x_set_cfg_pin(bp, pin_cfg, power ^ 1);
@@ -8474,14 +8351,12 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_LOW);
}
- /*
- * Check and set limiting mode / LRM mode on 8726. On 8727 it
+ /* Check and set limiting mode / LRM mode on 8726. On 8727 it
* is done automatically
*/
bnx2x_set_limiting_mode(params, phy, edc_mode);
- /*
- * Enable transmit for this module if the module is approved, or
+ /* Enable transmit for this module if the module is approved, or
* if unapproved modules should also enable the Tx laser
*/
if (rc == 0 ||
@@ -8536,8 +8411,7 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
bnx2x_set_gpio_int(bp, gpio_num,
MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
gpio_port);
- /*
- * Module was plugged out.
+ /* Module was plugged out.
* Disable transmit for this module
*/
phy->media_type = ETH_PHY_NOT_PRESENT;
@@ -8607,8 +8481,7 @@ static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "8706/8726 rx_sd 0x%x pcs_status 0x%x 1Gbps"
" link_status 0x%x\n", rx_sd, pcs_status, val2);
- /*
- * link is up if both bit 0 of pmd_rx_sd and bit 0 of pcs_status
+ /* Link is up if both bit 0 of pmd_rx_sd and bit 0 of pcs_status
* are set, or if the autoneg bit 1 is set
*/
link_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1)));
@@ -8722,8 +8595,7 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
}
bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
- /*
- * If TX Laser is controlled by GPIO_0, do not let PHY go into low
+ /* If TX Laser is controlled by GPIO_0, do not let PHY go into low
* power mode, if TX Laser is disabled
*/
@@ -8833,8 +8705,7 @@ static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
bnx2x_8726_external_rom_boot(phy, params);
- /*
- * Need to call module detected on initialization since the module
+ /* Need to call module detected on initialization since the module
* detection triggered by actual module insertion might occur before
* driver is loaded, and when driver is loaded, it reset all
* registers, including the transmitter
@@ -8871,8 +8742,7 @@ static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
- /*
- * Enable RX-ALARM control to receive interrupt for 1G speed
+ /* Enable RX-ALARM control to receive interrupt for 1G speed
* change
*/
bnx2x_cl45_write(bp, phy,
@@ -8973,8 +8843,7 @@ static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy,
struct link_params *params) {
u32 swap_val, swap_override;
u8 port;
- /*
- * The PHY reset is controlled by GPIO 1. Fake the port number
+ /* The PHY reset is controlled by GPIO 1. Fake the port number
* to cancel the swap done in set_gpio()
*/
struct bnx2x *bp = params->bp;
@@ -9012,14 +8881,12 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, lasi_ctrl_val);
- /*
- * Initially configure MOD_ABS to interrupt when module is
+ /* Initially configure MOD_ABS to interrupt when module is
* presence( bit 8)
*/
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
- /*
- * Set EDC off by setting OPTXLOS signal input to low (bit 9).
+ /* Set EDC off by setting OPTXLOS signal input to low (bit 9).
* When the EDC is off it locks onto a reference clock and avoids
* becoming 'lost'
*/
@@ -9040,8 +8907,7 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
if (phy->flags & FLAGS_NOC)
val |= (3<<5);
- /*
- * Set 8727 GPIOs to input to allow reading from the 8727 GPIO0
+ /* Set 8727 GPIOs to input to allow reading from the 8727 GPIO0
* status which reflect SFP+ module over-current
*/
if (!(phy->flags & FLAGS_NOC))
@@ -9067,8 +8933,7 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1);
DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1);
- /*
- * Power down the XAUI until link is up in case of dual-media
+ /* Power down the XAUI until link is up in case of dual-media
* and 1G
*/
if (DUAL_MEDIA(params)) {
@@ -9093,8 +8958,7 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy,
MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1300);
} else {
- /*
- * Since the 8727 has only single reset pin, need to set the 10G
+ /* Since the 8727 has only single reset pin, need to set the 10G
* registers although it is default
*/
bnx2x_cl45_write(bp, phy,
@@ -9109,8 +8973,7 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
0x0008);
}
- /*
- * Set 2-wire transfer rate of SFP+ module EEPROM
+ /* Set 2-wire transfer rate of SFP+ module EEPROM
* to 100Khz since some DACs(direct attached cables) do
* not work at 400Khz.
*/
@@ -9133,8 +8996,7 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
phy->tx_preemphasis[1]);
}
- /*
- * If TX Laser is controlled by GPIO_0, do not let PHY go into low
+ /* If TX Laser is controlled by GPIO_0, do not let PHY go into low
* power mode, if TX Laser is disabled
*/
tx_en_mode = REG_RD(bp, params->shmem_base +
@@ -9180,8 +9042,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK,
"MOD_ABS indication show module is absent\n");
phy->media_type = ETH_PHY_NOT_PRESENT;
- /*
- * 1. Set mod_abs to detect next module
+ /* 1. Set mod_abs to detect next module
* presence event
* 2. Set EDC off by setting OPTXLOS signal input to low
* (bit 9).
@@ -9195,8 +9056,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
- /*
- * Clear RX alarm since it stays up as long as
+ /* Clear RX alarm since it stays up as long as
* the mod_abs wasn't changed
*/
bnx2x_cl45_read(bp, phy,
@@ -9207,8 +9067,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
/* Module is present */
DP(NETIF_MSG_LINK,
"MOD_ABS indication show module is present\n");
- /*
- * First disable transmitter, and if the module is ok, the
+ /* First disable transmitter, and if the module is ok, the
* module_detection will enable it
* 1. Set mod_abs to detect next module absent event ( bit 8)
* 2. Restore the default polarity of the OPRXLOS signal and
@@ -9222,8 +9081,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
- /*
- * Clear RX alarm since it stays up as long as the mod_abs
+ /* Clear RX alarm since it stays up as long as the mod_abs
* wasn't changed. This is need to be done before calling the
* module detection, otherwise it will clear* the link update
* alarm
@@ -9284,8 +9142,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
- /*
- * If a module is present and there is need to check
+ /* If a module is present and there is need to check
* for over current
*/
if (!(phy->flags & FLAGS_NOC) && !(rx_alarm_status & (1<<5))) {
@@ -9350,8 +9207,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status);
- /*
- * Bits 0..2 --> speed detected,
+ /* Bits 0..2 --> speed detected,
* Bits 13..15--> link is down
*/
if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) {
@@ -9394,8 +9250,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8727_PCS_GP, &val1);
- /*
- * In case of dual-media board and 1G, power up the XAUI side,
+ /* In case of dual-media board and 1G, power up the XAUI side,
* otherwise power it down. For 10G it is done automatically
*/
if (link_up)
@@ -9561,8 +9416,7 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
/* Save spirom version */
bnx2x_save_848xx_spirom_version(phy, bp, params->port);
}
- /*
- * This phy uses the NIG latch mechanism since link indication
+ /* This phy uses the NIG latch mechanism since link indication
* arrives through its LED4 and not via its LASI signal, so we
* get steady signal instead of clear on read
*/
@@ -9667,8 +9521,7 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
if (phy->req_duplex == DUPLEX_FULL)
autoneg_val |= (1<<8);
- /*
- * Always write this if this is not 84833.
+ /* Always write this if this is not 84833.
* For 84833, write it only when it's a forced speed.
*/
if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
@@ -9916,8 +9769,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
/* Wait for GPHY to come out of reset */
msleep(50);
if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
- /*
- * BCM84823 requires that XGXS links up first @ 10G for normal
+ /* BCM84823 requires that XGXS links up first @ 10G for normal
* behavior.
*/
u16 temp;
@@ -10393,8 +10245,7 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
break;
}
- /*
- * This is a workaround for E3+84833 until autoneg
+ /* This is a workaround for E3+84833 until autoneg
* restart is fixed in f/w
*/
if (CHIP_IS_E3(bp)) {
@@ -10418,8 +10269,7 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "54618SE cfg init\n");
usleep_range(1000, 1000);
- /*
- * This works with E3 only, no need to check the chip
+ /* This works with E3 only, no need to check the chip
* before determining the port.
*/
port = params->port;
@@ -10441,7 +10291,7 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
MDIO_PMA_REG_CTRL, 0x8000);
bnx2x_wait_reset_complete(bp, phy, params);
- /*wait for GPHY to reset */
+ /* Wait for GPHY to reset */
msleep(50);
/* Configure LED4: set to INTR (0x6). */
@@ -10647,13 +10497,11 @@ static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy,
u32 cfg_pin;
u8 port;
- /*
- * In case of no EPIO routed to reset the GPHY, put it
+ /* In case of no EPIO routed to reset the GPHY, put it
* in low power mode.
*/
bnx2x_cl22_write(bp, phy, MDIO_PMA_REG_CTRL, 0x800);
- /*
- * This works with E3 only, no need to check the chip
+ /* This works with E3 only, no need to check the chip
* before determining the port.
*/
port = params->port;
@@ -10762,7 +10610,7 @@ 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 */
+ /* Report LP advertised speeds */
bnx2x_cl22_read(bp, phy, 0x5, &val);
if (val & (1<<5))
@@ -10827,8 +10675,7 @@ static void bnx2x_54618se_config_loopback(struct bnx2x_phy *phy,
/* This register opens the gate for the UMAC despite its name */
REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
- /*
- * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
+ /* Maximum Frame Length (RW). Defines a 14-Bit maximum frame
* length used by the MAC receive logic to check frames.
*/
REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
@@ -11101,22 +10948,23 @@ static struct bnx2x_phy phy_warpcore = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
.addr = 0xff,
.def_md_devad = 0,
- .flags = FLAGS_HW_LOCK_REQUIRED,
+ .flags = (FLAGS_HW_LOCK_REQUIRED |
+ FLAGS_TX_ERROR_CHECK),
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
.supported = (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full |
- SUPPORTED_10000baseT_Full |
- SUPPORTED_20000baseKR2_Full |
- SUPPORTED_20000baseMLD2_Full |
- SUPPORTED_FIBRE |
- SUPPORTED_Autoneg |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause),
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_20000baseKR2_Full |
+ SUPPORTED_20000baseMLD2_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
.media_type = ETH_PHY_UNSPECIFIED,
.ver_addr = 0,
.req_flow_ctrl = 0,
@@ -11258,7 +11106,8 @@ static struct bnx2x_phy phy_8726 = {
.addr = 0xff,
.def_md_devad = 0,
.flags = (FLAGS_HW_LOCK_REQUIRED |
- FLAGS_INIT_XGXS_FIRST),
+ FLAGS_INIT_XGXS_FIRST |
+ FLAGS_TX_ERROR_CHECK),
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -11289,7 +11138,8 @@ static struct bnx2x_phy phy_8727 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
.addr = 0xff,
.def_md_devad = 0,
- .flags = FLAGS_FAN_FAILURE_DET_REQ,
+ .flags = (FLAGS_FAN_FAILURE_DET_REQ |
+ FLAGS_TX_ERROR_CHECK),
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -11354,8 +11204,9 @@ static struct bnx2x_phy phy_84823 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
.addr = 0xff,
.def_md_devad = 0,
- .flags = FLAGS_FAN_FAILURE_DET_REQ |
- FLAGS_REARM_LATCH_SIGNAL,
+ .flags = (FLAGS_FAN_FAILURE_DET_REQ |
+ FLAGS_REARM_LATCH_SIGNAL |
+ FLAGS_TX_ERROR_CHECK),
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -11390,8 +11241,9 @@ static struct bnx2x_phy phy_84833 = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
.addr = 0xff,
.def_md_devad = 0,
- .flags = FLAGS_FAN_FAILURE_DET_REQ |
- FLAGS_REARM_LATCH_SIGNAL,
+ .flags = (FLAGS_FAN_FAILURE_DET_REQ |
+ FLAGS_REARM_LATCH_SIGNAL |
+ FLAGS_TX_ERROR_CHECK),
.rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
.mdio_ctrl = 0,
@@ -11466,9 +11318,8 @@ static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base,
/* Get the 4 lanes xgxs config rx and tx */
u32 rx = 0, tx = 0, i;
for (i = 0; i < 2; i++) {
- /*
- * INT_PHY and EXT_PHY1 share the same value location in the
- * shmem. When num_phys is greater than 1, than this value
+ /* INT_PHY and EXT_PHY1 share the same value location in
+ * the shmem. When num_phys is greater than 1, than this value
* applies only to EXT_PHY1
*/
if (phy_index == INT_PHY || phy_index == EXT_PHY1) {
@@ -11546,8 +11397,7 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
offsetof(struct shmem_region, dev_info.
port_hw_config[port].default_cfg)) &
PORT_HW_CFG_NET_SERDES_IF_MASK);
- /*
- * Set the appropriate supported and flags indications per
+ /* Set the appropriate supported and flags indications per
* interface type of the chip
*/
switch (serdes_net_if) {
@@ -11605,8 +11455,7 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
break;
}
- /*
- * Enable MDC/MDIO work-around for E3 A0 since free running MDC
+ /* Enable MDC/MDIO work-around for E3 A0 since free running MDC
* was not set as expected. For B0, ECO will be enabled so there
* won't be an issue there
*/
@@ -11719,8 +11568,7 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
phy->addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
bnx2x_populate_preemphasis(bp, shmem_base, phy, port, phy_index);
- /*
- * The shmem address of the phy version is located on different
+ /* The shmem address of the phy version is located on different
* structures. In case this structure is too old, do not set
* the address
*/
@@ -11754,8 +11602,7 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
(phy->ver_addr)) {
- /*
- * Remove 100Mb link supported for BCM84833 when phy fw
+ /* Remove 100Mb link supported for BCM84833 when phy fw
* version lower than or equal to 1.39
*/
u32 raw_ver = REG_RD(bp, phy->ver_addr);
@@ -11765,8 +11612,7 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
SUPPORTED_100baseT_Full);
}
- /*
- * In case mdc/mdio_access of the external phy is different than the
+ /* In case mdc/mdio_access of the external phy is different than the
* mdc/mdio access of the XGXS, a HW lock must be taken in each access
* to prevent one port interfere with another port's CL45 operations.
*/
@@ -11936,13 +11782,16 @@ int bnx2x_phy_probe(struct link_params *params)
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
break;
+ if (params->feature_config_flags &
+ FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET)
+ phy->flags &= ~FLAGS_TX_ERROR_CHECK;
+
sync_offset = params->shmem_base +
offsetof(struct shmem_region,
dev_info.port_hw_config[params->port].media_type);
media_types = REG_RD(bp, sync_offset);
- /*
- * Update media type for non-PMF sync only for the first time
+ /* Update media type for non-PMF sync only for the first time
* In case the media type changes afterwards, it will be updated
* using the update_status function
*/
@@ -12016,8 +11865,7 @@ void bnx2x_init_xmac_loopback(struct link_params *params,
vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->mac_type = MAC_TYPE_XMAC;
vars->phy_flags = PHY_XGXS_FLAG;
- /*
- * Set WC to loopback mode since link is required to provide clock
+ /* Set WC to loopback mode since link is required to provide clock
* to the XMAC in 20G mode
*/
bnx2x_set_aer_mmd(params, &params->phy[0]);
@@ -12162,6 +12010,7 @@ int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
bnx2x_link_int_enable(params);
break;
}
+ bnx2x_update_mng(params, vars->link_status);
return 0;
}
@@ -12302,7 +12151,8 @@ static int bnx2x_8073_common_init_phy(struct bnx2x *bp,
NIG_MASK_MI_INT));
/* Need to take the phy out of low power mode in order
- to write to access its registers */
+ * to write to access its registers
+ */
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
MISC_REGISTERS_GPIO_OUTPUT_HIGH,
port);
@@ -12350,8 +12200,7 @@ static int bnx2x_8073_common_init_phy(struct bnx2x *bp,
(val | 1<<10));
}
- /*
- * Toggle Transmitter: Power down and then up with 600ms delay
+ /* Toggle Transmitter: Power down and then up with 600ms delay
* between
*/
msleep(600);
@@ -12494,8 +12343,7 @@ static int bnx2x_8727_common_init_phy(struct bnx2x *bp,
reset_gpio = MISC_REGISTERS_GPIO_1;
port = 1;
- /*
- * Retrieve the reset gpio/port which control the reset.
+ /* Retrieve the reset gpio/port which control the reset.
* Default is GPIO1, PORT1
*/
bnx2x_get_ext_phy_reset_gpio(bp, shmem_base_path[0],
@@ -12670,8 +12518,7 @@ static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
- /*
- * GPIO1 affects both ports, so there's need to pull
+ /* GPIO1 affects both ports, so there's need to pull
* it for single port alone
*/
rc = bnx2x_8726_common_init_phy(bp, shmem_base_path,
@@ -12679,8 +12526,7 @@ static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
phy_index, chip_id);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
- /*
- * GPIO3's are linked, and so both need to be toggled
+ /* GPIO3's are linked, and so both need to be toggled
* to obtain required 2us pulse.
*/
rc = bnx2x_84833_common_init_phy(bp, shmem_base_path,
@@ -12779,7 +12625,8 @@ static void bnx2x_check_over_curr(struct link_params *params,
}
static void bnx2x_analyze_link_error(struct link_params *params,
- struct link_vars *vars, u32 lss_status)
+ struct link_vars *vars, u32 lss_status,
+ u8 notify)
{
struct bnx2x *bp = params->bp;
/* Compare new value with previous value */
@@ -12793,8 +12640,7 @@ static void bnx2x_analyze_link_error(struct link_params *params,
DP(NETIF_MSG_LINK, "Link changed:%x %x->%x\n", vars->link_up,
half_open_conn, lss_status);
- /*
- * a. Update shmem->link_status accordingly
+ /* a. Update shmem->link_status accordingly
* b. Update link_vars->link_up
*/
if (lss_status) {
@@ -12802,8 +12648,10 @@ static void bnx2x_analyze_link_error(struct link_params *params,
vars->link_status &= ~LINK_STATUS_LINK_UP;
vars->link_up = 0;
vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
- /*
- * Set LED mode to off since the PHY doesn't know about these
+
+ /* activate nig drain */
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 1);
+ /* Set LED mode to off since the PHY doesn't know about these
* errors
*/
led_mode = LED_MODE_OFF;
@@ -12813,7 +12661,11 @@ static void bnx2x_analyze_link_error(struct link_params *params,
vars->link_up = 1;
vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
led_mode = LED_MODE_OPER;
+
+ /* Clear nig drain */
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
}
+ bnx2x_sync_link(params, vars);
/* Update the LED according to the link state */
bnx2x_set_led(params, vars, led_mode, SPEED_10000);
@@ -12822,7 +12674,8 @@ static void bnx2x_analyze_link_error(struct link_params *params,
/* C. Trigger General Attention */
vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT;
- bnx2x_notify_link_changed(bp);
+ if (notify)
+ bnx2x_notify_link_changed(bp);
}
/******************************************************************************
@@ -12834,22 +12687,23 @@ static void bnx2x_analyze_link_error(struct link_params *params,
* a fault, for example, due to break in the TX side of fiber.
*
******************************************************************************/
-static void bnx2x_check_half_open_conn(struct link_params *params,
- struct link_vars *vars)
+int bnx2x_check_half_open_conn(struct link_params *params,
+ struct link_vars *vars,
+ u8 notify)
{
struct bnx2x *bp = params->bp;
u32 lss_status = 0;
u32 mac_base;
/* In case link status is physically up @ 10G do */
- if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
- return;
+ if (((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0) ||
+ (REG_RD(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4)))
+ return 0;
if (CHIP_IS_E3(bp) &&
(REG_RD(bp, MISC_REG_RESET_REG_2) &
(MISC_REGISTERS_RESET_REG_2_XMAC))) {
/* Check E3 XMAC */
- /*
- * Note that link speed cannot be queried here, since it may be
+ /* Note that link speed cannot be queried here, since it may be
* zero while link is down. In case UMAC is active, LSS will
* simply not be set
*/
@@ -12863,7 +12717,7 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS))
lss_status = 1;
- bnx2x_analyze_link_error(params, vars, lss_status);
+ bnx2x_analyze_link_error(params, vars, lss_status, notify);
} else if (REG_RD(bp, MISC_REG_RESET_REG_2) &
(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) {
/* Check E1X / E2 BMAC */
@@ -12880,18 +12734,21 @@ static void bnx2x_check_half_open_conn(struct link_params *params,
REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2);
lss_status = (wb_data[0] > 0);
- bnx2x_analyze_link_error(params, vars, lss_status);
+ bnx2x_analyze_link_error(params, vars, lss_status, notify);
}
+ return 0;
}
void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
{
- struct bnx2x *bp = params->bp;
u16 phy_idx;
+ struct bnx2x *bp = params->bp;
for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
bnx2x_set_aer_mmd(params, &params->phy[phy_idx]);
- bnx2x_check_half_open_conn(params, vars);
+ if (bnx2x_check_half_open_conn(params, vars, 1) !=
+ 0)
+ DP(NETIF_MSG_LINK, "Fault detection failed\n");
break;
}
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
index 763535ee4832..ea4371f4335f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
@@ -254,8 +254,10 @@ struct link_params {
#define FEATURE_CONFIG_PFC_ENABLED (1<<1)
#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2)
#define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3)
+#define FEATURE_CONFIG_BC_SUPPORTS_AFEX (1<<8)
#define FEATURE_CONFIG_AUTOGREEEN_ENABLED (1<<9)
#define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10)
+#define FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET (1<<11)
/* Will be populated during common init */
struct bnx2x_phy phy[MAX_PHYS];
@@ -495,4 +497,6 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
void bnx2x_period_func(struct link_params *params, struct link_vars *vars);
+int bnx2x_check_half_open_conn(struct link_params *params,
+ struct link_vars *vars, u8 notify);
#endif /* BNX2X_LINK_H */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index e077d2508727..f755a665dab3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -39,7 +39,6 @@
#include <linux/time.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
-#include <linux/if.h>
#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/ipv6.h>
@@ -93,15 +92,11 @@ MODULE_FIRMWARE(FW_FILE_NAME_E1);
MODULE_FIRMWARE(FW_FILE_NAME_E1H);
MODULE_FIRMWARE(FW_FILE_NAME_E2);
-static int multi_mode = 1;
-module_param(multi_mode, int, 0);
-MODULE_PARM_DESC(multi_mode, " Multi queue mode "
- "(0 Disable; 1 Enable (default))");
int num_queues;
module_param(num_queues, int, 0);
-MODULE_PARM_DESC(num_queues, " Number of queues for multi_mode=1"
- " (default is as a number of CPUs)");
+MODULE_PARM_DESC(num_queues,
+ " Set number of queues (default is as a number of CPUs)");
static int disable_tpa;
module_param(disable_tpa, int, 0);
@@ -141,7 +136,9 @@ enum bnx2x_board_type {
BCM57810,
BCM57810_MF,
BCM57840,
- BCM57840_MF
+ BCM57840_MF,
+ BCM57811,
+ BCM57811_MF
};
/* indexed by board_type, above */
@@ -158,8 +155,9 @@ static struct {
{ "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet" },
{ "Broadcom NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function" },
{ "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet" },
- { "Broadcom NetXtreme II BCM57840 10/20 Gigabit "
- "Ethernet Multi Function"}
+ { "Broadcom NetXtreme II BCM57840 10/20 Gigabit Ethernet Multi Function"},
+ { "Broadcom NetXtreme II BCM57811 10 Gigabit Ethernet"},
+ { "Broadcom NetXtreme II BCM57811 10 Gigabit Ethernet Multi Function"},
};
#ifndef PCI_DEVICE_ID_NX2_57710
@@ -195,6 +193,12 @@ static struct {
#ifndef PCI_DEVICE_ID_NX2_57840_MF
#define PCI_DEVICE_ID_NX2_57840_MF CHIP_NUM_57840_MF
#endif
+#ifndef PCI_DEVICE_ID_NX2_57811
+#define PCI_DEVICE_ID_NX2_57811 CHIP_NUM_57811
+#endif
+#ifndef PCI_DEVICE_ID_NX2_57811_MF
+#define PCI_DEVICE_ID_NX2_57811_MF CHIP_NUM_57811_MF
+#endif
static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 },
@@ -207,6 +211,8 @@ static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57810_MF), BCM57810_MF },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840), BCM57840 },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57840_MF), BCM57840_MF },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57811), BCM57811 },
+ { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57811_MF), BCM57811_MF },
{ 0 }
};
@@ -220,15 +226,15 @@ static LIST_HEAD(bnx2x_prev_list);
* General service functions
****************************************************************************/
-static inline void __storm_memset_dma_mapping(struct bnx2x *bp,
+static void __storm_memset_dma_mapping(struct bnx2x *bp,
u32 addr, dma_addr_t mapping)
{
REG_WR(bp, addr, U64_LO(mapping));
REG_WR(bp, addr + 4, U64_HI(mapping));
}
-static inline void storm_memset_spq_addr(struct bnx2x *bp,
- dma_addr_t mapping, u16 abs_fid)
+static void storm_memset_spq_addr(struct bnx2x *bp,
+ dma_addr_t mapping, u16 abs_fid)
{
u32 addr = XSEM_REG_FAST_MEMORY +
XSTORM_SPQ_PAGE_BASE_OFFSET(abs_fid);
@@ -236,8 +242,8 @@ static inline void storm_memset_spq_addr(struct bnx2x *bp,
__storm_memset_dma_mapping(bp, addr, mapping);
}
-static inline void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
- u16 pf_id)
+static void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
+ u16 pf_id)
{
REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_VF_TO_PF_OFFSET(abs_fid),
pf_id);
@@ -249,8 +255,8 @@ static inline void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
pf_id);
}
-static inline void storm_memset_func_en(struct bnx2x *bp, u16 abs_fid,
- u8 enable)
+static void storm_memset_func_en(struct bnx2x *bp, u16 abs_fid,
+ u8 enable)
{
REG_WR8(bp, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(abs_fid),
enable);
@@ -262,8 +268,8 @@ static inline void storm_memset_func_en(struct bnx2x *bp, u16 abs_fid,
enable);
}
-static inline void storm_memset_eq_data(struct bnx2x *bp,
- struct event_ring_data *eq_data,
+static void storm_memset_eq_data(struct bnx2x *bp,
+ struct event_ring_data *eq_data,
u16 pfid)
{
size_t size = sizeof(struct event_ring_data);
@@ -273,8 +279,8 @@ static inline void storm_memset_eq_data(struct bnx2x *bp,
__storm_memset_struct(bp, addr, size, (u32 *)eq_data);
}
-static inline void storm_memset_eq_prod(struct bnx2x *bp, u16 eq_prod,
- u16 pfid)
+static void storm_memset_eq_prod(struct bnx2x *bp, u16 eq_prod,
+ u16 pfid)
{
u32 addr = BAR_CSTRORM_INTMEM + CSTORM_EVENT_RING_PROD_OFFSET(pfid);
REG_WR16(bp, addr, eq_prod);
@@ -309,67 +315,6 @@ static u32 bnx2x_reg_rd_ind(struct bnx2x *bp, u32 addr)
#define DMAE_DP_DST_PCI "pci dst_addr [%x:%08x]"
#define DMAE_DP_DST_NONE "dst_addr [none]"
-static void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae,
- int msglvl)
-{
- u32 src_type = dmae->opcode & DMAE_COMMAND_SRC;
-
- switch (dmae->opcode & DMAE_COMMAND_DST) {
- case DMAE_CMD_DST_PCI:
- if (src_type == DMAE_CMD_SRC_PCI)
- DP(msglvl, "DMAE: opcode 0x%08x\n"
- "src [%x:%08x], len [%d*4], dst [%x:%08x]\n"
- "comp_addr [%x:%08x], comp_val 0x%08x\n",
- dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
- dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo,
- dmae->comp_addr_hi, dmae->comp_addr_lo,
- dmae->comp_val);
- else
- DP(msglvl, "DMAE: opcode 0x%08x\n"
- "src [%08x], len [%d*4], dst [%x:%08x]\n"
- "comp_addr [%x:%08x], comp_val 0x%08x\n",
- dmae->opcode, dmae->src_addr_lo >> 2,
- dmae->len, dmae->dst_addr_hi, dmae->dst_addr_lo,
- dmae->comp_addr_hi, dmae->comp_addr_lo,
- dmae->comp_val);
- break;
- case DMAE_CMD_DST_GRC:
- if (src_type == DMAE_CMD_SRC_PCI)
- DP(msglvl, "DMAE: opcode 0x%08x\n"
- "src [%x:%08x], len [%d*4], dst_addr [%08x]\n"
- "comp_addr [%x:%08x], comp_val 0x%08x\n",
- dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
- dmae->len, dmae->dst_addr_lo >> 2,
- dmae->comp_addr_hi, dmae->comp_addr_lo,
- dmae->comp_val);
- else
- DP(msglvl, "DMAE: opcode 0x%08x\n"
- "src [%08x], len [%d*4], dst [%08x]\n"
- "comp_addr [%x:%08x], comp_val 0x%08x\n",
- dmae->opcode, dmae->src_addr_lo >> 2,
- dmae->len, dmae->dst_addr_lo >> 2,
- dmae->comp_addr_hi, dmae->comp_addr_lo,
- dmae->comp_val);
- break;
- default:
- if (src_type == DMAE_CMD_SRC_PCI)
- DP(msglvl, "DMAE: opcode 0x%08x\n"
- "src_addr [%x:%08x] len [%d * 4] dst_addr [none]\n"
- "comp_addr [%x:%08x] comp_val 0x%08x\n",
- dmae->opcode, dmae->src_addr_hi, dmae->src_addr_lo,
- dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
- dmae->comp_val);
- else
- DP(msglvl, "DMAE: opcode 0x%08x\n"
- "src_addr [%08x] len [%d * 4] dst_addr [none]\n"
- "comp_addr [%x:%08x] comp_val 0x%08x\n",
- dmae->opcode, dmae->src_addr_lo >> 2,
- dmae->len, dmae->comp_addr_hi, dmae->comp_addr_lo,
- dmae->comp_val);
- break;
- }
-
-}
/* copy command into DMAE command memory and set DMAE command go */
void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx)
@@ -506,8 +451,6 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
dmae.dst_addr_hi = 0;
dmae.len = len32;
- bnx2x_dp_dmae(bp, &dmae, BNX2X_MSG_OFF);
-
/* issue the command and wait for completion */
bnx2x_issue_dmae_with_comp(bp, &dmae);
}
@@ -540,8 +483,6 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32)
dmae.dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, wb_data));
dmae.len = len32;
- bnx2x_dp_dmae(bp, &dmae, BNX2X_MSG_OFF);
-
/* issue the command and wait for completion */
bnx2x_issue_dmae_with_comp(bp, &dmae);
}
@@ -562,27 +503,6 @@ static void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr,
bnx2x_write_dmae(bp, phys_addr + offset, addr + offset, len);
}
-/* used only for slowpath so not inlined */
-static void bnx2x_wb_wr(struct bnx2x *bp, int reg, u32 val_hi, u32 val_lo)
-{
- u32 wb_write[2];
-
- wb_write[0] = val_hi;
- wb_write[1] = val_lo;
- REG_WR_DMAE(bp, reg, wb_write, 2);
-}
-
-#ifdef USE_WB_RD
-static u64 bnx2x_wb_rd(struct bnx2x *bp, int reg)
-{
- u32 wb_data[2];
-
- REG_RD_DMAE(bp, reg, wb_data, 2);
-
- return HILO_U64(wb_data[0], wb_data[1]);
-}
-#endif
-
static int bnx2x_mc_assert(struct bnx2x *bp)
{
char last_idx;
@@ -756,7 +676,7 @@ void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl)
printk("%s" "end of fw dump\n", lvl);
}
-static inline void bnx2x_fw_dump(struct bnx2x *bp)
+static void bnx2x_fw_dump(struct bnx2x *bp)
{
bnx2x_fw_dump_lvl(bp, KERN_ERR);
}
@@ -1076,8 +996,8 @@ static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x *bp,
poll_count-cur_cnt, FLR_WAIT_INTERVAL, regs->pN);
}
-static inline u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg,
- u32 expected, u32 poll_count)
+static u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg,
+ u32 expected, u32 poll_count)
{
u32 cur_cnt = poll_count;
u32 val;
@@ -1088,8 +1008,8 @@ static inline u32 bnx2x_flr_clnup_reg_poll(struct bnx2x *bp, u32 reg,
return val;
}
-static inline int bnx2x_flr_clnup_poll_hw_counter(struct bnx2x *bp, u32 reg,
- char *msg, u32 poll_cnt)
+static int bnx2x_flr_clnup_poll_hw_counter(struct bnx2x *bp, u32 reg,
+ char *msg, u32 poll_cnt)
{
u32 val = bnx2x_flr_clnup_reg_poll(bp, reg, 0, poll_cnt);
if (val != 0) {
@@ -1186,7 +1106,7 @@ static void bnx2x_tx_hw_flushed(struct bnx2x *bp, u32 poll_count)
(((index) << SDM_OP_GEN_AGG_VECT_IDX_SHIFT) & SDM_OP_GEN_AGG_VECT_IDX)
-static inline int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func,
+static int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func,
u32 poll_cnt)
{
struct sdm_op_gen op_gen = {0};
@@ -1220,7 +1140,7 @@ static inline int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func,
return ret;
}
-static inline u8 bnx2x_is_pcie_pending(struct pci_dev *dev)
+static u8 bnx2x_is_pcie_pending(struct pci_dev *dev)
{
int pos;
u16 status;
@@ -1361,14 +1281,17 @@ static void bnx2x_hc_int_enable(struct bnx2x *bp)
int port = BP_PORT(bp);
u32 addr = port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0;
u32 val = REG_RD(bp, addr);
- int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
- int msi = (bp->flags & USING_MSI_FLAG) ? 1 : 0;
+ bool msix = (bp->flags & USING_MSIX_FLAG) ? true : false;
+ bool single_msix = (bp->flags & USING_SINGLE_MSIX_FLAG) ? true : false;
+ bool msi = (bp->flags & USING_MSI_FLAG) ? true : false;
if (msix) {
val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
HC_CONFIG_0_REG_INT_LINE_EN_0);
val |= (HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 |
HC_CONFIG_0_REG_ATTN_BIT_EN_0);
+ if (single_msix)
+ val |= HC_CONFIG_0_REG_SINGLE_ISR_EN_0;
} else if (msi) {
val &= ~HC_CONFIG_0_REG_INT_LINE_EN_0;
val |= (HC_CONFIG_0_REG_SINGLE_ISR_EN_0 |
@@ -1425,8 +1348,9 @@ static void bnx2x_hc_int_enable(struct bnx2x *bp)
static void bnx2x_igu_int_enable(struct bnx2x *bp)
{
u32 val;
- int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
- int msi = (bp->flags & USING_MSI_FLAG) ? 1 : 0;
+ bool msix = (bp->flags & USING_MSIX_FLAG) ? true : false;
+ bool single_msix = (bp->flags & USING_SINGLE_MSIX_FLAG) ? true : false;
+ bool msi = (bp->flags & USING_MSI_FLAG) ? true : false;
val = REG_RD(bp, IGU_REG_PF_CONFIGURATION);
@@ -1436,6 +1360,9 @@ static void bnx2x_igu_int_enable(struct bnx2x *bp)
val |= (IGU_PF_CONF_FUNC_EN |
IGU_PF_CONF_MSI_MSIX_EN |
IGU_PF_CONF_ATTN_BIT_EN);
+
+ if (single_msix)
+ val |= IGU_PF_CONF_SINGLE_ISR_EN;
} else if (msi) {
val &= ~IGU_PF_CONF_INT_LINE_EN;
val |= (IGU_PF_CONF_FUNC_EN |
@@ -1455,6 +1382,9 @@ static void bnx2x_igu_int_enable(struct bnx2x *bp)
REG_WR(bp, IGU_REG_PF_CONFIGURATION, val);
+ if (val & IGU_PF_CONF_INT_LINE_EN)
+ pci_intx(bp->pdev, true);
+
barrier();
/* init leading/trailing edge */
@@ -1623,7 +1553,7 @@ static bool bnx2x_trylock_hw_lock(struct bnx2x *bp, u32 resource)
* Returns the recovery leader resource id according to the engine this function
* belongs to. Currently only only 2 engines is supported.
*/
-static inline int bnx2x_get_leader_lock_resource(struct bnx2x *bp)
+static int bnx2x_get_leader_lock_resource(struct bnx2x *bp)
{
if (BP_PATH(bp))
return HW_LOCK_RESOURCE_RECOVERY_LEADER_1;
@@ -1636,9 +1566,9 @@ static inline int bnx2x_get_leader_lock_resource(struct bnx2x *bp)
*
* @bp: driver handle
*
- * Tries to aquire a leader lock for cuurent engine.
+ * Tries to aquire a leader lock for current engine.
*/
-static inline bool bnx2x_trylock_leader_lock(struct bnx2x *bp)
+static bool bnx2x_trylock_leader_lock(struct bnx2x *bp)
{
return bnx2x_trylock_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
}
@@ -1719,6 +1649,27 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe)
DP(BNX2X_MSG_SP, "bp->cq_spq_left %x\n", atomic_read(&bp->cq_spq_left));
+ if ((drv_cmd == BNX2X_Q_CMD_UPDATE) && (IS_FCOE_FP(fp)) &&
+ (!!test_bit(BNX2X_AFEX_FCOE_Q_UPDATE_PENDING, &bp->sp_state))) {
+ /* if Q update ramrod is completed for last Q in AFEX vif set
+ * flow, then ACK MCP at the end
+ *
+ * mark pending ACK to MCP bit.
+ * prevent case that both bits are cleared.
+ * At the end of load/unload driver checks that
+ * sp_state is cleaerd, and this order prevents
+ * races
+ */
+ smp_mb__before_clear_bit();
+ set_bit(BNX2X_AFEX_PENDING_VIFSET_MCP_ACK, &bp->sp_state);
+ wmb();
+ clear_bit(BNX2X_AFEX_FCOE_Q_UPDATE_PENDING, &bp->sp_state);
+ smp_mb__after_clear_bit();
+
+ /* schedule workqueue to send ack to MCP */
+ queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
+ }
+
return;
}
@@ -2229,40 +2180,6 @@ u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes)
return rc;
}
-static void bnx2x_init_port_minmax(struct bnx2x *bp)
-{
- u32 r_param = bp->link_vars.line_speed / 8;
- u32 fair_periodic_timeout_usec;
- u32 t_fair;
-
- memset(&(bp->cmng.rs_vars), 0,
- sizeof(struct rate_shaping_vars_per_port));
- memset(&(bp->cmng.fair_vars), 0, sizeof(struct fairness_vars_per_port));
-
- /* 100 usec in SDM ticks = 25 since each tick is 4 usec */
- bp->cmng.rs_vars.rs_periodic_timeout = RS_PERIODIC_TIMEOUT_USEC / 4;
-
- /* this is the threshold below which no timer arming will occur
- 1.25 coefficient is for the threshold to be a little bigger
- than the real time, to compensate for timer in-accuracy */
- bp->cmng.rs_vars.rs_threshold =
- (RS_PERIODIC_TIMEOUT_USEC * r_param * 5) / 4;
-
- /* resolution of fairness timer */
- fair_periodic_timeout_usec = QM_ARB_BYTES / r_param;
- /* for 10G it is 1000usec. for 1G it is 10000usec. */
- t_fair = T_FAIR_COEF / bp->link_vars.line_speed;
-
- /* this is the threshold below which we won't arm the timer anymore */
- bp->cmng.fair_vars.fair_threshold = QM_ARB_BYTES;
-
- /* we multiply by 1e3/8 to get bytes/msec.
- We don't want the credits to pass a credit
- of the t_fair*FAIR_MEM (algorithm resolution) */
- bp->cmng.fair_vars.upper_bound = r_param * t_fair * FAIR_MEM;
- /* since each tick is 4 usec */
- bp->cmng.fair_vars.fairness_timeout = fair_periodic_timeout_usec / 4;
-}
/* Calculates the sum of vn_min_rates.
It's needed for further normalizing of the min_rates.
@@ -2273,12 +2190,12 @@ static void bnx2x_init_port_minmax(struct bnx2x *bp)
In the later case fainess algorithm should be deactivated.
If not all min_rates are zero then those that are zeroes will be set to 1.
*/
-static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
+static void bnx2x_calc_vn_min(struct bnx2x *bp,
+ struct cmng_init_input *input)
{
int all_zero = 1;
int vn;
- bp->vn_weight_sum = 0;
for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) {
u32 vn_cfg = bp->mf_config[vn];
u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
@@ -2286,106 +2203,56 @@ static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp)
/* Skip hidden vns */
if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE)
- continue;
-
+ vn_min_rate = 0;
/* If min rate is zero - set it to 1 */
- if (!vn_min_rate)
+ else if (!vn_min_rate)
vn_min_rate = DEF_MIN_RATE;
else
all_zero = 0;
- bp->vn_weight_sum += vn_min_rate;
+ input->vnic_min_rate[vn] = vn_min_rate;
}
/* if ETS or all min rates are zeros - disable fairness */
if (BNX2X_IS_ETS_ENABLED(bp)) {
- bp->cmng.flags.cmng_enables &=
+ input->flags.cmng_enables &=
~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
DP(NETIF_MSG_IFUP, "Fairness will be disabled due to ETS\n");
} else if (all_zero) {
- bp->cmng.flags.cmng_enables &=
+ input->flags.cmng_enables &=
~CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
- DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
- " fairness will be disabled\n");
+ DP(NETIF_MSG_IFUP,
+ "All MIN values are zeroes fairness will be disabled\n");
} else
- bp->cmng.flags.cmng_enables |=
+ input->flags.cmng_enables |=
CMNG_FLAGS_PER_PORT_FAIRNESS_VN;
}
-static void bnx2x_init_vn_minmax(struct bnx2x *bp, int vn)
+static void bnx2x_calc_vn_max(struct bnx2x *bp, int vn,
+ struct cmng_init_input *input)
{
- struct rate_shaping_vars_per_vn m_rs_vn;
- struct fairness_vars_per_vn m_fair_vn;
+ u16 vn_max_rate;
u32 vn_cfg = bp->mf_config[vn];
- int func = func_by_vn(bp, vn);
- u16 vn_min_rate, vn_max_rate;
- int i;
- /* If function is hidden - set min and max to zeroes */
- if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE) {
- vn_min_rate = 0;
+ if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE)
vn_max_rate = 0;
-
- } else {
+ else {
u32 maxCfg = bnx2x_extract_max_cfg(bp, vn_cfg);
- vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
- FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
- /* If fairness is enabled (not all min rates are zeroes) and
- if current min rate is zero - set it to 1.
- This is a requirement of the algorithm. */
- if (bp->vn_weight_sum && (vn_min_rate == 0))
- vn_min_rate = DEF_MIN_RATE;
-
- if (IS_MF_SI(bp))
+ if (IS_MF_SI(bp)) {
/* maxCfg in percents of linkspeed */
vn_max_rate = (bp->link_vars.line_speed * maxCfg) / 100;
- else
+ } else /* SD modes */
/* maxCfg is absolute in 100Mb units */
vn_max_rate = maxCfg * 100;
}
- DP(NETIF_MSG_IFUP,
- "func %d: vn_min_rate %d vn_max_rate %d vn_weight_sum %d\n",
- func, vn_min_rate, vn_max_rate, bp->vn_weight_sum);
-
- memset(&m_rs_vn, 0, sizeof(struct rate_shaping_vars_per_vn));
- memset(&m_fair_vn, 0, sizeof(struct fairness_vars_per_vn));
-
- /* global vn counter - maximal Mbps for this vn */
- m_rs_vn.vn_counter.rate = vn_max_rate;
-
- /* quota - number of bytes transmitted in this period */
- m_rs_vn.vn_counter.quota =
- (vn_max_rate * RS_PERIODIC_TIMEOUT_USEC) / 8;
-
- if (bp->vn_weight_sum) {
- /* credit for each period of the fairness algorithm:
- number of bytes in T_FAIR (the vn share the port rate).
- vn_weight_sum should not be larger than 10000, thus
- T_FAIR_COEF / (8 * vn_weight_sum) will always be greater
- than zero */
- m_fair_vn.vn_credit_delta =
- max_t(u32, (vn_min_rate * (T_FAIR_COEF /
- (8 * bp->vn_weight_sum))),
- (bp->cmng.fair_vars.fair_threshold +
- MIN_ABOVE_THRESH));
- DP(NETIF_MSG_IFUP, "m_fair_vn.vn_credit_delta %d\n",
- m_fair_vn.vn_credit_delta);
- }
-
- /* Store it to internal memory */
- for (i = 0; i < sizeof(struct rate_shaping_vars_per_vn)/4; i++)
- REG_WR(bp, BAR_XSTRORM_INTMEM +
- XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(func) + i * 4,
- ((u32 *)(&m_rs_vn))[i]);
-
- for (i = 0; i < sizeof(struct fairness_vars_per_vn)/4; i++)
- REG_WR(bp, BAR_XSTRORM_INTMEM +
- XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(func) + i * 4,
- ((u32 *)(&m_fair_vn))[i]);
+ DP(NETIF_MSG_IFUP, "vn %d: vn_max_rate %d\n", vn, vn_max_rate);
+
+ input->vnic_max_rate[vn] = vn_max_rate;
}
+
static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp)
{
if (CHIP_REV_IS_SLOW(bp))
@@ -2423,38 +2290,42 @@ void bnx2x_read_mf_cfg(struct bnx2x *bp)
bp->mf_config[vn] =
MF_CFG_RD(bp, func_mf_config[func].config);
}
+ if (bp->mf_config[BP_VN(bp)] & FUNC_MF_CFG_FUNC_DISABLED) {
+ DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n");
+ bp->flags |= MF_FUNC_DIS;
+ } else {
+ DP(NETIF_MSG_IFUP, "mf_cfg function enabled\n");
+ bp->flags &= ~MF_FUNC_DIS;
+ }
}
static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type)
{
+ struct cmng_init_input input;
+ memset(&input, 0, sizeof(struct cmng_init_input));
+
+ input.port_rate = bp->link_vars.line_speed;
if (cmng_type == CMNG_FNS_MINMAX) {
int vn;
- /* clear cmng_enables */
- bp->cmng.flags.cmng_enables = 0;
-
/* read mf conf from shmem */
if (read_cfg)
bnx2x_read_mf_cfg(bp);
- /* Init rate shaping and fairness contexts */
- bnx2x_init_port_minmax(bp);
-
/* vn_weight_sum and enable fairness if not 0 */
- bnx2x_calc_vn_weight_sum(bp);
+ bnx2x_calc_vn_min(bp, &input);
/* calculate and set min-max rate for each vn */
if (bp->port.pmf)
for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++)
- bnx2x_init_vn_minmax(bp, vn);
+ bnx2x_calc_vn_max(bp, vn, &input);
/* always enable rate shaping and fairness */
- bp->cmng.flags.cmng_enables |=
+ input.flags.cmng_enables |=
CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN;
- if (!bp->vn_weight_sum)
- DP(NETIF_MSG_IFUP, "All MIN values are zeroes"
- " fairness will be disabled\n");
+
+ bnx2x_init_cmng(&input, &bp->cmng);
return;
}
@@ -2463,6 +2334,35 @@ static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type)
"rate shaping and fairness are disabled\n");
}
+static void storm_memset_cmng(struct bnx2x *bp,
+ struct cmng_init *cmng,
+ u8 port)
+{
+ int vn;
+ size_t size = sizeof(struct cmng_struct_per_port);
+
+ u32 addr = BAR_XSTRORM_INTMEM +
+ XSTORM_CMNG_PER_PORT_VARS_OFFSET(port);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)&cmng->port);
+
+ for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) {
+ int func = func_by_vn(bp, vn);
+
+ addr = BAR_XSTRORM_INTMEM +
+ XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(func);
+ size = sizeof(struct rate_shaping_vars_per_vn);
+ __storm_memset_struct(bp, addr, size,
+ (u32 *)&cmng->vnic.vnic_max_rate[vn]);
+
+ addr = BAR_XSTRORM_INTMEM +
+ XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(func);
+ size = sizeof(struct fairness_vars_per_vn);
+ __storm_memset_struct(bp, addr, size,
+ (u32 *)&cmng->vnic.vnic_min_rate[vn]);
+ }
+}
+
/* This function is called upon link interrupt */
static void bnx2x_link_attn(struct bnx2x *bp)
{
@@ -2535,6 +2435,190 @@ void bnx2x__link_status_update(struct bnx2x *bp)
bnx2x_link_report(bp);
}
+static int bnx2x_afex_func_update(struct bnx2x *bp, u16 vifid,
+ u16 vlan_val, u8 allowed_prio)
+{
+ struct bnx2x_func_state_params func_params = {0};
+ struct bnx2x_func_afex_update_params *f_update_params =
+ &func_params.params.afex_update;
+
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_AFEX_UPDATE;
+
+ /* no need to wait for RAMROD completion, so don't
+ * set RAMROD_COMP_WAIT flag
+ */
+
+ f_update_params->vif_id = vifid;
+ f_update_params->afex_default_vlan = vlan_val;
+ f_update_params->allowed_priorities = allowed_prio;
+
+ /* if ramrod can not be sent, response to MCP immediately */
+ if (bnx2x_func_state_change(bp, &func_params) < 0)
+ bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0);
+
+ return 0;
+}
+
+static int bnx2x_afex_handle_vif_list_cmd(struct bnx2x *bp, u8 cmd_type,
+ u16 vif_index, u8 func_bit_map)
+{
+ struct bnx2x_func_state_params func_params = {0};
+ struct bnx2x_func_afex_viflists_params *update_params =
+ &func_params.params.afex_viflists;
+ int rc;
+ u32 drv_msg_code;
+
+ /* validate only LIST_SET and LIST_GET are received from switch */
+ if ((cmd_type != VIF_LIST_RULE_GET) && (cmd_type != VIF_LIST_RULE_SET))
+ BNX2X_ERR("BUG! afex_handle_vif_list_cmd invalid type 0x%x\n",
+ cmd_type);
+
+ func_params.f_obj = &bp->func_obj;
+ func_params.cmd = BNX2X_F_CMD_AFEX_VIFLISTS;
+
+ /* set parameters according to cmd_type */
+ update_params->afex_vif_list_command = cmd_type;
+ update_params->vif_list_index = cpu_to_le16(vif_index);
+ update_params->func_bit_map =
+ (cmd_type == VIF_LIST_RULE_GET) ? 0 : func_bit_map;
+ update_params->func_to_clear = 0;
+ drv_msg_code =
+ (cmd_type == VIF_LIST_RULE_GET) ?
+ DRV_MSG_CODE_AFEX_LISTGET_ACK :
+ DRV_MSG_CODE_AFEX_LISTSET_ACK;
+
+ /* if ramrod can not be sent, respond to MCP immediately for
+ * SET and GET requests (other are not triggered from MCP)
+ */
+ rc = bnx2x_func_state_change(bp, &func_params);
+ if (rc < 0)
+ bnx2x_fw_command(bp, drv_msg_code, 0);
+
+ return 0;
+}
+
+static void bnx2x_handle_afex_cmd(struct bnx2x *bp, u32 cmd)
+{
+ struct afex_stats afex_stats;
+ u32 func = BP_ABS_FUNC(bp);
+ u32 mf_config;
+ u16 vlan_val;
+ u32 vlan_prio;
+ u16 vif_id;
+ u8 allowed_prio;
+ u8 vlan_mode;
+ u32 addr_to_write, vifid, addrs, stats_type, i;
+
+ if (cmd & DRV_STATUS_AFEX_LISTGET_REQ) {
+ vifid = SHMEM2_RD(bp, afex_param1_to_driver[BP_FW_MB_IDX(bp)]);
+ DP(BNX2X_MSG_MCP,
+ "afex: got MCP req LISTGET_REQ for vifid 0x%x\n", vifid);
+ bnx2x_afex_handle_vif_list_cmd(bp, VIF_LIST_RULE_GET, vifid, 0);
+ }
+
+ if (cmd & DRV_STATUS_AFEX_LISTSET_REQ) {
+ vifid = SHMEM2_RD(bp, afex_param1_to_driver[BP_FW_MB_IDX(bp)]);
+ addrs = SHMEM2_RD(bp, afex_param2_to_driver[BP_FW_MB_IDX(bp)]);
+ DP(BNX2X_MSG_MCP,
+ "afex: got MCP req LISTSET_REQ for vifid 0x%x addrs 0x%x\n",
+ vifid, addrs);
+ bnx2x_afex_handle_vif_list_cmd(bp, VIF_LIST_RULE_SET, vifid,
+ addrs);
+ }
+
+ if (cmd & DRV_STATUS_AFEX_STATSGET_REQ) {
+ addr_to_write = SHMEM2_RD(bp,
+ afex_scratchpad_addr_to_write[BP_FW_MB_IDX(bp)]);
+ stats_type = SHMEM2_RD(bp,
+ afex_param1_to_driver[BP_FW_MB_IDX(bp)]);
+
+ DP(BNX2X_MSG_MCP,
+ "afex: got MCP req STATSGET_REQ, write to addr 0x%x\n",
+ addr_to_write);
+
+ bnx2x_afex_collect_stats(bp, (void *)&afex_stats, stats_type);
+
+ /* write response to scratchpad, for MCP */
+ for (i = 0; i < (sizeof(struct afex_stats)/sizeof(u32)); i++)
+ REG_WR(bp, addr_to_write + i*sizeof(u32),
+ *(((u32 *)(&afex_stats))+i));
+
+ /* send ack message to MCP */
+ bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_STATSGET_ACK, 0);
+ }
+
+ if (cmd & DRV_STATUS_AFEX_VIFSET_REQ) {
+ mf_config = MF_CFG_RD(bp, func_mf_config[func].config);
+ bp->mf_config[BP_VN(bp)] = mf_config;
+ DP(BNX2X_MSG_MCP,
+ "afex: got MCP req VIFSET_REQ, mf_config 0x%x\n",
+ mf_config);
+
+ /* if VIF_SET is "enabled" */
+ if (!(mf_config & FUNC_MF_CFG_FUNC_DISABLED)) {
+ /* set rate limit directly to internal RAM */
+ struct cmng_init_input cmng_input;
+ struct rate_shaping_vars_per_vn m_rs_vn;
+ size_t size = sizeof(struct rate_shaping_vars_per_vn);
+ u32 addr = BAR_XSTRORM_INTMEM +
+ XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(BP_FUNC(bp));
+
+ bp->mf_config[BP_VN(bp)] = mf_config;
+
+ bnx2x_calc_vn_max(bp, BP_VN(bp), &cmng_input);
+ m_rs_vn.vn_counter.rate =
+ cmng_input.vnic_max_rate[BP_VN(bp)];
+ m_rs_vn.vn_counter.quota =
+ (m_rs_vn.vn_counter.rate *
+ RS_PERIODIC_TIMEOUT_USEC) / 8;
+
+ __storm_memset_struct(bp, addr, size, (u32 *)&m_rs_vn);
+
+ /* read relevant values from mf_cfg struct in shmem */
+ vif_id =
+ (MF_CFG_RD(bp, func_mf_config[func].e1hov_tag) &
+ FUNC_MF_CFG_E1HOV_TAG_MASK) >>
+ FUNC_MF_CFG_E1HOV_TAG_SHIFT;
+ vlan_val =
+ (MF_CFG_RD(bp, func_mf_config[func].e1hov_tag) &
+ FUNC_MF_CFG_AFEX_VLAN_MASK) >>
+ FUNC_MF_CFG_AFEX_VLAN_SHIFT;
+ vlan_prio = (mf_config &
+ FUNC_MF_CFG_TRANSMIT_PRIORITY_MASK) >>
+ FUNC_MF_CFG_TRANSMIT_PRIORITY_SHIFT;
+ vlan_val |= (vlan_prio << VLAN_PRIO_SHIFT);
+ vlan_mode =
+ (MF_CFG_RD(bp,
+ func_mf_config[func].afex_config) &
+ FUNC_MF_CFG_AFEX_VLAN_MODE_MASK) >>
+ FUNC_MF_CFG_AFEX_VLAN_MODE_SHIFT;
+ allowed_prio =
+ (MF_CFG_RD(bp,
+ func_mf_config[func].afex_config) &
+ FUNC_MF_CFG_AFEX_COS_FILTER_MASK) >>
+ FUNC_MF_CFG_AFEX_COS_FILTER_SHIFT;
+
+ /* send ramrod to FW, return in case of failure */
+ if (bnx2x_afex_func_update(bp, vif_id, vlan_val,
+ allowed_prio))
+ return;
+
+ bp->afex_def_vlan_tag = vlan_val;
+ bp->afex_vlan_mode = vlan_mode;
+ } else {
+ /* notify link down because BP->flags is disabled */
+ bnx2x_link_report(bp);
+
+ /* send INVALID VIF ramrod to FW */
+ bnx2x_afex_func_update(bp, 0xFFFF, 0, 0);
+
+ /* Reset the default afex VLAN */
+ bp->afex_def_vlan_tag = -1;
+ }
+ }
+}
+
static void bnx2x_pmf_update(struct bnx2x *bp)
{
int port = BP_PORT(bp);
@@ -2619,6 +2703,18 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param)
}
+static void storm_memset_func_cfg(struct bnx2x *bp,
+ struct tstorm_eth_function_common_config *tcfg,
+ u16 abs_fid)
+{
+ size_t size = sizeof(struct tstorm_eth_function_common_config);
+
+ u32 addr = BAR_TSTRORM_INTMEM +
+ TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
+
+ __storm_memset_struct(bp, addr, size, (u32 *)tcfg);
+}
+
void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
{
if (CHIP_IS_E1x(bp)) {
@@ -2648,9 +2744,9 @@ void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p)
*
* Return the flags that are common for the Tx-only and not normal connections.
*/
-static inline unsigned long bnx2x_get_common_flags(struct bnx2x *bp,
- struct bnx2x_fastpath *fp,
- bool zero_stats)
+static unsigned long bnx2x_get_common_flags(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp,
+ bool zero_stats)
{
unsigned long flags = 0;
@@ -2670,9 +2766,9 @@ static inline unsigned long bnx2x_get_common_flags(struct bnx2x *bp,
return flags;
}
-static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
- struct bnx2x_fastpath *fp,
- bool leading)
+static unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
+ struct bnx2x_fastpath *fp,
+ bool leading)
{
unsigned long flags = 0;
@@ -2680,8 +2776,11 @@ static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
if (IS_MF_SD(bp))
__set_bit(BNX2X_Q_FLG_OV, &flags);
- if (IS_FCOE_FP(fp))
+ if (IS_FCOE_FP(fp)) {
__set_bit(BNX2X_Q_FLG_FCOE, &flags);
+ /* For FCoE - force usage of default priority (for afex) */
+ __set_bit(BNX2X_Q_FLG_FORCE_DEFAULT_PRI, &flags);
+ }
if (!fp->disable_tpa) {
__set_bit(BNX2X_Q_FLG_TPA, &flags);
@@ -2698,6 +2797,10 @@ static inline unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
/* Always set HW VLAN stripping */
__set_bit(BNX2X_Q_FLG_VLAN, &flags);
+ /* configure silent vlan removal */
+ if (IS_MF_AFEX(bp))
+ __set_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, &flags);
+
return flags | bnx2x_get_common_flags(bp, fp, true);
}
@@ -2800,6 +2903,13 @@ static void bnx2x_pf_rx_q_prep(struct bnx2x *bp,
rxq_init->sb_cq_index = HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS;
else
rxq_init->sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS;
+ /* configure silent vlan removal
+ * if multi function mode is afex, then mask default vlan
+ */
+ if (IS_MF_AFEX(bp)) {
+ rxq_init->silent_removal_value = bp->afex_def_vlan_tag;
+ rxq_init->silent_removal_mask = VLAN_VID_MASK;
+ }
}
static void bnx2x_pf_tx_q_prep(struct bnx2x *bp,
@@ -3051,7 +3161,7 @@ static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp)
* configure FW
* notify others function about the change
*/
-static inline void bnx2x_config_mf_bw(struct bnx2x *bp)
+static void bnx2x_config_mf_bw(struct bnx2x *bp)
{
if (bp->link_vars.link_up) {
bnx2x_cmng_fns_init(bp, true, CMNG_FNS_MINMAX);
@@ -3060,7 +3170,7 @@ static inline void bnx2x_config_mf_bw(struct bnx2x *bp)
storm_memset_cmng(bp, &bp->cmng, BP_PORT(bp));
}
-static inline void bnx2x_set_mf_bw(struct bnx2x *bp)
+static void bnx2x_set_mf_bw(struct bnx2x *bp)
{
bnx2x_config_mf_bw(bp);
bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW_ACK, 0);
@@ -3147,7 +3257,7 @@ static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event)
}
/* must be called under the spq lock */
-static inline struct eth_spe *bnx2x_sp_get_next(struct bnx2x *bp)
+static struct eth_spe *bnx2x_sp_get_next(struct bnx2x *bp)
{
struct eth_spe *next_spe = bp->spq_prod_bd;
@@ -3163,7 +3273,7 @@ static inline struct eth_spe *bnx2x_sp_get_next(struct bnx2x *bp)
}
/* must be called under the spq lock */
-static inline void bnx2x_sp_prod_update(struct bnx2x *bp)
+static void bnx2x_sp_prod_update(struct bnx2x *bp)
{
int func = BP_FUNC(bp);
@@ -3185,7 +3295,7 @@ static inline void bnx2x_sp_prod_update(struct bnx2x *bp)
* @cmd: command to check
* @cmd_type: command type
*/
-static inline bool bnx2x_is_contextless_ramrod(int cmd, int cmd_type)
+static bool bnx2x_is_contextless_ramrod(int cmd, int cmd_type)
{
if ((cmd_type == NONE_CONNECTION_TYPE) ||
(cmd == RAMROD_CMD_ID_ETH_FORWARD_SETUP) ||
@@ -3319,7 +3429,7 @@ static void bnx2x_release_alr(struct bnx2x *bp)
#define BNX2X_DEF_SB_ATT_IDX 0x0001
#define BNX2X_DEF_SB_IDX 0x0002
-static inline u16 bnx2x_update_dsb_idx(struct bnx2x *bp)
+static u16 bnx2x_update_dsb_idx(struct bnx2x *bp)
{
struct host_sp_status_block *def_sb = bp->def_status_blk;
u16 rc = 0;
@@ -3451,7 +3561,7 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
}
}
-static inline void bnx2x_fan_failure(struct bnx2x *bp)
+static void bnx2x_fan_failure(struct bnx2x *bp)
{
int port = BP_PORT(bp);
u32 ext_phy_config;
@@ -3481,7 +3591,7 @@ static inline void bnx2x_fan_failure(struct bnx2x *bp)
}
-static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
+static void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
{
int port = BP_PORT(bp);
int reg_offset;
@@ -3521,7 +3631,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
}
}
-static inline void bnx2x_attn_int_deasserted1(struct bnx2x *bp, u32 attn)
+static void bnx2x_attn_int_deasserted1(struct bnx2x *bp, u32 attn)
{
u32 val;
@@ -3552,7 +3662,7 @@ static inline void bnx2x_attn_int_deasserted1(struct bnx2x *bp, u32 attn)
}
}
-static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
+static void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
{
u32 val;
@@ -3596,7 +3706,7 @@ static inline void bnx2x_attn_int_deasserted2(struct bnx2x *bp, u32 attn)
}
}
-static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
+static void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
{
u32 val;
@@ -3606,6 +3716,7 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
int func = BP_FUNC(bp);
REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_12 + func*4, 0);
+ bnx2x_read_mf_cfg(bp);
bp->mf_config[BP_VN(bp)] = MF_CFG_RD(bp,
func_mf_config[BP_ABS_FUNC(bp)].config);
val = SHMEM_RD(bp,
@@ -3628,6 +3739,9 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
/* start dcbx state machine */
bnx2x_dcbx_set_params(bp,
BNX2X_DCBX_STATE_NEG_RECEIVED);
+ if (val & DRV_STATUS_AFEX_EVENT_MASK)
+ bnx2x_handle_afex_cmd(bp,
+ val & DRV_STATUS_AFEX_EVENT_MASK);
if (bp->link_vars.periodic_flags &
PERIODIC_FLAGS_LINK_EVENT) {
/* sync with link */
@@ -3722,7 +3836,7 @@ void bnx2x_set_reset_global(struct bnx2x *bp)
*
* Should be run under rtnl lock
*/
-static inline void bnx2x_clear_reset_global(struct bnx2x *bp)
+static void bnx2x_clear_reset_global(struct bnx2x *bp)
{
u32 val;
bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
@@ -3736,7 +3850,7 @@ static inline void bnx2x_clear_reset_global(struct bnx2x *bp)
*
* should be run under rtnl lock
*/
-static inline bool bnx2x_reset_is_global(struct bnx2x *bp)
+static bool bnx2x_reset_is_global(struct bnx2x *bp)
{
u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG);
@@ -3749,7 +3863,7 @@ static inline bool bnx2x_reset_is_global(struct bnx2x *bp)
*
* Should be run under rtnl lock
*/
-static inline void bnx2x_set_reset_done(struct bnx2x *bp)
+static void bnx2x_set_reset_done(struct bnx2x *bp)
{
u32 val;
u32 bit = BP_PATH(bp) ?
@@ -3874,7 +3988,7 @@ bool bnx2x_clear_pf_load(struct bnx2x *bp)
*
* should be run under rtnl lock
*/
-static inline bool bnx2x_get_load_status(struct bnx2x *bp, int engine)
+static bool bnx2x_get_load_status(struct bnx2x *bp, int engine)
{
u32 mask = (engine ? BNX2X_PATH1_LOAD_CNT_MASK :
BNX2X_PATH0_LOAD_CNT_MASK);
@@ -3895,7 +4009,7 @@ static inline bool bnx2x_get_load_status(struct bnx2x *bp, int engine)
/*
* Reset the load status for the current engine.
*/
-static inline void bnx2x_clear_load_status(struct bnx2x *bp)
+static void bnx2x_clear_load_status(struct bnx2x *bp)
{
u32 val;
u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK :
@@ -3906,13 +4020,13 @@ static inline void bnx2x_clear_load_status(struct bnx2x *bp)
bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG);
}
-static inline void _print_next_block(int idx, const char *blk)
+static void _print_next_block(int idx, const char *blk)
{
pr_cont("%s%s", idx ? ", " : "", blk);
}
-static inline int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
- bool print)
+static int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
+ bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -3959,8 +4073,8 @@ static inline int bnx2x_check_blocks_with_parity0(u32 sig, int par_num,
return par_num;
}
-static inline int bnx2x_check_blocks_with_parity1(u32 sig, int par_num,
- bool *global, bool print)
+static int bnx2x_check_blocks_with_parity1(u32 sig, int par_num,
+ bool *global, bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -4045,8 +4159,8 @@ static inline int bnx2x_check_blocks_with_parity1(u32 sig, int par_num,
return par_num;
}
-static inline int bnx2x_check_blocks_with_parity2(u32 sig, int par_num,
- bool print)
+static int bnx2x_check_blocks_with_parity2(u32 sig, int par_num,
+ bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -4097,8 +4211,8 @@ static inline int bnx2x_check_blocks_with_parity2(u32 sig, int par_num,
return par_num;
}
-static inline int bnx2x_check_blocks_with_parity3(u32 sig, int par_num,
- bool *global, bool print)
+static int bnx2x_check_blocks_with_parity3(u32 sig, int par_num,
+ bool *global, bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -4139,8 +4253,8 @@ static inline int bnx2x_check_blocks_with_parity3(u32 sig, int par_num,
return par_num;
}
-static inline int bnx2x_check_blocks_with_parity4(u32 sig, int par_num,
- bool print)
+static int bnx2x_check_blocks_with_parity4(u32 sig, int par_num,
+ bool print)
{
int i = 0;
u32 cur_bit = 0;
@@ -4166,8 +4280,8 @@ static inline int bnx2x_check_blocks_with_parity4(u32 sig, int par_num,
return par_num;
}
-static inline bool bnx2x_parity_attn(struct bnx2x *bp, bool *global, bool print,
- u32 *sig)
+static bool bnx2x_parity_attn(struct bnx2x *bp, bool *global, bool print,
+ u32 *sig)
{
if ((sig[0] & HW_PRTY_ASSERT_SET_0) ||
(sig[1] & HW_PRTY_ASSERT_SET_1) ||
@@ -4238,7 +4352,7 @@ bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print)
}
-static inline void bnx2x_attn_int_deasserted4(struct bnx2x *bp, u32 attn)
+static void bnx2x_attn_int_deasserted4(struct bnx2x *bp, u32 attn)
{
u32 val;
if (attn & AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT) {
@@ -4430,7 +4544,7 @@ void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
igu_addr);
}
-static inline void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
+static void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
{
/* No memory barriers */
storm_memset_eq_prod(bp, prod, BP_FUNC(bp));
@@ -4461,7 +4575,7 @@ static int bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
}
#endif
-static inline void bnx2x_handle_mcast_eqe(struct bnx2x *bp)
+static void bnx2x_handle_mcast_eqe(struct bnx2x *bp)
{
struct bnx2x_mcast_ramrod_params rparam;
int rc;
@@ -4486,8 +4600,8 @@ static inline void bnx2x_handle_mcast_eqe(struct bnx2x *bp)
netif_addr_unlock_bh(bp->dev);
}
-static inline void bnx2x_handle_classification_eqe(struct bnx2x *bp,
- union event_ring_elem *elem)
+static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
+ union event_ring_elem *elem)
{
unsigned long ramrod_flags = 0;
int rc = 0;
@@ -4534,7 +4648,7 @@ static inline void bnx2x_handle_classification_eqe(struct bnx2x *bp,
static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start);
#endif
-static inline void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
+static void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
{
netif_addr_lock_bh(bp->dev);
@@ -4555,7 +4669,94 @@ static inline void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
netif_addr_unlock_bh(bp->dev);
}
-static inline struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj(
+static void bnx2x_after_afex_vif_lists(struct bnx2x *bp,
+ union event_ring_elem *elem)
+{
+ if (elem->message.data.vif_list_event.echo == VIF_LIST_RULE_GET) {
+ DP(BNX2X_MSG_SP,
+ "afex: ramrod completed VIF LIST_GET, addrs 0x%x\n",
+ elem->message.data.vif_list_event.func_bit_map);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_LISTGET_ACK,
+ elem->message.data.vif_list_event.func_bit_map);
+ } else if (elem->message.data.vif_list_event.echo ==
+ VIF_LIST_RULE_SET) {
+ DP(BNX2X_MSG_SP, "afex: ramrod completed VIF LIST_SET\n");
+ bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_LISTSET_ACK, 0);
+ }
+}
+
+/* called with rtnl_lock */
+static void bnx2x_after_function_update(struct bnx2x *bp)
+{
+ int q, rc;
+ struct bnx2x_fastpath *fp;
+ struct bnx2x_queue_state_params queue_params = {NULL};
+ struct bnx2x_queue_update_params *q_update_params =
+ &queue_params.params.update;
+
+ /* Send Q update command with afex vlan removal values for all Qs */
+ queue_params.cmd = BNX2X_Q_CMD_UPDATE;
+
+ /* set silent vlan removal values according to vlan mode */
+ __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+ &q_update_params->update_flags);
+ __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+ &q_update_params->update_flags);
+ __set_bit(RAMROD_COMP_WAIT, &queue_params.ramrod_flags);
+
+ /* in access mode mark mask and value are 0 to strip all vlans */
+ if (bp->afex_vlan_mode == FUNC_MF_CFG_AFEX_VLAN_ACCESS_MODE) {
+ q_update_params->silent_removal_value = 0;
+ q_update_params->silent_removal_mask = 0;
+ } else {
+ q_update_params->silent_removal_value =
+ (bp->afex_def_vlan_tag & VLAN_VID_MASK);
+ q_update_params->silent_removal_mask = VLAN_VID_MASK;
+ }
+
+ for_each_eth_queue(bp, q) {
+ /* Set the appropriate Queue object */
+ fp = &bp->fp[q];
+ queue_params.q_obj = &fp->q_obj;
+
+ /* send the ramrod */
+ rc = bnx2x_queue_state_change(bp, &queue_params);
+ if (rc < 0)
+ BNX2X_ERR("Failed to config silent vlan rem for Q %d\n",
+ q);
+ }
+
+#ifdef BCM_CNIC
+ if (!NO_FCOE(bp)) {
+ fp = &bp->fp[FCOE_IDX];
+ queue_params.q_obj = &fp->q_obj;
+
+ /* clear pending completion bit */
+ __clear_bit(RAMROD_COMP_WAIT, &queue_params.ramrod_flags);
+
+ /* mark latest Q bit */
+ smp_mb__before_clear_bit();
+ set_bit(BNX2X_AFEX_FCOE_Q_UPDATE_PENDING, &bp->sp_state);
+ smp_mb__after_clear_bit();
+
+ /* send Q update ramrod for FCoE Q */
+ rc = bnx2x_queue_state_change(bp, &queue_params);
+ if (rc < 0)
+ BNX2X_ERR("Failed to config silent vlan rem for Q %d\n",
+ q);
+ } else {
+ /* If no FCoE ring - ACK MCP now */
+ bnx2x_link_report(bp);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0);
+ }
+#else
+ /* If no FCoE ring - ACK MCP now */
+ bnx2x_link_report(bp);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0);
+#endif /* BCM_CNIC */
+}
+
+static struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj(
struct bnx2x *bp, u32 cid)
{
DP(BNX2X_MSG_SP, "retrieving fp from cid %d\n", cid);
@@ -4653,6 +4854,28 @@ static void bnx2x_eq_int(struct bnx2x *bp)
break;
bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED);
goto next_spqe;
+ case EVENT_RING_OPCODE_FUNCTION_UPDATE:
+ DP(BNX2X_MSG_SP | BNX2X_MSG_MCP,
+ "AFEX: ramrod completed FUNCTION_UPDATE\n");
+ f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_AFEX_UPDATE);
+
+ /* We will perform the Queues update from sp_rtnl task
+ * as all Queue SP operations should run under
+ * rtnl_lock.
+ */
+ smp_mb__before_clear_bit();
+ set_bit(BNX2X_SP_RTNL_AFEX_F_UPDATE,
+ &bp->sp_rtnl_state);
+ smp_mb__after_clear_bit();
+
+ schedule_delayed_work(&bp->sp_rtnl_task, 0);
+ goto next_spqe;
+
+ case EVENT_RING_OPCODE_AFEX_VIF_LISTS:
+ f_obj->complete_cmd(bp, f_obj,
+ BNX2X_F_CMD_AFEX_VIFLISTS);
+ bnx2x_after_afex_vif_lists(bp, elem);
+ goto next_spqe;
case EVENT_RING_OPCODE_FUNCTION_START:
DP(BNX2X_MSG_SP | NETIF_MSG_IFUP,
"got FUNC_START ramrod\n");
@@ -4784,6 +5007,13 @@ static void bnx2x_sp_task(struct work_struct *work)
bnx2x_ack_sb(bp, bp->igu_dsb_id, ATTENTION_ID,
le16_to_cpu(bp->def_att_idx), IGU_INT_ENABLE, 1);
+
+ /* afex - poll to check if VIFSET_ACK should be sent to MFW */
+ if (test_and_clear_bit(BNX2X_AFEX_PENDING_VIFSET_MCP_ACK,
+ &bp->sp_state)) {
+ bnx2x_link_report(bp);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0);
+ }
}
irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
@@ -4870,7 +5100,7 @@ static void bnx2x_timer(unsigned long data)
* nic init service functions
*/
-static inline void bnx2x_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
+static void bnx2x_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
{
u32 i;
if (!(len%4) && !(addr%4))
@@ -4883,10 +5113,10 @@ static inline void bnx2x_fill(struct bnx2x *bp, u32 addr, int fill, u32 len)
}
/* helper: writes FP SP data to FW - data_size in dwords */
-static inline void bnx2x_wr_fp_sb_data(struct bnx2x *bp,
- int fw_sb_id,
- u32 *sb_data_p,
- u32 data_size)
+static void bnx2x_wr_fp_sb_data(struct bnx2x *bp,
+ int fw_sb_id,
+ u32 *sb_data_p,
+ u32 data_size)
{
int index;
for (index = 0; index < data_size; index++)
@@ -4896,7 +5126,7 @@ static inline void bnx2x_wr_fp_sb_data(struct bnx2x *bp,
*(sb_data_p + index));
}
-static inline void bnx2x_zero_fp_sb(struct bnx2x *bp, int fw_sb_id)
+static void bnx2x_zero_fp_sb(struct bnx2x *bp, int fw_sb_id)
{
u32 *sb_data_p;
u32 data_size = 0;
@@ -4929,7 +5159,7 @@ static inline void bnx2x_zero_fp_sb(struct bnx2x *bp, int fw_sb_id)
}
/* helper: writes SP SB data to FW */
-static inline void bnx2x_wr_sp_sb_data(struct bnx2x *bp,
+static void bnx2x_wr_sp_sb_data(struct bnx2x *bp,
struct hc_sp_status_block_data *sp_sb_data)
{
int func = BP_FUNC(bp);
@@ -4941,7 +5171,7 @@ static inline void bnx2x_wr_sp_sb_data(struct bnx2x *bp,
*((u32 *)sp_sb_data + i));
}
-static inline void bnx2x_zero_sp_sb(struct bnx2x *bp)
+static void bnx2x_zero_sp_sb(struct bnx2x *bp)
{
int func = BP_FUNC(bp);
struct hc_sp_status_block_data sp_sb_data;
@@ -4962,8 +5192,7 @@ static inline void bnx2x_zero_sp_sb(struct bnx2x *bp)
}
-static inline
-void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm,
+static void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm,
int igu_sb_id, int igu_seg_id)
{
hc_sm->igu_sb_id = igu_sb_id;
@@ -4974,8 +5203,7 @@ void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm,
/* allocates state machine ids. */
-static inline
-void bnx2x_map_sb_state_machines(struct hc_index_data *index_data)
+static void bnx2x_map_sb_state_machines(struct hc_index_data *index_data)
{
/* zero out state machine indices */
/* rx indices */
@@ -5383,7 +5611,7 @@ static inline u8 bnx2x_fp_fw_sb_id(struct bnx2x_fastpath *fp)
return fp->bp->base_fw_ndsb + fp->index + CNIC_PRESENT;
}
-static inline u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp)
+static u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp)
{
if (CHIP_IS_E1x(fp->bp))
return BP_L_ID(fp->bp) + fp->index;
@@ -5444,6 +5672,43 @@ static void bnx2x_init_eth_fp(struct bnx2x *bp, int fp_idx)
bnx2x_update_fpsb_idx(fp);
}
+static void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata)
+{
+ int i;
+
+ for (i = 1; i <= NUM_TX_RINGS; i++) {
+ struct eth_tx_next_bd *tx_next_bd =
+ &txdata->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
+
+ tx_next_bd->addr_hi =
+ cpu_to_le32(U64_HI(txdata->tx_desc_mapping +
+ BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
+ tx_next_bd->addr_lo =
+ cpu_to_le32(U64_LO(txdata->tx_desc_mapping +
+ BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
+ }
+
+ SET_FLAG(txdata->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
+ txdata->tx_db.data.zero_fill1 = 0;
+ txdata->tx_db.data.prod = 0;
+
+ txdata->tx_pkt_prod = 0;
+ txdata->tx_pkt_cons = 0;
+ txdata->tx_bd_prod = 0;
+ txdata->tx_bd_cons = 0;
+ txdata->tx_pkt = 0;
+}
+
+static void bnx2x_init_tx_rings(struct bnx2x *bp)
+{
+ int i;
+ u8 cos;
+
+ for_each_tx_queue(bp, i)
+ for_each_cos_in_tx_queue(&bp->fp[i], cos)
+ bnx2x_init_tx_ring_one(&bp->fp[i].txdata[cos]);
+}
+
void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
{
int i;
@@ -5968,7 +6233,7 @@ void bnx2x_pf_disable(struct bnx2x *bp)
REG_WR(bp, CFC_REG_WEAK_ENABLE_PF, 0);
}
-static inline void bnx2x__common_init_phy(struct bnx2x *bp)
+static void bnx2x__common_init_phy(struct bnx2x *bp)
{
u32 shmem_base[2], shmem2_base[2];
shmem_base[0] = bp->common.shmem_base;
@@ -6255,12 +6520,24 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
if (!CHIP_IS_E1(bp))
REG_WR(bp, PRS_REG_E1HOV_MODE, bp->path_has_ovlan);
- if (!CHIP_IS_E1x(bp) && !CHIP_IS_E3B0(bp))
- /* Bit-map indicating which L2 hdrs may appear
- * after the basic Ethernet header
- */
- REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC,
- bp->path_has_ovlan ? 7 : 6);
+ if (!CHIP_IS_E1x(bp) && !CHIP_IS_E3B0(bp)) {
+ if (IS_MF_AFEX(bp)) {
+ /* configure that VNTag and VLAN headers must be
+ * received in afex mode
+ */
+ REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC, 0xE);
+ REG_WR(bp, PRS_REG_MUST_HAVE_HDRS, 0xA);
+ REG_WR(bp, PRS_REG_HDRS_AFTER_TAG_0, 0x6);
+ REG_WR(bp, PRS_REG_TAG_ETHERTYPE_0, 0x8926);
+ REG_WR(bp, PRS_REG_TAG_LEN_0, 0x4);
+ } else {
+ /* Bit-map indicating which L2 hdrs may appear
+ * after the basic Ethernet header
+ */
+ REG_WR(bp, PRS_REG_HDRS_AFTER_BASIC,
+ bp->path_has_ovlan ? 7 : 6);
+ }
+ }
bnx2x_init_block(bp, BLOCK_TSDM, PHASE_COMMON);
bnx2x_init_block(bp, BLOCK_CSDM, PHASE_COMMON);
@@ -6294,9 +6571,21 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
bnx2x_init_block(bp, BLOCK_XPB, PHASE_COMMON);
bnx2x_init_block(bp, BLOCK_PBF, PHASE_COMMON);
- if (!CHIP_IS_E1x(bp))
- REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC,
- bp->path_has_ovlan ? 7 : 6);
+ if (!CHIP_IS_E1x(bp)) {
+ if (IS_MF_AFEX(bp)) {
+ /* configure that VNTag and VLAN headers must be
+ * sent in afex mode
+ */
+ REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC, 0xE);
+ REG_WR(bp, PBF_REG_MUST_HAVE_HDRS, 0xA);
+ REG_WR(bp, PBF_REG_HDRS_AFTER_TAG_0, 0x6);
+ REG_WR(bp, PBF_REG_TAG_ETHERTYPE_0, 0x8926);
+ REG_WR(bp, PBF_REG_TAG_LEN_0, 0x4);
+ } else {
+ REG_WR(bp, PBF_REG_HDRS_AFTER_BASIC,
+ bp->path_has_ovlan ? 7 : 6);
+ }
+ }
REG_WR(bp, SRC_REG_SOFT_RST, 1);
@@ -6514,15 +6803,29 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
bnx2x_init_block(bp, BLOCK_PRS, init_phase);
- if (CHIP_IS_E3B0(bp))
- /* Ovlan exists only if we are in multi-function +
- * switch-dependent mode, in switch-independent there
- * is no ovlan headers
- */
- REG_WR(bp, BP_PORT(bp) ?
- PRS_REG_HDRS_AFTER_BASIC_PORT_1 :
- PRS_REG_HDRS_AFTER_BASIC_PORT_0,
- (bp->path_has_ovlan ? 7 : 6));
+ if (CHIP_IS_E3B0(bp)) {
+ if (IS_MF_AFEX(bp)) {
+ /* configure headers for AFEX mode */
+ REG_WR(bp, BP_PORT(bp) ?
+ PRS_REG_HDRS_AFTER_BASIC_PORT_1 :
+ PRS_REG_HDRS_AFTER_BASIC_PORT_0, 0xE);
+ REG_WR(bp, BP_PORT(bp) ?
+ PRS_REG_HDRS_AFTER_TAG_0_PORT_1 :
+ PRS_REG_HDRS_AFTER_TAG_0_PORT_0, 0x6);
+ REG_WR(bp, BP_PORT(bp) ?
+ PRS_REG_MUST_HAVE_HDRS_PORT_1 :
+ PRS_REG_MUST_HAVE_HDRS_PORT_0, 0xA);
+ } else {
+ /* Ovlan exists only if we are in multi-function +
+ * switch-dependent mode, in switch-independent there
+ * is no ovlan headers
+ */
+ REG_WR(bp, BP_PORT(bp) ?
+ PRS_REG_HDRS_AFTER_BASIC_PORT_1 :
+ PRS_REG_HDRS_AFTER_BASIC_PORT_0,
+ (bp->path_has_ovlan ? 7 : 6));
+ }
+ }
bnx2x_init_block(bp, BLOCK_TSDM, init_phase);
bnx2x_init_block(bp, BLOCK_CSDM, init_phase);
@@ -6584,10 +6887,15 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
/* Bit-map indicating which L2 hdrs may appear after the
* basic Ethernet header
*/
- REG_WR(bp, BP_PORT(bp) ?
- NIG_REG_P1_HDRS_AFTER_BASIC :
- NIG_REG_P0_HDRS_AFTER_BASIC,
- IS_MF_SD(bp) ? 7 : 6);
+ if (IS_MF_AFEX(bp))
+ REG_WR(bp, BP_PORT(bp) ?
+ NIG_REG_P1_HDRS_AFTER_BASIC :
+ NIG_REG_P0_HDRS_AFTER_BASIC, 0xE);
+ else
+ REG_WR(bp, BP_PORT(bp) ?
+ NIG_REG_P1_HDRS_AFTER_BASIC :
+ NIG_REG_P0_HDRS_AFTER_BASIC,
+ IS_MF_SD(bp) ? 7 : 6);
if (CHIP_IS_E3(bp))
REG_WR(bp, BP_PORT(bp) ?
@@ -6609,6 +6917,7 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
val = 1;
break;
case MULTI_FUNCTION_SI:
+ case MULTI_FUNCTION_AFEX:
val = 2;
break;
}
@@ -6640,21 +6949,71 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
static void bnx2x_ilt_wr(struct bnx2x *bp, u32 index, dma_addr_t addr)
{
int reg;
+ u32 wb_write[2];
if (CHIP_IS_E1(bp))
reg = PXP2_REG_RQ_ONCHIP_AT + index*8;
else
reg = PXP2_REG_RQ_ONCHIP_AT_B0 + index*8;
- bnx2x_wb_wr(bp, reg, ONCHIP_ADDR1(addr), ONCHIP_ADDR2(addr));
+ wb_write[0] = ONCHIP_ADDR1(addr);
+ wb_write[1] = ONCHIP_ADDR2(addr);
+ REG_WR_DMAE(bp, reg, wb_write, 2);
}
-static inline void bnx2x_igu_clear_sb(struct bnx2x *bp, u8 idu_sb_id)
+static void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func,
+ u8 idu_sb_id, bool is_Pf)
+{
+ u32 data, ctl, cnt = 100;
+ u32 igu_addr_data = IGU_REG_COMMAND_REG_32LSB_DATA;
+ 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 ? 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 */
+ if (CHIP_INT_MODE_IS_BC(bp))
+ return;
+
+ data = (IGU_USE_REGISTER_cstorm_type_0_sb_cleanup
+ << IGU_REGULAR_CLEANUP_TYPE_SHIFT) |
+ IGU_REGULAR_CLEANUP_SET |
+ IGU_REGULAR_BCLEANUP;
+
+ ctl = addr_encode << IGU_CTRL_REG_ADDRESS_SHIFT |
+ func_encode << IGU_CTRL_REG_FID_SHIFT |
+ IGU_CTRL_CMD_TYPE_WR << IGU_CTRL_REG_TYPE_SHIFT;
+
+ DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
+ data, igu_addr_data);
+ REG_WR(bp, igu_addr_data, data);
+ mmiowb();
+ barrier();
+ DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
+ ctl, igu_addr_ctl);
+ REG_WR(bp, igu_addr_ctl, ctl);
+ mmiowb();
+ barrier();
+
+ /* wait for clean up to finish */
+ while (!(REG_RD(bp, igu_addr_ack) & sb_bit) && --cnt)
+ msleep(20);
+
+
+ if (!(REG_RD(bp, igu_addr_ack) & sb_bit)) {
+ DP(NETIF_MSG_HW,
+ "Unable to finish IGU cleanup: idu_sb_id %d offset %d bit %d (cnt %d)\n",
+ idu_sb_id, idu_sb_id/32, idu_sb_id%32, cnt);
+ }
+}
+
+static void bnx2x_igu_clear_sb(struct bnx2x *bp, u8 idu_sb_id)
{
bnx2x_igu_clear_sb_gen(bp, BP_FUNC(bp), idu_sb_id, true /*PF*/);
}
-static inline void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
+static void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
{
u32 i, base = FUNC_ILT_BASE(func);
for (i = base; i < base + ILT_PER_FUNC; i++)
@@ -7005,7 +7364,7 @@ void bnx2x_free_mem(struct bnx2x *bp)
BCM_PAGE_SIZE * NUM_EQ_PAGES);
}
-static inline int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp)
+static int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp)
{
int num_groups;
int is_fcoe_stats = NO_FCOE(bp) ? 0 : 1;
@@ -7192,7 +7551,8 @@ int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
unsigned long ramrod_flags = 0;
#ifdef BCM_CNIC
- if (is_zero_ether_addr(bp->dev->dev_addr) && IS_MF_STORAGE_SD(bp)) {
+ if (is_zero_ether_addr(bp->dev->dev_addr) &&
+ (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) {
DP(NETIF_MSG_IFUP | NETIF_MSG_IFDOWN,
"Ignoring Zero MAC for STORAGE SD mode\n");
return 0;
@@ -7230,7 +7590,7 @@ static void __devinit bnx2x_set_int_mode(struct bnx2x *bp)
BNX2X_DEV_INFO("set number of queues to 1\n");
break;
default:
- /* Set number of queues according to bp->multi_mode value */
+ /* Set number of queues for MSI-X mode */
bnx2x_set_num_queues(bp);
BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues);
@@ -7239,15 +7599,17 @@ static void __devinit bnx2x_set_int_mode(struct bnx2x *bp)
* so try to enable MSI-X with the requested number of fp's
* and fallback to MSI or legacy INTx with one fp
*/
- if (bnx2x_enable_msix(bp)) {
- /* failed to enable MSI-X */
- BNX2X_DEV_INFO("Failed to enable MSI-X (%d), set number of queues to %d\n",
+ if (bnx2x_enable_msix(bp) ||
+ bp->flags & USING_SINGLE_MSIX_FLAG) {
+ /* failed to enable multiple MSI-X */
+ BNX2X_DEV_INFO("Failed to enable multiple MSI-X (%d), set number of queues to %d\n",
bp->num_queues, 1 + NON_ETH_CONTEXT_USE);
bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
/* Try to enable MSI */
- if (!(bp->flags & DISABLE_MSI_FLAG))
+ if (!(bp->flags & USING_SINGLE_MSIX_FLAG) &&
+ !(bp->flags & DISABLE_MSI_FLAG))
bnx2x_enable_msi(bp);
}
break;
@@ -7368,7 +7730,7 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
* - HC configuration
* - Queue's CDU context
*/
-static inline void bnx2x_pf_q_prep_init(struct bnx2x *bp,
+static void bnx2x_pf_q_prep_init(struct bnx2x *bp,
struct bnx2x_fastpath *fp, struct bnx2x_queue_init_params *init_params)
{
@@ -7718,7 +8080,7 @@ static void bnx2x_reset_port(struct bnx2x *bp)
/* TODO: Close Doorbell port? */
}
-static inline int bnx2x_reset_hw(struct bnx2x *bp, u32 load_code)
+static int bnx2x_reset_hw(struct bnx2x *bp, u32 load_code)
{
struct bnx2x_func_state_params func_params = {NULL};
@@ -7733,7 +8095,7 @@ static inline int bnx2x_reset_hw(struct bnx2x *bp, u32 load_code)
return bnx2x_func_state_change(bp, &func_params);
}
-static inline int bnx2x_func_stop(struct bnx2x *bp)
+static int bnx2x_func_stop(struct bnx2x *bp)
{
struct bnx2x_func_state_params func_params = {NULL};
int rc;
@@ -7848,7 +8210,7 @@ void bnx2x_send_unload_done(struct bnx2x *bp)
bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
}
-static inline int bnx2x_func_wait_started(struct bnx2x *bp)
+static int bnx2x_func_wait_started(struct bnx2x *bp)
{
int tout = 50;
int msix = (bp->flags & USING_MSIX_FLAG) ? 1 : 0;
@@ -8158,7 +8520,7 @@ static void bnx2x_reset_mcp_prep(struct bnx2x *bp, u32 *magic_val)
*
* @bp: driver handle
*/
-static inline void bnx2x_mcp_wait_one(struct bnx2x *bp)
+static void bnx2x_mcp_wait_one(struct bnx2x *bp)
{
/* special handling for emulation and FPGA,
wait 10 times longer */
@@ -8494,7 +8856,7 @@ exit_leader_reset:
return rc;
}
-static inline void bnx2x_recovery_failed(struct bnx2x *bp)
+static void bnx2x_recovery_failed(struct bnx2x *bp)
{
netdev_err(bp->dev, "Recovery has failed. Power cycle is needed.\n");
@@ -8727,7 +9089,8 @@ sp_rtnl_not_reset:
#endif
if (test_and_clear_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state))
bnx2x_setup_tc(bp->dev, bp->dcbx_port_params.ets.num_of_cos);
-
+ if (test_and_clear_bit(BNX2X_SP_RTNL_AFEX_F_UPDATE, &bp->sp_rtnl_state))
+ bnx2x_after_function_update(bp);
/*
* in case of fan failure we need to reset id if the "stop on error"
* debug flag is set, since we trying to prevent permanent overheating
@@ -9122,13 +9485,34 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
return bnx2x_prev_mcp_done(bp);
}
+/* previous driver DMAE transaction may have occurred when pre-boot stage ended
+ * and boot began, or when kdump kernel was loaded. Either case would invalidate
+ * the addresses of the transaction, resulting in was-error bit set in the pci
+ * causing all hw-to-host pcie transactions to timeout. If this happened we want
+ * to clear the interrupt which detected this from the pglueb and the was done
+ * bit
+ */
+static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
+{
+ u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
+ if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) {
+ BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing");
+ REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp));
+ }
+}
+
static int __devinit bnx2x_prev_unload(struct bnx2x *bp)
{
int time_counter = 10;
u32 rc, fw, hw_lock_reg, hw_lock_val;
BNX2X_DEV_INFO("Entering Previous Unload Flow\n");
- /* Release previously held locks */
+ /* clear hw from errors which may have resulted from an interrupted
+ * dmae transaction.
+ */
+ bnx2x_prev_interrupted_dmae(bp);
+
+ /* Release previously held locks */
hw_lock_reg = (BP_FUNC(bp) <= 5) ?
(MISC_REG_DRIVER_CONTROL_1 + BP_FUNC(bp) * 8) :
(MISC_REG_DRIVER_CONTROL_7 + (BP_FUNC(bp) - 6) * 8);
@@ -9201,6 +9585,17 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
id |= (val & 0xf);
bp->common.chip_id = id;
+ /* force 57811 according to MISC register */
+ if (REG_RD(bp, MISC_REG_CHIP_TYPE) & MISC_REG_CHIP_TYPE_57811_MASK) {
+ if (CHIP_IS_57810(bp))
+ bp->common.chip_id = (CHIP_NUM_57811 << 16) |
+ (bp->common.chip_id & 0x0000FFFF);
+ else if (CHIP_IS_57810_MF(bp))
+ bp->common.chip_id = (CHIP_NUM_57811_MF << 16) |
+ (bp->common.chip_id & 0x0000FFFF);
+ bp->common.chip_id |= 0x1;
+ }
+
/* Set doorbell size */
bp->db_size = (1 << BNX2X_DB_SHIFT);
@@ -9293,7 +9688,9 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
bp->link_params.feature_config_flags |=
(val >= REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL) ?
FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY : 0;
-
+ bp->link_params.feature_config_flags |=
+ (val >= REQ_BC_VER_4_VRFY_AFEX_SUPPORTED) ?
+ FEATURE_CONFIG_BC_SUPPORTS_AFEX : 0;
bp->link_params.feature_config_flags |=
(val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ?
FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0;
@@ -9925,6 +10322,9 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
} else
bp->flags |= NO_FCOE_FLAG;
+
+ bp->mf_ext_config = cfg;
+
} else { /* SD MODE */
if (IS_MF_STORAGE_SD(bp)) {
if (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp)) {
@@ -9946,6 +10346,11 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
memset(bp->dev->dev_addr, 0, ETH_ALEN);
}
}
+
+ if (IS_MF_FCOE_AFEX(bp))
+ /* use FIP MAC as primary MAC */
+ memcpy(bp->dev->dev_addr, fip_mac, ETH_ALEN);
+
#endif
} else {
/* in SF read MACs from port configuration */
@@ -10118,6 +10523,19 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
} else
BNX2X_DEV_INFO("illegal MAC address for SI\n");
break;
+ case SHARED_FEAT_CFG_FORCE_SF_MODE_AFEX_MODE:
+ if ((!CHIP_IS_E1x(bp)) &&
+ (MF_CFG_RD(bp, func_mf_config[func].
+ mac_upper) != 0xffff) &&
+ (SHMEM2_HAS(bp,
+ afex_driver_support))) {
+ bp->mf_mode = MULTI_FUNCTION_AFEX;
+ bp->mf_config[vn] = MF_CFG_RD(bp,
+ func_mf_config[func].config);
+ } else {
+ BNX2X_DEV_INFO("can not configure afex mode\n");
+ }
+ break;
case SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED:
/* get OV configuration */
val = MF_CFG_RD(bp,
@@ -10158,6 +10576,9 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
return -EPERM;
}
break;
+ case MULTI_FUNCTION_AFEX:
+ BNX2X_DEV_INFO("func %d is in MF afex mode\n", func);
+ break;
case MULTI_FUNCTION_SI:
BNX2X_DEV_INFO("func %d is in MF switch-independent mode\n",
func);
@@ -10325,6 +10746,9 @@ static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
case MULTI_FUNCTION_SI:
SET_FLAGS(flags, MODE_MF_SI);
break;
+ case MULTI_FUNCTION_AFEX:
+ SET_FLAGS(flags, MODE_MF_AFEX);
+ break;
}
} else
SET_FLAGS(flags, MODE_SF);
@@ -10384,12 +10808,10 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
if (BP_NOMCP(bp) && (func == 0))
dev_err(&bp->pdev->dev, "MCP disabled, must load devices in order!\n");
- bp->multi_mode = multi_mode;
-
bp->disable_tpa = disable_tpa;
#ifdef BCM_CNIC
- bp->disable_tpa |= IS_MF_STORAGE_SD(bp);
+ bp->disable_tpa |= IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp);
#endif
/* Set TPA flags */
@@ -10408,7 +10830,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
bp->mrrs = mrrs;
- bp->tx_ring_size = MAX_TX_AVAIL;
+ bp->tx_ring_size = IS_MF_FCOE_AFEX(bp) ? 0 : MAX_TX_AVAIL;
/* make sure that the numbers are in the right granularity */
bp->tx_ticks = (50 / BNX2X_BTR) * BNX2X_BTR;
@@ -10439,8 +10861,6 @@ 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;
}
@@ -10530,8 +10950,8 @@ static int bnx2x_close(struct net_device *dev)
return 0;
}
-static inline int bnx2x_init_mcast_macs_list(struct bnx2x *bp,
- struct bnx2x_mcast_ramrod_params *p)
+static int bnx2x_init_mcast_macs_list(struct bnx2x *bp,
+ struct bnx2x_mcast_ramrod_params *p)
{
int mc_count = netdev_mc_count(bp->dev);
struct bnx2x_mcast_list_elem *mc_mac =
@@ -10554,7 +10974,7 @@ static inline int bnx2x_init_mcast_macs_list(struct bnx2x *bp,
return 0;
}
-static inline void bnx2x_free_mcast_macs_list(
+static void bnx2x_free_mcast_macs_list(
struct bnx2x_mcast_ramrod_params *p)
{
struct bnx2x_mcast_list_elem *mc_mac =
@@ -10572,7 +10992,7 @@ static inline void bnx2x_free_mcast_macs_list(
*
* We will use zero (0) as a MAC type for these MACs.
*/
-static inline int bnx2x_set_uc_list(struct bnx2x *bp)
+static int bnx2x_set_uc_list(struct bnx2x *bp)
{
int rc;
struct net_device *dev = bp->dev;
@@ -10603,7 +11023,7 @@ static inline int bnx2x_set_uc_list(struct bnx2x *bp)
BNX2X_UC_LIST_MAC, &ramrod_flags);
}
-static inline int bnx2x_set_mc_list(struct bnx2x *bp)
+static int bnx2x_set_mc_list(struct bnx2x *bp)
{
struct net_device *dev = bp->dev;
struct bnx2x_mcast_ramrod_params rparam = {NULL};
@@ -10789,7 +11209,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
#endif
};
-static inline int bnx2x_set_coherency_mask(struct bnx2x *bp)
+static int bnx2x_set_coherency_mask(struct bnx2x *bp)
{
struct device *dev = &bp->pdev->dev;
@@ -11055,7 +11475,7 @@ static int bnx2x_check_firmware(struct bnx2x *bp)
return 0;
}
-static inline void be32_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
+static void be32_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
{
const __be32 *source = (const __be32 *)_source;
u32 *target = (u32 *)_target;
@@ -11069,7 +11489,7 @@ static inline void be32_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
Ops array is stored in the following format:
{op(8bit), offset(24bit, big endian), data(32bit, big endian)}
*/
-static inline void bnx2x_prep_ops(const u8 *_source, u8 *_target, u32 n)
+static void bnx2x_prep_ops(const u8 *_source, u8 *_target, u32 n)
{
const __be32 *source = (const __be32 *)_source;
struct raw_op *target = (struct raw_op *)_target;
@@ -11087,7 +11507,7 @@ static inline void bnx2x_prep_ops(const u8 *_source, u8 *_target, u32 n)
* IRO array is stored in the following format:
* {base(24bit), m1(16bit), m2(16bit), m3(16bit), size(16bit) }
*/
-static inline void bnx2x_prep_iro(const u8 *_source, u8 *_target, u32 n)
+static void bnx2x_prep_iro(const u8 *_source, u8 *_target, u32 n)
{
const __be32 *source = (const __be32 *)_source;
struct iro *target = (struct iro *)_target;
@@ -11107,7 +11527,7 @@ static inline void bnx2x_prep_iro(const u8 *_source, u8 *_target, u32 n)
}
}
-static inline void be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
+static void be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n)
{
const __be16 *source = (const __be16 *)_source;
u16 *target = (u16 *)_target;
@@ -11244,11 +11664,13 @@ void bnx2x__init_func_obj(struct bnx2x *bp)
bnx2x_init_func_obj(bp, &bp->func_obj,
bnx2x_sp(bp, func_rdata),
bnx2x_sp_mapping(bp, func_rdata),
+ bnx2x_sp(bp, func_afex_rdata),
+ bnx2x_sp_mapping(bp, func_afex_rdata),
&bnx2x_func_sp_drv);
}
/* must be called after sriov-enable */
-static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp)
+static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
{
int cid_count = BNX2X_L2_CID_COUNT(bp);
@@ -11264,7 +11686,7 @@ static inline int bnx2x_set_qm_cid_count(struct bnx2x *bp)
* @dev: pci device
*
*/
-static inline int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
+static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
{
int pos;
u16 control;
@@ -11325,6 +11747,8 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
case BCM57810_MF:
case BCM57840:
case BCM57840_MF:
+ case BCM57811:
+ case BCM57811_MF:
max_cos_est = BNX2X_MULTI_TX_COS_E3B0;
break;
@@ -11738,7 +12162,7 @@ module_exit(bnx2x_cleanup);
* This function will wait until the ramdord completion returns.
* Return 0 if success, -ENODEV if ramrod doesn't return.
*/
-static inline int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp)
+static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp)
{
unsigned long ramrod_flags = 0;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index c25803b9c0ca..bbd387492a80 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
@@ -1483,6 +1483,11 @@
starts at 0x0 for the A0 tape-out and increments by one for each
all-layer tape-out. */
#define MISC_REG_CHIP_REV 0xa40c
+/* [R 14] otp_misc_do[100:0] spare bits collection: 13:11-
+ * otp_misc_do[100:98]; 10:7 - otp_misc_do[87:84]; 6:3 - otp_misc_do[75:72];
+ * 2:1 - otp_misc_do[51:50]; 0 - otp_misc_do[1]. */
+#define MISC_REG_CHIP_TYPE 0xac60
+#define MISC_REG_CHIP_TYPE_57811_MASK (1<<1)
/* [RW 32] The following driver registers(1...16) represent 16 drivers and
32 clients. Each client can be controlled by one driver only. One in each
bit represent that this driver control the appropriate client (Ex: bit 5
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index 513573321625..6c14b4a4e82c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -633,14 +633,17 @@ static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o)
}
-static inline void bnx2x_set_mac_in_nig(struct bnx2x *bp,
- bool add, unsigned char *dev_addr, int index)
+void bnx2x_set_mac_in_nig(struct bnx2x *bp,
+ bool add, unsigned char *dev_addr, int index)
{
u32 wb_data[2];
u32 reg_offset = BP_PORT(bp) ? NIG_REG_LLH1_FUNC_MEM :
NIG_REG_LLH0_FUNC_MEM;
- if (!IS_MF_SI(bp) || index > BNX2X_LLH_CAM_MAX_PF_LINE)
+ if (!IS_MF_SI(bp) && !IS_MF_AFEX(bp))
+ return;
+
+ if (index > BNX2X_LLH_CAM_MAX_PF_LINE)
return;
DP(BNX2X_MSG_SP, "Going to %s LLH configuration at entry %d\n",
@@ -4090,12 +4093,6 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
rss_mode = ETH_RSS_MODE_DISABLED;
else if (test_bit(BNX2X_RSS_MODE_REGULAR, &p->rss_flags))
rss_mode = ETH_RSS_MODE_REGULAR;
- else if (test_bit(BNX2X_RSS_MODE_VLAN_PRI, &p->rss_flags))
- rss_mode = ETH_RSS_MODE_VLAN_PRI;
- else if (test_bit(BNX2X_RSS_MODE_E1HOV_PRI, &p->rss_flags))
- rss_mode = ETH_RSS_MODE_E1HOV_PRI;
- else if (test_bit(BNX2X_RSS_MODE_IP_DSCP, &p->rss_flags))
- rss_mode = ETH_RSS_MODE_IP_DSCP;
data->rss_mode = rss_mode;
@@ -4404,6 +4401,9 @@ static void bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj *o,
test_bit(BNX2X_Q_FLG_TX_SWITCH, flags);
tx_data->anti_spoofing_flg =
test_bit(BNX2X_Q_FLG_ANTI_SPOOF, flags);
+ tx_data->force_default_pri_flg =
+ test_bit(BNX2X_Q_FLG_FORCE_DEFAULT_PRI, flags);
+
tx_data->tx_status_block_id = params->fw_sb_id;
tx_data->tx_sb_index_number = params->sb_cq_index;
tx_data->tss_leading_client_id = params->tss_leading_cl_id;
@@ -5331,6 +5331,17 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp,
case BNX2X_F_STATE_STARTED:
if (cmd == BNX2X_F_CMD_STOP)
next_state = BNX2X_F_STATE_INITIALIZED;
+ /* afex ramrods can be sent only in started mode, and only
+ * if not pending for function_stop ramrod completion
+ * for these events - next state remained STARTED.
+ */
+ else if ((cmd == BNX2X_F_CMD_AFEX_UPDATE) &&
+ (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
+ next_state = BNX2X_F_STATE_STARTED;
+
+ else if ((cmd == BNX2X_F_CMD_AFEX_VIFLISTS) &&
+ (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
+ next_state = BNX2X_F_STATE_STARTED;
else if (cmd == BNX2X_F_CMD_TX_STOP)
next_state = BNX2X_F_STATE_TX_STOPPED;
@@ -5618,6 +5629,83 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,
U64_LO(data_mapping), NONE_CONNECTION_TYPE);
}
+static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ struct function_update_data *rdata =
+ (struct function_update_data *)o->afex_rdata;
+ dma_addr_t data_mapping = o->afex_rdata_mapping;
+ struct bnx2x_func_afex_update_params *afex_update_params =
+ &params->params.afex_update;
+
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data with provided parameters */
+ rdata->vif_id_change_flg = 1;
+ rdata->vif_id = cpu_to_le16(afex_update_params->vif_id);
+ rdata->afex_default_vlan_change_flg = 1;
+ rdata->afex_default_vlan =
+ cpu_to_le16(afex_update_params->afex_default_vlan);
+ rdata->allowed_priorities_change_flg = 1;
+ rdata->allowed_priorities = afex_update_params->allowed_priorities;
+
+ /* No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+ DP(BNX2X_MSG_SP,
+ "afex: sending func_update vif_id 0x%x dvlan 0x%x prio 0x%x\n",
+ rdata->vif_id,
+ rdata->afex_default_vlan, rdata->allowed_priorities);
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
+ U64_HI(data_mapping),
+ U64_LO(data_mapping), NONE_CONNECTION_TYPE);
+}
+
+static
+inline int bnx2x_func_send_afex_viflists(struct bnx2x *bp,
+ struct bnx2x_func_state_params *params)
+{
+ struct bnx2x_func_sp_obj *o = params->f_obj;
+ struct afex_vif_list_ramrod_data *rdata =
+ (struct afex_vif_list_ramrod_data *)o->afex_rdata;
+ struct bnx2x_func_afex_viflists_params *afex_viflist_params =
+ &params->params.afex_viflists;
+ u64 *p_rdata = (u64 *)rdata;
+
+ memset(rdata, 0, sizeof(*rdata));
+
+ /* Fill the ramrod data with provided parameters */
+ rdata->vif_list_index = afex_viflist_params->vif_list_index;
+ rdata->func_bit_map = afex_viflist_params->func_bit_map;
+ rdata->afex_vif_list_command =
+ afex_viflist_params->afex_vif_list_command;
+ rdata->func_to_clear = afex_viflist_params->func_to_clear;
+
+ /* send in echo type of sub command */
+ rdata->echo = afex_viflist_params->afex_vif_list_command;
+
+ /* No need for an explicit memory barrier here as long we would
+ * need to ensure the ordering of writing to the SPQ element
+ * and updating of the SPQ producer which involves a memory
+ * read and we will have to put a full memory barrier there
+ * (inside bnx2x_sp_post()).
+ */
+
+ DP(BNX2X_MSG_SP, "afex: ramrod lists, cmd 0x%x index 0x%x func_bit_map 0x%x func_to_clr 0x%x\n",
+ rdata->afex_vif_list_command, rdata->vif_list_index,
+ rdata->func_bit_map, rdata->func_to_clear);
+
+ /* this ramrod sends data directly and not through DMA mapping */
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_AFEX_VIF_LISTS, 0,
+ U64_HI(*p_rdata), U64_LO(*p_rdata),
+ NONE_CONNECTION_TYPE);
+}
+
static inline int bnx2x_func_send_stop(struct bnx2x *bp,
struct bnx2x_func_state_params *params)
{
@@ -5669,6 +5757,10 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp,
return bnx2x_func_send_stop(bp, params);
case BNX2X_F_CMD_HW_RESET:
return bnx2x_func_hw_reset(bp, params);
+ case BNX2X_F_CMD_AFEX_UPDATE:
+ return bnx2x_func_send_afex_update(bp, params);
+ case BNX2X_F_CMD_AFEX_VIFLISTS:
+ return bnx2x_func_send_afex_viflists(bp, params);
case BNX2X_F_CMD_TX_STOP:
return bnx2x_func_send_tx_stop(bp, params);
case BNX2X_F_CMD_TX_START:
@@ -5682,6 +5774,7 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp,
void bnx2x_init_func_obj(struct bnx2x *bp,
struct bnx2x_func_sp_obj *obj,
void *rdata, dma_addr_t rdata_mapping,
+ void *afex_rdata, dma_addr_t afex_rdata_mapping,
struct bnx2x_func_sp_drv_ops *drv_iface)
{
memset(obj, 0, sizeof(*obj));
@@ -5690,7 +5783,8 @@ void bnx2x_init_func_obj(struct bnx2x *bp,
obj->rdata = rdata;
obj->rdata_mapping = rdata_mapping;
-
+ obj->afex_rdata = afex_rdata;
+ obj->afex_rdata_mapping = afex_rdata_mapping;
obj->send_cmd = bnx2x_func_send_cmd;
obj->check_transition = bnx2x_func_chk_transition;
obj->complete_cmd = bnx2x_func_comp_cmd;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index 61a7670adfcd..efd80bdd0dfe 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -62,6 +62,8 @@ enum {
BNX2X_FILTER_MCAST_PENDING,
BNX2X_FILTER_MCAST_SCHED,
BNX2X_FILTER_RSS_CONF_PENDING,
+ BNX2X_AFEX_FCOE_Q_UPDATE_PENDING,
+ BNX2X_AFEX_PENDING_VIFSET_MCP_ACK
};
struct bnx2x_raw_obj {
@@ -432,6 +434,8 @@ enum {
BNX2X_LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE / 2
};
+void bnx2x_set_mac_in_nig(struct bnx2x *bp,
+ bool add, unsigned char *dev_addr, int index);
/** RX_MODE verbs:DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */
@@ -685,9 +689,6 @@ enum {
/* RSS_MODE bits are mutually exclusive */
BNX2X_RSS_MODE_DISABLED,
BNX2X_RSS_MODE_REGULAR,
- BNX2X_RSS_MODE_VLAN_PRI,
- BNX2X_RSS_MODE_E1HOV_PRI,
- BNX2X_RSS_MODE_IP_DSCP,
BNX2X_RSS_SET_SRCH, /* Setup searcher, E1x specific flag */
@@ -801,7 +802,8 @@ enum {
BNX2X_Q_FLG_TX_SWITCH,
BNX2X_Q_FLG_TX_SEC,
BNX2X_Q_FLG_ANTI_SPOOF,
- BNX2X_Q_FLG_SILENT_VLAN_REM
+ BNX2X_Q_FLG_SILENT_VLAN_REM,
+ BNX2X_Q_FLG_FORCE_DEFAULT_PRI
};
/* Queue type options: queue type may be a compination of below. */
@@ -963,6 +965,11 @@ struct bnx2x_queue_state_params {
} params;
};
+struct bnx2x_viflist_params {
+ u8 echo_res;
+ u8 func_bit_map_res;
+};
+
struct bnx2x_queue_sp_obj {
u32 cids[BNX2X_MULTI_TX_COS];
u8 cl_id;
@@ -1045,6 +1052,8 @@ enum bnx2x_func_cmd {
BNX2X_F_CMD_START,
BNX2X_F_CMD_STOP,
BNX2X_F_CMD_HW_RESET,
+ BNX2X_F_CMD_AFEX_UPDATE,
+ BNX2X_F_CMD_AFEX_VIFLISTS,
BNX2X_F_CMD_TX_STOP,
BNX2X_F_CMD_TX_START,
BNX2X_F_CMD_MAX,
@@ -1089,6 +1098,18 @@ struct bnx2x_func_start_params {
u8 network_cos_mode;
};
+struct bnx2x_func_afex_update_params {
+ u16 vif_id;
+ u16 afex_default_vlan;
+ u8 allowed_priorities;
+};
+
+struct bnx2x_func_afex_viflists_params {
+ u16 vif_list_index;
+ u8 func_bit_map;
+ u8 afex_vif_list_command;
+ u8 func_to_clear;
+};
struct bnx2x_func_tx_start_params {
struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES];
u8 dcb_enabled;
@@ -1110,6 +1131,8 @@ struct bnx2x_func_state_params {
struct bnx2x_func_hw_init_params hw_init;
struct bnx2x_func_hw_reset_params hw_reset;
struct bnx2x_func_start_params start;
+ struct bnx2x_func_afex_update_params afex_update;
+ struct bnx2x_func_afex_viflists_params afex_viflists;
struct bnx2x_func_tx_start_params tx_start;
} params;
};
@@ -1154,6 +1177,13 @@ struct bnx2x_func_sp_obj {
void *rdata;
dma_addr_t rdata_mapping;
+ /* Buffer to use as a afex ramrod data and its mapping.
+ * This can't be same rdata as above because afex ramrod requests
+ * can arrive to the object in parallel to other ramrod requests.
+ */
+ void *afex_rdata;
+ dma_addr_t afex_rdata_mapping;
+
/* this mutex validates that when pending flag is taken, the next
* ramrod to be sent will be the one set the pending bit
*/
@@ -1197,6 +1227,7 @@ union bnx2x_qable_obj {
void bnx2x_init_func_obj(struct bnx2x *bp,
struct bnx2x_func_sp_obj *obj,
void *rdata, dma_addr_t rdata_mapping,
+ void *afex_rdata, dma_addr_t afex_rdata_mapping,
struct bnx2x_func_sp_drv_ops *drv_iface);
int bnx2x_func_state_change(struct bnx2x *bp,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
index e1c9310fb07c..1e2785cd11d0 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
@@ -1316,7 +1316,7 @@ static void bnx2x_port_stats_base_init(struct bnx2x *bp)
*
* @param bp
*/
-static inline void bnx2x_prep_fw_stats_req(struct bnx2x *bp)
+static void bnx2x_prep_fw_stats_req(struct bnx2x *bp)
{
int i;
int first_queue_query_index;
@@ -1561,3 +1561,274 @@ void bnx2x_save_statistics(struct bnx2x *bp)
UPDATE_FW_STAT_OLD(mac_discard);
}
}
+
+void bnx2x_afex_collect_stats(struct bnx2x *bp, void *void_afex_stats,
+ u32 stats_type)
+{
+ int i;
+ struct afex_stats *afex_stats = (struct afex_stats *)void_afex_stats;
+ struct bnx2x_eth_stats *estats = &bp->eth_stats;
+ struct per_queue_stats *fcoe_q_stats =
+ &bp->fw_stats_data->queue_stats[FCOE_IDX];
+
+ struct tstorm_per_queue_stats *fcoe_q_tstorm_stats =
+ &fcoe_q_stats->tstorm_queue_statistics;
+
+ struct ustorm_per_queue_stats *fcoe_q_ustorm_stats =
+ &fcoe_q_stats->ustorm_queue_statistics;
+
+ struct xstorm_per_queue_stats *fcoe_q_xstorm_stats =
+ &fcoe_q_stats->xstorm_queue_statistics;
+
+ struct fcoe_statistics_params *fw_fcoe_stat =
+ &bp->fw_stats_data->fcoe;
+
+ memset(afex_stats, 0, sizeof(struct afex_stats));
+
+ for_each_eth_queue(bp, i) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
+ struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
+
+ ADD_64(afex_stats->rx_unicast_bytes_hi,
+ qstats->total_unicast_bytes_received_hi,
+ afex_stats->rx_unicast_bytes_lo,
+ qstats->total_unicast_bytes_received_lo);
+
+ ADD_64(afex_stats->rx_broadcast_bytes_hi,
+ qstats->total_broadcast_bytes_received_hi,
+ afex_stats->rx_broadcast_bytes_lo,
+ qstats->total_broadcast_bytes_received_lo);
+
+ ADD_64(afex_stats->rx_multicast_bytes_hi,
+ qstats->total_multicast_bytes_received_hi,
+ afex_stats->rx_multicast_bytes_lo,
+ qstats->total_multicast_bytes_received_lo);
+
+ ADD_64(afex_stats->rx_unicast_frames_hi,
+ qstats->total_unicast_packets_received_hi,
+ afex_stats->rx_unicast_frames_lo,
+ qstats->total_unicast_packets_received_lo);
+
+ ADD_64(afex_stats->rx_broadcast_frames_hi,
+ qstats->total_broadcast_packets_received_hi,
+ afex_stats->rx_broadcast_frames_lo,
+ qstats->total_broadcast_packets_received_lo);
+
+ ADD_64(afex_stats->rx_multicast_frames_hi,
+ qstats->total_multicast_packets_received_hi,
+ afex_stats->rx_multicast_frames_lo,
+ qstats->total_multicast_packets_received_lo);
+
+ /* sum to rx_frames_discarded all discraded
+ * packets due to size, ttl0 and checksum
+ */
+ ADD_64(afex_stats->rx_frames_discarded_hi,
+ qstats->total_packets_received_checksum_discarded_hi,
+ afex_stats->rx_frames_discarded_lo,
+ qstats->total_packets_received_checksum_discarded_lo);
+
+ ADD_64(afex_stats->rx_frames_discarded_hi,
+ qstats->total_packets_received_ttl0_discarded_hi,
+ afex_stats->rx_frames_discarded_lo,
+ qstats->total_packets_received_ttl0_discarded_lo);
+
+ ADD_64(afex_stats->rx_frames_discarded_hi,
+ qstats->etherstatsoverrsizepkts_hi,
+ afex_stats->rx_frames_discarded_lo,
+ qstats->etherstatsoverrsizepkts_lo);
+
+ ADD_64(afex_stats->rx_frames_dropped_hi,
+ qstats->no_buff_discard_hi,
+ afex_stats->rx_frames_dropped_lo,
+ qstats->no_buff_discard_lo);
+
+ ADD_64(afex_stats->tx_unicast_bytes_hi,
+ qstats->total_unicast_bytes_transmitted_hi,
+ afex_stats->tx_unicast_bytes_lo,
+ qstats->total_unicast_bytes_transmitted_lo);
+
+ ADD_64(afex_stats->tx_broadcast_bytes_hi,
+ qstats->total_broadcast_bytes_transmitted_hi,
+ afex_stats->tx_broadcast_bytes_lo,
+ qstats->total_broadcast_bytes_transmitted_lo);
+
+ ADD_64(afex_stats->tx_multicast_bytes_hi,
+ qstats->total_multicast_bytes_transmitted_hi,
+ afex_stats->tx_multicast_bytes_lo,
+ qstats->total_multicast_bytes_transmitted_lo);
+
+ ADD_64(afex_stats->tx_unicast_frames_hi,
+ qstats->total_unicast_packets_transmitted_hi,
+ afex_stats->tx_unicast_frames_lo,
+ qstats->total_unicast_packets_transmitted_lo);
+
+ ADD_64(afex_stats->tx_broadcast_frames_hi,
+ qstats->total_broadcast_packets_transmitted_hi,
+ afex_stats->tx_broadcast_frames_lo,
+ qstats->total_broadcast_packets_transmitted_lo);
+
+ ADD_64(afex_stats->tx_multicast_frames_hi,
+ qstats->total_multicast_packets_transmitted_hi,
+ afex_stats->tx_multicast_frames_lo,
+ qstats->total_multicast_packets_transmitted_lo);
+
+ ADD_64(afex_stats->tx_frames_dropped_hi,
+ qstats->total_transmitted_dropped_packets_error_hi,
+ afex_stats->tx_frames_dropped_lo,
+ qstats->total_transmitted_dropped_packets_error_lo);
+ }
+
+ /* now add FCoE statistics which are collected separately
+ * (both offloaded and non offloaded)
+ */
+ if (!NO_FCOE(bp)) {
+ ADD_64_LE(afex_stats->rx_unicast_bytes_hi,
+ LE32_0,
+ afex_stats->rx_unicast_bytes_lo,
+ fw_fcoe_stat->rx_stat0.fcoe_rx_byte_cnt);
+
+ ADD_64_LE(afex_stats->rx_unicast_bytes_hi,
+ fcoe_q_tstorm_stats->rcv_ucast_bytes.hi,
+ afex_stats->rx_unicast_bytes_lo,
+ fcoe_q_tstorm_stats->rcv_ucast_bytes.lo);
+
+ ADD_64_LE(afex_stats->rx_broadcast_bytes_hi,
+ fcoe_q_tstorm_stats->rcv_bcast_bytes.hi,
+ afex_stats->rx_broadcast_bytes_lo,
+ fcoe_q_tstorm_stats->rcv_bcast_bytes.lo);
+
+ ADD_64_LE(afex_stats->rx_multicast_bytes_hi,
+ fcoe_q_tstorm_stats->rcv_mcast_bytes.hi,
+ afex_stats->rx_multicast_bytes_lo,
+ fcoe_q_tstorm_stats->rcv_mcast_bytes.lo);
+
+ ADD_64_LE(afex_stats->rx_unicast_frames_hi,
+ LE32_0,
+ afex_stats->rx_unicast_frames_lo,
+ fw_fcoe_stat->rx_stat0.fcoe_rx_pkt_cnt);
+
+ ADD_64_LE(afex_stats->rx_unicast_frames_hi,
+ LE32_0,
+ afex_stats->rx_unicast_frames_lo,
+ fcoe_q_tstorm_stats->rcv_ucast_pkts);
+
+ ADD_64_LE(afex_stats->rx_broadcast_frames_hi,
+ LE32_0,
+ afex_stats->rx_broadcast_frames_lo,
+ fcoe_q_tstorm_stats->rcv_bcast_pkts);
+
+ ADD_64_LE(afex_stats->rx_multicast_frames_hi,
+ LE32_0,
+ afex_stats->rx_multicast_frames_lo,
+ fcoe_q_tstorm_stats->rcv_ucast_pkts);
+
+ ADD_64_LE(afex_stats->rx_frames_discarded_hi,
+ LE32_0,
+ afex_stats->rx_frames_discarded_lo,
+ fcoe_q_tstorm_stats->checksum_discard);
+
+ ADD_64_LE(afex_stats->rx_frames_discarded_hi,
+ LE32_0,
+ afex_stats->rx_frames_discarded_lo,
+ fcoe_q_tstorm_stats->pkts_too_big_discard);
+
+ ADD_64_LE(afex_stats->rx_frames_discarded_hi,
+ LE32_0,
+ afex_stats->rx_frames_discarded_lo,
+ fcoe_q_tstorm_stats->ttl0_discard);
+
+ ADD_64_LE16(afex_stats->rx_frames_dropped_hi,
+ LE16_0,
+ afex_stats->rx_frames_dropped_lo,
+ fcoe_q_tstorm_stats->no_buff_discard);
+
+ ADD_64_LE(afex_stats->rx_frames_dropped_hi,
+ LE32_0,
+ afex_stats->rx_frames_dropped_lo,
+ fcoe_q_ustorm_stats->ucast_no_buff_pkts);
+
+ ADD_64_LE(afex_stats->rx_frames_dropped_hi,
+ LE32_0,
+ afex_stats->rx_frames_dropped_lo,
+ fcoe_q_ustorm_stats->mcast_no_buff_pkts);
+
+ ADD_64_LE(afex_stats->rx_frames_dropped_hi,
+ LE32_0,
+ afex_stats->rx_frames_dropped_lo,
+ fcoe_q_ustorm_stats->bcast_no_buff_pkts);
+
+ ADD_64_LE(afex_stats->rx_frames_dropped_hi,
+ LE32_0,
+ afex_stats->rx_frames_dropped_lo,
+ fw_fcoe_stat->rx_stat1.fcoe_rx_drop_pkt_cnt);
+
+ ADD_64_LE(afex_stats->rx_frames_dropped_hi,
+ LE32_0,
+ afex_stats->rx_frames_dropped_lo,
+ fw_fcoe_stat->rx_stat2.fcoe_rx_drop_pkt_cnt);
+
+ ADD_64_LE(afex_stats->tx_unicast_bytes_hi,
+ LE32_0,
+ afex_stats->tx_unicast_bytes_lo,
+ fw_fcoe_stat->tx_stat.fcoe_tx_byte_cnt);
+
+ ADD_64_LE(afex_stats->tx_unicast_bytes_hi,
+ fcoe_q_xstorm_stats->ucast_bytes_sent.hi,
+ afex_stats->tx_unicast_bytes_lo,
+ fcoe_q_xstorm_stats->ucast_bytes_sent.lo);
+
+ ADD_64_LE(afex_stats->tx_broadcast_bytes_hi,
+ fcoe_q_xstorm_stats->bcast_bytes_sent.hi,
+ afex_stats->tx_broadcast_bytes_lo,
+ fcoe_q_xstorm_stats->bcast_bytes_sent.lo);
+
+ ADD_64_LE(afex_stats->tx_multicast_bytes_hi,
+ fcoe_q_xstorm_stats->mcast_bytes_sent.hi,
+ afex_stats->tx_multicast_bytes_lo,
+ fcoe_q_xstorm_stats->mcast_bytes_sent.lo);
+
+ ADD_64_LE(afex_stats->tx_unicast_frames_hi,
+ LE32_0,
+ afex_stats->tx_unicast_frames_lo,
+ fw_fcoe_stat->tx_stat.fcoe_tx_pkt_cnt);
+
+ ADD_64_LE(afex_stats->tx_unicast_frames_hi,
+ LE32_0,
+ afex_stats->tx_unicast_frames_lo,
+ fcoe_q_xstorm_stats->ucast_pkts_sent);
+
+ ADD_64_LE(afex_stats->tx_broadcast_frames_hi,
+ LE32_0,
+ afex_stats->tx_broadcast_frames_lo,
+ fcoe_q_xstorm_stats->bcast_pkts_sent);
+
+ ADD_64_LE(afex_stats->tx_multicast_frames_hi,
+ LE32_0,
+ afex_stats->tx_multicast_frames_lo,
+ fcoe_q_xstorm_stats->mcast_pkts_sent);
+
+ ADD_64_LE(afex_stats->tx_frames_dropped_hi,
+ LE32_0,
+ afex_stats->tx_frames_dropped_lo,
+ fcoe_q_xstorm_stats->error_drop_pkts);
+ }
+
+ /* if port stats are requested, add them to the PMF
+ * stats, as anyway they will be accumulated by the
+ * MCP before sent to the switch
+ */
+ if ((bp->port.pmf) && (stats_type == VICSTATST_UIF_INDEX)) {
+ ADD_64(afex_stats->rx_frames_dropped_hi,
+ 0,
+ afex_stats->rx_frames_dropped_lo,
+ estats->mac_filter_discard);
+ ADD_64(afex_stats->rx_frames_dropped_hi,
+ 0,
+ afex_stats->rx_frames_dropped_lo,
+ estats->brb_truncate_discard);
+ ADD_64(afex_stats->rx_frames_discarded_hi,
+ 0,
+ afex_stats->rx_frames_discarded_lo,
+ estats->mac_discard);
+ }
+}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
index 2b46e1eb7fd1..93e689fdfeda 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
@@ -338,6 +338,18 @@ struct bnx2x_fw_port_stats_old {
s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \
} while (0)
+#define LE32_0 ((__force __le32) 0)
+#define LE16_0 ((__force __le16) 0)
+
+/* The _force is for cases where high value is 0 */
+#define ADD_64_LE(s_hi, a_hi_le, s_lo, a_lo_le) \
+ ADD_64(s_hi, le32_to_cpu(a_hi_le), \
+ s_lo, le32_to_cpu(a_lo_le))
+
+#define ADD_64_LE16(s_hi, a_hi_le, s_lo, a_lo_le) \
+ ADD_64(s_hi, le16_to_cpu(a_hi_le), \
+ s_lo, le16_to_cpu(a_lo_le))
+
/* difference = minuend - subtrahend */
#define DIFF_64(d_hi, m_hi, s_hi, d_lo, m_lo, s_lo) \
do { \
@@ -529,4 +541,7 @@ void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event);
* @bp: driver handle
*/
void bnx2x_save_statistics(struct bnx2x *bp);
+
+void bnx2x_afex_collect_stats(struct bnx2x *bp, void *void_afex_stats,
+ u32 stats_type);
#endif /* BNX2X_STATS_H */
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index ceeab8e852ef..edeeb516807a 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -5622,17 +5622,29 @@ static void tg3_tx(struct tg3_napi *tnapi)
}
}
+static void tg3_frag_free(bool is_frag, void *data)
+{
+ if (is_frag)
+ put_page(virt_to_head_page(data));
+ else
+ kfree(data);
+}
+
static void tg3_rx_data_free(struct tg3 *tp, struct ring_info *ri, u32 map_sz)
{
+ unsigned int skb_size = SKB_DATA_ALIGN(map_sz + TG3_RX_OFFSET(tp)) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
if (!ri->data)
return;
pci_unmap_single(tp->pdev, dma_unmap_addr(ri, mapping),
map_sz, PCI_DMA_FROMDEVICE);
- kfree(ri->data);
+ tg3_frag_free(skb_size <= PAGE_SIZE, ri->data);
ri->data = NULL;
}
+
/* Returns size of skb allocated or < 0 on error.
*
* We only need to fill in the address because the other members
@@ -5645,7 +5657,8 @@ static void tg3_rx_data_free(struct tg3 *tp, struct ring_info *ri, u32 map_sz)
* (to fetch the error flags, vlan tag, checksum, and opaque cookie).
*/
static int tg3_alloc_rx_data(struct tg3 *tp, struct tg3_rx_prodring_set *tpr,
- u32 opaque_key, u32 dest_idx_unmasked)
+ u32 opaque_key, u32 dest_idx_unmasked,
+ unsigned int *frag_size)
{
struct tg3_rx_buffer_desc *desc;
struct ring_info *map;
@@ -5680,7 +5693,13 @@ static int tg3_alloc_rx_data(struct tg3 *tp, struct tg3_rx_prodring_set *tpr,
*/
skb_size = SKB_DATA_ALIGN(data_size + TG3_RX_OFFSET(tp)) +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
- data = kmalloc(skb_size, GFP_ATOMIC);
+ if (skb_size <= PAGE_SIZE) {
+ data = netdev_alloc_frag(skb_size);
+ *frag_size = skb_size;
+ } else {
+ data = kmalloc(skb_size, GFP_ATOMIC);
+ *frag_size = 0;
+ }
if (!data)
return -ENOMEM;
@@ -5688,8 +5707,8 @@ static int tg3_alloc_rx_data(struct tg3 *tp, struct tg3_rx_prodring_set *tpr,
data + TG3_RX_OFFSET(tp),
data_size,
PCI_DMA_FROMDEVICE);
- if (pci_dma_mapping_error(tp->pdev, mapping)) {
- kfree(data);
+ if (unlikely(pci_dma_mapping_error(tp->pdev, mapping))) {
+ tg3_frag_free(skb_size <= PAGE_SIZE, data);
return -EIO;
}
@@ -5840,18 +5859,19 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
if (len > TG3_RX_COPY_THRESH(tp)) {
int skb_size;
+ unsigned int frag_size;
skb_size = tg3_alloc_rx_data(tp, tpr, opaque_key,
- *post_ptr);
+ *post_ptr, &frag_size);
if (skb_size < 0)
goto drop_it;
pci_unmap_single(tp->pdev, dma_addr, skb_size,
PCI_DMA_FROMDEVICE);
- skb = build_skb(data);
+ skb = build_skb(data, frag_size);
if (!skb) {
- kfree(data);
+ tg3_frag_free(frag_size != 0, data);
goto drop_it_no_recycle;
}
skb_reserve(skb, TG3_RX_OFFSET(tp));
@@ -7287,7 +7307,10 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
/* Now allocate fresh SKBs for each rx ring. */
for (i = 0; i < tp->rx_pending; i++) {
- if (tg3_alloc_rx_data(tp, tpr, RXD_OPAQUE_RING_STD, i) < 0) {
+ unsigned int frag_size;
+
+ if (tg3_alloc_rx_data(tp, tpr, RXD_OPAQUE_RING_STD, i,
+ &frag_size) < 0) {
netdev_warn(tp->dev,
"Using a smaller RX standard ring. Only "
"%d out of %d buffers were allocated "
@@ -7319,7 +7342,10 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
}
for (i = 0; i < tp->rx_jumbo_pending; i++) {
- if (tg3_alloc_rx_data(tp, tpr, RXD_OPAQUE_RING_JUMBO, i) < 0) {
+ unsigned int frag_size;
+
+ if (tg3_alloc_rx_data(tp, tpr, RXD_OPAQUE_RING_JUMBO, i,
+ &frag_size) < 0) {
netdev_warn(tp->dev,
"Using a smaller RX jumbo ring. Only %d "
"out of %d buffers were allocated "
@@ -12248,6 +12274,7 @@ static const struct ethtool_ops tg3_ethtool_ops = {
.get_rxfh_indir_size = tg3_get_rxfh_indir_size,
.get_rxfh_indir = tg3_get_rxfh_indir,
.set_rxfh_indir = tg3_set_rxfh_indir,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
@@ -15856,8 +15883,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
if (dev) {
struct tg3 *tp = netdev_priv(dev);
- if (tp->fw)
- release_firmware(tp->fw);
+ release_firmware(tp->fw);
tg3_reset_task_cancel(tp);
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index 77977d735dd7..0b640fafbda3 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -70,7 +70,6 @@ static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force);
static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc);
static void bfa_ioc_mbox_flush(struct bfa_ioc *ioc);
static void bfa_ioc_recover(struct bfa_ioc *ioc);
-static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
static void bfa_ioc_event_notify(struct bfa_ioc *, enum bfa_ioc_event);
static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
@@ -346,8 +345,6 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
switch (event) {
case IOC_E_FWRSP_GETATTR:
del_timer(&ioc->ioc_timer);
- bfa_ioc_check_attr_wwns(ioc);
- bfa_ioc_hb_monitor(ioc);
bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
break;
@@ -380,6 +377,7 @@ bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
{
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
+ bfa_ioc_hb_monitor(ioc);
}
static void
@@ -1207,27 +1205,62 @@ bfa_nw_ioc_sem_release(void __iomem *sem_reg)
writel(1, sem_reg);
}
+/* Clear fwver hdr */
+static void
+bfa_ioc_fwver_clear(struct bfa_ioc *ioc)
+{
+ u32 pgnum, pgoff, loff = 0;
+ int i;
+
+ pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
+ pgoff = PSS_SMEM_PGOFF(loff);
+ writel(pgnum, ioc->ioc_regs.host_page_num_fn);
+
+ for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32)); i++) {
+ writel(0, ioc->ioc_regs.smem_page_start + loff);
+ loff += sizeof(u32);
+ }
+}
+
+
static void
bfa_ioc_hw_sem_init(struct bfa_ioc *ioc)
{
struct bfi_ioc_image_hdr fwhdr;
- u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+ u32 fwstate, r32;
- if (fwstate == BFI_IOC_UNINIT)
+ /* Spin on init semaphore to serialize. */
+ r32 = readl(ioc->ioc_regs.ioc_init_sem_reg);
+ while (r32 & 0x1) {
+ udelay(20);
+ r32 = readl(ioc->ioc_regs.ioc_init_sem_reg);
+ }
+
+ fwstate = readl(ioc->ioc_regs.ioc_fwstate);
+ if (fwstate == BFI_IOC_UNINIT) {
+ writel(1, ioc->ioc_regs.ioc_init_sem_reg);
return;
+ }
bfa_nw_ioc_fwver_get(ioc, &fwhdr);
- if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL)
+ if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL) {
+ writel(1, ioc->ioc_regs.ioc_init_sem_reg);
return;
+ }
+ bfa_ioc_fwver_clear(ioc);
writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+ writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
/*
* Try to lock and then unlock the semaphore.
*/
readl(ioc->ioc_regs.ioc_sem_reg);
writel(1, ioc->ioc_regs.ioc_sem_reg);
+
+ /* Unlock init semaphore */
+ writel(1, ioc->ioc_regs.ioc_init_sem_reg);
}
static void
@@ -1585,11 +1618,6 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
u32 i;
u32 asicmode;
- /**
- * Initialize LMEM first before code download
- */
- bfa_ioc_lmem_init(ioc);
-
fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
pgnum = bfa_ioc_smem_pgnum(ioc, loff);
@@ -1914,6 +1942,10 @@ bfa_ioc_pll_init(struct bfa_ioc *ioc)
bfa_ioc_pll_init_asic(ioc);
ioc->pllinit = true;
+
+ /* Initialize LMEM */
+ bfa_ioc_lmem_init(ioc);
+
/*
* release semaphore.
*/
@@ -2513,13 +2545,6 @@ bfa_ioc_recover(struct bfa_ioc *ioc)
bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
}
-static void
-bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc)
-{
- if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
- return;
-}
-
/**
* @dg hal_iocpf_pvt BFA IOC PF private functions
* @{
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c b/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c
index 348479bbfa3a..b6b036a143ae 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c
@@ -199,9 +199,9 @@ bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc)
* Host to LPU mailbox message addresses
*/
static const struct {
- u32 hfn_mbox;
- u32 lpu_mbox;
- u32 hfn_pgn;
+ u32 hfn_mbox;
+ u32 lpu_mbox;
+ u32 hfn_pgn;
} ct_fnreg[] = {
{ HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 },
{ HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 },
@@ -803,17 +803,72 @@ bfa_ioc_ct2_mac_reset(void __iomem *rb)
}
#define CT2_NFC_MAX_DELAY 1000
+#define CT2_NFC_VER_VALID 0x143
+#define BFA_IOC_PLL_POLL 1000000
+
+static bool
+bfa_ioc_ct2_nfc_halted(void __iomem *rb)
+{
+ volatile u32 r32;
+
+ r32 = readl(rb + CT2_NFC_CSR_SET_REG);
+ if (r32 & __NFC_CONTROLLER_HALTED)
+ return true;
+
+ return false;
+}
+
+static void
+bfa_ioc_ct2_nfc_resume(void __iomem *rb)
+{
+ volatile u32 r32;
+ int i;
+
+ writel(__HALT_NFC_CONTROLLER, rb + CT2_NFC_CSR_CLR_REG);
+ for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
+ r32 = readl(rb + CT2_NFC_CSR_SET_REG);
+ if (!(r32 & __NFC_CONTROLLER_HALTED))
+ return;
+ udelay(1000);
+ }
+ BUG_ON(1);
+}
+
static enum bfa_status
bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode asic_mode)
{
volatile u32 wgn, r32;
- int i;
+ u32 nfc_ver, i;
- /*
- * Initialize PLL if not already done by NFC
- */
wgn = readl(rb + CT2_WGN_STATUS);
- if (!(wgn & __GLBL_PF_VF_CFG_RDY)) {
+
+ nfc_ver = readl(rb + CT2_RSC_GPR15_REG);
+
+ if ((wgn == (__A2T_AHB_LOAD | __WGN_READY)) &&
+ (nfc_ver >= CT2_NFC_VER_VALID)) {
+ if (bfa_ioc_ct2_nfc_halted(rb))
+ bfa_ioc_ct2_nfc_resume(rb);
+ writel(__RESET_AND_START_SCLK_LCLK_PLLS,
+ rb + CT2_CSI_FW_CTL_SET_REG);
+
+ for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
+ r32 = readl(rb + CT2_APP_PLL_LCLK_CTL_REG);
+ if (r32 & __RESET_AND_START_SCLK_LCLK_PLLS)
+ break;
+ }
+ BUG_ON(!(r32 & __RESET_AND_START_SCLK_LCLK_PLLS));
+
+ for (i = 0; i < BFA_IOC_PLL_POLL; i++) {
+ r32 = readl(rb + CT2_APP_PLL_LCLK_CTL_REG);
+ if (!(r32 & __RESET_AND_START_SCLK_LCLK_PLLS))
+ break;
+ }
+ BUG_ON(r32 & __RESET_AND_START_SCLK_LCLK_PLLS);
+ udelay(1000);
+
+ r32 = readl(rb + CT2_CSI_FW_CTL_REG);
+ BUG_ON(r32 & __RESET_AND_START_SCLK_LCLK_PLLS);
+ } else {
writel(__HALT_NFC_CONTROLLER, (rb + CT2_NFC_CSR_SET_REG));
for (i = 0; i < CT2_NFC_MAX_DELAY; i++) {
r32 = readl(rb + CT2_NFC_CSR_SET_REG);
@@ -821,53 +876,48 @@ bfa_ioc_ct2_pll_init(void __iomem *rb, enum bfi_asic_mode asic_mode)
break;
udelay(1000);
}
+
+ bfa_ioc_ct2_mac_reset(rb);
+ bfa_ioc_ct2_sclk_init(rb);
+ bfa_ioc_ct2_lclk_init(rb);
+
+ /* release soft reset on s_clk & l_clk */
+ r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
+ writel(r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET,
+ rb + CT2_APP_PLL_SCLK_CTL_REG);
+ r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
+ writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
+ rb + CT2_APP_PLL_LCLK_CTL_REG);
+ }
+
+ /* Announce flash device presence, if flash was corrupted. */
+ if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
+ r32 = readl((rb + PSS_GPIO_OUT_REG));
+ writel(r32 & ~1, rb + PSS_GPIO_OUT_REG);
+ r32 = readl((rb + PSS_GPIO_OE_REG));
+ writel(r32 | 1, rb + PSS_GPIO_OE_REG);
}
/*
* Mask the interrupts and clear any
* pending interrupts left by BIOS/EFI
*/
-
writel(1, (rb + CT2_LPU0_HOSTFN_MBOX0_MSK));
writel(1, (rb + CT2_LPU1_HOSTFN_MBOX0_MSK));
- r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
- if (r32 == 1) {
- writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT));
- readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
- }
- r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
- if (r32 == 1) {
- writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT));
- readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
- }
-
- bfa_ioc_ct2_mac_reset(rb);
- bfa_ioc_ct2_sclk_init(rb);
- bfa_ioc_ct2_lclk_init(rb);
-
- /*
- * release soft reset on s_clk & l_clk
- */
- r32 = readl((rb + CT2_APP_PLL_SCLK_CTL_REG));
- writel((r32 & ~__APP_PLL_SCLK_LOGIC_SOFT_RESET),
- (rb + CT2_APP_PLL_SCLK_CTL_REG));
-
- /*
- * release soft reset on s_clk & l_clk
- */
- r32 = readl((rb + CT2_APP_PLL_LCLK_CTL_REG));
- writel(r32 & ~__APP_PLL_LCLK_LOGIC_SOFT_RESET,
- (rb + CT2_APP_PLL_LCLK_CTL_REG));
-
- /*
- * Announce flash device presence, if flash was corrupted.
- */
- if (wgn == (__WGN_READY | __GLBL_PF_VF_CFG_RDY)) {
- r32 = readl((rb + PSS_GPIO_OUT_REG));
- writel((r32 & ~1), (rb + PSS_GPIO_OUT_REG));
- r32 = readl((rb + PSS_GPIO_OE_REG));
- writel((r32 | 1), (rb + PSS_GPIO_OE_REG));
+ /* For first time initialization, no need to clear interrupts */
+ r32 = readl(rb + HOST_SEM5_REG);
+ if (r32 & 0x1) {
+ r32 = readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
+ if (r32 == 1) {
+ writel(1, (rb + CT2_LPU0_HOSTFN_CMD_STAT));
+ readl((rb + CT2_LPU0_HOSTFN_CMD_STAT));
+ }
+ r32 = readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
+ if (r32 == 1) {
+ writel(1, (rb + CT2_LPU1_HOSTFN_CMD_STAT));
+ readl((rb + CT2_LPU1_HOSTFN_CMD_STAT));
+ }
}
bfa_ioc_ct2_mem_init(rb);
diff --git a/drivers/net/ethernet/brocade/bna/bfi_reg.h b/drivers/net/ethernet/brocade/bna/bfi_reg.h
index efacff3ab51d..0e094fe46dfd 100644
--- a/drivers/net/ethernet/brocade/bna/bfi_reg.h
+++ b/drivers/net/ethernet/brocade/bna/bfi_reg.h
@@ -339,10 +339,16 @@ enum {
#define __A2T_AHB_LOAD 0x00000800
#define __WGN_READY 0x00000400
#define __GLBL_PF_VF_CFG_RDY 0x00000200
+#define CT2_NFC_CSR_CLR_REG 0x00027420
#define CT2_NFC_CSR_SET_REG 0x00027424
#define __HALT_NFC_CONTROLLER 0x00000002
#define __NFC_CONTROLLER_HALTED 0x00001000
+#define CT2_RSC_GPR15_REG 0x0002765c
+#define CT2_CSI_FW_CTL_REG 0x00027080
+#define __RESET_AND_START_SCLK_LCLK_PLLS 0x00010000
+#define CT2_CSI_FW_CTL_SET_REG 0x00027088
+
#define CT2_CSI_MAC0_CONTROL_REG 0x000270d0
#define __CSI_MAC_RESET 0x00000010
#define __CSI_MAC_AHB_RESET 0x00000008
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index ff78f770dec9..67cd2ed0306a 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -80,8 +80,6 @@ do { \
(sizeof(struct bnad_skb_unmap) * ((_depth) - 1)); \
} while (0)
-#define BNAD_TXRX_SYNC_MDELAY 250 /* 250 msecs */
-
static void
bnad_add_to_list(struct bnad *bnad)
{
@@ -103,7 +101,7 @@ bnad_remove_from_list(struct bnad *bnad)
* Reinitialize completions in CQ, once Rx is taken down
*/
static void
-bnad_cq_cmpl_init(struct bnad *bnad, struct bna_ccb *ccb)
+bnad_cq_cleanup(struct bnad *bnad, struct bna_ccb *ccb)
{
struct bna_cq_entry *cmpl, *next_cmpl;
unsigned int wi_range, wis = 0, ccb_prod = 0;
@@ -141,7 +139,8 @@ bnad_pci_unmap_skb(struct device *pdev, struct bnad_skb_unmap *array,
for (j = 0; j < frag; j++) {
dma_unmap_page(pdev, dma_unmap_addr(&array[index], dma_addr),
- skb_frag_size(&skb_shinfo(skb)->frags[j]), DMA_TO_DEVICE);
+ skb_frag_size(&skb_shinfo(skb)->frags[j]),
+ DMA_TO_DEVICE);
dma_unmap_addr_set(&array[index], dma_addr, 0);
BNA_QE_INDX_ADD(index, 1, depth);
}
@@ -155,7 +154,7 @@ bnad_pci_unmap_skb(struct device *pdev, struct bnad_skb_unmap *array,
* so DMA unmap & freeing is fine.
*/
static void
-bnad_free_all_txbufs(struct bnad *bnad,
+bnad_txq_cleanup(struct bnad *bnad,
struct bna_tcb *tcb)
{
u32 unmap_cons;
@@ -183,13 +182,12 @@ bnad_free_all_txbufs(struct bnad *bnad,
/* Data Path Handlers */
/*
- * bnad_free_txbufs : Frees the Tx bufs on Tx completion
+ * bnad_txcmpl_process : Frees the Tx bufs on Tx completion
* Can be called in a) Interrupt context
* b) Sending context
- * c) Tasklet context
*/
static u32
-bnad_free_txbufs(struct bnad *bnad,
+bnad_txcmpl_process(struct bnad *bnad,
struct bna_tcb *tcb)
{
u32 unmap_cons, sent_packets = 0, sent_bytes = 0;
@@ -198,13 +196,7 @@ bnad_free_txbufs(struct bnad *bnad,
struct bnad_skb_unmap *unmap_array;
struct sk_buff *skb;
- /*
- * Just return if TX is stopped. This check is useful
- * when bnad_free_txbufs() runs out of a tasklet scheduled
- * before bnad_cb_tx_cleanup() cleared BNAD_TXQ_TX_STARTED bit
- * but this routine runs actually after the cleanup has been
- * executed.
- */
+ /* Just return if TX is stopped */
if (!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
return 0;
@@ -243,57 +235,8 @@ bnad_free_txbufs(struct bnad *bnad,
return sent_packets;
}
-/* Tx Free Tasklet function */
-/* Frees for all the tcb's in all the Tx's */
-/*
- * Scheduled from sending context, so that
- * the fat Tx lock is not held for too long
- * in the sending context.
- */
-static void
-bnad_tx_free_tasklet(unsigned long bnad_ptr)
-{
- struct bnad *bnad = (struct bnad *)bnad_ptr;
- struct bna_tcb *tcb;
- u32 acked = 0;
- int i, j;
-
- for (i = 0; i < bnad->num_tx; i++) {
- for (j = 0; j < bnad->num_txq_per_tx; j++) {
- tcb = bnad->tx_info[i].tcb[j];
- if (!tcb)
- continue;
- if (((u16) (*tcb->hw_consumer_index) !=
- tcb->consumer_index) &&
- (!test_and_set_bit(BNAD_TXQ_FREE_SENT,
- &tcb->flags))) {
- acked = bnad_free_txbufs(bnad, tcb);
- if (likely(test_bit(BNAD_TXQ_TX_STARTED,
- &tcb->flags)))
- bna_ib_ack(tcb->i_dbell, acked);
- smp_mb__before_clear_bit();
- clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
- }
- if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED,
- &tcb->flags)))
- continue;
- if (netif_queue_stopped(bnad->netdev)) {
- if (acked && netif_carrier_ok(bnad->netdev) &&
- BNA_QE_FREE_CNT(tcb, tcb->q_depth) >=
- BNAD_NETIF_WAKE_THRESHOLD) {
- netif_wake_queue(bnad->netdev);
- /* TODO */
- /* Counters for individual TxQs? */
- BNAD_UPDATE_CTR(bnad,
- netif_queue_wakeup);
- }
- }
- }
- }
-}
-
static u32
-bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
+bnad_tx_complete(struct bnad *bnad, struct bna_tcb *tcb)
{
struct net_device *netdev = bnad->netdev;
u32 sent = 0;
@@ -301,7 +244,7 @@ bnad_tx(struct bnad *bnad, struct bna_tcb *tcb)
if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
return 0;
- sent = bnad_free_txbufs(bnad, tcb);
+ sent = bnad_txcmpl_process(bnad, tcb);
if (sent) {
if (netif_queue_stopped(netdev) &&
netif_carrier_ok(netdev) &&
@@ -330,13 +273,13 @@ bnad_msix_tx(int irq, void *data)
struct bna_tcb *tcb = (struct bna_tcb *)data;
struct bnad *bnad = tcb->bnad;
- bnad_tx(bnad, tcb);
+ bnad_tx_complete(bnad, tcb);
return IRQ_HANDLED;
}
static void
-bnad_reset_rcb(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_rcb_cleanup(struct bnad *bnad, struct bna_rcb *rcb)
{
struct bnad_unmap_q *unmap_q = rcb->unmap_q;
@@ -348,7 +291,7 @@ bnad_reset_rcb(struct bnad *bnad, struct bna_rcb *rcb)
}
static void
-bnad_free_all_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_rxq_cleanup(struct bnad *bnad, struct bna_rcb *rcb)
{
struct bnad_unmap_q *unmap_q;
struct bnad_skb_unmap *unmap_array;
@@ -369,11 +312,11 @@ bnad_free_all_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
DMA_FROM_DEVICE);
dev_kfree_skb(skb);
}
- bnad_reset_rcb(bnad, rcb);
+ bnad_rcb_cleanup(bnad, rcb);
}
static void
-bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
+bnad_rxq_post(struct bnad *bnad, struct bna_rcb *rcb)
{
u16 to_alloc, alloced, unmap_prod, wi_range;
struct bnad_unmap_q *unmap_q = rcb->unmap_q;
@@ -434,14 +377,14 @@ bnad_refill_rxq(struct bnad *bnad, struct bna_rcb *rcb)
if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
>> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
- bnad_alloc_n_post_rxbufs(bnad, rcb);
+ bnad_rxq_post(bnad, rcb);
smp_mb__before_clear_bit();
clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
}
}
static u32
-bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
+bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget)
{
struct bna_cq_entry *cmpl, *next_cmpl;
struct bna_rcb *rcb = NULL;
@@ -453,12 +396,8 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl);
- set_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
-
- if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)) {
- clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags);
+ if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags))
return 0;
- }
prefetch(bnad->netdev);
BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl,
@@ -533,9 +472,8 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
if (skb->ip_summed == CHECKSUM_UNNECESSARY)
napi_gro_receive(&rx_ctrl->napi, skb);
- else {
+ else
netif_receive_skb(skb);
- }
next:
cmpl->valid = 0;
@@ -646,7 +584,7 @@ bnad_isr(int irq, void *data)
for (j = 0; j < bnad->num_txq_per_tx; j++) {
tcb = bnad->tx_info[i].tcb[j];
if (tcb && test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
- bnad_tx(bnad, bnad->tx_info[i].tcb[j]);
+ bnad_tx_complete(bnad, bnad->tx_info[i].tcb[j]);
}
}
/* Rx processing */
@@ -839,20 +777,9 @@ bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb)
{
struct bnad_tx_info *tx_info =
(struct bnad_tx_info *)tcb->txq->tx->priv;
- struct bnad_unmap_q *unmap_q = tcb->unmap_q;
-
- while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
- cpu_relax();
-
- bnad_free_all_txbufs(bnad, tcb);
-
- unmap_q->producer_index = 0;
- unmap_q->consumer_index = 0;
-
- smp_mb__before_clear_bit();
- clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
tx_info->tcb[tcb->id] = NULL;
+ tcb->priv = NULL;
}
static void
@@ -866,12 +793,6 @@ bnad_cb_rcb_setup(struct bnad *bnad, struct bna_rcb *rcb)
}
static void
-bnad_cb_rcb_destroy(struct bnad *bnad, struct bna_rcb *rcb)
-{
- bnad_free_all_rxbufs(bnad, rcb);
-}
-
-static void
bnad_cb_ccb_setup(struct bnad *bnad, struct bna_ccb *ccb)
{
struct bnad_rx_info *rx_info =
@@ -916,7 +837,6 @@ bnad_cb_tx_resume(struct bnad *bnad, struct bna_tx *tx)
{
struct bnad_tx_info *tx_info = (struct bnad_tx_info *)tx->priv;
struct bna_tcb *tcb;
- struct bnad_unmap_q *unmap_q;
u32 txq_id;
int i;
@@ -926,23 +846,9 @@ bnad_cb_tx_resume(struct bnad *bnad, struct bna_tx *tx)
continue;
txq_id = tcb->id;
- unmap_q = tcb->unmap_q;
-
- if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))
- continue;
-
- while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags))
- cpu_relax();
-
- bnad_free_all_txbufs(bnad, tcb);
-
- unmap_q->producer_index = 0;
- unmap_q->consumer_index = 0;
-
- smp_mb__before_clear_bit();
- clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
-
+ BUG_ON(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags));
set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags);
+ BUG_ON(*(tcb->hw_consumer_index) != 0);
if (netif_carrier_ok(bnad->netdev)) {
printk(KERN_INFO "bna: %s %d TXQ_STARTED\n",
@@ -963,6 +869,54 @@ bnad_cb_tx_resume(struct bnad *bnad, struct bna_tx *tx)
}
}
+/*
+ * Free all TxQs buffers and then notify TX_E_CLEANUP_DONE to Tx fsm.
+ */
+static void
+bnad_tx_cleanup(struct delayed_work *work)
+{
+ struct bnad_tx_info *tx_info =
+ container_of(work, struct bnad_tx_info, tx_cleanup_work);
+ struct bnad *bnad = NULL;
+ struct bnad_unmap_q *unmap_q;
+ struct bna_tcb *tcb;
+ unsigned long flags;
+ uint32_t i, pending = 0;
+
+ for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) {
+ tcb = tx_info->tcb[i];
+ if (!tcb)
+ continue;
+
+ bnad = tcb->bnad;
+
+ if (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
+ pending++;
+ continue;
+ }
+
+ bnad_txq_cleanup(bnad, tcb);
+
+ unmap_q = tcb->unmap_q;
+ unmap_q->producer_index = 0;
+ unmap_q->consumer_index = 0;
+
+ smp_mb__before_clear_bit();
+ clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags);
+ }
+
+ if (pending) {
+ queue_delayed_work(bnad->work_q, &tx_info->tx_cleanup_work,
+ msecs_to_jiffies(1));
+ return;
+ }
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_tx_cleanup_complete(tx_info->tx);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
+
static void
bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tx *tx)
{
@@ -976,8 +930,7 @@ bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tx *tx)
continue;
}
- mdelay(BNAD_TXRX_SYNC_MDELAY);
- bna_tx_cleanup_complete(tx);
+ queue_delayed_work(bnad->work_q, &tx_info->tx_cleanup_work, 0);
}
static void
@@ -1001,6 +954,44 @@ bnad_cb_rx_stall(struct bnad *bnad, struct bna_rx *rx)
}
}
+/*
+ * Free all RxQs buffers and then notify RX_E_CLEANUP_DONE to Rx fsm.
+ */
+static void
+bnad_rx_cleanup(void *work)
+{
+ struct bnad_rx_info *rx_info =
+ container_of(work, struct bnad_rx_info, rx_cleanup_work);
+ struct bnad_rx_ctrl *rx_ctrl;
+ struct bnad *bnad = NULL;
+ unsigned long flags;
+ uint32_t i;
+
+ for (i = 0; i < BNAD_MAX_RXP_PER_RX; i++) {
+ rx_ctrl = &rx_info->rx_ctrl[i];
+
+ if (!rx_ctrl->ccb)
+ continue;
+
+ bnad = rx_ctrl->ccb->bnad;
+
+ /*
+ * Wait till the poll handler has exited
+ * and nothing can be scheduled anymore
+ */
+ napi_disable(&rx_ctrl->napi);
+
+ bnad_cq_cleanup(bnad, rx_ctrl->ccb);
+ bnad_rxq_cleanup(bnad, rx_ctrl->ccb->rcb[0]);
+ if (rx_ctrl->ccb->rcb[1])
+ bnad_rxq_cleanup(bnad, rx_ctrl->ccb->rcb[1]);
+ }
+
+ spin_lock_irqsave(&bnad->bna_lock, flags);
+ bna_rx_cleanup_complete(rx_info->rx);
+ spin_unlock_irqrestore(&bnad->bna_lock, flags);
+}
+
static void
bnad_cb_rx_cleanup(struct bnad *bnad, struct bna_rx *rx)
{
@@ -1009,8 +1000,6 @@ bnad_cb_rx_cleanup(struct bnad *bnad, struct bna_rx *rx)
struct bnad_rx_ctrl *rx_ctrl;
int i;
- mdelay(BNAD_TXRX_SYNC_MDELAY);
-
for (i = 0; i < BNAD_MAX_RXP_PER_RX; i++) {
rx_ctrl = &rx_info->rx_ctrl[i];
ccb = rx_ctrl->ccb;
@@ -1021,12 +1010,9 @@ bnad_cb_rx_cleanup(struct bnad *bnad, struct bna_rx *rx)
if (ccb->rcb[1])
clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags);
-
- while (test_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags))
- cpu_relax();
}
- bna_rx_cleanup_complete(rx);
+ queue_work(bnad->work_q, &rx_info->rx_cleanup_work);
}
static void
@@ -1046,13 +1032,12 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx)
if (!ccb)
continue;
- bnad_cq_cmpl_init(bnad, ccb);
+ napi_enable(&rx_ctrl->napi);
for (j = 0; j < BNAD_MAX_RXQ_PER_RXP; j++) {
rcb = ccb->rcb[j];
if (!rcb)
continue;
- bnad_free_all_rxbufs(bnad, rcb);
set_bit(BNAD_RXQ_STARTED, &rcb->flags);
set_bit(BNAD_RXQ_POST_OK, &rcb->flags);
@@ -1063,7 +1048,7 @@ bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx)
if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) {
if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth)
>> BNAD_RXQ_REFILL_THRESHOLD_SHIFT)
- bnad_alloc_n_post_rxbufs(bnad, rcb);
+ bnad_rxq_post(bnad, rcb);
smp_mb__before_clear_bit();
clear_bit(BNAD_RXQ_REFILL, &rcb->flags);
}
@@ -1687,7 +1672,7 @@ bnad_napi_poll_rx(struct napi_struct *napi, int budget)
if (!netif_carrier_ok(bnad->netdev))
goto poll_exit;
- rcvd = bnad_poll_cq(bnad, rx_ctrl->ccb, budget);
+ rcvd = bnad_cq_process(bnad, rx_ctrl->ccb, budget);
if (rcvd >= budget)
return rcvd;
@@ -1704,7 +1689,7 @@ poll_exit:
#define BNAD_NAPI_POLL_QUOTA 64
static void
-bnad_napi_init(struct bnad *bnad, u32 rx_id)
+bnad_napi_add(struct bnad *bnad, u32 rx_id)
{
struct bnad_rx_ctrl *rx_ctrl;
int i;
@@ -1718,34 +1703,18 @@ bnad_napi_init(struct bnad *bnad, u32 rx_id)
}
static void
-bnad_napi_enable(struct bnad *bnad, u32 rx_id)
-{
- struct bnad_rx_ctrl *rx_ctrl;
- int i;
-
- /* Initialize & enable NAPI */
- for (i = 0; i < bnad->num_rxp_per_rx; i++) {
- rx_ctrl = &bnad->rx_info[rx_id].rx_ctrl[i];
-
- napi_enable(&rx_ctrl->napi);
- }
-}
-
-static void
-bnad_napi_disable(struct bnad *bnad, u32 rx_id)
+bnad_napi_delete(struct bnad *bnad, u32 rx_id)
{
int i;
/* First disable and then clean up */
- for (i = 0; i < bnad->num_rxp_per_rx; i++) {
- napi_disable(&bnad->rx_info[rx_id].rx_ctrl[i].napi);
+ for (i = 0; i < bnad->num_rxp_per_rx; i++)
netif_napi_del(&bnad->rx_info[rx_id].rx_ctrl[i].napi);
- }
}
/* Should be held with conf_lock held */
void
-bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
+bnad_destroy_tx(struct bnad *bnad, u32 tx_id)
{
struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id];
struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0];
@@ -1764,9 +1733,6 @@ bnad_cleanup_tx(struct bnad *bnad, u32 tx_id)
bnad_tx_msix_unregister(bnad, tx_info,
bnad->num_txq_per_tx);
- if (0 == tx_id)
- tasklet_kill(&bnad->tx_free_tasklet);
-
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_tx_destroy(tx_info->tx);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
@@ -1832,6 +1798,9 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id)
goto err_return;
tx_info->tx = tx;
+ INIT_DELAYED_WORK(&tx_info->tx_cleanup_work,
+ (work_func_t)bnad_tx_cleanup);
+
/* Register ISR for the Tx object */
if (intr_info->intr_type == BNA_INTR_T_MSIX) {
err = bnad_tx_msix_register(bnad, tx_info,
@@ -1896,7 +1865,7 @@ bnad_rx_ctrl_init(struct bnad *bnad, u32 rx_id)
/* Called with mutex_lock(&bnad->conf_mutex) held */
void
-bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
+bnad_destroy_rx(struct bnad *bnad, u32 rx_id)
{
struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id];
struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
@@ -1928,7 +1897,7 @@ bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
if (rx_info->rx_ctrl[0].ccb->intr_type == BNA_INTR_T_MSIX)
bnad_rx_msix_unregister(bnad, rx_info, rx_config->num_paths);
- bnad_napi_disable(bnad, rx_id);
+ bnad_napi_delete(bnad, rx_id);
spin_lock_irqsave(&bnad->bna_lock, flags);
bna_rx_destroy(rx_info->rx);
@@ -1952,7 +1921,7 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
static const struct bna_rx_event_cbfn rx_cbfn = {
.rcb_setup_cbfn = bnad_cb_rcb_setup,
- .rcb_destroy_cbfn = bnad_cb_rcb_destroy,
+ .rcb_destroy_cbfn = NULL,
.ccb_setup_cbfn = bnad_cb_ccb_setup,
.ccb_destroy_cbfn = bnad_cb_ccb_destroy,
.rx_stall_cbfn = bnad_cb_rx_stall,
@@ -1998,11 +1967,14 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
rx_info->rx = rx;
spin_unlock_irqrestore(&bnad->bna_lock, flags);
+ INIT_WORK(&rx_info->rx_cleanup_work,
+ (work_func_t)(bnad_rx_cleanup));
+
/*
* Init NAPI, so that state is set to NAPI_STATE_SCHED,
* so that IRQ handler cannot schedule NAPI at this point.
*/
- bnad_napi_init(bnad, rx_id);
+ bnad_napi_add(bnad, rx_id);
/* Register ISR for the Rx object */
if (intr_info->intr_type == BNA_INTR_T_MSIX) {
@@ -2028,13 +2000,10 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
bna_rx_enable(rx);
spin_unlock_irqrestore(&bnad->bna_lock, flags);
- /* Enable scheduling of NAPI */
- bnad_napi_enable(bnad, rx_id);
-
return 0;
err_return:
- bnad_cleanup_rx(bnad, rx_id);
+ bnad_destroy_rx(bnad, rx_id);
return err;
}
@@ -2519,7 +2488,7 @@ bnad_open(struct net_device *netdev)
return 0;
cleanup_tx:
- bnad_cleanup_tx(bnad, 0);
+ bnad_destroy_tx(bnad, 0);
err_return:
mutex_unlock(&bnad->conf_mutex);
@@ -2546,8 +2515,8 @@ bnad_stop(struct net_device *netdev)
wait_for_completion(&bnad->bnad_completions.enet_comp);
- bnad_cleanup_tx(bnad, 0);
- bnad_cleanup_rx(bnad, 0);
+ bnad_destroy_tx(bnad, 0);
+ bnad_destroy_rx(bnad, 0);
/* Synchronize mailbox IRQ */
bnad_mbox_irq_sync(bnad);
@@ -2620,7 +2589,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
if ((u16) (*tcb->hw_consumer_index) !=
tcb->consumer_index &&
!test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) {
- acked = bnad_free_txbufs(bnad, tcb);
+ acked = bnad_txcmpl_process(bnad, tcb);
if (likely(test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)))
bna_ib_ack(tcb->i_dbell, acked);
smp_mb__before_clear_bit();
@@ -2843,9 +2812,6 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
bna_txq_prod_indx_doorbell(tcb);
smp_mb();
- if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index)
- tasklet_schedule(&bnad->tx_free_tasklet);
-
return NETDEV_TX_OK;
}
@@ -3127,8 +3093,8 @@ bnad_netdev_init(struct bnad *bnad, bool using_dac)
/*
* 1. Initialize the bnad structure
* 2. Setup netdev pointer in pci_dev
- * 3. Initialze Tx free tasklet
- * 4. Initialize no. of TxQ & CQs & MSIX vectors
+ * 3. Initialize no. of TxQ & CQs & MSIX vectors
+ * 4. Initialize work queue.
*/
static int
bnad_init(struct bnad *bnad,
@@ -3171,8 +3137,11 @@ bnad_init(struct bnad *bnad,
bnad->tx_coalescing_timeo = BFI_TX_COALESCING_TIMEO;
bnad->rx_coalescing_timeo = BFI_RX_COALESCING_TIMEO;
- tasklet_init(&bnad->tx_free_tasklet, bnad_tx_free_tasklet,
- (unsigned long)bnad);
+ sprintf(bnad->wq_name, "%s_wq_%d", BNAD_NAME, bnad->id);
+ bnad->work_q = create_singlethread_workqueue(bnad->wq_name);
+
+ if (!bnad->work_q)
+ return -ENOMEM;
return 0;
}
@@ -3185,6 +3154,12 @@ bnad_init(struct bnad *bnad,
static void
bnad_uninit(struct bnad *bnad)
{
+ if (bnad->work_q) {
+ flush_workqueue(bnad->work_q);
+ destroy_workqueue(bnad->work_q);
+ bnad->work_q = NULL;
+ }
+
if (bnad->bar0)
iounmap(bnad->bar0);
pci_set_drvdata(bnad->pcidev, NULL);
@@ -3304,7 +3279,6 @@ bnad_pci_probe(struct pci_dev *pdev,
/*
* Initialize bnad structure
* Setup relation between pci_dev & netdev
- * Init Tx free tasklet
*/
err = bnad_init(bnad, pdev, netdev);
if (err)
@@ -3546,9 +3520,7 @@ static void __exit
bnad_module_exit(void)
{
pci_unregister_driver(&bnad_pci_driver);
-
- if (bfi_fw)
- release_firmware(bfi_fw);
+ release_firmware(bfi_fw);
}
module_init(bnad_module_init);
diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h
index 55824d92699f..72742be11277 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.h
+++ b/drivers/net/ethernet/brocade/bna/bnad.h
@@ -71,7 +71,7 @@ struct bnad_rx_ctrl {
#define BNAD_NAME "bna"
#define BNAD_NAME_LEN 64
-#define BNAD_VERSION "3.0.2.2"
+#define BNAD_VERSION "3.0.23.0"
#define BNAD_MAILBOX_MSIX_INDEX 0
#define BNAD_MAILBOX_MSIX_VECTORS 1
@@ -210,6 +210,7 @@ struct bnad_tx_info {
struct bna_tx *tx; /* 1:1 between tx_info & tx */
struct bna_tcb *tcb[BNAD_MAX_TXQ_PER_TX];
u32 tx_id;
+ struct delayed_work tx_cleanup_work;
} ____cacheline_aligned;
struct bnad_rx_info {
@@ -217,6 +218,7 @@ struct bnad_rx_info {
struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXP_PER_RX];
u32 rx_id;
+ struct work_struct rx_cleanup_work;
} ____cacheline_aligned;
/* Unmap queues for Tx / Rx cleanup */
@@ -318,7 +320,7 @@ struct bnad {
/* Burnt in MAC address */
mac_t perm_addr;
- struct tasklet_struct tx_free_tasklet;
+ struct workqueue_struct *work_q;
/* Statistics */
struct bnad_stats stats;
@@ -328,6 +330,7 @@ struct bnad {
char adapter_name[BNAD_NAME_LEN];
char port_name[BNAD_NAME_LEN];
char mbox_irq_name[BNAD_NAME_LEN];
+ char wq_name[BNAD_NAME_LEN];
/* debugfs specific data */
char *regdata;
@@ -370,8 +373,8 @@ extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad);
extern int bnad_setup_rx(struct bnad *bnad, u32 rx_id);
extern int bnad_setup_tx(struct bnad *bnad, u32 tx_id);
-extern void bnad_cleanup_tx(struct bnad *bnad, u32 tx_id);
-extern void bnad_cleanup_rx(struct bnad *bnad, u32 rx_id);
+extern void bnad_destroy_tx(struct bnad *bnad, u32 tx_id);
+extern void bnad_destroy_rx(struct bnad *bnad, u32 rx_id);
/* Timer start/stop protos */
extern void bnad_dim_timer_start(struct bnad *bnad);
diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
index ab753d7334a6..40e1e84f4984 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
@@ -464,7 +464,7 @@ bnad_set_ringparam(struct net_device *netdev,
for (i = 0; i < bnad->num_rx; i++) {
if (!bnad->rx_info[i].rx)
continue;
- bnad_cleanup_rx(bnad, i);
+ bnad_destroy_rx(bnad, i);
current_err = bnad_setup_rx(bnad, i);
if (current_err && !err)
err = current_err;
@@ -492,7 +492,7 @@ bnad_set_ringparam(struct net_device *netdev,
for (i = 0; i < bnad->num_tx; i++) {
if (!bnad->tx_info[i].tx)
continue;
- bnad_cleanup_tx(bnad, i);
+ bnad_destroy_tx(bnad, i);
current_err = bnad_setup_tx(bnad, i);
if (current_err && !err)
err = current_err;
@@ -539,7 +539,7 @@ bnad_set_pauseparam(struct net_device *netdev,
}
static void
-bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
+bnad_get_strings(struct net_device *netdev, u32 stringset, u8 *string)
{
struct bnad *bnad = netdev_priv(netdev);
int i, j, q_num;
diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
index 906117016fc4..77884191a8c6 100644
--- a/drivers/net/ethernet/cadence/at91_ether.c
+++ b/drivers/net/ethernet/cadence/at91_ether.c
@@ -30,6 +30,7 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/gfp.h>
+#include <linux/phy.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -51,21 +52,17 @@
/*
* Read from a EMAC register.
*/
-static inline unsigned long at91_emac_read(unsigned int reg)
+static inline unsigned long at91_emac_read(struct at91_private *lp, unsigned int reg)
{
- void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
-
- return __raw_readl(emac_base + reg);
+ return __raw_readl(lp->emac_base + reg);
}
/*
* Write to a EMAC register.
*/
-static inline void at91_emac_write(unsigned int reg, unsigned long value)
+static inline void at91_emac_write(struct at91_private *lp, unsigned int reg, unsigned long value)
{
- void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC;
-
- __raw_writel(value, emac_base + reg);
+ __raw_writel(value, lp->emac_base + reg);
}
/* ........................... PHY INTERFACE ........................... */
@@ -75,32 +72,33 @@ static inline void at91_emac_write(unsigned int reg, unsigned long value)
* When not called from an interrupt-handler, access to the PHY must be
* protected by a spinlock.
*/
-static void enable_mdi(void)
+static void enable_mdi(struct at91_private *lp)
{
unsigned long ctl;
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */
+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+ at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */
}
/*
* Disable the MDIO bit in the MAC control register
*/
-static void disable_mdi(void)
+static void disable_mdi(struct at91_private *lp)
{
unsigned long ctl;
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */
+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+ at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */
}
/*
* Wait until the PHY operation is complete.
*/
-static inline void at91_phy_wait(void) {
+static inline void at91_phy_wait(struct at91_private *lp)
+{
unsigned long timeout = jiffies + 2;
- while (!(at91_emac_read(AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
+ while (!(at91_emac_read(lp, AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
if (time_after(jiffies, timeout)) {
printk("at91_ether: MIO timeout\n");
break;
@@ -113,28 +111,28 @@ static inline void at91_phy_wait(void) {
* Write value to the a PHY register
* Note: MDI interface is assumed to already have been enabled.
*/
-static void write_phy(unsigned char phy_addr, unsigned char address, unsigned int value)
+static void write_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int value)
{
- at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
+ at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
| ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA));
/* Wait until IDLE bit in Network Status register is cleared */
- at91_phy_wait();
+ at91_phy_wait(lp);
}
/*
* Read value stored in a PHY register.
* Note: MDI interface is assumed to already have been enabled.
*/
-static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int *value)
+static void read_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int *value)
{
- at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
+ at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
| ((phy_addr & 0x1f) << 23) | (address << 18));
/* Wait until IDLE bit in Network Status register is cleared */
- at91_phy_wait();
+ at91_phy_wait(lp);
- *value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA;
+ *value = at91_emac_read(lp, AT91_EMAC_MAN) & AT91_EMAC_DATA;
}
/* ........................... PHY MANAGEMENT .......................... */
@@ -158,13 +156,13 @@ static void update_linkspeed(struct net_device *dev, int silent)
}
/* Link up, or auto-negotiation still in progress */
- read_phy(lp->phy_address, MII_BMSR, &bmsr);
- read_phy(lp->phy_address, MII_BMCR, &bmcr);
+ read_phy(lp, lp->phy_address, MII_BMSR, &bmsr);
+ read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */
if (!(bmsr & BMSR_ANEGCOMPLETE))
return; /* Do nothing - another interrupt generated when negotiation complete */
- read_phy(lp->phy_address, MII_LPA, &lpa);
+ read_phy(lp, lp->phy_address, MII_LPA, &lpa);
if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
else speed = SPEED_10;
if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
@@ -175,7 +173,7 @@ static void update_linkspeed(struct net_device *dev, int silent)
}
/* Update the MAC */
- mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
+ mac_cfg = at91_emac_read(lp, AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
if (speed == SPEED_100) {
if (duplex == DUPLEX_FULL) /* 100 Full Duplex */
mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD;
@@ -186,7 +184,7 @@ static void update_linkspeed(struct net_device *dev, int silent)
mac_cfg |= AT91_EMAC_FD;
else {} /* 10 Half Duplex */
}
- at91_emac_write(AT91_EMAC_CFG, mac_cfg);
+ at91_emac_write(lp, AT91_EMAC_CFG, mac_cfg);
if (!silent)
printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
@@ -207,34 +205,34 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
* level-triggering. We therefore have to check if the PHY actually has
* an IRQ pending.
*/
- enable_mdi();
+ enable_mdi(lp);
if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
- read_phy(lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */
+ read_phy(lp, lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */
if (!(phy & (1 << 0)))
goto done;
}
else if (lp->phy_type == MII_LXT971A_ID) {
- read_phy(lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */
+ read_phy(lp, lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */
if (!(phy & (1 << 2)))
goto done;
}
else if (lp->phy_type == MII_BCM5221_ID) {
- read_phy(lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */
+ read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */
if (!(phy & (1 << 0)))
goto done;
}
else if (lp->phy_type == MII_KS8721_ID) {
- read_phy(lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */
+ read_phy(lp, lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */
if (!(phy & ((1 << 2) | 1)))
goto done;
}
- else if (lp->phy_type == MII_T78Q21x3_ID) { /* ack interrupt in Teridian PHY */
- read_phy(lp->phy_address, MII_T78Q21INT_REG, &phy);
+ else if (lp->phy_type == MII_T78Q21x3_ID) { /* ack interrupt in Teridian PHY */
+ read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &phy);
if (!(phy & ((1 << 2) | 1)))
goto done;
}
else if (lp->phy_type == MII_DP83848_ID) {
- read_phy(lp->phy_address, MII_DPPHYSTS_REG, &phy); /* ack interrupt in DP83848 PHY */
+ read_phy(lp, lp->phy_address, MII_DPPHYSTS_REG, &phy); /* ack interrupt in DP83848 PHY */
if (!(phy & (1 << 7)))
goto done;
}
@@ -242,7 +240,7 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
update_linkspeed(dev, 0);
done:
- disable_mdi();
+ disable_mdi(lp);
return IRQ_HANDLED;
}
@@ -265,7 +263,7 @@ static void enable_phyirq(struct net_device *dev)
return;
}
- irq_number = lp->board_data.phy_irq_pin;
+ irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
if (status) {
printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
@@ -273,41 +271,41 @@ static void enable_phyirq(struct net_device *dev)
}
spin_lock_irq(&lp->lock);
- enable_mdi();
+ enable_mdi(lp);
if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */
- read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
+ read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
dsintr = dsintr & ~0xf00; /* clear bits 8..11 */
- write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
+ write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
}
else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
- read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
+ read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */
- write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
+ write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
}
else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */
dsintr = (1 << 15) | ( 1 << 14);
- write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
+ write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
}
else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */
dsintr = (1 << 10) | ( 1 << 8);
- write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
+ write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
}
else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */
- read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
+ read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
dsintr = dsintr | 0x500; /* set bits 8, 10 */
- write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
+ write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
}
else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */
- read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
+ read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
dsintr = dsintr | 0x3c; /* set bits 2..5 */
- write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
- read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
+ write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
+ read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
dsintr = dsintr | 0x3; /* set bits 0,1 */
- write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
+ write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
}
- disable_mdi();
+ disable_mdi(lp);
spin_unlock_irq(&lp->lock);
}
@@ -326,46 +324,46 @@ static void disable_phyirq(struct net_device *dev)
}
spin_lock_irq(&lp->lock);
- enable_mdi();
+ enable_mdi(lp);
if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */
- read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr);
+ read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
dsintr = dsintr | 0xf00; /* set bits 8..11 */
- write_phy(lp->phy_address, MII_DSINTR_REG, dsintr);
+ write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
}
else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
- read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr);
+ read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */
- write_phy(lp->phy_address, MII_ISINTE_REG, dsintr);
+ write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
}
else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */
- read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr);
+ read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &dsintr);
dsintr = ~(1 << 14);
- write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr);
+ write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
}
else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */
- read_phy(lp->phy_address, MII_TPISTATUS, &dsintr);
+ read_phy(lp, lp->phy_address, MII_TPISTATUS, &dsintr);
dsintr = ~((1 << 10) | (1 << 8));
- write_phy(lp->phy_address, MII_TPISTATUS, dsintr);
+ write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
}
else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */
- read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr);
+ read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
dsintr = dsintr & ~0x500; /* clear bits 8, 10 */
- write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr);
+ write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
}
else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */
- read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr);
+ read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
dsintr = dsintr & ~0x3; /* clear bits 0, 1 */
- write_phy(lp->phy_address, MII_DPMICR_REG, dsintr);
- read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr);
+ write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
+ read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
dsintr = dsintr & ~0x3c; /* clear bits 2..5 */
- write_phy(lp->phy_address, MII_DPMISR_REG, dsintr);
+ write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
}
- disable_mdi();
+ disable_mdi(lp);
spin_unlock_irq(&lp->lock);
- irq_number = lp->board_data.phy_irq_pin;
+ irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
free_irq(irq_number, dev); /* Free interrupt handler */
}
@@ -379,17 +377,17 @@ static void reset_phy(struct net_device *dev)
unsigned int bmcr;
spin_lock_irq(&lp->lock);
- enable_mdi();
+ enable_mdi(lp);
/* Perform PHY reset */
- write_phy(lp->phy_address, MII_BMCR, BMCR_RESET);
+ write_phy(lp, lp->phy_address, MII_BMCR, BMCR_RESET);
/* Wait until PHY reset is complete */
do {
- read_phy(lp->phy_address, MII_BMCR, &bmcr);
+ read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
} while (!(bmcr & BMCR_RESET));
- disable_mdi();
+ disable_mdi(lp);
spin_unlock_irq(&lp->lock);
}
#endif
@@ -399,13 +397,37 @@ static void at91ether_check_link(unsigned long dev_id)
struct net_device *dev = (struct net_device *) dev_id;
struct at91_private *lp = netdev_priv(dev);
- enable_mdi();
+ enable_mdi(lp);
update_linkspeed(dev, 1);
- disable_mdi();
+ disable_mdi(lp);
mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
}
+/*
+ * Perform any PHY-specific initialization.
+ */
+static void __init initialize_phy(struct at91_private *lp)
+{
+ unsigned int val;
+
+ spin_lock_irq(&lp->lock);
+ enable_mdi(lp);
+
+ if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
+ read_phy(lp, lp->phy_address, MII_DSCR_REG, &val);
+ if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */
+ lp->phy_media = PORT_FIBRE;
+ } else if (machine_is_csb337()) {
+ /* mix link activity status into LED2 link state */
+ write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x0d22);
+ } else if (machine_is_ecbat91())
+ write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x156A);
+
+ disable_mdi(lp);
+ spin_unlock_irq(&lp->lock);
+}
+
/* ......................... ADDRESS MANAGEMENT ........................ */
/*
@@ -454,17 +476,19 @@ static short __init unpack_mac_address(struct net_device *dev, unsigned int hi,
*/
static void __init get_mac_address(struct net_device *dev)
{
+ struct at91_private *lp = netdev_priv(dev);
+
/* Check Specific-Address 1 */
- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA1H), at91_emac_read(AT91_EMAC_SA1L)))
+ if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA1H), at91_emac_read(lp, AT91_EMAC_SA1L)))
return;
/* Check Specific-Address 2 */
- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA2H), at91_emac_read(AT91_EMAC_SA2L)))
+ if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA2H), at91_emac_read(lp, AT91_EMAC_SA2L)))
return;
/* Check Specific-Address 3 */
- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA3H), at91_emac_read(AT91_EMAC_SA3L)))
+ if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA3H), at91_emac_read(lp, AT91_EMAC_SA3L)))
return;
/* Check Specific-Address 4 */
- if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA4H), at91_emac_read(AT91_EMAC_SA4L)))
+ if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA4H), at91_emac_read(lp, AT91_EMAC_SA4L)))
return;
printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n");
@@ -475,11 +499,13 @@ static void __init get_mac_address(struct net_device *dev)
*/
static void update_mac_address(struct net_device *dev)
{
- at91_emac_write(AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
- at91_emac_write(AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
+ struct at91_private *lp = netdev_priv(dev);
- at91_emac_write(AT91_EMAC_SA2L, 0);
- at91_emac_write(AT91_EMAC_SA2H, 0);
+ at91_emac_write(lp, AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
+ at91_emac_write(lp, AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
+
+ at91_emac_write(lp, AT91_EMAC_SA2L, 0);
+ at91_emac_write(lp, AT91_EMAC_SA2H, 0);
}
/*
@@ -559,6 +585,7 @@ static int hash_get_index(__u8 *addr)
*/
static void at91ether_sethashtable(struct net_device *dev)
{
+ struct at91_private *lp = netdev_priv(dev);
struct netdev_hw_addr *ha;
unsigned long mc_filter[2];
unsigned int bitnr;
@@ -570,8 +597,8 @@ static void at91ether_sethashtable(struct net_device *dev)
mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
}
- at91_emac_write(AT91_EMAC_HSL, mc_filter[0]);
- at91_emac_write(AT91_EMAC_HSH, mc_filter[1]);
+ at91_emac_write(lp, AT91_EMAC_HSL, mc_filter[0]);
+ at91_emac_write(lp, AT91_EMAC_HSH, mc_filter[1]);
}
/*
@@ -579,9 +606,10 @@ static void at91ether_sethashtable(struct net_device *dev)
*/
static void at91ether_set_multicast_list(struct net_device *dev)
{
+ struct at91_private *lp = netdev_priv(dev);
unsigned long cfg;
- cfg = at91_emac_read(AT91_EMAC_CFG);
+ cfg = at91_emac_read(lp, AT91_EMAC_CFG);
if (dev->flags & IFF_PROMISC) /* Enable promiscuous mode */
cfg |= AT91_EMAC_CAF;
@@ -589,34 +617,37 @@ static void at91ether_set_multicast_list(struct net_device *dev)
cfg &= ~AT91_EMAC_CAF;
if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */
- at91_emac_write(AT91_EMAC_HSH, -1);
- at91_emac_write(AT91_EMAC_HSL, -1);
+ at91_emac_write(lp, AT91_EMAC_HSH, -1);
+ at91_emac_write(lp, AT91_EMAC_HSL, -1);
cfg |= AT91_EMAC_MTI;
} else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */
at91ether_sethashtable(dev);
cfg |= AT91_EMAC_MTI;
} else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */
- at91_emac_write(AT91_EMAC_HSH, 0);
- at91_emac_write(AT91_EMAC_HSL, 0);
+ at91_emac_write(lp, AT91_EMAC_HSH, 0);
+ at91_emac_write(lp, AT91_EMAC_HSL, 0);
cfg &= ~AT91_EMAC_MTI;
}
- at91_emac_write(AT91_EMAC_CFG, cfg);
+ at91_emac_write(lp, AT91_EMAC_CFG, cfg);
}
/* ......................... ETHTOOL SUPPORT ........................... */
static int mdio_read(struct net_device *dev, int phy_id, int location)
{
+ struct at91_private *lp = netdev_priv(dev);
unsigned int value;
- read_phy(phy_id, location, &value);
+ read_phy(lp, phy_id, location, &value);
return value;
}
static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
{
- write_phy(phy_id, location, value);
+ struct at91_private *lp = netdev_priv(dev);
+
+ write_phy(lp, phy_id, location, value);
}
static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -625,11 +656,11 @@ static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cm
int ret;
spin_lock_irq(&lp->lock);
- enable_mdi();
+ enable_mdi(lp);
ret = mii_ethtool_gset(&lp->mii, cmd);
- disable_mdi();
+ disable_mdi(lp);
spin_unlock_irq(&lp->lock);
if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */
@@ -646,11 +677,11 @@ static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cm
int ret;
spin_lock_irq(&lp->lock);
- enable_mdi();
+ enable_mdi(lp);
ret = mii_ethtool_sset(&lp->mii, cmd);
- disable_mdi();
+ disable_mdi(lp);
spin_unlock_irq(&lp->lock);
return ret;
@@ -662,11 +693,11 @@ static int at91ether_nwayreset(struct net_device *dev)
int ret;
spin_lock_irq(&lp->lock);
- enable_mdi();
+ enable_mdi(lp);
ret = mii_nway_restart(&lp->mii);
- disable_mdi();
+ disable_mdi(lp);
spin_unlock_irq(&lp->lock);
return ret;
@@ -696,9 +727,9 @@ static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return -EINVAL;
spin_lock_irq(&lp->lock);
- enable_mdi();
+ enable_mdi(lp);
res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
- disable_mdi();
+ disable_mdi(lp);
spin_unlock_irq(&lp->lock);
return res;
@@ -731,11 +762,11 @@ static void at91ether_start(struct net_device *dev)
lp->rxBuffIndex = 0;
/* Program address of descriptor list in Rx Buffer Queue register */
- at91_emac_write(AT91_EMAC_RBQP, (unsigned long) dlist_phys);
+ at91_emac_write(lp, AT91_EMAC_RBQP, (unsigned long) dlist_phys);
/* Enable Receive and Transmit */
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+ at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
}
/*
@@ -752,8 +783,8 @@ static int at91ether_open(struct net_device *dev)
clk_enable(lp->ether_clk); /* Re-enable Peripheral clock */
/* Clear internal statistics */
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+ at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
/* Update the MAC address (incase user has changed it) */
update_mac_address(dev);
@@ -762,15 +793,15 @@ static int at91ether_open(struct net_device *dev)
enable_phyirq(dev);
/* Enable MAC interrupts */
- at91_emac_write(AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
+ at91_emac_write(lp, AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
| AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
| AT91_EMAC_ROVR | AT91_EMAC_ABT);
/* Determine current link speed */
spin_lock_irq(&lp->lock);
- enable_mdi();
+ enable_mdi(lp);
update_linkspeed(dev, 0);
- disable_mdi();
+ disable_mdi(lp);
spin_unlock_irq(&lp->lock);
at91ether_start(dev);
@@ -787,14 +818,14 @@ static int at91ether_close(struct net_device *dev)
unsigned long ctl;
/* Disable Receiver and Transmitter */
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+ at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
/* Disable PHY interrupt */
disable_phyirq(dev);
/* Disable MAC interrupts */
- at91_emac_write(AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
+ at91_emac_write(lp, AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
| AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
| AT91_EMAC_ROVR | AT91_EMAC_ABT);
@@ -812,7 +843,7 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct at91_private *lp = netdev_priv(dev);
- if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
+ if (at91_emac_read(lp, AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
netif_stop_queue(dev);
/* Store packet information (to free when Tx completed) */
@@ -822,9 +853,9 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_bytes += skb->len;
/* Set address of the data in the Transmit Address register */
- at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr);
+ at91_emac_write(lp, AT91_EMAC_TAR, lp->skb_physaddr);
/* Set length of the packet in the Transmit Control register */
- at91_emac_write(AT91_EMAC_TCR, skb->len);
+ at91_emac_write(lp, AT91_EMAC_TCR, skb->len);
} else {
printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n");
@@ -841,31 +872,32 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static struct net_device_stats *at91ether_stats(struct net_device *dev)
{
+ struct at91_private *lp = netdev_priv(dev);
int ale, lenerr, seqe, lcol, ecol;
if (netif_running(dev)) {
- dev->stats.rx_packets += at91_emac_read(AT91_EMAC_OK); /* Good frames received */
- ale = at91_emac_read(AT91_EMAC_ALE);
+ dev->stats.rx_packets += at91_emac_read(lp, AT91_EMAC_OK); /* Good frames received */
+ ale = at91_emac_read(lp, AT91_EMAC_ALE);
dev->stats.rx_frame_errors += ale; /* Alignment errors */
- lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF);
+ lenerr = at91_emac_read(lp, AT91_EMAC_ELR) + at91_emac_read(lp, AT91_EMAC_USF);
dev->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
- seqe = at91_emac_read(AT91_EMAC_SEQE);
+ seqe = at91_emac_read(lp, AT91_EMAC_SEQE);
dev->stats.rx_crc_errors += seqe; /* CRC error */
- dev->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC); /* Receive buffer not available */
+ dev->stats.rx_fifo_errors += at91_emac_read(lp, AT91_EMAC_DRFC);/* Receive buffer not available */
dev->stats.rx_errors += (ale + lenerr + seqe
- + at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB));
+ + at91_emac_read(lp, AT91_EMAC_CDE) + at91_emac_read(lp, AT91_EMAC_RJB));
- dev->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA); /* Frames successfully transmitted */
- dev->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE); /* Transmit FIFO underruns */
- dev->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE); /* Carrier Sense errors */
- dev->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
+ dev->stats.tx_packets += at91_emac_read(lp, AT91_EMAC_FRA); /* Frames successfully transmitted */
+ dev->stats.tx_fifo_errors += at91_emac_read(lp, AT91_EMAC_TUE); /* Transmit FIFO underruns */
+ dev->stats.tx_carrier_errors += at91_emac_read(lp, AT91_EMAC_CSE); /* Carrier Sense errors */
+ dev->stats.tx_heartbeat_errors += at91_emac_read(lp, AT91_EMAC_SQEE);/* Heartbeat error */
- lcol = at91_emac_read(AT91_EMAC_LCOL);
- ecol = at91_emac_read(AT91_EMAC_ECOL);
+ lcol = at91_emac_read(lp, AT91_EMAC_LCOL);
+ ecol = at91_emac_read(lp, AT91_EMAC_ECOL);
dev->stats.tx_window_errors += lcol; /* Late collisions */
dev->stats.tx_aborted_errors += ecol; /* 16 collisions */
- dev->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
+ dev->stats.collisions += (at91_emac_read(lp, AT91_EMAC_SCOL) + at91_emac_read(lp, AT91_EMAC_MCOL) + lcol + ecol);
}
return &dev->stats;
}
@@ -922,7 +954,7 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
/* MAC Interrupt Status register indicates what interrupts are pending.
It is automatically cleared once read. */
- intstatus = at91_emac_read(AT91_EMAC_ISR);
+ intstatus = at91_emac_read(lp, AT91_EMAC_ISR);
if (intstatus & AT91_EMAC_RCOM) /* Receive complete */
at91ether_rx(dev);
@@ -942,9 +974,9 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
/* Work-around for Errata #11 */
if (intstatus & AT91_EMAC_RBNA) {
- ctl = at91_emac_read(AT91_EMAC_CTL);
- at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
- at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
+ ctl = at91_emac_read(lp, AT91_EMAC_CTL);
+ at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
+ at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
}
if (intstatus & AT91_EMAC_ROVR)
@@ -980,189 +1012,199 @@ static const struct net_device_ops at91ether_netdev_ops = {
};
/*
- * Initialize the ethernet interface
+ * Detect the PHY type, and its address.
*/
-static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address,
- struct platform_device *pdev, struct clk *ether_clk)
+static int __init at91ether_phy_detect(struct at91_private *lp)
+{
+ unsigned int phyid1, phyid2;
+ unsigned long phy_id;
+ unsigned short phy_address = 0;
+
+ while (phy_address < PHY_MAX_ADDR) {
+ /* Read the PHY ID registers */
+ enable_mdi(lp);
+ read_phy(lp, phy_address, MII_PHYSID1, &phyid1);
+ read_phy(lp, phy_address, MII_PHYSID2, &phyid2);
+ disable_mdi(lp);
+
+ phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
+ switch (phy_id) {
+ case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
+ case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
+ case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
+ case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
+ case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
+ case MII_DP83847_ID: /* National Semiconductor DP83847: */
+ case MII_DP83848_ID: /* National Semiconductor DP83848: */
+ case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
+ case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
+ case MII_T78Q21x3_ID: /* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
+ case MII_LAN83C185_ID: /* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
+ /* store detected values */
+ lp->phy_type = phy_id; /* Type of PHY connected */
+ lp->phy_address = phy_address; /* MDI address of PHY */
+ return 1;
+ }
+
+ phy_address++;
+ }
+
+ return 0; /* not detected */
+}
+
+
+/*
+ * Detect MAC & PHY and perform ethernet interface initialization
+ */
+static int __init at91ether_probe(struct platform_device *pdev)
{
struct macb_platform_data *board_data = pdev->dev.platform_data;
+ struct resource *regs;
struct net_device *dev;
struct at91_private *lp;
- unsigned int val;
int res;
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs)
+ return -ENOENT;
+
dev = alloc_etherdev(sizeof(struct at91_private));
if (!dev)
return -ENOMEM;
- dev->base_addr = AT91_VA_BASE_EMAC;
- dev->irq = AT91RM9200_ID_EMAC;
+ lp = netdev_priv(dev);
+ lp->board_data = *board_data;
+ spin_lock_init(&lp->lock);
+
+ dev->base_addr = regs->start; /* physical base address */
+ lp->emac_base = ioremap(regs->start, regs->end - regs->start + 1);
+ if (!lp->emac_base) {
+ res = -ENOMEM;
+ goto err_free_dev;
+ }
+
+ /* Clock */
+ lp->ether_clk = clk_get(&pdev->dev, "ether_clk");
+ if (IS_ERR(lp->ether_clk)) {
+ res = -ENODEV;
+ goto err_ioumap;
+ }
+ clk_enable(lp->ether_clk);
/* Install the interrupt handler */
+ dev->irq = platform_get_irq(pdev, 0);
if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) {
- free_netdev(dev);
- return -EBUSY;
+ res = -EBUSY;
+ goto err_disable_clock;
}
/* Allocate memory for DMA Receive descriptors */
- lp = netdev_priv(dev);
lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
if (lp->dlist == NULL) {
- free_irq(dev->irq, dev);
- free_netdev(dev);
- return -ENOMEM;
+ res = -ENOMEM;
+ goto err_free_irq;
}
- lp->board_data = *board_data;
- lp->ether_clk = ether_clk;
- platform_set_drvdata(pdev, dev);
-
- spin_lock_init(&lp->lock);
ether_setup(dev);
dev->netdev_ops = &at91ether_netdev_ops;
dev->ethtool_ops = &at91ether_ethtool_ops;
-
+ platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */
update_mac_address(dev); /* Program ethernet address into MAC */
- at91_emac_write(AT91_EMAC_CTL, 0);
+ at91_emac_write(lp, AT91_EMAC_CTL, 0);
- if (lp->board_data.is_rmii)
- at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
+ if (board_data->is_rmii)
+ at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
else
- at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
+ at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
- /* Perform PHY-specific initialization */
- spin_lock_irq(&lp->lock);
- enable_mdi();
- if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
- read_phy(phy_address, MII_DSCR_REG, &val);
- if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */
- lp->phy_media = PORT_FIBRE;
- } else if (machine_is_csb337()) {
- /* mix link activity status into LED2 link state */
- write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22);
- } else if (machine_is_ecbat91())
- write_phy(phy_address, MII_LEDCTRL_REG, 0x156A);
+ /* Detect PHY */
+ if (!at91ether_phy_detect(lp)) {
+ printk(KERN_ERR "at91_ether: Could not detect ethernet PHY\n");
+ res = -ENODEV;
+ goto err_free_dmamem;
+ }
- disable_mdi();
- spin_unlock_irq(&lp->lock);
+ initialize_phy(lp);
lp->mii.dev = dev; /* Support for ethtool */
lp->mii.mdio_read = mdio_read;
lp->mii.mdio_write = mdio_write;
- lp->mii.phy_id = phy_address;
+ lp->mii.phy_id = lp->phy_address;
lp->mii.phy_id_mask = 0x1f;
lp->mii.reg_num_mask = 0x1f;
- lp->phy_type = phy_type; /* Type of PHY connected */
- lp->phy_address = phy_address; /* MDI address of PHY */
-
/* Register the network interface */
res = register_netdev(dev);
- if (res) {
- free_irq(dev->irq, dev);
- free_netdev(dev);
- dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
- return res;
- }
+ if (res)
+ goto err_free_dmamem;
/* Determine current link speed */
spin_lock_irq(&lp->lock);
- enable_mdi();
+ enable_mdi(lp);
update_linkspeed(dev, 0);
- disable_mdi();
+ disable_mdi(lp);
spin_unlock_irq(&lp->lock);
netif_carrier_off(dev); /* will be enabled in open() */
/* If board has no PHY IRQ, use a timer to poll the PHY */
- if (!gpio_is_valid(lp->board_data.phy_irq_pin)) {
+ if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
+ gpio_request(board_data->phy_irq_pin, "ethernet_phy");
+ } else {
+ /* If board has no PHY IRQ, use a timer to poll the PHY */
init_timer(&lp->check_timer);
lp->check_timer.data = (unsigned long)dev;
lp->check_timer.function = at91ether_check_link;
- } else if (lp->board_data.phy_irq_pin >= 32)
- gpio_request(lp->board_data.phy_irq_pin, "ethernet_phy");
+ }
/* Display ethernet banner */
printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n",
dev->name, (uint) dev->base_addr, dev->irq,
- at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
- at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
+ at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
+ at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
dev->dev_addr);
- if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
+ if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
- else if (phy_type == MII_LXT971A_ID)
+ else if (lp->phy_type == MII_LXT971A_ID)
printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
- else if (phy_type == MII_RTL8201_ID)
+ else if (lp->phy_type == MII_RTL8201_ID)
printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name);
- else if (phy_type == MII_BCM5221_ID)
+ else if (lp->phy_type == MII_BCM5221_ID)
printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
- else if (phy_type == MII_DP83847_ID)
+ else if (lp->phy_type == MII_DP83847_ID)
printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name);
- else if (phy_type == MII_DP83848_ID)
+ else if (lp->phy_type == MII_DP83848_ID)
printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name);
- else if (phy_type == MII_AC101L_ID)
+ else if (lp->phy_type == MII_AC101L_ID)
printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
- else if (phy_type == MII_KS8721_ID)
+ else if (lp->phy_type == MII_KS8721_ID)
printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
- else if (phy_type == MII_T78Q21x3_ID)
+ else if (lp->phy_type == MII_T78Q21x3_ID)
printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name);
- else if (phy_type == MII_LAN83C185_ID)
+ else if (lp->phy_type == MII_LAN83C185_ID)
printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name);
- return 0;
-}
-
-/*
- * Detect MAC and PHY and perform initialization
- */
-static int __init at91ether_probe(struct platform_device *pdev)
-{
- unsigned int phyid1, phyid2;
- int detected = -1;
- unsigned long phy_id;
- unsigned short phy_address = 0;
- struct clk *ether_clk;
-
- ether_clk = clk_get(&pdev->dev, "ether_clk");
- if (IS_ERR(ether_clk)) {
- printk(KERN_ERR "at91_ether: no clock defined\n");
- return -ENODEV;
- }
- clk_enable(ether_clk); /* Enable Peripheral clock */
-
- while ((detected != 0) && (phy_address < 32)) {
- /* Read the PHY ID registers */
- enable_mdi();
- read_phy(phy_address, MII_PHYSID1, &phyid1);
- read_phy(phy_address, MII_PHYSID2, &phyid2);
- disable_mdi();
-
- phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
- switch (phy_id) {
- case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
- case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
- case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
- case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
- case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
- case MII_DP83847_ID: /* National Semiconductor DP83847: */
- case MII_DP83848_ID: /* National Semiconductor DP83848: */
- case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
- case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
- case MII_T78Q21x3_ID: /* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
- case MII_LAN83C185_ID: /* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
- detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk);
- break;
- }
+ clk_disable(lp->ether_clk); /* Disable Peripheral clock */
- phy_address++;
- }
+ return 0;
- clk_disable(ether_clk); /* Disable Peripheral clock */
- return detected;
+err_free_dmamem:
+ platform_set_drvdata(pdev, NULL);
+ dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
+err_free_irq:
+ free_irq(dev->irq, dev);
+err_disable_clock:
+ clk_disable(lp->ether_clk);
+ clk_put(lp->ether_clk);
+err_ioumap:
+ iounmap(lp->emac_base);
+err_free_dev:
+ free_netdev(dev);
+ return res;
}
static int __devexit at91ether_remove(struct platform_device *pdev)
@@ -1170,8 +1212,7 @@ static int __devexit at91ether_remove(struct platform_device *pdev)
struct net_device *dev = platform_get_drvdata(pdev);
struct at91_private *lp = netdev_priv(dev);
- if (gpio_is_valid(lp->board_data.phy_irq_pin) &&
- lp->board_data.phy_irq_pin >= 32)
+ if (gpio_is_valid(lp->board_data.phy_irq_pin))
gpio_free(lp->board_data.phy_irq_pin);
unregister_netdev(dev);
@@ -1193,7 +1234,7 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
if (netif_running(net_dev)) {
if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
- int phy_irq = lp->board_data.phy_irq_pin;
+ int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
disable_irq(phy_irq);
}
@@ -1217,7 +1258,7 @@ static int at91ether_resume(struct platform_device *pdev)
netif_start_queue(net_dev);
if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
- int phy_irq = lp->board_data.phy_irq_pin;
+ int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
enable_irq(phy_irq);
}
}
diff --git a/drivers/net/ethernet/cadence/at91_ether.h b/drivers/net/ethernet/cadence/at91_ether.h
index 3725fbb0defe..0ef6328fa7f8 100644
--- a/drivers/net/ethernet/cadence/at91_ether.h
+++ b/drivers/net/ethernet/cadence/at91_ether.h
@@ -88,6 +88,7 @@ struct at91_private
struct macb_platform_data board_data; /* board-specific
* configuration (shared with
* macb for common data */
+ void __iomem *emac_base; /* base register address */
struct clk *ether_clk; /* clock */
/* PHY */
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index c4834c23be35..1466bc4e3dda 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -1213,6 +1213,7 @@ static const struct ethtool_ops macb_ethtool_ops = {
.set_settings = macb_set_settings,
.get_drvinfo = macb_get_drvinfo,
.get_link = ethtool_op_get_link,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 0fe18850c838..ec2dafe8ae5b 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -51,6 +51,8 @@
#define FW_VERSION_MINOR 1
#define FW_VERSION_MICRO 0
+#define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
+
enum {
MAX_NPORTS = 4, /* max # of ports */
SERNUM_LEN = 24, /* Serial # length */
@@ -64,6 +66,15 @@ enum {
MEM_MC
};
+enum {
+ MEMWIN0_APERTURE = 65536,
+ MEMWIN0_BASE = 0x30000,
+ MEMWIN1_APERTURE = 32768,
+ MEMWIN1_BASE = 0x28000,
+ MEMWIN2_APERTURE = 2048,
+ MEMWIN2_BASE = 0x1b800,
+};
+
enum dev_master {
MASTER_CANT,
MASTER_MAY,
@@ -403,6 +414,9 @@ struct sge_txq {
struct tx_sw_desc *sdesc; /* address of SW Tx descriptor ring */
struct sge_qstat *stat; /* queue status entry */
dma_addr_t phys_addr; /* physical address of the ring */
+ spinlock_t db_lock;
+ int db_disabled;
+ unsigned short db_pidx;
};
struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */
@@ -475,6 +489,7 @@ struct adapter {
void __iomem *regs;
struct pci_dev *pdev;
struct device *pdev_dev;
+ unsigned int mbox;
unsigned int fn;
unsigned int flags;
@@ -504,6 +519,8 @@ struct adapter {
void **tid_release_head;
spinlock_t tid_release_lock;
struct work_struct tid_release_task;
+ struct work_struct db_full_task;
+ struct work_struct db_drop_task;
bool tid_release_task_busy;
struct dentry *debugfs_root;
@@ -605,6 +622,7 @@ irqreturn_t t4_sge_intr_msix(int irq, void *cookie);
void t4_sge_init(struct adapter *adap);
void t4_sge_start(struct adapter *adap);
void t4_sge_stop(struct adapter *adap);
+extern int dbfifo_int_thresh;
#define for_each_port(adapter, iter) \
for (iter = 0; iter < (adapter)->params.nports; ++iter)
@@ -719,4 +737,9 @@ int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int eqid);
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
+void t4_db_full(struct adapter *adapter);
+void t4_db_dropped(struct adapter *adapter);
+int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len);
+int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
+ u32 addr, u32 val);
#endif /* __CXGB4_H__ */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index b126b98065a9..e1f96fbb48c1 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -149,15 +149,6 @@ static unsigned int pfvfres_pmask(struct adapter *adapter,
#endif
enum {
- MEMWIN0_APERTURE = 65536,
- MEMWIN0_BASE = 0x30000,
- MEMWIN1_APERTURE = 32768,
- MEMWIN1_BASE = 0x28000,
- MEMWIN2_APERTURE = 2048,
- MEMWIN2_BASE = 0x1b800,
-};
-
-enum {
MAX_TXQ_ENTRIES = 16384,
MAX_CTRL_TXQ_ENTRIES = 1024,
MAX_RSPQ_ENTRIES = 16384,
@@ -371,6 +362,15 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
uhash | mhash, sleep);
}
+int dbfifo_int_thresh = 10; /* 10 == 640 entry threshold */
+module_param(dbfifo_int_thresh, int, 0644);
+MODULE_PARM_DESC(dbfifo_int_thresh, "doorbell fifo interrupt threshold");
+
+int dbfifo_drain_delay = 1000; /* usecs to sleep while draining the dbfifo */
+module_param(dbfifo_drain_delay, int, 0644);
+MODULE_PARM_DESC(dbfifo_drain_delay,
+ "usecs to sleep while draining the dbfifo");
+
/*
* Set Rx properties of a port, such as promiscruity, address filters, and MTU.
* If @mtu is -1 it is left unchanged.
@@ -389,6 +389,8 @@ static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok)
return ret;
}
+static struct workqueue_struct *workq;
+
/**
* link_start - enable a port
* @dev: the port to enable
@@ -2196,7 +2198,7 @@ static void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
adap->tid_release_head = (void **)((uintptr_t)p | chan);
if (!adap->tid_release_task_busy) {
adap->tid_release_task_busy = true;
- schedule_work(&adap->tid_release_task);
+ queue_work(workq, &adap->tid_release_task);
}
spin_unlock_bh(&adap->tid_release_lock);
}
@@ -2366,6 +2368,16 @@ unsigned int cxgb4_port_chan(const struct net_device *dev)
}
EXPORT_SYMBOL(cxgb4_port_chan);
+unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
+{
+ struct adapter *adap = netdev2adap(dev);
+ u32 v;
+
+ v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
+ return lpfifo ? G_LP_COUNT(v) : G_HP_COUNT(v);
+}
+EXPORT_SYMBOL(cxgb4_dbfifo_count);
+
/**
* cxgb4_port_viid - get the VI id of a port
* @dev: the net device for the port
@@ -2413,6 +2425,59 @@ void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask,
}
EXPORT_SYMBOL(cxgb4_iscsi_init);
+int cxgb4_flush_eq_cache(struct net_device *dev)
+{
+ struct adapter *adap = netdev2adap(dev);
+ int ret;
+
+ ret = t4_fwaddrspace_write(adap, adap->mbox,
+ 0xe1000000 + A_SGE_CTXT_CMD, 0x20000000);
+ return ret;
+}
+EXPORT_SYMBOL(cxgb4_flush_eq_cache);
+
+static int read_eq_indices(struct adapter *adap, u16 qid, u16 *pidx, u16 *cidx)
+{
+ u32 addr = t4_read_reg(adap, A_SGE_DBQ_CTXT_BADDR) + 24 * qid + 8;
+ __be64 indices;
+ int ret;
+
+ ret = t4_mem_win_read_len(adap, addr, (__be32 *)&indices, 8);
+ if (!ret) {
+ indices = be64_to_cpu(indices);
+ *cidx = (indices >> 25) & 0xffff;
+ *pidx = (indices >> 9) & 0xffff;
+ }
+ return ret;
+}
+
+int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx,
+ u16 size)
+{
+ struct adapter *adap = netdev2adap(dev);
+ u16 hw_pidx, hw_cidx;
+ int ret;
+
+ ret = read_eq_indices(adap, qid, &hw_pidx, &hw_cidx);
+ if (ret)
+ goto out;
+
+ if (pidx != hw_pidx) {
+ u16 delta;
+
+ if (pidx >= hw_pidx)
+ delta = pidx - hw_pidx;
+ else
+ delta = size - hw_pidx + pidx;
+ wmb();
+ t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL),
+ V_QID(qid) | V_PIDX(delta));
+ }
+out:
+ return ret;
+}
+EXPORT_SYMBOL(cxgb4_sync_txq_pidx);
+
static struct pci_driver cxgb4_driver;
static void check_neigh_update(struct neighbour *neigh)
@@ -2446,6 +2511,144 @@ static struct notifier_block cxgb4_netevent_nb = {
.notifier_call = netevent_cb
};
+static void drain_db_fifo(struct adapter *adap, int usecs)
+{
+ u32 v;
+
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies(usecs));
+ v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
+ if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0)
+ break;
+ } while (1);
+}
+
+static void disable_txq_db(struct sge_txq *q)
+{
+ spin_lock_irq(&q->db_lock);
+ q->db_disabled = 1;
+ spin_unlock_irq(&q->db_lock);
+}
+
+static void enable_txq_db(struct sge_txq *q)
+{
+ spin_lock_irq(&q->db_lock);
+ q->db_disabled = 0;
+ spin_unlock_irq(&q->db_lock);
+}
+
+static void disable_dbs(struct adapter *adap)
+{
+ int i;
+
+ for_each_ethrxq(&adap->sge, i)
+ disable_txq_db(&adap->sge.ethtxq[i].q);
+ for_each_ofldrxq(&adap->sge, i)
+ disable_txq_db(&adap->sge.ofldtxq[i].q);
+ for_each_port(adap, i)
+ disable_txq_db(&adap->sge.ctrlq[i].q);
+}
+
+static void enable_dbs(struct adapter *adap)
+{
+ int i;
+
+ for_each_ethrxq(&adap->sge, i)
+ enable_txq_db(&adap->sge.ethtxq[i].q);
+ for_each_ofldrxq(&adap->sge, i)
+ enable_txq_db(&adap->sge.ofldtxq[i].q);
+ for_each_port(adap, i)
+ enable_txq_db(&adap->sge.ctrlq[i].q);
+}
+
+static void sync_txq_pidx(struct adapter *adap, struct sge_txq *q)
+{
+ u16 hw_pidx, hw_cidx;
+ int ret;
+
+ spin_lock_bh(&q->db_lock);
+ ret = read_eq_indices(adap, (u16)q->cntxt_id, &hw_pidx, &hw_cidx);
+ if (ret)
+ goto out;
+ if (q->db_pidx != hw_pidx) {
+ u16 delta;
+
+ if (q->db_pidx >= hw_pidx)
+ delta = q->db_pidx - hw_pidx;
+ else
+ delta = q->size - hw_pidx + q->db_pidx;
+ wmb();
+ t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL),
+ V_QID(q->cntxt_id) | V_PIDX(delta));
+ }
+out:
+ q->db_disabled = 0;
+ spin_unlock_bh(&q->db_lock);
+ if (ret)
+ CH_WARN(adap, "DB drop recovery failed.\n");
+}
+static void recover_all_queues(struct adapter *adap)
+{
+ int i;
+
+ for_each_ethrxq(&adap->sge, i)
+ sync_txq_pidx(adap, &adap->sge.ethtxq[i].q);
+ for_each_ofldrxq(&adap->sge, i)
+ sync_txq_pidx(adap, &adap->sge.ofldtxq[i].q);
+ for_each_port(adap, i)
+ sync_txq_pidx(adap, &adap->sge.ctrlq[i].q);
+}
+
+static void notify_rdma_uld(struct adapter *adap, enum cxgb4_control cmd)
+{
+ mutex_lock(&uld_mutex);
+ if (adap->uld_handle[CXGB4_ULD_RDMA])
+ ulds[CXGB4_ULD_RDMA].control(adap->uld_handle[CXGB4_ULD_RDMA],
+ cmd);
+ mutex_unlock(&uld_mutex);
+}
+
+static void process_db_full(struct work_struct *work)
+{
+ struct adapter *adap;
+
+ adap = container_of(work, struct adapter, db_full_task);
+
+ notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL);
+ drain_db_fifo(adap, dbfifo_drain_delay);
+ t4_set_reg_field(adap, A_SGE_INT_ENABLE3,
+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT,
+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT);
+ notify_rdma_uld(adap, CXGB4_CONTROL_DB_EMPTY);
+}
+
+static void process_db_drop(struct work_struct *work)
+{
+ struct adapter *adap;
+
+ adap = container_of(work, struct adapter, db_drop_task);
+
+ t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_DROPPED_DB, 0);
+ disable_dbs(adap);
+ notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
+ drain_db_fifo(adap, 1);
+ recover_all_queues(adap);
+ enable_dbs(adap);
+}
+
+void t4_db_full(struct adapter *adap)
+{
+ t4_set_reg_field(adap, A_SGE_INT_ENABLE3,
+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT, 0);
+ queue_work(workq, &adap->db_full_task);
+}
+
+void t4_db_dropped(struct adapter *adap)
+{
+ queue_work(workq, &adap->db_drop_task);
+}
+
static void uld_attach(struct adapter *adap, unsigned int uld)
{
void *handle;
@@ -2479,6 +2682,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS);
lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL);
lli.fw_vers = adap->params.fw_vers;
+ lli.dbfifo_int_thresh = dbfifo_int_thresh;
handle = ulds[uld].add(&lli);
if (IS_ERR(handle)) {
@@ -2649,6 +2853,8 @@ static void cxgb_down(struct adapter *adapter)
{
t4_intr_disable(adapter);
cancel_work_sync(&adapter->tid_release_task);
+ cancel_work_sync(&adapter->db_full_task);
+ cancel_work_sync(&adapter->db_drop_task);
adapter->tid_release_task_busy = false;
adapter->tid_release_head = NULL;
@@ -3593,6 +3799,7 @@ static int __devinit init_one(struct pci_dev *pdev,
adapter->pdev = pdev;
adapter->pdev_dev = &pdev->dev;
+ adapter->mbox = func;
adapter->fn = func;
adapter->msg_enable = dflt_msg_enable;
memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map));
@@ -3601,6 +3808,8 @@ static int __devinit init_one(struct pci_dev *pdev,
spin_lock_init(&adapter->tid_release_lock);
INIT_WORK(&adapter->tid_release_task, process_tid_release_list);
+ INIT_WORK(&adapter->db_full_task, process_db_full);
+ INIT_WORK(&adapter->db_drop_task, process_db_drop);
err = t4_prep_adapter(adapter);
if (err)
@@ -3788,6 +3997,10 @@ static int __init cxgb4_init_module(void)
{
int ret;
+ workq = create_singlethread_workqueue("cxgb4");
+ if (!workq)
+ return -ENOMEM;
+
/* Debugfs support is optional, just warn if this fails */
cxgb4_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
if (!cxgb4_debugfs_root)
@@ -3803,6 +4016,8 @@ static void __exit cxgb4_cleanup_module(void)
{
pci_unregister_driver(&cxgb4_driver);
debugfs_remove(cxgb4_debugfs_root); /* NULL ok */
+ flush_workqueue(workq);
+ destroy_workqueue(workq);
}
module_init(cxgb4_init_module);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index b1d39b8d141a..d79980c5fc63 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -163,6 +163,12 @@ enum cxgb4_state {
CXGB4_STATE_DETACH
};
+enum cxgb4_control {
+ CXGB4_CONTROL_DB_FULL,
+ CXGB4_CONTROL_DB_EMPTY,
+ CXGB4_CONTROL_DB_DROP,
+};
+
struct pci_dev;
struct l2t_data;
struct net_device;
@@ -212,6 +218,7 @@ struct cxgb4_lld_info {
unsigned short ucq_density; /* # of user CQs/page */
void __iomem *gts_reg; /* address of GTS register */
void __iomem *db_reg; /* address of kernel doorbell */
+ int dbfifo_int_thresh; /* doorbell fifo int threshold */
};
struct cxgb4_uld_info {
@@ -220,11 +227,13 @@ struct cxgb4_uld_info {
int (*rx_handler)(void *handle, const __be64 *rsp,
const struct pkt_gl *gl);
int (*state_change)(void *handle, enum cxgb4_state new_state);
+ int (*control)(void *handle, enum cxgb4_control control, ...);
};
int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
int cxgb4_unregister_uld(enum cxgb4_uld type);
int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb);
+unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo);
unsigned int cxgb4_port_chan(const struct net_device *dev);
unsigned int cxgb4_port_viid(const struct net_device *dev);
unsigned int cxgb4_port_idx(const struct net_device *dev);
@@ -236,4 +245,6 @@ void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask,
const unsigned int *pgsz_order);
struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl,
unsigned int skb_len, unsigned int pull_len);
+int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx, u16 size);
+int cxgb4_flush_eq_cache(struct net_device *dev);
#endif /* !__CXGB4_OFLD_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 2dae7959f000..e111d974afd8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -767,8 +767,13 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *q,
static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
{
wmb(); /* write descriptors before telling HW */
- t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL),
- QID(q->cntxt_id) | PIDX(n));
+ spin_lock(&q->db_lock);
+ if (!q->db_disabled) {
+ t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL),
+ V_QID(q->cntxt_id) | V_PIDX(n));
+ }
+ q->db_pidx = q->pidx;
+ spin_unlock(&q->db_lock);
}
/**
@@ -2081,6 +2086,7 @@ static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
q->stops = q->restarts = 0;
q->stat = (void *)&q->desc[q->size];
q->cntxt_id = id;
+ spin_lock_init(&q->db_lock);
adap->sge.egr_map[id - adap->sge.egr_start] = q;
}
@@ -2415,6 +2421,18 @@ void t4_sge_init(struct adapter *adap)
RXPKTCPLMODE |
(STAT_LEN == 128 ? EGRSTATUSPAGESIZE : 0));
+ /*
+ * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows
+ * and generate an interrupt when this occurs so we can recover.
+ */
+ t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
+ V_HP_INT_THRESH(M_HP_INT_THRESH) |
+ V_LP_INT_THRESH(M_LP_INT_THRESH),
+ V_HP_INT_THRESH(dbfifo_int_thresh) |
+ V_LP_INT_THRESH(dbfifo_int_thresh));
+ t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_ENABLE_DROP,
+ F_ENABLE_DROP);
+
for (i = v = 0; i < 32; i += 4)
v |= (PAGE_SHIFT - 10) << i;
t4_write_reg(adap, SGE_HOST_PAGE_SIZE, v);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index d1ec111aebd8..32e1dd566a14 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -868,11 +868,14 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port)
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
+typedef void (*int_handler_t)(struct adapter *adap);
+
struct intr_info {
unsigned int mask; /* bits to check in interrupt status */
const char *msg; /* message to print or NULL */
short stat_idx; /* stat counter to increment or -1 */
unsigned short fatal; /* whether the condition reported is fatal */
+ int_handler_t int_handler; /* platform-specific int handler */
};
/**
@@ -905,6 +908,8 @@ static int t4_handle_intr_status(struct adapter *adapter, unsigned int reg,
} else if (acts->msg && printk_ratelimit())
dev_warn(adapter->pdev_dev, "%s (0x%x)\n", acts->msg,
status & acts->mask);
+ if (acts->int_handler)
+ acts->int_handler(adapter);
mask |= acts->mask;
}
status &= mask;
@@ -1013,7 +1018,9 @@ static void sge_intr_handler(struct adapter *adapter)
{ ERR_INVALID_CIDX_INC,
"SGE GTS CIDX increment too large", -1, 0 },
{ ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
- { ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 },
+ { F_DBFIFO_LP_INT, NULL, -1, 0, t4_db_full },
+ { F_DBFIFO_HP_INT, NULL, -1, 0, t4_db_full },
+ { F_ERR_DROPPED_DB, NULL, -1, 0, t4_db_dropped },
{ ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0,
"SGE IQID > 1023 received CPL for FL", -1, 0 },
{ ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1,
@@ -1034,10 +1041,10 @@ static void sge_intr_handler(struct adapter *adapter)
};
v = (u64)t4_read_reg(adapter, SGE_INT_CAUSE1) |
- ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32);
+ ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32);
if (v) {
dev_alert(adapter->pdev_dev, "SGE parity error (%#llx)\n",
- (unsigned long long)v);
+ (unsigned long long)v);
t4_write_reg(adapter, SGE_INT_CAUSE1, v);
t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32);
}
@@ -1513,6 +1520,7 @@ void t4_intr_enable(struct adapter *adapter)
ERR_BAD_DB_PIDX2 | ERR_BAD_DB_PIDX1 |
ERR_BAD_DB_PIDX0 | ERR_ING_CTXT_PRIO |
ERR_EGR_CTXT_PRIO | INGRESS_SIZE_ERR |
+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT |
EGRESS_SIZE_ERR);
t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE), PF_INTR_MASK);
t4_set_reg_field(adapter, PL_INT_MAP0, 0, 1 << pf);
@@ -1986,6 +1994,54 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
(var).retval_len16 = htonl(FW_LEN16(var)); \
} while (0)
+int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
+ u32 addr, u32 val)
+{
+ struct fw_ldst_cmd c;
+
+ memset(&c, 0, sizeof(c));
+ c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE |
+ V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE));
+ c.cycles_to_len16 = htonl(FW_LEN16(c));
+ c.u.addrval.addr = htonl(addr);
+ c.u.addrval.val = htonl(val);
+
+ return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
+}
+
+/*
+ * t4_mem_win_read_len - read memory through PCIE memory window
+ * @adap: the adapter
+ * @addr: address of first byte requested aligned on 32b.
+ * @data: len bytes to hold the data read
+ * @len: amount of data to read from window. Must be <=
+ * MEMWIN0_APERATURE after adjusting for 16B alignment
+ * requirements of the the memory window.
+ *
+ * Read len bytes of data from MC starting at @addr.
+ */
+int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
+{
+ int i;
+ int off;
+
+ /*
+ * Align on a 16B boundary.
+ */
+ off = addr & 15;
+ if ((addr & 3) || (len + off) > MEMWIN0_APERTURE)
+ return -EINVAL;
+
+ t4_write_reg(adap, A_PCIE_MEM_ACCESS_OFFSET, addr & ~15);
+ t4_read_reg(adap, A_PCIE_MEM_ACCESS_OFFSET);
+
+ for (i = 0; i < len; i += 4)
+ *data++ = t4_read_reg(adap, (MEMWIN0_BASE + off + i));
+
+ return 0;
+}
+
/**
* t4_mdio_rd - read a PHY register through MDIO
* @adap: the adapter
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 0adc5bcec7c4..111fc323f155 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -190,6 +190,59 @@
#define SGE_DEBUG_DATA_LOW 0x10d4
#define SGE_INGRESS_QUEUES_PER_PAGE_PF 0x10f4
+#define S_LP_INT_THRESH 12
+#define V_LP_INT_THRESH(x) ((x) << S_LP_INT_THRESH)
+#define S_HP_INT_THRESH 28
+#define V_HP_INT_THRESH(x) ((x) << S_HP_INT_THRESH)
+#define A_SGE_DBFIFO_STATUS 0x10a4
+
+#define S_ENABLE_DROP 13
+#define V_ENABLE_DROP(x) ((x) << S_ENABLE_DROP)
+#define F_ENABLE_DROP V_ENABLE_DROP(1U)
+#define A_SGE_DOORBELL_CONTROL 0x10a8
+
+#define A_SGE_CTXT_CMD 0x11fc
+#define A_SGE_DBQ_CTXT_BADDR 0x1084
+
+#define A_SGE_PF_KDOORBELL 0x0
+
+#define S_QID 15
+#define V_QID(x) ((x) << S_QID)
+
+#define S_PIDX 0
+#define V_PIDX(x) ((x) << S_PIDX)
+
+#define M_LP_COUNT 0x7ffU
+#define S_LP_COUNT 0
+#define G_LP_COUNT(x) (((x) >> S_LP_COUNT) & M_LP_COUNT)
+
+#define M_HP_COUNT 0x7ffU
+#define S_HP_COUNT 16
+#define G_HP_COUNT(x) (((x) >> S_HP_COUNT) & M_HP_COUNT)
+
+#define A_SGE_INT_ENABLE3 0x1040
+
+#define S_DBFIFO_HP_INT 8
+#define V_DBFIFO_HP_INT(x) ((x) << S_DBFIFO_HP_INT)
+#define F_DBFIFO_HP_INT V_DBFIFO_HP_INT(1U)
+
+#define S_DBFIFO_LP_INT 7
+#define V_DBFIFO_LP_INT(x) ((x) << S_DBFIFO_LP_INT)
+#define F_DBFIFO_LP_INT V_DBFIFO_LP_INT(1U)
+
+#define S_DROPPED_DB 0
+#define V_DROPPED_DB(x) ((x) << S_DROPPED_DB)
+#define F_DROPPED_DB V_DROPPED_DB(1U)
+
+#define S_ERR_DROPPED_DB 18
+#define V_ERR_DROPPED_DB(x) ((x) << S_ERR_DROPPED_DB)
+#define F_ERR_DROPPED_DB V_ERR_DROPPED_DB(1U)
+
+#define A_PCIE_MEM_ACCESS_OFFSET 0x306c
+
+#define M_HP_INT_THRESH 0xfU
+#define M_LP_INT_THRESH 0xfU
+
#define PCIE_PF_CLI 0x44
#define PCIE_INT_CAUSE 0x3004
#define UNXSPLCPLERR 0x20000000U
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index edcfd7ec7802..ad53f796b574 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -1620,4 +1620,19 @@ struct fw_hdr {
#define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff)
#define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff)
#define FW_HDR_FW_VER_BUILD_GET(x) (((x) >> 0) & 0xff)
+
+#define S_FW_CMD_OP 24
+#define V_FW_CMD_OP(x) ((x) << S_FW_CMD_OP)
+
+#define S_FW_CMD_REQUEST 23
+#define V_FW_CMD_REQUEST(x) ((x) << S_FW_CMD_REQUEST)
+#define F_FW_CMD_REQUEST V_FW_CMD_REQUEST(1U)
+
+#define S_FW_CMD_WRITE 21
+#define V_FW_CMD_WRITE(x) ((x) << S_FW_CMD_WRITE)
+#define F_FW_CMD_WRITE V_FW_CMD_WRITE(1U)
+
+#define S_FW_LDST_CMD_ADDRSPACE 0
+#define V_FW_LDST_CMD_ADDRSPACE(x) ((x) << S_FW_LDST_CMD_ADDRSPACE)
+
#endif /* _T4FW_INTERFACE_H_ */
diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c
index b9406cbfc180..845b2020f291 100644
--- a/drivers/net/ethernet/cirrus/cs89x0.c
+++ b/drivers/net/ethernet/cirrus/cs89x0.c
@@ -1,105 +1,27 @@
/* cs89x0.c: A Crystal Semiconductor (Now Cirrus Logic) CS89[02]0
- * driver for linux.
+ * driver for linux.
+ * Written 1996 by Russell Nelson, with reference to skeleton.c
+ * written 1993-1994 by Donald Becker.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * The author may be reached at nelson@crynwr.com, Crynwr
+ * Software, 521 Pleasant Valley Rd., Potsdam, NY 13676
+ *
+ * Other contributors:
+ * Mike Cruse : mcruse@cti-ltd.com
+ * Russ Nelson
+ * Melody Lee : ethernet@crystal.cirrus.com
+ * Alan Cox
+ * Andrew Morton
+ * Oskar Schirmer : oskar@scara.com
+ * Deepak Saxena : dsaxena@plexity.net
+ * Dmitry Pervushin : dpervushin@ru.mvista.com
+ * Deepak Saxena : dsaxena@plexity.net
+ * Domenico Andreoli : cavokz@gmail.com
*/
-/*
- Written 1996 by Russell Nelson, with reference to skeleton.c
- written 1993-1994 by Donald Becker.
-
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
- The author may be reached at nelson@crynwr.com, Crynwr
- Software, 521 Pleasant Valley Rd., Potsdam, NY 13676
-
- Changelog:
-
- Mike Cruse : mcruse@cti-ltd.com
- : Changes for Linux 2.0 compatibility.
- : Added dev_id parameter in net_interrupt(),
- : request_irq() and free_irq(). Just NULL for now.
-
- Mike Cruse : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros
- : in net_open() and net_close() so kerneld would know
- : that the module is in use and wouldn't eject the
- : driver prematurely.
-
- Mike Cruse : Rewrote init_module() and cleanup_module using 8390.c
- : as an example. Disabled autoprobing in init_module(),
- : not a good thing to do to other devices while Linux
- : is running from all accounts.
-
- Russ Nelson : Jul 13 1998. Added RxOnly DMA support.
-
- Melody Lee : Aug 10 1999. Changes for Linux 2.2.5 compatibility.
- : email: ethernet@crystal.cirrus.com
-
- Alan Cox : Removed 1.2 support, added 2.1 extra counters.
-
- Andrew Morton : Kernel 2.3.48
- : Handle kmalloc() failures
- : Other resource allocation fixes
- : Add SMP locks
- : Integrate Russ Nelson's ALLOW_DMA functionality back in.
- : If ALLOW_DMA is true, make DMA runtime selectable
- : Folded in changes from Cirrus (Melody Lee
- : <klee@crystal.cirrus.com>)
- : Don't call netif_wake_queue() in net_send_packet()
- : Fixed an out-of-mem bug in dma_rx()
- : Updated Documentation/networking/cs89x0.txt
-
- Andrew Morton : Kernel 2.3.99-pre1
- : Use skb_reserve to longword align IP header (two places)
- : Remove a delay loop from dma_rx()
- : Replace '100' with HZ
- : Clean up a couple of skb API abuses
- : Added 'cs89x0_dma=N' kernel boot option
- : Correctly initialise lp->lock in non-module compile
-
- Andrew Morton : Kernel 2.3.99-pre4-1
- : MOD_INC/DEC race fix (see
- : http://www.uwsg.indiana.edu/hypermail/linux/kernel/0003.3/1532.html)
-
- Andrew Morton : Kernel 2.4.0-test7-pre2
- : Enhanced EEPROM support to cover more devices,
- : abstracted IRQ mapping to support CONFIG_ARCH_CLPS7500 arch
- : (Jason Gunthorpe <jgg@ualberta.ca>)
-
- Andrew Morton : Kernel 2.4.0-test11-pre4
- : Use dev->name in request_*() (Andrey Panin)
- : Fix an error-path memleak in init_module()
- : Preserve return value from request_irq()
- : Fix type of `media' module parm (Keith Owens)
- : Use SET_MODULE_OWNER()
- : Tidied up strange request_irq() abuse in net_open().
-
- Andrew Morton : Kernel 2.4.3-pre1
- : Request correct number of pages for DMA (Hugh Dickens)
- : Select PP_ChipID _after_ unregister_netdev in cleanup_module()
- : because unregister_netdev() calls get_stats.
- : Make `version[]' __initdata
- : Uninlined the read/write reg/word functions.
-
- Oskar Schirmer : oskar@scara.com
- : HiCO.SH4 (superh) support added (irq#1, cs89x0_media=)
-
- Deepak Saxena : dsaxena@plexity.net
- : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support
-
- Dmitry Pervushin : dpervushin@ru.mvista.com
- : PNX010X platform support
-
- Deepak Saxena : dsaxena@plexity.net
- : Intel IXDP2351 platform support
-
- Dmitry Pervushin : dpervushin@ru.mvista.com
- : PNX010X platform support
-
- Domenico Andreoli : cavokz@gmail.com
- : QQ2440 platform support
-
-*/
-
/*
* Set this to zero to disable DMA code
@@ -119,14 +41,12 @@
*/
#define DEBUGGING 1
-/*
- Sources:
-
- Crynwr packet driver epktisa.
-
- Crystal Semiconductor data sheets.
+/* Sources:
+ * Crynwr packet driver epktisa.
+ * Crystal Semiconductor data sheets.
+ */
-*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/printk.h>
@@ -147,8 +67,8 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/gfp.h>
+#include <linux/io.h>
-#include <asm/io.h>
#include <asm/irq.h>
#include <linux/atomic.h>
#if ALLOW_DMA
@@ -157,35 +77,55 @@
#include "cs89x0.h"
+#define cs89_dbg(val, level, fmt, ...) \
+do { \
+ if (val <= net_debug) \
+ pr_##level(fmt, ##__VA_ARGS__); \
+} while (0)
+
static char version[] __initdata =
-"cs89x0.c: v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton\n";
+ "v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton";
#define DRV_NAME "cs89x0"
/* First, a few definitions that the brave might change.
- A zero-terminated list of I/O addresses to be probed. Some special flags..
- Addr & 1 = Read back the address port, look for signature and reset
- the page window before probing
- Addr & 3 = Reset the page window and probe
- The CLPS eval board has the Cirrus chip at 0x80090300, in ARM IO space,
- but it is possible that a Cirrus board could be plugged into the ISA
- slots. */
+ * A zero-terminated list of I/O addresses to be probed. Some special flags..
+ * Addr & 1 = Read back the address port, look for signature and reset
+ * the page window before probing
+ * Addr & 3 = Reset the page window and probe
+ * The CLPS eval board has the Cirrus chip at 0x80090300, in ARM IO space,
+ * but it is possible that a Cirrus board could be plugged into the ISA
+ * slots.
+ */
/* The cs8900 has 4 IRQ pins, software selectable. cs8900_irq_map maps
- them to system IRQ numbers. This mapping is card specific and is set to
- the configuration of the Cirrus Eval board for this chip. */
+ * them to system IRQ numbers. This mapping is card specific and is set to
+ * the configuration of the Cirrus Eval board for this chip.
+ */
#if defined(CONFIG_MACH_IXDP2351)
#define CS89x0_NONISA_IRQ
-static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
-static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
+static unsigned int netcard_portlist[] __used __initdata = {
+ IXDP2351_VIRT_CS8900_BASE, 0
+};
+static unsigned int cs8900_irq_map[] = {
+ IRQ_IXDP2351_CS8900, 0, 0, 0
+};
#elif defined(CONFIG_ARCH_IXDP2X01)
#define CS89x0_NONISA_IRQ
-static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
-static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
+static unsigned int netcard_portlist[] __used __initdata = {
+ IXDP2X01_CS8900_VIRT_BASE, 0
+};
+static unsigned int cs8900_irq_map[] = {
+ IRQ_IXDP2X01_CS8900, 0, 0, 0
+};
#else
#ifndef CONFIG_CS89x0_PLATFORM
-static unsigned int netcard_portlist[] __used __initdata =
- { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
-static unsigned int cs8900_irq_map[] = {10,11,12,5};
+static unsigned int netcard_portlist[] __used __initdata = {
+ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240,
+ 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0
+};
+static unsigned int cs8900_irq_map[] = {
+ 10, 11, 12, 5
+};
#endif
#endif
@@ -222,6 +162,8 @@ struct net_local {
int send_underrun; /* keep track of how many underruns in a row we get */
int force; /* force various values; see FORCE* above. */
spinlock_t lock;
+ void __iomem *virt_addr;/* CS89x0 virtual address. */
+ unsigned long size; /* Length of CS89x0 memory region. */
#if ALLOW_DMA
int use_dma; /* Flag: we're using dma */
int dma; /* DMA channel */
@@ -230,119 +172,42 @@ struct net_local {
unsigned char *end_dma_buff; /* points to the end of the buffer */
unsigned char *rx_dma_ptr; /* points to the next packet */
#endif
-#ifdef CONFIG_CS89x0_PLATFORM
- void __iomem *virt_addr;/* Virtual address for accessing the CS89x0. */
- unsigned long phys_addr;/* Physical address for accessing the CS89x0. */
- unsigned long size; /* Length of CS89x0 memory region. */
-#endif
};
-/* Index to functions, as function prototypes. */
-
-static int cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular);
-static int net_open(struct net_device *dev);
-static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id);
-static void set_multicast_list(struct net_device *dev);
-static void net_timeout(struct net_device *dev);
-static void net_rx(struct net_device *dev);
-static int net_close(struct net_device *dev);
-static struct net_device_stats *net_get_stats(struct net_device *dev);
-static void reset_chip(struct net_device *dev);
-static int get_eeprom_data(struct net_device *dev, int off, int len, int *buffer);
-static int get_eeprom_cksum(int off, int len, int *buffer);
-static int set_mac_address(struct net_device *dev, void *addr);
-static void count_rx_errors(int status, struct net_device *dev);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void net_poll_controller(struct net_device *dev);
-#endif
-#if ALLOW_DMA
-static void get_dma_channel(struct net_device *dev);
-static void release_dma_buff(struct net_local *lp);
-#endif
-
/* Example routines you must write ;->. */
#define tx_done(dev) 1
/*
* Permit 'cs89x0_dma=N' in the kernel boot environment
*/
-#if !defined(MODULE) && (ALLOW_DMA != 0)
+#if !defined(MODULE)
+#if ALLOW_DMA
static int g_cs89x0_dma;
static int __init dma_fn(char *str)
{
- g_cs89x0_dma = simple_strtol(str,NULL,0);
+ g_cs89x0_dma = simple_strtol(str, NULL, 0);
return 1;
}
__setup("cs89x0_dma=", dma_fn);
-#endif /* !defined(MODULE) && (ALLOW_DMA != 0) */
+#endif /* ALLOW_DMA */
-#ifndef MODULE
static int g_cs89x0_media__force;
static int __init media_fn(char *str)
{
- if (!strcmp(str, "rj45")) g_cs89x0_media__force = FORCE_RJ45;
- else if (!strcmp(str, "aui")) g_cs89x0_media__force = FORCE_AUI;
- else if (!strcmp(str, "bnc")) g_cs89x0_media__force = FORCE_BNC;
+ if (!strcmp(str, "rj45"))
+ g_cs89x0_media__force = FORCE_RJ45;
+ else if (!strcmp(str, "aui"))
+ g_cs89x0_media__force = FORCE_AUI;
+ else if (!strcmp(str, "bnc"))
+ g_cs89x0_media__force = FORCE_BNC;
+
return 1;
}
__setup("cs89x0_media=", media_fn);
-
-
-#ifndef CONFIG_CS89x0_PLATFORM
-/* Check for a network adaptor of this type, and return '0' iff one exists.
- If dev->base_addr == 0, probe all likely locations.
- If dev->base_addr == 1, always return failure.
- If dev->base_addr == 2, allocate space for the device and return success
- (detachable devices only).
- Return 0 on success.
- */
-
-struct net_device * __init cs89x0_probe(int unit)
-{
- struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
- unsigned *port;
- int err = 0;
- int irq;
- int io;
-
- if (!dev)
- return ERR_PTR(-ENODEV);
-
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
- io = dev->base_addr;
- irq = dev->irq;
-
- if (net_debug)
- printk("cs89x0:cs89x0_probe(0x%x)\n", io);
-
- if (io > 0x1ff) { /* Check a single specified location. */
- err = cs89x0_probe1(dev, io, 0);
- } else if (io != 0) { /* Don't probe at all. */
- err = -ENXIO;
- } else {
- for (port = netcard_portlist; *port; port++) {
- if (cs89x0_probe1(dev, *port, 0) == 0)
- break;
- dev->irq = irq;
- }
- if (!*port)
- err = -ENODEV;
- }
- if (err)
- goto out;
- return dev;
-out:
- free_netdev(dev);
- printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n");
- return ERR_PTR(err);
-}
-#endif
#endif
#if defined(CONFIG_MACH_IXDP2351)
@@ -369,36 +234,22 @@ writeword(unsigned long base_addr, int portno, u16 value)
{
__raw_writel(value, base_addr + (portno << 1));
}
-#else
-static u16
-readword(unsigned long base_addr, int portno)
-{
- return inw(base_addr + portno);
-}
-
-static void
-writeword(unsigned long base_addr, int portno, u16 value)
-{
- outw(value, base_addr + portno);
-}
#endif
-static void
-readwords(unsigned long base_addr, int portno, void *buf, int length)
+static void readwords(struct net_local *lp, int portno, void *buf, int length)
{
u8 *buf8 = (u8 *)buf;
do {
u16 tmp16;
- tmp16 = readword(base_addr, portno);
+ tmp16 = ioread16(lp->virt_addr + portno);
*buf8++ = (u8)tmp16;
*buf8++ = (u8)(tmp16 >> 8);
} while (--length);
}
-static void
-writewords(unsigned long base_addr, int portno, void *buf, int length)
+static void writewords(struct net_local *lp, int portno, void *buf, int length)
{
u8 *buf8 = (u8 *)buf;
@@ -407,32 +258,37 @@ writewords(unsigned long base_addr, int portno, void *buf, int length)
tmp16 = *buf8++;
tmp16 |= (*buf8++) << 8;
- writeword(base_addr, portno, tmp16);
+ iowrite16(tmp16, lp->virt_addr + portno);
} while (--length);
}
static u16
readreg(struct net_device *dev, u16 regno)
{
- writeword(dev->base_addr, ADD_PORT, regno);
- return readword(dev->base_addr, DATA_PORT);
+ struct net_local *lp = netdev_priv(dev);
+
+ iowrite16(regno, lp->virt_addr + ADD_PORT);
+ return ioread16(lp->virt_addr + DATA_PORT);
}
static void
writereg(struct net_device *dev, u16 regno, u16 value)
{
- writeword(dev->base_addr, ADD_PORT, regno);
- writeword(dev->base_addr, DATA_PORT, value);
+ struct net_local *lp = netdev_priv(dev);
+
+ iowrite16(regno, lp->virt_addr + ADD_PORT);
+ iowrite16(value, lp->virt_addr + DATA_PORT);
}
static int __init
wait_eeprom_ready(struct net_device *dev)
{
int timeout = jiffies;
- /* check to see if the EEPROM is ready, a timeout is used -
- just in case EEPROM is ready when SI_BUSY in the
- PP_SelfST is clear */
- while(readreg(dev, PP_SelfST) & SI_BUSY)
+ /* check to see if the EEPROM is ready,
+ * a timeout is used just in case EEPROM is ready when
+ * SI_BUSY in the PP_SelfST is clear
+ */
+ while (readreg(dev, PP_SelfST) & SI_BUSY)
if (jiffies - timeout >= 40)
return -1;
return 0;
@@ -443,17 +299,19 @@ get_eeprom_data(struct net_device *dev, int off, int len, int *buffer)
{
int i;
- if (net_debug > 3) printk("EEPROM data from %x for %x:\n",off,len);
+ cs89_dbg(3, info, "EEPROM data from %x for %x:", off, len);
for (i = 0; i < len; i++) {
- if (wait_eeprom_ready(dev) < 0) return -1;
+ if (wait_eeprom_ready(dev) < 0)
+ return -1;
/* Now send the EEPROM read command and EEPROM location to read */
writereg(dev, PP_EECMD, (off + i) | EEPROM_READ_CMD);
- if (wait_eeprom_ready(dev) < 0) return -1;
+ if (wait_eeprom_ready(dev) < 0)
+ return -1;
buffer[i] = readreg(dev, PP_EEData);
- if (net_debug > 3) printk("%04x ", buffer[i]);
+ cs89_dbg(3, cont, " %04x", buffer[i]);
}
- if (net_debug > 3) printk("\n");
- return 0;
+ cs89_dbg(3, cont, "\n");
+ return 0;
}
static int __init
@@ -470,341 +328,52 @@ get_eeprom_cksum(int off, int len, int *buffer)
return -1;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling receive - used by netconsole and other diagnostic tools
- * to allow network i/o with interrupts disabled.
- */
-static void net_poll_controller(struct net_device *dev)
-{
- disable_irq(dev->irq);
- net_interrupt(dev->irq, dev);
- enable_irq(dev->irq);
-}
-#endif
-
-static const struct net_device_ops net_ops = {
- .ndo_open = net_open,
- .ndo_stop = net_close,
- .ndo_tx_timeout = net_timeout,
- .ndo_start_xmit = net_send_packet,
- .ndo_get_stats = net_get_stats,
- .ndo_set_rx_mode = set_multicast_list,
- .ndo_set_mac_address = set_mac_address,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = net_poll_controller,
-#endif
- .ndo_change_mtu = eth_change_mtu,
- .ndo_validate_addr = eth_validate_addr,
-};
-
-/* This is the real probe routine. Linux has a history of friendly device
- probes on the ISA bus. A good device probes avoids doing writes, and
- verifies that the correct device exists and functions.
- Return 0 on success.
- */
-
-static int __init
-cs89x0_probe1(struct net_device *dev, unsigned long ioaddr, int modular)
+static void
+write_irq(struct net_device *dev, int chip_type, int irq)
{
- struct net_local *lp = netdev_priv(dev);
- static unsigned version_printed;
int i;
- int tmp;
- unsigned rev_type = 0;
- int eeprom_buff[CHKSUM_LEN];
- int retval;
-
- /* Initialize the device structure. */
- if (!modular) {
- memset(lp, 0, sizeof(*lp));
- spin_lock_init(&lp->lock);
-#ifndef MODULE
-#if ALLOW_DMA
- if (g_cs89x0_dma) {
- lp->use_dma = 1;
- lp->dma = g_cs89x0_dma;
- lp->dmasize = 16; /* Could make this an option... */
- }
-#endif
- lp->force = g_cs89x0_media__force;
-#endif
-
- }
-
- /* Grab the region so we can find another board if autoIRQ fails. */
- /* WTF is going on here? */
- if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) {
- printk(KERN_ERR "%s: request_region(0x%lx, 0x%x) failed\n",
- DRV_NAME, ioaddr, NETCARD_IO_EXTENT);
- retval = -EBUSY;
- goto out1;
- }
-
- /* if they give us an odd I/O address, then do ONE write to
- the address port, to get it back to address zero, where we
- expect to find the EISA signature word. An IO with a base of 0x3
- will skip the test for the ADD_PORT. */
- if (ioaddr & 1) {
- if (net_debug > 1)
- printk(KERN_INFO "%s: odd ioaddr 0x%lx\n", dev->name, ioaddr);
- if ((ioaddr & 2) != 2)
- if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) {
- printk(KERN_ERR "%s: bad signature 0x%x\n",
- dev->name, readword(ioaddr & ~3, ADD_PORT));
- retval = -ENODEV;
- goto out2;
- }
- }
-
- ioaddr &= ~3;
- printk(KERN_DEBUG "PP_addr at %lx[%x]: 0x%x\n",
- ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));
- writeword(ioaddr, ADD_PORT, PP_ChipID);
-
- tmp = readword(ioaddr, DATA_PORT);
- if (tmp != CHIP_EISA_ID_SIG) {
- printk(KERN_DEBUG "%s: incorrect signature at %lx[%x]: 0x%x!="
- CHIP_EISA_ID_SIG_STR "\n",
- dev->name, ioaddr, DATA_PORT, tmp);
- retval = -ENODEV;
- goto out2;
- }
-
- /* Fill in the 'dev' fields. */
- dev->base_addr = ioaddr;
-
- /* get the chip type */
- rev_type = readreg(dev, PRODUCT_ID_ADD);
- lp->chip_type = rev_type &~ REVISON_BITS;
- lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
-
- /* Check the chip type and revision in order to set the correct send command
- CS8920 revision C and CS8900 revision F can use the faster send. */
- lp->send_cmd = TX_AFTER_381;
- if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
- lp->send_cmd = TX_NOW;
- if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
- lp->send_cmd = TX_NOW;
-
- if (net_debug && version_printed++ == 0)
- printk(version);
-
- printk(KERN_INFO "%s: cs89%c0%s rev %c found at %#3lx ",
- dev->name,
- lp->chip_type==CS8900?'0':'2',
- lp->chip_type==CS8920M?"M":"",
- lp->chip_revision,
- dev->base_addr);
-
- reset_chip(dev);
-
- /* Here we read the current configuration of the chip. If there
- is no Extended EEPROM then the idea is to not disturb the chip
- configuration, it should have been correctly setup by automatic
- EEPROM read on reset. So, if the chip says it read the EEPROM
- the driver will always do *something* instead of complain that
- adapter_cnf is 0. */
-
-
- if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
- (EEPROM_OK|EEPROM_PRESENT)) {
- /* Load the MAC. */
- for (i=0; i < ETH_ALEN/2; i++) {
- unsigned int Addr;
- Addr = readreg(dev, PP_IA+i*2);
- dev->dev_addr[i*2] = Addr & 0xFF;
- dev->dev_addr[i*2+1] = Addr >> 8;
- }
-
- /* Load the Adapter Configuration.
- Note: Barring any more specific information from some
- other source (ie EEPROM+Schematics), we would not know
- how to operate a 10Base2 interface on the AUI port.
- However, since we do read the status of HCB1 and use
- settings that always result in calls to control_dc_dc(dev,0)
- a BNC interface should work if the enable pin
- (dc/dc converter) is on HCB1. It will be called AUI
- however. */
-
- lp->adapter_cnf = 0;
- i = readreg(dev, PP_LineCTL);
- /* Preserve the setting of the HCB1 pin. */
- if ((i & (HCB1 | HCB1_ENBL)) == (HCB1 | HCB1_ENBL))
- lp->adapter_cnf |= A_CNF_DC_DC_POLARITY;
- /* Save the sqelch bit */
- if ((i & LOW_RX_SQUELCH) == LOW_RX_SQUELCH)
- lp->adapter_cnf |= A_CNF_EXTND_10B_2 | A_CNF_LOW_RX_SQUELCH;
- /* Check if the card is in 10Base-t only mode */
- if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == 0)
- lp->adapter_cnf |= A_CNF_10B_T | A_CNF_MEDIA_10B_T;
- /* Check if the card is in AUI only mode */
- if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUI_ONLY)
- lp->adapter_cnf |= A_CNF_AUI | A_CNF_MEDIA_AUI;
- /* Check if the card is in Auto mode. */
- if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUTO_AUI_10BASET)
- lp->adapter_cnf |= A_CNF_AUI | A_CNF_10B_T |
- A_CNF_MEDIA_AUI | A_CNF_MEDIA_10B_T | A_CNF_MEDIA_AUTO;
-
- if (net_debug > 1)
- printk(KERN_INFO "%s: PP_LineCTL=0x%x, adapter_cnf=0x%x\n",
- dev->name, i, lp->adapter_cnf);
-
- /* IRQ. Other chips already probe, see below. */
- if (lp->chip_type == CS8900)
- lp->isa_config = readreg(dev, PP_CS8900_ISAINT) & INT_NO_MASK;
-
- printk( "[Cirrus EEPROM] ");
- }
-
- printk("\n");
-
- /* First check to see if an EEPROM is attached. */
-
- if ((readreg(dev, PP_SelfST) & EEPROM_PRESENT) == 0)
- printk(KERN_WARNING "cs89x0: No EEPROM, relying on command line....\n");
- else if (get_eeprom_data(dev, START_EEPROM_DATA,CHKSUM_LEN,eeprom_buff) < 0) {
- printk(KERN_WARNING "\ncs89x0: EEPROM read failed, relying on command line.\n");
- } else if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN,eeprom_buff) < 0) {
- /* Check if the chip was able to read its own configuration starting
- at 0 in the EEPROM*/
- if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) !=
- (EEPROM_OK|EEPROM_PRESENT))
- printk(KERN_WARNING "cs89x0: Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command line\n");
-
- } else {
- /* This reads an extended EEPROM that is not documented
- in the CS8900 datasheet. */
-
- /* get transmission control word but keep the autonegotiation bits */
- if (!lp->auto_neg_cnf) lp->auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
- /* Store adapter configuration */
- if (!lp->adapter_cnf) lp->adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET/2];
- /* Store ISA configuration */
- lp->isa_config = eeprom_buff[ISA_CNF_OFFSET/2];
- dev->mem_start = eeprom_buff[PACKET_PAGE_OFFSET/2] << 8;
-
- /* eeprom_buff has 32-bit ints, so we can't just memcpy it */
- /* store the initial memory base address */
- for (i = 0; i < ETH_ALEN/2; i++) {
- dev->dev_addr[i*2] = eeprom_buff[i];
- dev->dev_addr[i*2+1] = eeprom_buff[i] >> 8;
- }
- if (net_debug > 1)
- printk(KERN_DEBUG "%s: new adapter_cnf: 0x%x\n",
- dev->name, lp->adapter_cnf);
- }
-
- /* allow them to force multiple transceivers. If they force multiple, autosense */
- {
- int count = 0;
- if (lp->force & FORCE_RJ45) {lp->adapter_cnf |= A_CNF_10B_T; count++; }
- if (lp->force & FORCE_AUI) {lp->adapter_cnf |= A_CNF_AUI; count++; }
- if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_10B_2; count++; }
- if (count > 1) {lp->adapter_cnf |= A_CNF_MEDIA_AUTO; }
- else if (lp->force & FORCE_RJ45){lp->adapter_cnf |= A_CNF_MEDIA_10B_T; }
- else if (lp->force & FORCE_AUI) {lp->adapter_cnf |= A_CNF_MEDIA_AUI; }
- else if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_MEDIA_10B_2; }
- }
-
- if (net_debug > 1)
- printk(KERN_DEBUG "%s: after force 0x%x, adapter_cnf=0x%x\n",
- dev->name, lp->force, lp->adapter_cnf);
-
- /* FIXME: We don't let you set dc-dc polarity or low RX squelch from the command line: add it here */
-
- /* FIXME: We don't let you set the IMM bit from the command line: add it to lp->auto_neg_cnf here */
-
- /* FIXME: we don't set the Ethernet address on the command line. Use
- ifconfig IFACE hw ether AABBCCDDEEFF */
-
- printk(KERN_INFO "cs89x0 media %s%s%s",
- (lp->adapter_cnf & A_CNF_10B_T)?"RJ-45,":"",
- (lp->adapter_cnf & A_CNF_AUI)?"AUI,":"",
- (lp->adapter_cnf & A_CNF_10B_2)?"BNC,":"");
-
- lp->irq_map = 0xffff;
- /* If this is a CS8900 then no pnp soft */
- if (lp->chip_type != CS8900 &&
- /* Check if the ISA IRQ has been set */
- (i = readreg(dev, PP_CS8920_ISAINT) & 0xff,
- (i != 0 && i < CS8920_NO_INTS))) {
- if (!dev->irq)
- dev->irq = i;
- } else {
- i = lp->isa_config & INT_NO_MASK;
+ if (chip_type == CS8900) {
#ifndef CONFIG_CS89x0_PLATFORM
- if (lp->chip_type == CS8900) {
-#ifdef CS89x0_NONISA_IRQ
- i = cs8900_irq_map[0];
+ /* Search the mapping table for the corresponding IRQ pin. */
+ for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++)
+ if (cs8900_irq_map[i] == irq)
+ break;
+ /* Not found */
+ if (i == ARRAY_SIZE(cs8900_irq_map))
+ i = 3;
#else
- /* Translate the IRQ using the IRQ mapping table. */
- if (i >= ARRAY_SIZE(cs8900_irq_map))
- printk("\ncs89x0: invalid ISA interrupt number %d\n", i);
- else
- i = cs8900_irq_map[i];
-
- lp->irq_map = CS8900_IRQ_MAP; /* fixed IRQ map for CS8900 */
- } else {
- int irq_map_buff[IRQ_MAP_LEN/2];
-
- if (get_eeprom_data(dev, IRQ_MAP_EEPROM_DATA,
- IRQ_MAP_LEN/2,
- irq_map_buff) >= 0) {
- if ((irq_map_buff[0] & 0xff) == PNP_IRQ_FRMT)
- lp->irq_map = (irq_map_buff[0]>>8) | (irq_map_buff[1] << 8);
- }
-#endif
- }
-#endif
- if (!dev->irq)
- dev->irq = i;
- }
-
- printk(" IRQ %d", dev->irq);
-
-#if ALLOW_DMA
- if (lp->use_dma) {
- get_dma_channel(dev);
- printk(", DMA %d", dev->dma);
- }
- else
+ /* INTRQ0 pin is used for interrupt generation. */
+ i = 0;
#endif
- {
- printk(", programmed I/O");
+ writereg(dev, PP_CS8900_ISAINT, i);
+ } else {
+ writereg(dev, PP_CS8920_ISAINT, irq);
}
-
- /* print the ethernet address. */
- printk(", MAC %pM", dev->dev_addr);
-
- dev->netdev_ops = &net_ops;
- dev->watchdog_timeo = HZ;
-
- printk("\n");
- if (net_debug)
- printk("cs89x0_probe1() successful\n");
-
- retval = register_netdev(dev);
- if (retval)
- goto out3;
- return 0;
-out3:
- writeword(dev->base_addr, ADD_PORT, PP_ChipID);
-out2:
- release_region(ioaddr & ~3, NETCARD_IO_EXTENT);
-out1:
- return retval;
}
+static void
+count_rx_errors(int status, struct net_device *dev)
+{
+ dev->stats.rx_errors++;
+ if (status & RX_RUNT)
+ dev->stats.rx_length_errors++;
+ if (status & RX_EXTRA_DATA)
+ dev->stats.rx_length_errors++;
+ if ((status & RX_CRC_ERROR) && !(status & (RX_EXTRA_DATA | RX_RUNT)))
+ /* per str 172 */
+ dev->stats.rx_crc_errors++;
+ if (status & RX_DRIBBLE)
+ dev->stats.rx_frame_errors++;
+}
/*********************************
* This page contains DMA routines
-**********************************/
+ *********************************/
#if ALLOW_DMA
-#define dma_page_eq(ptr1, ptr2) ((long)(ptr1)>>17 == (long)(ptr2)>>17)
+#define dma_page_eq(ptr1, ptr2) ((long)(ptr1) >> 17 == (long)(ptr2) >> 17)
static void
get_dma_channel(struct net_device *dev)
@@ -833,11 +402,10 @@ write_dma(struct net_device *dev, int chip_type, int dma)
struct net_local *lp = netdev_priv(dev);
if ((lp->isa_config & ANY_ISA_DMA) == 0)
return;
- if (chip_type == CS8900) {
- writereg(dev, PP_CS8900_ISADMA, dma-5);
- } else {
+ if (chip_type == CS8900)
+ writereg(dev, PP_CS8900_ISADMA, dma - 5);
+ else
writereg(dev, PP_CS8920_ISADMA, dma);
- }
}
static void
@@ -847,18 +415,15 @@ set_dma_cfg(struct net_device *dev)
if (lp->use_dma) {
if ((lp->isa_config & ANY_ISA_DMA) == 0) {
- if (net_debug > 3)
- printk("set_dma_cfg(): no DMA\n");
+ cs89_dbg(3, err, "set_dma_cfg(): no DMA\n");
return;
}
if (lp->isa_config & ISA_RxDMA) {
lp->curr_rx_cfg |= RX_DMA_ONLY;
- if (net_debug > 3)
- printk("set_dma_cfg(): RX_DMA_ONLY\n");
+ cs89_dbg(3, info, "set_dma_cfg(): RX_DMA_ONLY\n");
} else {
lp->curr_rx_cfg |= AUTO_RX_DMA; /* not that we support it... */
- if (net_debug > 3)
- printk("set_dma_cfg(): AUTO_RX_DMA\n");
+ cs89_dbg(3, info, "set_dma_cfg(): AUTO_RX_DMA\n");
}
}
}
@@ -868,7 +433,7 @@ dma_bufcfg(struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
if (lp->use_dma)
- return (lp->isa_config & ANY_ISA_DMA)? RX_DMA_ENBL : 0;
+ return (lp->isa_config & ANY_ISA_DMA) ? RX_DMA_ENBL : 0;
else
return 0;
}
@@ -898,13 +463,13 @@ dma_rx(struct net_device *dev)
int status, length;
unsigned char *bp = lp->rx_dma_ptr;
- status = bp[0] + (bp[1]<<8);
- length = bp[2] + (bp[3]<<8);
+ status = bp[0] + (bp[1] << 8);
+ length = bp[2] + (bp[3] << 8);
bp += 4;
- if (net_debug > 5) {
- printk( "%s: receiving DMA packet at %lx, status %x, length %x\n",
- dev->name, (unsigned long)bp, status, length);
- }
+
+ cs89_dbg(5, debug, "%s: receiving DMA packet at %lx, status %x, length %x\n",
+ dev->name, (unsigned long)bp, status, length);
+
if ((status & RX_OK) == 0) {
count_rx_errors(status, dev);
goto skip_this_frame;
@@ -913,14 +478,16 @@ dma_rx(struct net_device *dev)
/* Malloc up new buffer. */
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);
+ /* I don't think we want to do this to a stressed system */
+ cs89_dbg(0, err, "%s: Memory squeeze, dropping packet\n",
+ dev->name);
dev->stats.rx_dropped++;
/* AKPM: advance bp to the next frame */
skip_this_frame:
bp += (length + 3) & ~3;
- if (bp >= lp->end_dma_buff) bp -= lp->dmasize*1024;
+ if (bp >= lp->end_dma_buff)
+ bp -= lp->dmasize * 1024;
lp->rx_dma_ptr = bp;
return;
}
@@ -928,63 +495,38 @@ skip_this_frame:
if (bp + length > lp->end_dma_buff) {
int semi_cnt = lp->end_dma_buff - bp;
- memcpy(skb_put(skb,semi_cnt), bp, semi_cnt);
- memcpy(skb_put(skb,length - semi_cnt), lp->dma_buff,
+ memcpy(skb_put(skb, semi_cnt), bp, semi_cnt);
+ memcpy(skb_put(skb, length - semi_cnt), lp->dma_buff,
length - semi_cnt);
} else {
- memcpy(skb_put(skb,length), bp, length);
+ memcpy(skb_put(skb, length), bp, length);
}
bp += (length + 3) & ~3;
- if (bp >= lp->end_dma_buff) bp -= lp->dmasize*1024;
+ if (bp >= lp->end_dma_buff)
+ bp -= lp->dmasize*1024;
lp->rx_dma_ptr = bp;
- if (net_debug > 3) {
- printk( "%s: received %d byte DMA packet of type %x\n",
- dev->name, length,
- (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
- }
- skb->protocol=eth_type_trans(skb,dev);
+ cs89_dbg(3, info, "%s: received %d byte DMA packet of type %x\n",
+ dev->name, length,
+ ((skb->data[ETH_ALEN + ETH_ALEN] << 8) |
+ skb->data[ETH_ALEN + ETH_ALEN + 1]));
+
+ skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += length;
}
-#endif /* ALLOW_DMA */
-
-static void __init reset_chip(struct net_device *dev)
+static void release_dma_buff(struct net_local *lp)
{
-#if !defined(CONFIG_MACH_MX31ADS)
-#if !defined(CS89x0_NONISA_IRQ)
- struct net_local *lp = netdev_priv(dev);
- int ioaddr = dev->base_addr;
-#endif /* CS89x0_NONISA_IRQ */
- int reset_start_time;
-
- writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
-
- /* wait 30 ms */
- msleep(30);
-
-#if !defined(CS89x0_NONISA_IRQ)
- if (lp->chip_type != CS8900) {
- /* Hardware problem requires PNP registers to be reconfigured after a reset */
- writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT);
- outb(dev->irq, ioaddr + DATA_PORT);
- outb(0, ioaddr + DATA_PORT + 1);
-
- writeword(ioaddr, ADD_PORT, PP_CS8920_ISAMemB);
- outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT);
- outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT + 1);
+ if (lp->dma_buff) {
+ free_pages((unsigned long)(lp->dma_buff),
+ get_order(lp->dmasize * 1024));
+ lp->dma_buff = NULL;
}
-#endif /* CS89x0_NONISA_IRQ */
-
- /* Wait until the chip is reset */
- reset_start_time = jiffies;
- while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
- ;
-#endif /* !CONFIG_MACH_MX31ADS */
}
+#endif /* ALLOW_DMA */
static void
control_dc_dc(struct net_device *dev, int on_not_off)
@@ -993,8 +535,9 @@ control_dc_dc(struct net_device *dev, int on_not_off)
unsigned int selfcontrol;
int timenow = jiffies;
/* control the DC to DC convertor in the SelfControl register.
- Note: This is hooked up to a general purpose pin, might not
- always be a DC to DC convertor. */
+ * Note: This is hooked up to a general purpose pin, might not
+ * always be a DC to DC convertor.
+ */
selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */
if (((lp->adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off)
@@ -1008,6 +551,49 @@ control_dc_dc(struct net_device *dev, int on_not_off)
;
}
+/* send a test packet - return true if carrier bits are ok */
+static int
+send_test_pkt(struct net_device *dev)
+{
+ struct net_local *lp = netdev_priv(dev);
+ char test_packet[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 46, /* A 46 in network order */
+ 0, 0, /* DSAP=0 & SSAP=0 fields */
+ 0xf3, 0 /* Control (Test Req + P bit set) */
+ };
+ long timenow = jiffies;
+
+ writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_TX_ON);
+
+ memcpy(test_packet, dev->dev_addr, ETH_ALEN);
+ memcpy(test_packet + ETH_ALEN, dev->dev_addr, ETH_ALEN);
+
+ iowrite16(TX_AFTER_ALL, lp->virt_addr + TX_CMD_PORT);
+ iowrite16(ETH_ZLEN, lp->virt_addr + TX_LEN_PORT);
+
+ /* Test to see if the chip has allocated memory for the packet */
+ while (jiffies - timenow < 5)
+ if (readreg(dev, PP_BusST) & READY_FOR_TX_NOW)
+ break;
+ if (jiffies - timenow >= 5)
+ return 0; /* this shouldn't happen */
+
+ /* Write the contents of the packet */
+ writewords(lp, TX_FRAME_PORT, test_packet, (ETH_ZLEN + 1) >> 1);
+
+ cs89_dbg(1, debug, "Sending test packet ");
+ /* wait a couple of jiffies for packet to be received */
+ for (timenow = jiffies; jiffies - timenow < 3;)
+ ;
+ if ((readreg(dev, PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
+ cs89_dbg(1, cont, "succeeded\n");
+ return 1;
+ }
+ cs89_dbg(1, cont, "failed\n");
+ return 0;
+}
+
#define DETECTED_NONE 0
#define DETECTED_RJ45H 1
#define DETECTED_RJ45F 2
@@ -1021,40 +607,46 @@ detect_tp(struct net_device *dev)
int timenow = jiffies;
int fdx;
- if (net_debug > 1) printk("%s: Attempting TP\n", dev->name);
+ cs89_dbg(1, debug, "%s: Attempting TP\n", dev->name);
- /* If connected to another full duplex capable 10-Base-T card the link pulses
- seem to be lost when the auto detect bit in the LineCTL is set.
- To overcome this the auto detect bit will be cleared whilst testing the
- 10-Base-T interface. This would not be necessary for the sparrow chip but
- is simpler to do it anyway. */
- writereg(dev, PP_LineCTL, lp->linectl &~ AUI_ONLY);
+ /* If connected to another full duplex capable 10-Base-T card
+ * the link pulses seem to be lost when the auto detect bit in
+ * the LineCTL is set. To overcome this the auto detect bit will
+ * be cleared whilst testing the 10-Base-T interface. This would
+ * not be necessary for the sparrow chip but is simpler to do it
+ * anyway.
+ */
+ writereg(dev, PP_LineCTL, lp->linectl & ~AUI_ONLY);
control_dc_dc(dev, 0);
- /* Delay for the hardware to work out if the TP cable is present - 150ms */
- for (timenow = jiffies; jiffies - timenow < 15; )
- ;
+ /* Delay for the hardware to work out if the TP cable is present
+ * - 150ms
+ */
+ for (timenow = jiffies; jiffies - timenow < 15;)
+ ;
if ((readreg(dev, PP_LineST) & LINK_OK) == 0)
return DETECTED_NONE;
if (lp->chip_type == CS8900) {
- switch (lp->force & 0xf0) {
+ switch (lp->force & 0xf0) {
#if 0
- case FORCE_AUTO:
- printk("%s: cs8900 doesn't autonegotiate\n",dev->name);
- return DETECTED_NONE;
+ case FORCE_AUTO:
+ pr_info("%s: cs8900 doesn't autonegotiate\n",
+ dev->name);
+ return DETECTED_NONE;
#endif
- /* CS8900 doesn't support AUTO, change to HALF*/
- case FORCE_AUTO:
+ /* CS8900 doesn't support AUTO, change to HALF*/
+ case FORCE_AUTO:
lp->force &= ~FORCE_AUTO;
- lp->force |= FORCE_HALF;
+ lp->force |= FORCE_HALF;
break;
case FORCE_HALF:
break;
- case FORCE_FULL:
- writereg(dev, PP_TestCTL, readreg(dev, PP_TestCTL) | FDX_8900);
+ case FORCE_FULL:
+ writereg(dev, PP_TestCTL,
+ readreg(dev, PP_TestCTL) | FDX_8900);
break;
- }
+ }
fdx = readreg(dev, PP_TestCTL) & FDX_8900;
} else {
switch (lp->force & 0xf0) {
@@ -1067,15 +659,15 @@ detect_tp(struct net_device *dev)
case FORCE_FULL:
lp->auto_neg_cnf = RE_NEG_NOW | ALLOW_FDX;
break;
- }
+ }
writereg(dev, PP_AutoNegCTL, lp->auto_neg_cnf & AUTO_NEG_MASK);
if ((lp->auto_neg_cnf & AUTO_NEG_BITS) == AUTO_NEG_ENABLE) {
- printk(KERN_INFO "%s: negotiating duplex...\n",dev->name);
+ pr_info("%s: negotiating duplex...\n", dev->name);
while (readreg(dev, PP_AutoNegST) & AUTO_NEG_BUSY) {
if (jiffies - timenow > 4000) {
- printk(KERN_ERR "**** Full / half duplex auto-negotiation timed out ****\n");
+ pr_err("**** Full / half duplex auto-negotiation timed out ****\n");
break;
}
}
@@ -1088,56 +680,31 @@ detect_tp(struct net_device *dev)
return DETECTED_RJ45H;
}
-/* send a test packet - return true if carrier bits are ok */
static int
-send_test_pkt(struct net_device *dev)
+detect_bnc(struct net_device *dev)
{
- char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
- 0, 46, /* A 46 in network order */
- 0, 0, /* DSAP=0 & SSAP=0 fields */
- 0xf3, 0 /* Control (Test Req + P bit set) */ };
- long timenow = jiffies;
-
- writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_TX_ON);
-
- memcpy(test_packet, dev->dev_addr, ETH_ALEN);
- memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN);
-
- writeword(dev->base_addr, TX_CMD_PORT, TX_AFTER_ALL);
- writeword(dev->base_addr, TX_LEN_PORT, ETH_ZLEN);
+ struct net_local *lp = netdev_priv(dev);
- /* Test to see if the chip has allocated memory for the packet */
- while (jiffies - timenow < 5)
- if (readreg(dev, PP_BusST) & READY_FOR_TX_NOW)
- break;
- if (jiffies - timenow >= 5)
- return 0; /* this shouldn't happen */
+ cs89_dbg(1, debug, "%s: Attempting BNC\n", dev->name);
+ control_dc_dc(dev, 1);
- /* Write the contents of the packet */
- writewords(dev->base_addr, TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
+ writereg(dev, PP_LineCTL, (lp->linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
- if (net_debug > 1) printk("Sending test packet ");
- /* wait a couple of jiffies for packet to be received */
- for (timenow = jiffies; jiffies - timenow < 3; )
- ;
- if ((readreg(dev, PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
- if (net_debug > 1) printk("succeeded\n");
- return 1;
- }
- if (net_debug > 1) printk("failed\n");
- return 0;
+ if (send_test_pkt(dev))
+ return DETECTED_BNC;
+ else
+ return DETECTED_NONE;
}
-
static int
detect_aui(struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
- if (net_debug > 1) printk("%s: Attempting AUI\n", dev->name);
+ cs89_dbg(1, debug, "%s: Attempting AUI\n", dev->name);
control_dc_dc(dev, 0);
- writereg(dev, PP_LineCTL, (lp->linectl &~ AUTO_AUI_10BASET) | AUI_ONLY);
+ writereg(dev, PP_LineCTL, (lp->linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
if (send_test_pkt(dev))
return DETECTED_AUI;
@@ -1145,45 +712,154 @@ detect_aui(struct net_device *dev)
return DETECTED_NONE;
}
-static int
-detect_bnc(struct net_device *dev)
+/* We have a good packet(s), get it/them out of the buffers. */
+static void
+net_rx(struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
+ struct sk_buff *skb;
+ int status, length;
- if (net_debug > 1) printk("%s: Attempting BNC\n", dev->name);
- control_dc_dc(dev, 1);
+ status = ioread16(lp->virt_addr + RX_FRAME_PORT);
+ length = ioread16(lp->virt_addr + RX_FRAME_PORT);
- writereg(dev, PP_LineCTL, (lp->linectl &~ AUTO_AUI_10BASET) | AUI_ONLY);
+ if ((status & RX_OK) == 0) {
+ count_rx_errors(status, dev);
+ return;
+ }
- if (send_test_pkt(dev))
- return DETECTED_BNC;
- else
- return DETECTED_NONE;
+ /* Malloc up new buffer. */
+ skb = netdev_alloc_skb(dev, length + 2);
+ if (skb == NULL) {
+#if 0 /* Again, this seems a cruel thing to do */
+ pr_warn("%s: Memory squeeze, dropping packet\n", dev->name);
+#endif
+ dev->stats.rx_dropped++;
+ return;
+ }
+ skb_reserve(skb, 2); /* longword align L3 header */
+
+ readwords(lp, RX_FRAME_PORT, skb_put(skb, length), length >> 1);
+ if (length & 1)
+ skb->data[length-1] = ioread16(lp->virt_addr + RX_FRAME_PORT);
+
+ cs89_dbg(3, debug, "%s: received %d byte packet of type %x\n",
+ dev->name, length,
+ (skb->data[ETH_ALEN + ETH_ALEN] << 8) |
+ skb->data[ETH_ALEN + ETH_ALEN + 1]);
+
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += length;
}
+/* The typical workload of the driver:
+ * Handle the network interface interrupts.
+ */
-static void
-write_irq(struct net_device *dev, int chip_type, int irq)
+static irqreturn_t net_interrupt(int irq, void *dev_id)
{
- int i;
+ struct net_device *dev = dev_id;
+ struct net_local *lp;
+ int status;
+ int handled = 0;
- if (chip_type == CS8900) {
-#ifndef CONFIG_CS89x0_PLATFORM
- /* Search the mapping table for the corresponding IRQ pin. */
- for (i = 0; i != ARRAY_SIZE(cs8900_irq_map); i++)
- if (cs8900_irq_map[i] == irq)
- break;
- /* Not found */
- if (i == ARRAY_SIZE(cs8900_irq_map))
- i = 3;
-#else
- /* INTRQ0 pin is used for interrupt generation. */
- i = 0;
+ lp = netdev_priv(dev);
+
+ /* we MUST read all the events out of the ISQ, otherwise we'll never
+ * get interrupted again. As a consequence, we can't have any limit
+ * on the number of times we loop in the interrupt handler. The
+ * hardware guarantees that eventually we'll run out of events. Of
+ * course, if you're on a slow machine, and packets are arriving
+ * faster than you can read them off, you're screwed. Hasta la
+ * vista, baby!
+ */
+ while ((status = ioread16(lp->virt_addr + ISQ_PORT))) {
+ cs89_dbg(4, debug, "%s: event=%04x\n", dev->name, status);
+ handled = 1;
+ switch (status & ISQ_EVENT_MASK) {
+ case ISQ_RECEIVER_EVENT:
+ /* Got a packet(s). */
+ net_rx(dev);
+ break;
+ case ISQ_TRANSMITTER_EVENT:
+ dev->stats.tx_packets++;
+ netif_wake_queue(dev); /* Inform upper layers. */
+ if ((status & (TX_OK |
+ TX_LOST_CRS |
+ TX_SQE_ERROR |
+ TX_LATE_COL |
+ TX_16_COL)) != TX_OK) {
+ if ((status & TX_OK) == 0)
+ dev->stats.tx_errors++;
+ if (status & TX_LOST_CRS)
+ dev->stats.tx_carrier_errors++;
+ if (status & TX_SQE_ERROR)
+ dev->stats.tx_heartbeat_errors++;
+ if (status & TX_LATE_COL)
+ dev->stats.tx_window_errors++;
+ if (status & TX_16_COL)
+ dev->stats.tx_aborted_errors++;
+ }
+ break;
+ case ISQ_BUFFER_EVENT:
+ if (status & READY_FOR_TX) {
+ /* we tried to transmit a packet earlier,
+ * but inexplicably ran out of buffers.
+ * That shouldn't happen since we only ever
+ * load one packet. Shrug. Do the right
+ * thing anyway.
+ */
+ netif_wake_queue(dev); /* Inform upper layers. */
+ }
+ if (status & TX_UNDERRUN) {
+ cs89_dbg(0, err, "%s: transmit underrun\n",
+ dev->name);
+ lp->send_underrun++;
+ if (lp->send_underrun == 3)
+ lp->send_cmd = TX_AFTER_381;
+ else if (lp->send_underrun == 6)
+ lp->send_cmd = TX_AFTER_ALL;
+ /* transmit cycle is done, although
+ * frame wasn't transmitted - this
+ * avoids having to wait for the upper
+ * layers to timeout on us, in the
+ * event of a tx underrun
+ */
+ netif_wake_queue(dev); /* Inform upper layers. */
+ }
+#if ALLOW_DMA
+ if (lp->use_dma && (status & RX_DMA)) {
+ int count = readreg(dev, PP_DmaFrameCnt);
+ while (count) {
+ cs89_dbg(5, debug,
+ "%s: receiving %d DMA frames\n",
+ dev->name, count);
+ if (count > 1)
+ cs89_dbg(2, debug,
+ "%s: receiving %d DMA frames\n",
+ dev->name, count);
+ dma_rx(dev);
+ if (--count == 0)
+ count = readreg(dev, PP_DmaFrameCnt);
+ if (count > 0)
+ cs89_dbg(2, debug,
+ "%s: continuing with %d DMA frames\n",
+ dev->name, count);
+ }
+ }
#endif
- writereg(dev, PP_CS8900_ISAINT, i);
- } else {
- writereg(dev, PP_CS8920_ISAINT, irq);
+ break;
+ case ISQ_RX_MISS_EVENT:
+ dev->stats.rx_missed_errors += (status >> 6);
+ break;
+ case ISQ_TX_COL_EVENT:
+ dev->stats.collisions += (status >> 6);
+ break;
+ }
}
+ return IRQ_RETVAL(handled);
}
/* Open/initialize the board. This is called (in the current kernel)
@@ -1192,7 +868,7 @@ write_irq(struct net_device *dev, int chip_type, int irq)
This routine should set everything up anew at each open, even
registers that "should" only need to be set once at boot, so that
there is non-reboot way to recover if something goes wrong.
- */
+*/
/* AKPM: do we need to do any locking here? */
@@ -1208,14 +884,15 @@ net_open(struct net_device *dev)
/* Allow interrupts to be generated by the chip */
/* Cirrus' release had this: */
#if 0
- writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
+ writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ);
#endif
/* And 2.3.47 had this: */
writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
for (i = 2; i < CS8920_NO_INTS; i++) {
if ((1 << i) & lp->irq_map) {
- if (request_irq(i, net_interrupt, 0, dev->name, dev) == 0) {
+ if (request_irq(i, net_interrupt, 0, dev->name,
+ dev) == 0) {
dev->irq = i;
write_irq(dev, lp->chip_type, i);
/* writereg(dev, PP_BufCFG, GENERATE_SW_INTERRUPT); */
@@ -1226,23 +903,21 @@ net_open(struct net_device *dev)
if (i >= CS8920_NO_INTS) {
writereg(dev, PP_BusCTL, 0); /* disable interrupts. */
- printk(KERN_ERR "cs89x0: can't get an interrupt\n");
+ pr_err("can't get an interrupt\n");
ret = -EAGAIN;
goto bad_out;
}
- }
- else
- {
+ } else {
#if !defined(CS89x0_NONISA_IRQ) && !defined(CONFIG_CS89x0_PLATFORM)
if (((1 << dev->irq) & lp->irq_map) == 0) {
- printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
- dev->name, dev->irq, lp->irq_map);
+ pr_err("%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
+ dev->name, dev->irq, lp->irq_map);
ret = -EAGAIN;
goto bad_out;
}
#endif
/* FIXME: Cirrus' release had this: */
- writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
+ writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ);
/* And 2.3.47 had this: */
#if 0
writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
@@ -1250,147 +925,168 @@ net_open(struct net_device *dev)
write_irq(dev, lp->chip_type, dev->irq);
ret = request_irq(dev->irq, net_interrupt, 0, dev->name, dev);
if (ret) {
- printk(KERN_ERR "cs89x0: request_irq(%d) failed\n", dev->irq);
+ pr_err("request_irq(%d) failed\n", dev->irq);
goto bad_out;
}
}
#if ALLOW_DMA
- if (lp->use_dma) {
- if (lp->isa_config & ANY_ISA_DMA) {
- unsigned long flags;
- lp->dma_buff = (unsigned char *)__get_dma_pages(GFP_KERNEL,
- get_order(lp->dmasize * 1024));
-
- if (!lp->dma_buff) {
- printk(KERN_ERR "%s: cannot get %dK memory for DMA\n", dev->name, lp->dmasize);
- goto release_irq;
- }
- if (net_debug > 1) {
- printk( "%s: dma %lx %lx\n",
- dev->name,
- (unsigned long)lp->dma_buff,
- (unsigned long)isa_virt_to_bus(lp->dma_buff));
- }
- if ((unsigned long) lp->dma_buff >= MAX_DMA_ADDRESS ||
- !dma_page_eq(lp->dma_buff, lp->dma_buff+lp->dmasize*1024-1)) {
- printk(KERN_ERR "%s: not usable as DMA buffer\n", dev->name);
- goto release_irq;
- }
- memset(lp->dma_buff, 0, lp->dmasize * 1024); /* Why? */
- if (request_dma(dev->dma, dev->name)) {
- printk(KERN_ERR "%s: cannot get dma channel %d\n", dev->name, dev->dma);
- goto release_irq;
- }
- write_dma(dev, lp->chip_type, dev->dma);
- lp->rx_dma_ptr = lp->dma_buff;
- lp->end_dma_buff = lp->dma_buff + lp->dmasize*1024;
- spin_lock_irqsave(&lp->lock, flags);
- disable_dma(dev->dma);
- clear_dma_ff(dev->dma);
- set_dma_mode(dev->dma, DMA_RX_MODE); /* auto_init as well */
- set_dma_addr(dev->dma, isa_virt_to_bus(lp->dma_buff));
- set_dma_count(dev->dma, lp->dmasize*1024);
- enable_dma(dev->dma);
- spin_unlock_irqrestore(&lp->lock, flags);
+ if (lp->use_dma && (lp->isa_config & ANY_ISA_DMA)) {
+ unsigned long flags;
+ lp->dma_buff = (unsigned char *)__get_dma_pages(GFP_KERNEL,
+ get_order(lp->dmasize * 1024));
+ if (!lp->dma_buff) {
+ pr_err("%s: cannot get %dK memory for DMA\n",
+ dev->name, lp->dmasize);
+ goto release_irq;
+ }
+ cs89_dbg(1, debug, "%s: dma %lx %lx\n",
+ dev->name,
+ (unsigned long)lp->dma_buff,
+ (unsigned long)isa_virt_to_bus(lp->dma_buff));
+ if ((unsigned long)lp->dma_buff >= MAX_DMA_ADDRESS ||
+ !dma_page_eq(lp->dma_buff,
+ lp->dma_buff + lp->dmasize * 1024 - 1)) {
+ pr_err("%s: not usable as DMA buffer\n", dev->name);
+ goto release_irq;
}
+ memset(lp->dma_buff, 0, lp->dmasize * 1024); /* Why? */
+ if (request_dma(dev->dma, dev->name)) {
+ pr_err("%s: cannot get dma channel %d\n",
+ dev->name, dev->dma);
+ goto release_irq;
+ }
+ write_dma(dev, lp->chip_type, dev->dma);
+ lp->rx_dma_ptr = lp->dma_buff;
+ lp->end_dma_buff = lp->dma_buff + lp->dmasize * 1024;
+ spin_lock_irqsave(&lp->lock, flags);
+ disable_dma(dev->dma);
+ clear_dma_ff(dev->dma);
+ set_dma_mode(dev->dma, DMA_RX_MODE); /* auto_init as well */
+ set_dma_addr(dev->dma, isa_virt_to_bus(lp->dma_buff));
+ set_dma_count(dev->dma, lp->dmasize * 1024);
+ enable_dma(dev->dma);
+ spin_unlock_irqrestore(&lp->lock, flags);
}
#endif /* ALLOW_DMA */
/* 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));
+ 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)));
/* while we're testing the interface, leave interrupts disabled */
writereg(dev, PP_BusCTL, MEMORY_ON);
/* Set the LineCTL quintuplet based on adapter configuration read from EEPROM */
- if ((lp->adapter_cnf & A_CNF_EXTND_10B_2) && (lp->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
- lp->linectl = LOW_RX_SQUELCH;
+ if ((lp->adapter_cnf & A_CNF_EXTND_10B_2) &&
+ (lp->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
+ lp->linectl = LOW_RX_SQUELCH;
else
- lp->linectl = 0;
-
- /* check to make sure that they have the "right" hardware available */
- switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
- case A_CNF_MEDIA_10B_T: result = lp->adapter_cnf & A_CNF_10B_T; break;
- case A_CNF_MEDIA_AUI: result = lp->adapter_cnf & A_CNF_AUI; break;
- case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
- default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
- }
- if (!result) {
- printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name);
+ lp->linectl = 0;
+
+ /* check to make sure that they have the "right" hardware available */
+ switch (lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
+ case A_CNF_MEDIA_10B_T:
+ result = lp->adapter_cnf & A_CNF_10B_T;
+ break;
+ case A_CNF_MEDIA_AUI:
+ result = lp->adapter_cnf & A_CNF_AUI;
+ break;
+ case A_CNF_MEDIA_10B_2:
+ result = lp->adapter_cnf & A_CNF_10B_2;
+ break;
+ default:
+ result = lp->adapter_cnf & (A_CNF_10B_T |
+ A_CNF_AUI |
+ A_CNF_10B_2);
+ }
+ if (!result) {
+ pr_err("%s: EEPROM is configured for unavailable media\n",
+ dev->name);
release_dma:
#if ALLOW_DMA
free_dma(dev->dma);
release_irq:
release_dma_buff(lp);
#endif
- writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
- free_irq(dev->irq, dev);
+ writereg(dev, PP_LineCTL,
+ readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
+ free_irq(dev->irq, dev);
ret = -EAGAIN;
goto bad_out;
}
- /* set the hardware to the configured choice */
- switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
+ /* set the hardware to the configured choice */
+ switch (lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
case A_CNF_MEDIA_10B_T:
- result = detect_tp(dev);
- if (result==DETECTED_NONE) {
- printk(KERN_WARNING "%s: 10Base-T (RJ-45) has no cable\n", dev->name);
- if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
- result = DETECTED_RJ45H; /* Yes! I don't care if I see a link pulse */
- }
+ result = detect_tp(dev);
+ if (result == DETECTED_NONE) {
+ pr_warn("%s: 10Base-T (RJ-45) has no cable\n",
+ dev->name);
+ if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
+ result = DETECTED_RJ45H; /* Yes! I don't care if I see a link pulse */
+ }
break;
case A_CNF_MEDIA_AUI:
- result = detect_aui(dev);
- if (result==DETECTED_NONE) {
- printk(KERN_WARNING "%s: 10Base-5 (AUI) has no cable\n", dev->name);
- if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
- result = DETECTED_AUI; /* Yes! I don't care if I see a carrrier */
- }
+ result = detect_aui(dev);
+ if (result == DETECTED_NONE) {
+ pr_warn("%s: 10Base-5 (AUI) has no cable\n", dev->name);
+ if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
+ result = DETECTED_AUI; /* Yes! I don't care if I see a carrrier */
+ }
break;
case A_CNF_MEDIA_10B_2:
- result = detect_bnc(dev);
- if (result==DETECTED_NONE) {
- printk(KERN_WARNING "%s: 10Base-2 (BNC) has no cable\n", dev->name);
- if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
- result = DETECTED_BNC; /* Yes! I don't care if I can xmit a packet */
- }
+ result = detect_bnc(dev);
+ if (result == DETECTED_NONE) {
+ pr_warn("%s: 10Base-2 (BNC) has no cable\n", dev->name);
+ if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */
+ result = DETECTED_BNC; /* Yes! I don't care if I can xmit a packet */
+ }
break;
case A_CNF_MEDIA_AUTO:
writereg(dev, PP_LineCTL, lp->linectl | AUTO_AUI_10BASET);
- if (lp->adapter_cnf & A_CNF_10B_T)
- if ((result = detect_tp(dev)) != DETECTED_NONE)
+ if (lp->adapter_cnf & A_CNF_10B_T) {
+ result = detect_tp(dev);
+ if (result != DETECTED_NONE)
break;
- if (lp->adapter_cnf & A_CNF_AUI)
- if ((result = detect_aui(dev)) != DETECTED_NONE)
+ }
+ if (lp->adapter_cnf & A_CNF_AUI) {
+ result = detect_aui(dev);
+ if (result != DETECTED_NONE)
break;
- if (lp->adapter_cnf & A_CNF_10B_2)
- if ((result = detect_bnc(dev)) != DETECTED_NONE)
+ }
+ if (lp->adapter_cnf & A_CNF_10B_2) {
+ result = detect_bnc(dev);
+ if (result != DETECTED_NONE)
break;
- printk(KERN_ERR "%s: no media detected\n", dev->name);
+ }
+ pr_err("%s: no media detected\n", dev->name);
goto release_dma;
}
- switch(result) {
+ switch (result) {
case DETECTED_NONE:
- printk(KERN_ERR "%s: no network cable attached to configured media\n", dev->name);
+ pr_err("%s: no network cable attached to configured media\n",
+ dev->name);
goto release_dma;
case DETECTED_RJ45H:
- printk(KERN_INFO "%s: using half-duplex 10Base-T (RJ-45)\n", dev->name);
+ pr_info("%s: using half-duplex 10Base-T (RJ-45)\n", dev->name);
break;
case DETECTED_RJ45F:
- printk(KERN_INFO "%s: using full-duplex 10Base-T (RJ-45)\n", dev->name);
+ pr_info("%s: using full-duplex 10Base-T (RJ-45)\n", dev->name);
break;
case DETECTED_AUI:
- printk(KERN_INFO "%s: using 10Base-5 (AUI)\n", dev->name);
+ pr_info("%s: using 10Base-5 (AUI)\n", dev->name);
break;
case DETECTED_BNC:
- printk(KERN_INFO "%s: using 10Base-2 (BNC)\n", dev->name);
+ pr_info("%s: using 10Base-2 (BNC)\n", dev->name);
break;
}
/* Turn on both receive and transmit operations */
- writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
+ writereg(dev, PP_LineCTL,
+ readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
/* Receive only error free packets addressed to this card */
lp->rx_mode = 0;
@@ -1405,358 +1101,653 @@ release_irq:
#endif
writereg(dev, PP_RxCFG, lp->curr_rx_cfg);
- writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |
- TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
+ writereg(dev, PP_TxCFG, (TX_LOST_CRS_ENBL |
+ TX_SQE_ERROR_ENBL |
+ TX_OK_ENBL |
+ TX_LATE_COL_ENBL |
+ TX_JBR_ENBL |
+ TX_ANY_COL_ENBL |
+ TX_16_COL_ENBL));
- writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |
+ writereg(dev, PP_BufCFG, (READY_FOR_TX_ENBL |
+ RX_MISS_COUNT_OVRFLOW_ENBL |
#if ALLOW_DMA
- dma_bufcfg(dev) |
+ dma_bufcfg(dev) |
#endif
- TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);
+ TX_COL_COUNT_OVRFLOW_ENBL |
+ TX_UNDERRUN_ENBL));
/* now that we've got our act together, enable everything */
- writereg(dev, PP_BusCTL, ENABLE_IRQ
- | (dev->mem_start?MEMORY_ON : 0) /* turn memory on */
+ writereg(dev, PP_BusCTL, (ENABLE_IRQ
+ | (dev->mem_start ? MEMORY_ON : 0) /* turn memory on */
#if ALLOW_DMA
- | dma_busctl(dev)
+ | dma_busctl(dev)
#endif
- );
- netif_start_queue(dev);
- if (net_debug > 1)
- printk("cs89x0: net_open() succeeded\n");
+ ));
+ netif_start_queue(dev);
+ cs89_dbg(1, debug, "net_open() succeeded\n");
return 0;
bad_out:
return ret;
}
+/* The inverse routine to net_open(). */
+static int
+net_close(struct net_device *dev)
+{
+#if ALLOW_DMA
+ struct net_local *lp = netdev_priv(dev);
+#endif
+
+ netif_stop_queue(dev);
+
+ writereg(dev, PP_RxCFG, 0);
+ writereg(dev, PP_TxCFG, 0);
+ writereg(dev, PP_BufCFG, 0);
+ writereg(dev, PP_BusCTL, 0);
+
+ free_irq(dev->irq, dev);
+
+#if ALLOW_DMA
+ if (lp->use_dma && lp->dma) {
+ free_dma(dev->dma);
+ release_dma_buff(lp);
+ }
+#endif
+
+ /* Update the statistics here. */
+ return 0;
+}
+
+/* Get the current statistics.
+ * This may be called with the card open or closed.
+ */
+static struct net_device_stats *
+net_get_stats(struct net_device *dev)
+{
+ struct net_local *lp = netdev_priv(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&lp->lock, flags);
+ /* Update the statistics from the device registers. */
+ dev->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
+ dev->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ return &dev->stats;
+}
+
static void net_timeout(struct net_device *dev)
{
/* If we get here, some higher level has decided we are broken.
There should really be a "kick me" function call instead. */
- if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
- tx_done(dev) ? "IRQ conflict ?" : "network cable problem");
+ cs89_dbg(0, err, "%s: transmit timed out, %s?\n",
+ dev->name,
+ tx_done(dev) ? "IRQ conflict" : "network cable problem");
/* Try to restart the adaptor. */
netif_wake_queue(dev);
}
-static netdev_tx_t net_send_packet(struct sk_buff *skb,struct net_device *dev)
+static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
unsigned long flags;
- if (net_debug > 3) {
- printk("%s: sent %d byte packet of type %x\n",
- dev->name, skb->len,
- (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
- }
+ cs89_dbg(3, debug, "%s: sent %d byte packet of type %x\n",
+ dev->name, skb->len,
+ ((skb->data[ETH_ALEN + ETH_ALEN] << 8) |
+ skb->data[ETH_ALEN + ETH_ALEN + 1]));
/* keep the upload from being interrupted, since we
- ask the chip to start transmitting before the
- whole packet has been completely uploaded. */
+ * ask the chip to start transmitting before the
+ * whole packet has been completely uploaded.
+ */
spin_lock_irqsave(&lp->lock, flags);
netif_stop_queue(dev);
/* initiate a transmit sequence */
- writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd);
- writeword(dev->base_addr, TX_LEN_PORT, skb->len);
+ iowrite16(lp->send_cmd, lp->virt_addr + TX_CMD_PORT);
+ iowrite16(skb->len, lp->virt_addr + TX_LEN_PORT);
/* Test to see if the chip has allocated memory for the packet */
if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
- /*
- * Gasp! It hasn't. But that shouldn't happen since
+ /* Gasp! It hasn't. But that shouldn't happen since
* we're waiting for TxOk, so return 1 and requeue this packet.
*/
spin_unlock_irqrestore(&lp->lock, flags);
- if (net_debug) printk("cs89x0: Tx buffer not free!\n");
+ cs89_dbg(0, err, "Tx buffer not free!\n");
return NETDEV_TX_BUSY;
}
/* Write the contents of the packet */
- writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
+ writewords(lp, TX_FRAME_PORT, skb->data, (skb->len + 1) >> 1);
spin_unlock_irqrestore(&lp->lock, flags);
dev->stats.tx_bytes += skb->len;
- dev_kfree_skb (skb);
+ dev_kfree_skb(skb);
- /*
- * We DO NOT call netif_wake_queue() here.
+ /* We DO NOT call netif_wake_queue() here.
* We also DO NOT call netif_start_queue().
*
* Either of these would cause another bottom half run through
- * net_send_packet() before this packet has fully gone out. That causes
- * us to hit the "Gasp!" above and the send is rescheduled. it runs like
- * a dog. We just return and wait for the Tx completion interrupt handler
- * to restart the netdevice layer
+ * net_send_packet() before this packet has fully gone out.
+ * That causes us to hit the "Gasp!" above and the send is rescheduled.
+ * it runs like a dog. We just return and wait for the Tx completion
+ * interrupt handler to restart the netdevice layer
*/
return NETDEV_TX_OK;
}
-/* The typical workload of the driver:
- Handle the network interface interrupts. */
+static void set_multicast_list(struct net_device *dev)
+{
+ struct net_local *lp = netdev_priv(dev);
+ unsigned long flags;
-static irqreturn_t net_interrupt(int irq, void *dev_id)
+ spin_lock_irqsave(&lp->lock, flags);
+ if (dev->flags & IFF_PROMISC)
+ lp->rx_mode = RX_ALL_ACCEPT;
+ else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev))
+ /* The multicast-accept list is initialized to accept-all,
+ * and we rely on higher-level filtering for now.
+ */
+ lp->rx_mode = RX_MULTCAST_ACCEPT;
+ else
+ lp->rx_mode = 0;
+
+ writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
+
+ /* in promiscuous mode, we accept errored packets,
+ * so we have to enable interrupts on them also
+ */
+ writereg(dev, PP_RxCFG,
+ (lp->curr_rx_cfg |
+ (lp->rx_mode == RX_ALL_ACCEPT)
+ ? (RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL)
+ : 0));
+ spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+static int set_mac_address(struct net_device *dev, void *p)
{
- struct net_device *dev = dev_id;
- struct net_local *lp;
- int ioaddr, status;
- int handled = 0;
+ int i;
+ struct sockaddr *addr = p;
- ioaddr = dev->base_addr;
- lp = netdev_priv(dev);
+ if (netif_running(dev))
+ return -EBUSY;
- /* we MUST read all the events out of the ISQ, otherwise we'll never
- get interrupted again. As a consequence, we can't have any limit
- on the number of times we loop in the interrupt handler. The
- hardware guarantees that eventually we'll run out of events. Of
- course, if you're on a slow machine, and packets are arriving
- faster than you can read them off, you're screwed. Hasta la
- vista, baby! */
- while ((status = readword(dev->base_addr, ISQ_PORT))) {
- if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
- handled = 1;
- switch(status & ISQ_EVENT_MASK) {
- case ISQ_RECEIVER_EVENT:
- /* Got a packet(s). */
- net_rx(dev);
- break;
- case ISQ_TRANSMITTER_EVENT:
- dev->stats.tx_packets++;
- netif_wake_queue(dev); /* Inform upper layers. */
- if ((status & ( TX_OK |
- TX_LOST_CRS |
- TX_SQE_ERROR |
- TX_LATE_COL |
- TX_16_COL)) != TX_OK) {
- if ((status & TX_OK) == 0)
- dev->stats.tx_errors++;
- if (status & TX_LOST_CRS)
- dev->stats.tx_carrier_errors++;
- if (status & TX_SQE_ERROR)
- dev->stats.tx_heartbeat_errors++;
- if (status & TX_LATE_COL)
- dev->stats.tx_window_errors++;
- if (status & TX_16_COL)
- dev->stats.tx_aborted_errors++;
- }
- break;
- case ISQ_BUFFER_EVENT:
- if (status & READY_FOR_TX) {
- /* we tried to transmit a packet earlier,
- but inexplicably ran out of buffers.
- That shouldn't happen since we only ever
- load one packet. Shrug. Do the right
- thing anyway. */
- netif_wake_queue(dev); /* Inform upper layers. */
- }
- if (status & TX_UNDERRUN) {
- if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
- lp->send_underrun++;
- if (lp->send_underrun == 3) lp->send_cmd = TX_AFTER_381;
- else if (lp->send_underrun == 6) lp->send_cmd = TX_AFTER_ALL;
- /* transmit cycle is done, although
- frame wasn't transmitted - this
- avoids having to wait for the upper
- layers to timeout on us, in the
- event of a tx underrun */
- netif_wake_queue(dev); /* Inform upper layers. */
- }
-#if ALLOW_DMA
- if (lp->use_dma && (status & RX_DMA)) {
- int count = readreg(dev, PP_DmaFrameCnt);
- while(count) {
- if (net_debug > 5)
- printk("%s: receiving %d DMA frames\n", dev->name, count);
- if (net_debug > 2 && count >1)
- printk("%s: receiving %d DMA frames\n", dev->name, count);
- dma_rx(dev);
- if (--count == 0)
- count = readreg(dev, PP_DmaFrameCnt);
- if (net_debug > 2 && count > 0)
- printk("%s: continuing with %d DMA frames\n", dev->name, count);
- }
- }
-#endif
- break;
- case ISQ_RX_MISS_EVENT:
- dev->stats.rx_missed_errors += (status >> 6);
- break;
- case ISQ_TX_COL_EVENT:
- dev->stats.collisions += (status >> 6);
- break;
- }
- }
- return IRQ_RETVAL(handled);
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ cs89_dbg(0, debug, "%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)));
+
+ return 0;
}
-static void
-count_rx_errors(int status, struct net_device *dev)
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void net_poll_controller(struct net_device *dev)
{
- dev->stats.rx_errors++;
- if (status & RX_RUNT)
- dev->stats.rx_length_errors++;
- if (status & RX_EXTRA_DATA)
- dev->stats.rx_length_errors++;
- if ((status & RX_CRC_ERROR) && !(status & (RX_EXTRA_DATA|RX_RUNT)))
- /* per str 172 */
- dev->stats.rx_crc_errors++;
- if (status & RX_DRIBBLE)
- dev->stats.rx_frame_errors++;
+ disable_irq(dev->irq);
+ net_interrupt(dev->irq, dev);
+ enable_irq(dev->irq);
}
+#endif
-/* We have a good packet(s), get it/them out of the buffers. */
-static void
-net_rx(struct net_device *dev)
+static const struct net_device_ops net_ops = {
+ .ndo_open = net_open,
+ .ndo_stop = net_close,
+ .ndo_tx_timeout = net_timeout,
+ .ndo_start_xmit = net_send_packet,
+ .ndo_get_stats = net_get_stats,
+ .ndo_set_rx_mode = set_multicast_list,
+ .ndo_set_mac_address = set_mac_address,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = net_poll_controller,
+#endif
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
+static void __init reset_chip(struct net_device *dev)
{
- struct sk_buff *skb;
- int status, length;
+#if !defined(CONFIG_MACH_MX31ADS)
+#if !defined(CS89x0_NONISA_IRQ)
+ struct net_local *lp = netdev_priv(dev);
+#endif /* CS89x0_NONISA_IRQ */
+ int reset_start_time;
- int ioaddr = dev->base_addr;
- status = readword(ioaddr, RX_FRAME_PORT);
- length = readword(ioaddr, RX_FRAME_PORT);
+ writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
- if ((status & RX_OK) == 0) {
- count_rx_errors(status, dev);
- return;
+ /* wait 30 ms */
+ msleep(30);
+
+#if !defined(CS89x0_NONISA_IRQ)
+ if (lp->chip_type != CS8900) {
+ /* Hardware problem requires PNP registers to be reconfigured after a reset */
+ iowrite16(PP_CS8920_ISAINT, lp->virt_addr + ADD_PORT);
+ iowrite8(dev->irq, lp->virt_addr + DATA_PORT);
+ iowrite8(0, lp->virt_addr + DATA_PORT + 1);
+
+ iowrite16(PP_CS8920_ISAMemB, lp->virt_addr + ADD_PORT);
+ iowrite8((dev->mem_start >> 16) & 0xff,
+ lp->virt_addr + DATA_PORT);
+ iowrite8((dev->mem_start >> 8) & 0xff,
+ lp->virt_addr + DATA_PORT + 1);
}
+#endif /* CS89x0_NONISA_IRQ */
- /* Malloc up new buffer. */
- 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);
+ /* Wait until the chip is reset */
+ reset_start_time = jiffies;
+ while ((readreg(dev, PP_SelfST) & INIT_DONE) == 0 &&
+ jiffies - reset_start_time < 2)
+ ;
+#endif /* !CONFIG_MACH_MX31ADS */
+}
+
+/* This is the real probe routine.
+ * Linux has a history of friendly device probes on the ISA bus.
+ * A good device probes avoids doing writes, and
+ * verifies that the correct device exists and functions.
+ * Return 0 on success.
+ */
+static int __init
+cs89x0_probe1(struct net_device *dev, void __iomem *ioaddr, int modular)
+{
+ struct net_local *lp = netdev_priv(dev);
+ int i;
+ int tmp;
+ unsigned rev_type = 0;
+ int eeprom_buff[CHKSUM_LEN];
+ int retval;
+
+ /* Initialize the device structure. */
+ if (!modular) {
+ memset(lp, 0, sizeof(*lp));
+ spin_lock_init(&lp->lock);
+#ifndef MODULE
+#if ALLOW_DMA
+ if (g_cs89x0_dma) {
+ lp->use_dma = 1;
+ lp->dma = g_cs89x0_dma;
+ lp->dmasize = 16; /* Could make this an option... */
+ }
+#endif
+ lp->force = g_cs89x0_media__force;
#endif
- dev->stats.rx_dropped++;
- return;
}
- skb_reserve(skb, 2); /* longword align L3 header */
- readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1);
- if (length & 1)
- skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT);
+ pr_debug("PP_addr at %p[%x]: 0x%x\n",
+ ioaddr, ADD_PORT, ioread16(ioaddr + ADD_PORT));
+ iowrite16(PP_ChipID, ioaddr + ADD_PORT);
- if (net_debug > 3) {
- printk( "%s: received %d byte packet of type %x\n",
- dev->name, length,
- (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
+ tmp = ioread16(ioaddr + DATA_PORT);
+ if (tmp != CHIP_EISA_ID_SIG) {
+ pr_debug("%s: incorrect signature at %p[%x]: 0x%x!="
+ CHIP_EISA_ID_SIG_STR "\n",
+ dev->name, ioaddr, DATA_PORT, tmp);
+ retval = -ENODEV;
+ goto out1;
}
- skb->protocol=eth_type_trans(skb,dev);
- netif_rx(skb);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += length;
-}
+ lp->virt_addr = ioaddr;
-#if ALLOW_DMA
-static void release_dma_buff(struct net_local *lp)
-{
- if (lp->dma_buff) {
- free_pages((unsigned long)(lp->dma_buff), get_order(lp->dmasize * 1024));
- lp->dma_buff = NULL;
+ /* get the chip type */
+ rev_type = readreg(dev, PRODUCT_ID_ADD);
+ lp->chip_type = rev_type & ~REVISON_BITS;
+ lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
+
+ /* Check the chip type and revision in order to set the correct
+ * send command. CS8920 revision C and CS8900 revision F can use
+ * the faster send.
+ */
+ lp->send_cmd = TX_AFTER_381;
+ if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
+ lp->send_cmd = TX_NOW;
+ if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
+ lp->send_cmd = TX_NOW;
+
+ pr_info_once("%s\n", version);
+
+ pr_info("%s: cs89%c0%s rev %c found at %p ",
+ dev->name,
+ lp->chip_type == CS8900 ? '0' : '2',
+ lp->chip_type == CS8920M ? "M" : "",
+ lp->chip_revision,
+ lp->virt_addr);
+
+ reset_chip(dev);
+
+ /* Here we read the current configuration of the chip.
+ * If there is no Extended EEPROM then the idea is to not disturb
+ * the chip configuration, it should have been correctly setup by
+ * automatic EEPROM read on reset. So, if the chip says it read
+ * the EEPROM the driver will always do *something* instead of
+ * complain that adapter_cnf is 0.
+ */
+
+ if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
+ (EEPROM_OK | EEPROM_PRESENT)) {
+ /* Load the MAC. */
+ for (i = 0; i < ETH_ALEN / 2; i++) {
+ unsigned int Addr;
+ Addr = readreg(dev, PP_IA + i * 2);
+ dev->dev_addr[i * 2] = Addr & 0xFF;
+ dev->dev_addr[i * 2 + 1] = Addr >> 8;
+ }
+
+ /* Load the Adapter Configuration.
+ * Note: Barring any more specific information from some
+ * other source (ie EEPROM+Schematics), we would not know
+ * how to operate a 10Base2 interface on the AUI port.
+ * However, since we do read the status of HCB1 and use
+ * settings that always result in calls to control_dc_dc(dev,0)
+ * a BNC interface should work if the enable pin
+ * (dc/dc converter) is on HCB1.
+ * It will be called AUI however.
+ */
+
+ lp->adapter_cnf = 0;
+ i = readreg(dev, PP_LineCTL);
+ /* Preserve the setting of the HCB1 pin. */
+ if ((i & (HCB1 | HCB1_ENBL)) == (HCB1 | HCB1_ENBL))
+ lp->adapter_cnf |= A_CNF_DC_DC_POLARITY;
+ /* Save the sqelch bit */
+ if ((i & LOW_RX_SQUELCH) == LOW_RX_SQUELCH)
+ lp->adapter_cnf |= A_CNF_EXTND_10B_2 | A_CNF_LOW_RX_SQUELCH;
+ /* Check if the card is in 10Base-t only mode */
+ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == 0)
+ lp->adapter_cnf |= A_CNF_10B_T | A_CNF_MEDIA_10B_T;
+ /* Check if the card is in AUI only mode */
+ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUI_ONLY)
+ lp->adapter_cnf |= A_CNF_AUI | A_CNF_MEDIA_AUI;
+ /* Check if the card is in Auto mode. */
+ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUTO_AUI_10BASET)
+ lp->adapter_cnf |= A_CNF_AUI | A_CNF_10B_T |
+ A_CNF_MEDIA_AUI | A_CNF_MEDIA_10B_T | A_CNF_MEDIA_AUTO;
+
+ cs89_dbg(1, info, "%s: PP_LineCTL=0x%x, adapter_cnf=0x%x\n",
+ dev->name, i, lp->adapter_cnf);
+
+ /* IRQ. Other chips already probe, see below. */
+ if (lp->chip_type == CS8900)
+ lp->isa_config = readreg(dev, PP_CS8900_ISAINT) & INT_NO_MASK;
+
+ pr_cont("[Cirrus EEPROM] ");
}
-}
-#endif
-/* The inverse routine to net_open(). */
-static int
-net_close(struct net_device *dev)
-{
-#if ALLOW_DMA
- struct net_local *lp = netdev_priv(dev);
-#endif
+ pr_cont("\n");
- netif_stop_queue(dev);
+ /* First check to see if an EEPROM is attached. */
- writereg(dev, PP_RxCFG, 0);
- writereg(dev, PP_TxCFG, 0);
- writereg(dev, PP_BufCFG, 0);
- writereg(dev, PP_BusCTL, 0);
+ if ((readreg(dev, PP_SelfST) & EEPROM_PRESENT) == 0)
+ pr_warn("No EEPROM, relying on command line....\n");
+ else if (get_eeprom_data(dev, START_EEPROM_DATA, CHKSUM_LEN, eeprom_buff) < 0) {
+ pr_warn("EEPROM read failed, relying on command line\n");
+ } else if (get_eeprom_cksum(START_EEPROM_DATA, CHKSUM_LEN, eeprom_buff) < 0) {
+ /* Check if the chip was able to read its own configuration starting
+ at 0 in the EEPROM*/
+ if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) !=
+ (EEPROM_OK | EEPROM_PRESENT))
+ pr_warn("Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command line\n");
- free_irq(dev->irq, dev);
+ } else {
+ /* This reads an extended EEPROM that is not documented
+ * in the CS8900 datasheet.
+ */
-#if ALLOW_DMA
- if (lp->use_dma && lp->dma) {
- free_dma(dev->dma);
- release_dma_buff(lp);
+ /* get transmission control word but keep the autonegotiation bits */
+ if (!lp->auto_neg_cnf)
+ lp->auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET / 2];
+ /* Store adapter configuration */
+ if (!lp->adapter_cnf)
+ lp->adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET / 2];
+ /* Store ISA configuration */
+ lp->isa_config = eeprom_buff[ISA_CNF_OFFSET / 2];
+ dev->mem_start = eeprom_buff[PACKET_PAGE_OFFSET / 2] << 8;
+
+ /* eeprom_buff has 32-bit ints, so we can't just memcpy it */
+ /* store the initial memory base address */
+ for (i = 0; i < ETH_ALEN / 2; i++) {
+ dev->dev_addr[i * 2] = eeprom_buff[i];
+ dev->dev_addr[i * 2 + 1] = eeprom_buff[i] >> 8;
+ }
+ cs89_dbg(1, debug, "%s: new adapter_cnf: 0x%x\n",
+ dev->name, lp->adapter_cnf);
}
+
+ /* allow them to force multiple transceivers. If they force multiple, autosense */
+ {
+ int count = 0;
+ if (lp->force & FORCE_RJ45) {
+ lp->adapter_cnf |= A_CNF_10B_T;
+ count++;
+ }
+ if (lp->force & FORCE_AUI) {
+ lp->adapter_cnf |= A_CNF_AUI;
+ count++;
+ }
+ if (lp->force & FORCE_BNC) {
+ lp->adapter_cnf |= A_CNF_10B_2;
+ count++;
+ }
+ if (count > 1)
+ lp->adapter_cnf |= A_CNF_MEDIA_AUTO;
+ else if (lp->force & FORCE_RJ45)
+ lp->adapter_cnf |= A_CNF_MEDIA_10B_T;
+ else if (lp->force & FORCE_AUI)
+ lp->adapter_cnf |= A_CNF_MEDIA_AUI;
+ else if (lp->force & FORCE_BNC)
+ lp->adapter_cnf |= A_CNF_MEDIA_10B_2;
+ }
+
+ cs89_dbg(1, debug, "%s: after force 0x%x, adapter_cnf=0x%x\n",
+ dev->name, lp->force, lp->adapter_cnf);
+
+ /* FIXME: We don't let you set dc-dc polarity or low RX squelch from the command line: add it here */
+
+ /* FIXME: We don't let you set the IMM bit from the command line: add it to lp->auto_neg_cnf here */
+
+ /* FIXME: we don't set the Ethernet address on the command line. Use
+ * ifconfig IFACE hw ether AABBCCDDEEFF
+ */
+
+ pr_info("media %s%s%s",
+ (lp->adapter_cnf & A_CNF_10B_T) ? "RJ-45," : "",
+ (lp->adapter_cnf & A_CNF_AUI) ? "AUI," : "",
+ (lp->adapter_cnf & A_CNF_10B_2) ? "BNC," : "");
+
+ lp->irq_map = 0xffff;
+
+ /* If this is a CS8900 then no pnp soft */
+ if (lp->chip_type != CS8900 &&
+ /* Check if the ISA IRQ has been set */
+ (i = readreg(dev, PP_CS8920_ISAINT) & 0xff,
+ (i != 0 && i < CS8920_NO_INTS))) {
+ if (!dev->irq)
+ dev->irq = i;
+ } else {
+ i = lp->isa_config & INT_NO_MASK;
+#ifndef CONFIG_CS89x0_PLATFORM
+ if (lp->chip_type == CS8900) {
+#ifdef CS89x0_NONISA_IRQ
+ i = cs8900_irq_map[0];
+#else
+ /* Translate the IRQ using the IRQ mapping table. */
+ if (i >= ARRAY_SIZE(cs8900_irq_map))
+ pr_err("invalid ISA interrupt number %d\n", i);
+ else
+ i = cs8900_irq_map[i];
+
+ lp->irq_map = CS8900_IRQ_MAP; /* fixed IRQ map for CS8900 */
+ } else {
+ int irq_map_buff[IRQ_MAP_LEN/2];
+
+ if (get_eeprom_data(dev, IRQ_MAP_EEPROM_DATA,
+ IRQ_MAP_LEN / 2,
+ irq_map_buff) >= 0) {
+ if ((irq_map_buff[0] & 0xff) == PNP_IRQ_FRMT)
+ lp->irq_map = ((irq_map_buff[0] >> 8) |
+ (irq_map_buff[1] << 8));
+ }
#endif
+ }
+#endif
+ if (!dev->irq)
+ dev->irq = i;
+ }
- /* Update the statistics here. */
- return 0;
-}
+ pr_cont(" IRQ %d", dev->irq);
-/* Get the current statistics. This may be called with the card open or
- closed. */
-static struct net_device_stats *
-net_get_stats(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- unsigned long flags;
+#if ALLOW_DMA
+ if (lp->use_dma) {
+ get_dma_channel(dev);
+ pr_cont(", DMA %d", dev->dma);
+ } else
+#endif
+ pr_cont(", programmed I/O");
- spin_lock_irqsave(&lp->lock, flags);
- /* Update the statistics from the device registers. */
- dev->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
- dev->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
- spin_unlock_irqrestore(&lp->lock, flags);
+ /* print the ethernet address. */
+ pr_cont(", MAC %pM\n", dev->dev_addr);
- return &dev->stats;
+ dev->netdev_ops = &net_ops;
+ dev->watchdog_timeo = HZ;
+
+ cs89_dbg(0, info, "cs89x0_probe1() successful\n");
+
+ retval = register_netdev(dev);
+ if (retval)
+ goto out2;
+ return 0;
+out2:
+ iowrite16(PP_ChipID, lp->virt_addr + ADD_PORT);
+out1:
+ return retval;
}
-static void set_multicast_list(struct net_device *dev)
+#ifndef CONFIG_CS89x0_PLATFORM
+/*
+ * This function converts the I/O port addres used by the cs89x0_probe() and
+ * init_module() functions to the I/O memory address used by the
+ * cs89x0_probe1() function.
+ */
+static int __init
+cs89x0_ioport_probe(struct net_device *dev, unsigned long ioport, int modular)
{
struct net_local *lp = netdev_priv(dev);
- unsigned long flags;
+ int ret;
+ void __iomem *io_mem;
- spin_lock_irqsave(&lp->lock, flags);
- if(dev->flags&IFF_PROMISC)
- {
- lp->rx_mode = RX_ALL_ACCEPT;
+ if (!lp)
+ return -ENOMEM;
+
+ dev->base_addr = ioport;
+
+ if (!request_region(ioport, NETCARD_IO_EXTENT, DRV_NAME)) {
+ ret = -EBUSY;
+ goto out;
}
- else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev))
- {
- /* The multicast-accept list is initialized to accept-all, and we
- rely on higher-level filtering for now. */
- lp->rx_mode = RX_MULTCAST_ACCEPT;
+
+ io_mem = ioport_map(ioport & ~3, NETCARD_IO_EXTENT);
+ if (!io_mem) {
+ ret = -ENOMEM;
+ goto release;
}
- else
- lp->rx_mode = 0;
- writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
+ /* if they give us an odd I/O address, then do ONE write to
+ * the address port, to get it back to address zero, where we
+ * expect to find the EISA signature word. An IO with a base of 0x3
+ * will skip the test for the ADD_PORT.
+ */
+ if (ioport & 1) {
+ cs89_dbg(1, info, "%s: odd ioaddr 0x%lx\n", dev->name, ioport);
+ if ((ioport & 2) != 2) {
+ if ((ioread16(io_mem + ADD_PORT) & ADD_MASK) !=
+ ADD_SIG) {
+ pr_err("%s: bad signature 0x%x\n",
+ dev->name, ioread16(io_mem + ADD_PORT));
+ ret = -ENODEV;
+ goto unmap;
+ }
+ }
+ }
- /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */
- writereg(dev, PP_RxCFG, lp->curr_rx_cfg |
- (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));
- spin_unlock_irqrestore(&lp->lock, flags);
+ ret = cs89x0_probe1(dev, io_mem, modular);
+ if (!ret)
+ goto out;
+unmap:
+ ioport_unmap(io_mem);
+release:
+ release_region(ioport, NETCARD_IO_EXTENT);
+out:
+ return ret;
}
+#ifndef MODULE
+/* Check for a network adaptor of this type, and return '0' iff one exists.
+ * If dev->base_addr == 0, probe all likely locations.
+ * If dev->base_addr == 1, always return failure.
+ * If dev->base_addr == 2, allocate space for the device and return success
+ * (detachable devices only).
+ * Return 0 on success.
+ */
-static int set_mac_address(struct net_device *dev, void *p)
+struct net_device * __init cs89x0_probe(int unit)
{
- int i;
- struct sockaddr *addr = p;
-
- if (netif_running(dev))
- return -EBUSY;
+ struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
+ unsigned *port;
+ int err = 0;
+ int irq;
+ int io;
- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ if (!dev)
+ return ERR_PTR(-ENODEV);
- if (net_debug)
- printk("%s: Setting MAC address to %pM.\n",
- dev->name, dev->dev_addr);
+ sprintf(dev->name, "eth%d", unit);
+ netdev_boot_setup_check(dev);
+ io = dev->base_addr;
+ irq = dev->irq;
- /* 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));
+ cs89_dbg(0, info, "cs89x0_probe(0x%x)\n", io);
- return 0;
+ if (io > 0x1ff) { /* Check a single specified location. */
+ err = cs89x0_ioport_probe(dev, io, 0);
+ } else if (io != 0) { /* Don't probe at all. */
+ err = -ENXIO;
+ } else {
+ for (port = netcard_portlist; *port; port++) {
+ if (cs89x0_ioport_probe(dev, *port, 0) == 0)
+ break;
+ dev->irq = irq;
+ }
+ if (!*port)
+ err = -ENODEV;
+ }
+ if (err)
+ goto out;
+ return dev;
+out:
+ free_netdev(dev);
+ pr_warn("no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n");
+ return ERR_PTR(err);
}
+#endif
+#endif
#if defined(MODULE) && !defined(CONFIG_CS89x0_PLATFORM)
static struct net_device *dev_cs89x0;
-/*
- * Support the 'debug' module parm even if we're compiled for non-debug to
+/* Support the 'debug' module parm even if we're compiled for non-debug to
* avoid breaking someone's startup scripts
*/
@@ -1764,11 +1755,11 @@ static int io;
static int irq;
static int debug;
static char media[8];
-static int duplex=-1;
+static int duplex = -1;
static int use_dma; /* These generate unused var warnings if ALLOW_DMA = 0 */
static int dma;
-static int dmasize=16; /* or 64 */
+static int dmasize = 16; /* or 64 */
module_param(io, int, 0);
module_param(irq, int, 0);
@@ -1801,32 +1792,28 @@ MODULE_PARM_DESC(use_dma , "(ignored)");
MODULE_AUTHOR("Mike Cruse, Russwll Nelson <nelson@crynwr.com>, Andrew Morton");
MODULE_LICENSE("GPL");
-
/*
-* media=t - specify media type
- or media=2
- or media=aui
- or medai=auto
-* duplex=0 - specify forced half/full/autonegotiate duplex
-* debug=# - debug level
-
-
-* Default Chip Configuration:
- * DMA Burst = enabled
- * IOCHRDY Enabled = enabled
- * UseSA = enabled
- * CS8900 defaults to half-duplex if not specified on command-line
- * CS8920 defaults to autoneg if not specified on command-line
- * Use reset defaults for other config parameters
-
-* Assumptions:
- * media type specified is supported (circuitry is present)
- * if memory address is > 1MB, then required mem decode hw is present
- * if 10B-2, then agent other than driver will enable DC/DC converter
- (hw or software util)
-
-
-*/
+ * media=t - specify media type
+ * or media=2
+ * or media=aui
+ * or medai=auto
+ * duplex=0 - specify forced half/full/autonegotiate duplex
+ * debug=# - debug level
+ *
+ * Default Chip Configuration:
+ * DMA Burst = enabled
+ * IOCHRDY Enabled = enabled
+ * UseSA = enabled
+ * CS8900 defaults to half-duplex if not specified on command-line
+ * CS8920 defaults to autoneg if not specified on command-line
+ * Use reset defaults for other config parameters
+ *
+ * Assumptions:
+ * media type specified is supported (circuitry is present)
+ * if memory address is > 1MB, then required mem decode hw is present
+ * if 10B-2, then agent other than driver will enable DC/DC converter
+ * (hw or software util)
+ */
int __init init_module(void)
{
@@ -1856,8 +1843,8 @@ int __init init_module(void)
spin_lock_init(&lp->lock);
- /* boy, they'd better get these right */
- if (!strcmp(media, "rj45"))
+ /* boy, they'd better get these right */
+ if (!strcmp(media, "rj45"))
lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;
else if (!strcmp(media, "aui"))
lp->adapter_cnf = A_CNF_MEDIA_AUI | A_CNF_AUI;
@@ -1866,27 +1853,28 @@ int __init init_module(void)
else
lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;
- if (duplex==-1)
+ if (duplex == -1)
lp->auto_neg_cnf = AUTO_NEG_ENABLE;
- if (io == 0) {
- printk(KERN_ERR "cs89x0.c: Module autoprobing not allowed.\n");
- printk(KERN_ERR "cs89x0.c: Append io=0xNNN\n");
- ret = -EPERM;
+ if (io == 0) {
+ pr_err("Module autoprobing not allowed\n");
+ pr_err("Append io=0xNNN\n");
+ ret = -EPERM;
goto out;
- } else if (io <= 0x1ff) {
+ } else if (io <= 0x1ff) {
ret = -ENXIO;
goto out;
}
#if ALLOW_DMA
if (use_dma && dmasize != 16 && dmasize != 64) {
- printk(KERN_ERR "cs89x0.c: dma size must be either 16K or 64K, not %dK\n", dmasize);
+ pr_err("dma size must be either 16K or 64K, not %dK\n",
+ dmasize);
ret = -EPERM;
goto out;
}
#endif
- ret = cs89x0_probe1(dev, io, 1);
+ ret = cs89x0_ioport_probe(dev, io, 1);
if (ret)
goto out;
@@ -1900,8 +1888,11 @@ out:
void __exit
cleanup_module(void)
{
+ struct net_local *lp = netdev_priv(dev_cs89x0);
+
unregister_netdev(dev_cs89x0);
- writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID);
+ iowrite16(PP_ChipID, lp->virt_addr + ADD_PORT);
+ ioport_unmap(lp->virt_addr);
release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
free_netdev(dev_cs89x0);
}
@@ -1913,6 +1904,7 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev)
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
struct net_local *lp;
struct resource *mem_res;
+ void __iomem *virt_addr;
int err;
if (!dev)
@@ -1923,29 +1915,28 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev)
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->irq = platform_get_irq(pdev, 0);
if (mem_res == NULL || dev->irq <= 0) {
- dev_warn(&dev->dev, "memory/interrupt resource missing.\n");
+ dev_warn(&dev->dev, "memory/interrupt resource missing\n");
err = -ENXIO;
goto free;
}
- lp->phys_addr = mem_res->start;
lp->size = resource_size(mem_res);
- if (!request_mem_region(lp->phys_addr, lp->size, DRV_NAME)) {
- dev_warn(&dev->dev, "request_mem_region() failed.\n");
+ if (!request_mem_region(mem_res->start, lp->size, DRV_NAME)) {
+ dev_warn(&dev->dev, "request_mem_region() failed\n");
err = -EBUSY;
goto free;
}
- lp->virt_addr = ioremap(lp->phys_addr, lp->size);
- if (!lp->virt_addr) {
- dev_warn(&dev->dev, "ioremap() failed.\n");
+ virt_addr = ioremap(mem_res->start, lp->size);
+ if (!virt_addr) {
+ dev_warn(&dev->dev, "ioremap() failed\n");
err = -ENOMEM;
goto release;
}
- err = cs89x0_probe1(dev, (unsigned long)lp->virt_addr, 0);
+ err = cs89x0_probe1(dev, virt_addr, 0);
if (err) {
- dev_warn(&dev->dev, "no cs8900 or cs8920 detected.\n");
+ dev_warn(&dev->dev, "no cs8900 or cs8920 detected\n");
goto unmap;
}
@@ -1953,9 +1944,9 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev)
return 0;
unmap:
- iounmap(lp->virt_addr);
+ iounmap(virt_addr);
release:
- release_mem_region(lp->phys_addr, lp->size);
+ release_mem_region(mem_res->start, lp->size);
free:
free_netdev(dev);
return err;
@@ -1965,10 +1956,16 @@ static int cs89x0_platform_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct net_local *lp = netdev_priv(dev);
+ struct resource *mem_res;
+ /* This platform_get_resource() call will not return NULL, because
+ * the same call in cs89x0_platform_probe() has returned a non NULL
+ * value.
+ */
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
unregister_netdev(dev);
iounmap(lp->virt_addr);
- release_mem_region(lp->phys_addr, lp->size);
+ release_mem_region(mem_res->start, lp->size);
free_netdev(dev);
return 0;
}
@@ -1996,13 +1993,3 @@ static void __exit cs89x0_cleanup(void)
module_exit(cs89x0_cleanup);
#endif /* CONFIG_CS89x0_PLATFORM */
-
-/*
- * Local variables:
- * version-control: t
- * kept-new-versions: 5
- * c-indent-level: 8
- * tab-width: 8
- * End:
- *
- */
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 77b4e873f91c..8132c785cea8 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -944,8 +944,7 @@ static void enic_update_multicast_addr_list(struct enic *enic)
for (i = 0; i < enic->mc_count; i++) {
for (j = 0; j < mc_count; j++)
- if (compare_ether_addr(enic->mc_addr[i],
- mc_addr[j]) == 0)
+ if (ether_addr_equal(enic->mc_addr[i], mc_addr[j]))
break;
if (j == mc_count)
enic_dev_del_addr(enic, enic->mc_addr[i]);
@@ -953,8 +952,7 @@ static void enic_update_multicast_addr_list(struct enic *enic)
for (i = 0; i < mc_count; i++) {
for (j = 0; j < enic->mc_count; j++)
- if (compare_ether_addr(mc_addr[i],
- enic->mc_addr[j]) == 0)
+ if (ether_addr_equal(mc_addr[i], enic->mc_addr[j]))
break;
if (j == enic->mc_count)
enic_dev_add_addr(enic, mc_addr[i]);
@@ -999,8 +997,7 @@ static void enic_update_unicast_addr_list(struct enic *enic)
for (i = 0; i < enic->uc_count; i++) {
for (j = 0; j < uc_count; j++)
- if (compare_ether_addr(enic->uc_addr[i],
- uc_addr[j]) == 0)
+ if (ether_addr_equal(enic->uc_addr[i], uc_addr[j]))
break;
if (j == uc_count)
enic_dev_del_addr(enic, enic->uc_addr[i]);
@@ -1008,8 +1005,7 @@ static void enic_update_unicast_addr_list(struct enic *enic)
for (i = 0; i < uc_count; i++) {
for (j = 0; j < enic->uc_count; j++)
- if (compare_ether_addr(uc_addr[i],
- enic->uc_addr[j]) == 0)
+ if (ether_addr_equal(uc_addr[i], enic->uc_addr[j]))
break;
if (j == enic->uc_count)
enic_dev_add_addr(enic, uc_addr[i]);
@@ -1193,18 +1189,16 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
if (err)
return err;
- NLA_PUT_U16(skb, IFLA_PORT_REQUEST, pp->request);
- NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response);
- if (pp->set & ENIC_SET_NAME)
- NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
- pp->name);
- if (pp->set & ENIC_SET_INSTANCE)
- NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
- pp->instance_uuid);
- if (pp->set & ENIC_SET_HOST)
- NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
- pp->host_uuid);
-
+ if (nla_put_u16(skb, IFLA_PORT_REQUEST, pp->request) ||
+ nla_put_u16(skb, IFLA_PORT_RESPONSE, response) ||
+ ((pp->set & ENIC_SET_NAME) &&
+ nla_put(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX, pp->name)) ||
+ ((pp->set & ENIC_SET_INSTANCE) &&
+ nla_put(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
+ pp->instance_uuid)) ||
+ ((pp->set & ENIC_SET_HOST) &&
+ nla_put(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX, pp->host_uuid)))
+ goto nla_put_failure;
return 0;
nla_put_failure:
diff --git a/drivers/net/ethernet/cisco/enic/enic_pp.c b/drivers/net/ethernet/cisco/enic/enic_pp.c
index dafea1ecb7b1..43464f0a4f99 100644
--- a/drivers/net/ethernet/cisco/enic/enic_pp.c
+++ b/drivers/net/ethernet/cisco/enic/enic_pp.c
@@ -184,7 +184,7 @@ static int (*enic_pp_handlers[])(struct enic *enic, int vf,
};
static const int enic_pp_handlers_count =
- sizeof(enic_pp_handlers)/sizeof(*enic_pp_handlers);
+ ARRAY_SIZE(enic_pp_handlers);
static int enic_pp_preassociate(struct enic *enic, int vf,
struct enic_port_profile *prev_pp, int *restore_pp)
diff --git a/drivers/net/ethernet/davicom/Kconfig b/drivers/net/ethernet/davicom/Kconfig
index 972b62b31837..9745fe5e8039 100644
--- a/drivers/net/ethernet/davicom/Kconfig
+++ b/drivers/net/ethernet/davicom/Kconfig
@@ -4,7 +4,7 @@
config DM9000
tristate "DM9000 support"
- depends on ARM || BLACKFIN || MIPS
+ depends on ARM || BLACKFIN || MIPS || COLDFIRE
select CRC32
select NET_CORE
select MII
diff --git a/drivers/net/ethernet/dec/ewrk3.c b/drivers/net/ethernet/dec/ewrk3.c
index 1879f84a25a3..17ae8c619680 100644
--- a/drivers/net/ethernet/dec/ewrk3.c
+++ b/drivers/net/ethernet/dec/ewrk3.c
@@ -1016,7 +1016,8 @@ static int ewrk3_rx(struct net_device *dev)
} else {
lp->pktStats.multicast++;
}
- } else if (compare_ether_addr(p, dev->dev_addr) == 0) {
+ } else if (ether_addr_equal(p,
+ dev->dev_addr)) {
lp->pktStats.unicast++;
}
lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */
diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
index 68f1c39184df..61cc09342865 100644
--- a/drivers/net/ethernet/dec/tulip/de2104x.c
+++ b/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -1380,6 +1380,7 @@ static void de_free_rings (struct de_private *de)
static int de_open (struct net_device *dev)
{
struct de_private *de = netdev_priv(dev);
+ const int irq = de->pdev->irq;
int rc;
netif_dbg(de, ifup, dev, "enabling interface\n");
@@ -1394,10 +1395,9 @@ static int de_open (struct net_device *dev)
dw32(IntrMask, 0);
- rc = request_irq(dev->irq, de_interrupt, IRQF_SHARED, dev->name, dev);
+ rc = request_irq(irq, de_interrupt, IRQF_SHARED, dev->name, dev);
if (rc) {
- netdev_err(dev, "IRQ %d request failure, err=%d\n",
- dev->irq, rc);
+ netdev_err(dev, "IRQ %d request failure, err=%d\n", irq, rc);
goto err_out_free;
}
@@ -1413,7 +1413,7 @@ static int de_open (struct net_device *dev)
return 0;
err_out_free_irq:
- free_irq(dev->irq, dev);
+ free_irq(irq, dev);
err_out_free:
de_free_rings(de);
return rc;
@@ -1434,7 +1434,7 @@ static int de_close (struct net_device *dev)
netif_carrier_off(dev);
spin_unlock_irqrestore(&de->lock, flags);
- free_irq(dev->irq, dev);
+ free_irq(de->pdev->irq, dev);
de_free_rings(de);
de_adapter_sleep(de);
@@ -1444,6 +1444,7 @@ static int de_close (struct net_device *dev)
static void de_tx_timeout (struct net_device *dev)
{
struct de_private *de = netdev_priv(dev);
+ const int irq = de->pdev->irq;
netdev_dbg(dev, "NIC status %08x mode %08x sia %08x desc %u/%u/%u\n",
dr32(MacStatus), dr32(MacMode), dr32(SIAStatus),
@@ -1451,7 +1452,7 @@ static void de_tx_timeout (struct net_device *dev)
del_timer_sync(&de->media_timer);
- disable_irq(dev->irq);
+ disable_irq(irq);
spin_lock_irq(&de->lock);
de_stop_hw(de);
@@ -1459,12 +1460,12 @@ static void de_tx_timeout (struct net_device *dev)
netif_carrier_off(dev);
spin_unlock_irq(&de->lock);
- enable_irq(dev->irq);
+ enable_irq(irq);
/* Update the error counts. */
__de_get_stats(de);
- synchronize_irq(dev->irq);
+ synchronize_irq(irq);
de_clean_rings(de);
de_init_rings(de);
@@ -2024,8 +2025,6 @@ static int __devinit de_init_one (struct pci_dev *pdev,
goto err_out_res;
}
- dev->irq = pdev->irq;
-
/* obtain and check validity of PCI I/O address */
pciaddr = pci_resource_start(pdev, 1);
if (!pciaddr) {
@@ -2050,7 +2049,6 @@ static int __devinit de_init_one (struct pci_dev *pdev,
pciaddr, pci_name(pdev));
goto err_out_res;
}
- dev->base_addr = (unsigned long) regs;
de->regs = regs;
de_adapter_wake(de);
@@ -2078,11 +2076,9 @@ static int __devinit de_init_one (struct pci_dev *pdev,
goto err_out_iomap;
/* print info about board and interface just registered */
- netdev_info(dev, "%s at 0x%lx, %pM, IRQ %d\n",
+ netdev_info(dev, "%s at %p, %pM, IRQ %d\n",
de->de21040 ? "21040" : "21041",
- dev->base_addr,
- dev->dev_addr,
- dev->irq);
+ regs, dev->dev_addr, pdev->irq);
pci_set_drvdata(pdev, dev);
@@ -2130,9 +2126,11 @@ static int de_suspend (struct pci_dev *pdev, pm_message_t state)
rtnl_lock();
if (netif_running (dev)) {
+ const int irq = pdev->irq;
+
del_timer_sync(&de->media_timer);
- disable_irq(dev->irq);
+ disable_irq(irq);
spin_lock_irq(&de->lock);
de_stop_hw(de);
@@ -2141,12 +2139,12 @@ static int de_suspend (struct pci_dev *pdev, pm_message_t state)
netif_carrier_off(dev);
spin_unlock_irq(&de->lock);
- enable_irq(dev->irq);
+ enable_irq(irq);
/* Update the error counts. */
__de_get_stats(de);
- synchronize_irq(dev->irq);
+ synchronize_irq(irq);
de_clean_rings(de);
de_adapter_sleep(de);
diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c
index 18b106cc6d2b..d3cd489d11a2 100644
--- a/drivers/net/ethernet/dec/tulip/de4x5.c
+++ b/drivers/net/ethernet/dec/tulip/de4x5.c
@@ -1874,7 +1874,7 @@ de4x5_local_stats(struct net_device *dev, char *buf, int pkt_len)
} else {
lp->pktStats.multicast++;
}
- } else if (compare_ether_addr(buf, dev->dev_addr) == 0) {
+ } else if (ether_addr_equal(buf, dev->dev_addr)) {
lp->pktStats.unicast++;
}
diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c
index 1eccf4945485..4d6fe604fa64 100644
--- a/drivers/net/ethernet/dec/tulip/dmfe.c
+++ b/drivers/net/ethernet/dec/tulip/dmfe.c
@@ -150,6 +150,12 @@
#define DMFE_TX_TIMEOUT ((3*HZ)/2) /* tx packet time-out time 1.5 s" */
#define DMFE_TX_KICK (HZ/2) /* tx packet Kick-out time 0.5 s" */
+#define dw32(reg, val) iowrite32(val, ioaddr + (reg))
+#define dw16(reg, val) iowrite16(val, ioaddr + (reg))
+#define dr32(reg) ioread32(ioaddr + (reg))
+#define dr16(reg) ioread16(ioaddr + (reg))
+#define dr8(reg) ioread8(ioaddr + (reg))
+
#define DMFE_DBUG(dbug_now, msg, value) \
do { \
if (dmfe_debug || (dbug_now)) \
@@ -178,14 +184,6 @@
#define SROM_V41_CODE 0x14
-#define SROM_CLK_WRITE(data, ioaddr) \
- outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \
- udelay(5); \
- outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr); \
- udelay(5); \
- outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \
- udelay(5);
-
#define __CHK_IO_SIZE(pci_id, dev_rev) \
(( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x30) ) ? \
DM9102A_IO_SIZE: DM9102_IO_SIZE)
@@ -213,11 +211,11 @@ struct rx_desc {
struct dmfe_board_info {
u32 chip_id; /* Chip vendor/Device ID */
u8 chip_revision; /* Chip revision */
- struct DEVICE *next_dev; /* next device */
+ struct net_device *next_dev; /* next device */
struct pci_dev *pdev; /* PCI device */
spinlock_t lock;
- long ioaddr; /* I/O base address */
+ void __iomem *ioaddr; /* I/O base address */
u32 cr0_data;
u32 cr5_data;
u32 cr6_data;
@@ -320,20 +318,20 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *, struct DEVICE *);
static int dmfe_stop(struct DEVICE *);
static void dmfe_set_filter_mode(struct DEVICE *);
static const struct ethtool_ops netdev_ethtool_ops;
-static u16 read_srom_word(long ,int);
+static u16 read_srom_word(void __iomem *, int);
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 net_device *, unsigned long);
+static void dmfe_descriptor_init(struct net_device *);
static void allocate_rx_buffer(struct net_device *);
-static void update_cr6(u32, unsigned long);
+static void update_cr6(u32, void __iomem *);
static void send_filter_frame(struct DEVICE *);
static void dm9132_id_table(struct DEVICE *);
-static u16 phy_read(unsigned long, u8, u8, u32);
-static void phy_write(unsigned long, u8, u8, u16, u32);
-static void phy_write_1bit(unsigned long, u32);
-static u16 phy_read_1bit(unsigned long);
+static u16 phy_read(void __iomem *, u8, u8, u32);
+static void phy_write(void __iomem *, u8, u8, u16, u32);
+static void phy_write_1bit(void __iomem *, u32);
+static u16 phy_read_1bit(void __iomem *);
static u8 dmfe_sense_speed(struct dmfe_board_info *);
static void dmfe_process_mode(struct dmfe_board_info *);
static void dmfe_timer(unsigned long);
@@ -462,14 +460,16 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
db->buf_pool_dma_start = db->buf_pool_dma_ptr;
db->chip_id = ent->driver_data;
- db->ioaddr = pci_resource_start(pdev, 0);
+ /* IO type range. */
+ db->ioaddr = pci_iomap(pdev, 0, 0);
+ if (!db->ioaddr)
+ goto err_out_free_buf;
+
db->chip_revision = pdev->revision;
db->wol_mode = 0;
db->pdev = pdev;
- dev->base_addr = db->ioaddr;
- dev->irq = pdev->irq;
pci_set_drvdata(pdev, dev);
dev->netdev_ops = &netdev_ops;
dev->ethtool_ops = &netdev_ethtool_ops;
@@ -484,9 +484,10 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
db->chip_type = 0;
/* read 64 word srom data */
- for (i = 0; i < 64; i++)
+ for (i = 0; i < 64; i++) {
((__le16 *) db->srom)[i] =
cpu_to_le16(read_srom_word(db->ioaddr, i));
+ }
/* Set Node address */
for (i = 0; i < 6; i++)
@@ -494,16 +495,18 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
err = register_netdev (dev);
if (err)
- goto err_out_free_buf;
+ goto err_out_unmap;
dev_info(&dev->dev, "Davicom DM%04lx at pci%s, %pM, irq %d\n",
ent->driver_data >> 16,
- pci_name(pdev), dev->dev_addr, dev->irq);
+ pci_name(pdev), dev->dev_addr, pdev->irq);
pci_set_master(pdev);
return 0;
+err_out_unmap:
+ pci_iounmap(pdev, db->ioaddr);
err_out_free_buf:
pci_free_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
db->buf_pool_ptr, db->buf_pool_dma_ptr);
@@ -532,7 +535,7 @@ static void __devexit dmfe_remove_one (struct pci_dev *pdev)
if (dev) {
unregister_netdev(dev);
-
+ pci_iounmap(db->pdev, db->ioaddr);
pci_free_consistent(db->pdev, sizeof(struct tx_desc) *
DESC_ALL_CNT + 0x20, db->desc_pool_ptr,
db->desc_pool_dma_ptr);
@@ -555,13 +558,13 @@ static void __devexit dmfe_remove_one (struct pci_dev *pdev)
static int dmfe_open(struct DEVICE *dev)
{
- int ret;
struct dmfe_board_info *db = netdev_priv(dev);
+ const int irq = db->pdev->irq;
+ int ret;
DMFE_DBUG(0, "dmfe_open", 0);
- ret = request_irq(dev->irq, dmfe_interrupt,
- IRQF_SHARED, dev->name, dev);
+ ret = request_irq(irq, dmfe_interrupt, IRQF_SHARED, dev->name, dev);
if (ret)
return ret;
@@ -615,14 +618,14 @@ static int dmfe_open(struct DEVICE *dev)
static void dmfe_init_dm910x(struct DEVICE *dev)
{
struct dmfe_board_info *db = netdev_priv(dev);
- unsigned long ioaddr = db->ioaddr;
+ void __iomem *ioaddr = db->ioaddr;
DMFE_DBUG(0, "dmfe_init_dm910x()", 0);
/* Reset DM910x MAC controller */
- outl(DM910X_RESET, ioaddr + DCR0); /* RESET MAC */
+ dw32(DCR0, DM910X_RESET); /* RESET MAC */
udelay(100);
- outl(db->cr0_data, ioaddr + DCR0);
+ dw32(DCR0, db->cr0_data);
udelay(5);
/* Phy addr : DM910(A)2/DM9132/9801, phy address = 1 */
@@ -633,12 +636,12 @@ static void dmfe_init_dm910x(struct DEVICE *dev)
db->media_mode = dmfe_media_mode;
/* RESET Phyxcer Chip by GPR port bit 7 */
- outl(0x180, ioaddr + DCR12); /* Let bit 7 output port */
+ dw32(DCR12, 0x180); /* Let bit 7 output port */
if (db->chip_id == PCI_DM9009_ID) {
- outl(0x80, ioaddr + DCR12); /* Issue RESET signal */
+ dw32(DCR12, 0x80); /* Issue RESET signal */
mdelay(300); /* Delay 300 ms */
}
- outl(0x0, ioaddr + DCR12); /* Clear RESET signal */
+ dw32(DCR12, 0x0); /* Clear RESET signal */
/* Process Phyxcer Media Mode */
if ( !(db->media_mode & 0x10) ) /* Force 1M mode */
@@ -649,7 +652,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(dev, ioaddr);
+ dmfe_descriptor_init(dev);
/* Init CR6 to program DM910x operation */
update_cr6(db->cr6_data, ioaddr);
@@ -662,10 +665,10 @@ static void dmfe_init_dm910x(struct DEVICE *dev)
/* Init CR7, interrupt active bit */
db->cr7_data = CR7_DEFAULT;
- outl(db->cr7_data, ioaddr + DCR7);
+ dw32(DCR7, db->cr7_data);
/* Init CR15, Tx jabber and Rx watchdog timer */
- outl(db->cr15_data, ioaddr + DCR15);
+ dw32(DCR15, db->cr15_data);
/* Enable DM910X Tx/Rx function */
db->cr6_data |= CR6_RXSC | CR6_TXSC | 0x40000;
@@ -682,6 +685,7 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb,
struct DEVICE *dev)
{
struct dmfe_board_info *db = netdev_priv(dev);
+ void __iomem *ioaddr = db->ioaddr;
struct tx_desc *txptr;
unsigned long flags;
@@ -707,7 +711,7 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb,
}
/* Disable NIC interrupt */
- outl(0, dev->base_addr + DCR7);
+ dw32(DCR7, 0);
/* transmit this packet */
txptr = db->tx_insert_ptr;
@@ -721,11 +725,11 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb,
if ( (!db->tx_queue_cnt) && (db->tx_packet_cnt < TX_MAX_SEND_CNT) ) {
txptr->tdes0 = cpu_to_le32(0x80000000); /* Set owner bit */
db->tx_packet_cnt++; /* Ready to send */
- outl(0x1, dev->base_addr + DCR1); /* Issue Tx polling */
+ dw32(DCR1, 0x1); /* Issue Tx polling */
dev->trans_start = jiffies; /* saved time stamp */
} else {
db->tx_queue_cnt++; /* queue TX packet */
- outl(0x1, dev->base_addr + DCR1); /* Issue Tx polling */
+ dw32(DCR1, 0x1); /* Issue Tx polling */
}
/* Tx resource check */
@@ -734,7 +738,7 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb,
/* Restore CR7 to enable interrupt */
spin_unlock_irqrestore(&db->lock, flags);
- outl(db->cr7_data, dev->base_addr + DCR7);
+ dw32(DCR7, db->cr7_data);
/* free this SKB */
dev_kfree_skb(skb);
@@ -751,7 +755,7 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb,
static int dmfe_stop(struct DEVICE *dev)
{
struct dmfe_board_info *db = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = db->ioaddr;
DMFE_DBUG(0, "dmfe_stop", 0);
@@ -762,12 +766,12 @@ static int dmfe_stop(struct DEVICE *dev)
del_timer_sync(&db->timer);
/* Reset & stop DM910X board */
- outl(DM910X_RESET, ioaddr + DCR0);
- udelay(5);
- phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
+ dw32(DCR0, DM910X_RESET);
+ udelay(100);
+ phy_write(ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
/* free interrupt */
- free_irq(dev->irq, dev);
+ free_irq(db->pdev->irq, dev);
/* free allocated rx buffer */
dmfe_free_rxbuffer(db);
@@ -794,7 +798,7 @@ static irqreturn_t dmfe_interrupt(int irq, void *dev_id)
{
struct DEVICE *dev = dev_id;
struct dmfe_board_info *db = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = db->ioaddr;
unsigned long flags;
DMFE_DBUG(0, "dmfe_interrupt()", 0);
@@ -802,15 +806,15 @@ static irqreturn_t dmfe_interrupt(int irq, void *dev_id)
spin_lock_irqsave(&db->lock, flags);
/* Got DM910X status */
- db->cr5_data = inl(ioaddr + DCR5);
- outl(db->cr5_data, ioaddr + DCR5);
+ db->cr5_data = dr32(DCR5);
+ dw32(DCR5, db->cr5_data);
if ( !(db->cr5_data & 0xc1) ) {
spin_unlock_irqrestore(&db->lock, flags);
return IRQ_HANDLED;
}
/* Disable all interrupt in CR7 to solve the interrupt edge problem */
- outl(0, ioaddr + DCR7);
+ dw32(DCR7, 0);
/* Check system status */
if (db->cr5_data & 0x2000) {
@@ -838,11 +842,11 @@ static irqreturn_t dmfe_interrupt(int irq, void *dev_id)
if (db->dm910x_chk_mode & 0x2) {
db->dm910x_chk_mode = 0x4;
db->cr6_data |= 0x100;
- update_cr6(db->cr6_data, db->ioaddr);
+ update_cr6(db->cr6_data, ioaddr);
}
/* Restore CR7 to enable interrupt mask */
- outl(db->cr7_data, ioaddr + DCR7);
+ dw32(DCR7, db->cr7_data);
spin_unlock_irqrestore(&db->lock, flags);
return IRQ_HANDLED;
@@ -858,11 +862,14 @@ static irqreturn_t dmfe_interrupt(int irq, void *dev_id)
static void poll_dmfe (struct net_device *dev)
{
+ struct dmfe_board_info *db = netdev_priv(dev);
+ const int irq = db->pdev->irq;
+
/* disable_irq here is not very nice, but with the lockless
interrupt handler we have no other choice. */
- disable_irq(dev->irq);
- dmfe_interrupt (dev->irq, dev);
- enable_irq(dev->irq);
+ disable_irq(irq);
+ dmfe_interrupt (irq, dev);
+ enable_irq(irq);
}
#endif
@@ -873,7 +880,7 @@ static void poll_dmfe (struct net_device *dev)
static void dmfe_free_tx_pkt(struct DEVICE *dev, struct dmfe_board_info * db)
{
struct tx_desc *txptr;
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = db->ioaddr;
u32 tdes0;
txptr = db->tx_remove_ptr;
@@ -897,7 +904,7 @@ static void dmfe_free_tx_pkt(struct DEVICE *dev, struct dmfe_board_info * db)
db->tx_fifo_underrun++;
if ( !(db->cr6_data & CR6_SFT) ) {
db->cr6_data = db->cr6_data | CR6_SFT;
- update_cr6(db->cr6_data, db->ioaddr);
+ update_cr6(db->cr6_data, ioaddr);
}
}
if (tdes0 & 0x0100)
@@ -924,7 +931,7 @@ static void dmfe_free_tx_pkt(struct DEVICE *dev, struct dmfe_board_info * db)
txptr->tdes0 = cpu_to_le32(0x80000000); /* Set owner bit */
db->tx_packet_cnt++; /* Ready to send */
db->tx_queue_cnt--;
- outl(0x1, ioaddr + DCR1); /* Issue Tx polling */
+ dw32(DCR1, 0x1); /* Issue Tx polling */
dev->trans_start = jiffies; /* saved time stamp */
}
@@ -1087,12 +1094,7 @@ static void dmfe_ethtool_get_drvinfo(struct net_device *dev,
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
- if (np->pdev)
- strlcpy(info->bus_info, pci_name(np->pdev),
- sizeof(info->bus_info));
- else
- sprintf(info->bus_info, "EISA 0x%lx %d",
- dev->base_addr, dev->irq);
+ strlcpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info));
}
static int dmfe_ethtool_set_wol(struct net_device *dev,
@@ -1132,10 +1134,11 @@ static const struct ethtool_ops netdev_ethtool_ops = {
static void dmfe_timer(unsigned long data)
{
+ struct net_device *dev = (struct net_device *)data;
+ struct dmfe_board_info *db = netdev_priv(dev);
+ void __iomem *ioaddr = db->ioaddr;
u32 tmp_cr8;
unsigned char tmp_cr12;
- struct DEVICE *dev = (struct DEVICE *) data;
- struct dmfe_board_info *db = netdev_priv(dev);
unsigned long flags;
int link_ok, link_ok_phy;
@@ -1148,11 +1151,10 @@ static void dmfe_timer(unsigned long data)
db->first_in_callback = 1;
if (db->chip_type && (db->chip_id==PCI_DM9102_ID)) {
db->cr6_data &= ~0x40000;
- update_cr6(db->cr6_data, db->ioaddr);
- phy_write(db->ioaddr,
- db->phy_addr, 0, 0x1000, db->chip_id);
+ update_cr6(db->cr6_data, ioaddr);
+ phy_write(ioaddr, db->phy_addr, 0, 0x1000, db->chip_id);
db->cr6_data |= 0x40000;
- update_cr6(db->cr6_data, db->ioaddr);
+ update_cr6(db->cr6_data, ioaddr);
db->timer.expires = DMFE_TIMER_WUT + HZ * 2;
add_timer(&db->timer);
spin_unlock_irqrestore(&db->lock, flags);
@@ -1167,7 +1169,7 @@ static void dmfe_timer(unsigned long data)
db->dm910x_chk_mode = 0x4;
/* Dynamic reset DM910X : system error or transmit time-out */
- tmp_cr8 = inl(db->ioaddr + DCR8);
+ tmp_cr8 = dr32(DCR8);
if ( (db->interval_rx_cnt==0) && (tmp_cr8) ) {
db->reset_cr8++;
db->wait_reset = 1;
@@ -1177,7 +1179,7 @@ static void dmfe_timer(unsigned long data)
/* TX polling kick monitor */
if ( db->tx_packet_cnt &&
time_after(jiffies, dev_trans_start(dev) + DMFE_TX_KICK) ) {
- outl(0x1, dev->base_addr + DCR1); /* Tx polling again */
+ dw32(DCR1, 0x1); /* Tx polling again */
/* TX Timeout */
if (time_after(jiffies, dev_trans_start(dev) + DMFE_TX_TIMEOUT) ) {
@@ -1200,9 +1202,9 @@ static void dmfe_timer(unsigned long data)
/* Link status check, Dynamic media type change */
if (db->chip_id == PCI_DM9132_ID)
- tmp_cr12 = inb(db->ioaddr + DCR9 + 3); /* DM9132 */
+ tmp_cr12 = dr8(DCR9 + 3); /* DM9132 */
else
- tmp_cr12 = inb(db->ioaddr + DCR12); /* DM9102/DM9102A */
+ tmp_cr12 = dr8(DCR12); /* DM9102/DM9102A */
if ( ((db->chip_id == PCI_DM9102_ID) &&
(db->chip_revision == 0x30)) ||
@@ -1251,7 +1253,7 @@ static void dmfe_timer(unsigned long data)
/* 10/100M link failed, used 1M Home-Net */
db->cr6_data|=0x00040000; /* bit18=1, MII */
db->cr6_data&=~0x00000200; /* bit9=0, HD mode */
- update_cr6(db->cr6_data, db->ioaddr);
+ update_cr6(db->cr6_data, ioaddr);
}
} else if (!netif_carrier_ok(dev)) {
@@ -1288,17 +1290,18 @@ static void dmfe_timer(unsigned long data)
* Re-initialize DM910X board
*/
-static void dmfe_dynamic_reset(struct DEVICE *dev)
+static void dmfe_dynamic_reset(struct net_device *dev)
{
struct dmfe_board_info *db = netdev_priv(dev);
+ void __iomem *ioaddr = db->ioaddr;
DMFE_DBUG(0, "dmfe_dynamic_reset()", 0);
/* Sopt MAC controller */
db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */
- update_cr6(db->cr6_data, dev->base_addr);
- outl(0, dev->base_addr + DCR7); /* Disable Interrupt */
- outl(inl(dev->base_addr + DCR5), dev->base_addr + DCR5);
+ update_cr6(db->cr6_data, ioaddr);
+ dw32(DCR7, 0); /* Disable Interrupt */
+ dw32(DCR5, dr32(DCR5));
/* Disable upper layer interface */
netif_stop_queue(dev);
@@ -1364,9 +1367,10 @@ 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 net_device *dev, unsigned long ioaddr)
+static void dmfe_descriptor_init(struct net_device *dev)
{
struct dmfe_board_info *db = netdev_priv(dev);
+ void __iomem *ioaddr = db->ioaddr;
struct tx_desc *tmp_tx;
struct rx_desc *tmp_rx;
unsigned char *tmp_buf;
@@ -1379,7 +1383,7 @@ static void dmfe_descriptor_init(struct net_device *dev, unsigned long ioaddr)
/* tx descriptor start pointer */
db->tx_insert_ptr = db->first_tx_desc;
db->tx_remove_ptr = db->first_tx_desc;
- outl(db->first_tx_desc_dma, ioaddr + DCR4); /* TX DESC address */
+ dw32(DCR4, db->first_tx_desc_dma); /* TX DESC address */
/* rx descriptor start pointer */
db->first_rx_desc = (void *)db->first_tx_desc +
@@ -1389,7 +1393,7 @@ static void dmfe_descriptor_init(struct net_device *dev, unsigned long ioaddr)
sizeof(struct tx_desc) * TX_DESC_CNT;
db->rx_insert_ptr = db->first_rx_desc;
db->rx_ready_ptr = db->first_rx_desc;
- outl(db->first_rx_desc_dma, ioaddr + DCR3); /* RX DESC address */
+ dw32(DCR3, db->first_rx_desc_dma); /* RX DESC address */
/* Init Transmit chain */
tmp_buf = db->buf_pool_start;
@@ -1431,14 +1435,14 @@ static void dmfe_descriptor_init(struct net_device *dev, unsigned long ioaddr)
* Firstly stop DM910X , then written value and start
*/
-static void update_cr6(u32 cr6_data, unsigned long ioaddr)
+static void update_cr6(u32 cr6_data, void __iomem *ioaddr)
{
u32 cr6_tmp;
cr6_tmp = cr6_data & ~0x2002; /* stop Tx/Rx */
- outl(cr6_tmp, ioaddr + DCR6);
+ dw32(DCR6, cr6_tmp);
udelay(5);
- outl(cr6_data, ioaddr + DCR6);
+ dw32(DCR6, cr6_data);
udelay(5);
}
@@ -1448,24 +1452,19 @@ static void update_cr6(u32 cr6_data, unsigned long ioaddr)
* This setup frame initialize DM910X address filter mode
*/
-static void dm9132_id_table(struct DEVICE *dev)
+static void dm9132_id_table(struct net_device *dev)
{
+ struct dmfe_board_info *db = netdev_priv(dev);
+ void __iomem *ioaddr = db->ioaddr + 0xc0;
+ u16 *addrptr = (u16 *)dev->dev_addr;
struct netdev_hw_addr *ha;
- u16 * addrptr;
- unsigned long ioaddr = dev->base_addr+0xc0; /* ID Table */
- u32 hash_val;
u16 i, hash_table[4];
- DMFE_DBUG(0, "dm9132_id_table()", 0);
-
/* Node address */
- addrptr = (u16 *) dev->dev_addr;
- outw(addrptr[0], ioaddr);
- ioaddr += 4;
- outw(addrptr[1], ioaddr);
- ioaddr += 4;
- outw(addrptr[2], ioaddr);
- ioaddr += 4;
+ for (i = 0; i < 3; i++) {
+ dw16(0, addrptr[i]);
+ ioaddr += 4;
+ }
/* Clear Hash Table */
memset(hash_table, 0, sizeof(hash_table));
@@ -1475,13 +1474,14 @@ static void dm9132_id_table(struct DEVICE *dev)
/* the multicast address in Hash Table : 64 bits */
netdev_for_each_mc_addr(ha, dev) {
- hash_val = cal_CRC((char *) ha->addr, 6, 0) & 0x3f;
+ u32 hash_val = cal_CRC((char *)ha->addr, 6, 0) & 0x3f;
+
hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
}
/* Write the hash table to MAC MD table */
for (i = 0; i < 4; i++, ioaddr += 4)
- outw(hash_table[i], ioaddr);
+ dw16(0, hash_table[i]);
}
@@ -1490,7 +1490,7 @@ static void dm9132_id_table(struct DEVICE *dev)
* This setup frame initialize DM910X address filter mode
*/
-static void send_filter_frame(struct DEVICE *dev)
+static void send_filter_frame(struct net_device *dev)
{
struct dmfe_board_info *db = netdev_priv(dev);
struct netdev_hw_addr *ha;
@@ -1535,12 +1535,14 @@ static void send_filter_frame(struct DEVICE *dev)
/* Resource Check and Send the setup packet */
if (!db->tx_packet_cnt) {
+ void __iomem *ioaddr = db->ioaddr;
+
/* Resource Empty */
db->tx_packet_cnt++;
txptr->tdes0 = cpu_to_le32(0x80000000);
- update_cr6(db->cr6_data | 0x2000, dev->base_addr);
- outl(0x1, dev->base_addr + DCR1); /* Issue Tx polling */
- update_cr6(db->cr6_data, dev->base_addr);
+ update_cr6(db->cr6_data | 0x2000, ioaddr);
+ dw32(DCR1, 0x1); /* Issue Tx polling */
+ update_cr6(db->cr6_data, ioaddr);
dev->trans_start = jiffies;
} else
db->tx_queue_cnt++; /* Put in TX queue */
@@ -1575,43 +1577,59 @@ static void allocate_rx_buffer(struct net_device *dev)
db->rx_insert_ptr = rxptr;
}
+static void srom_clk_write(void __iomem *ioaddr, u32 data)
+{
+ static const u32 cmd[] = {
+ CR9_SROM_READ | CR9_SRCS,
+ CR9_SROM_READ | CR9_SRCS | CR9_SRCLK,
+ CR9_SROM_READ | CR9_SRCS
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cmd); i++) {
+ dw32(DCR9, data | cmd[i]);
+ udelay(5);
+ }
+}
/*
* Read one word data from the serial ROM
*/
-
-static u16 read_srom_word(long ioaddr, int offset)
+static u16 read_srom_word(void __iomem *ioaddr, int offset)
{
+ u16 srom_data;
int i;
- u16 srom_data = 0;
- long cr9_ioaddr = ioaddr + DCR9;
- outl(CR9_SROM_READ, cr9_ioaddr);
- outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ dw32(DCR9, CR9_SROM_READ);
+ udelay(5);
+ dw32(DCR9, CR9_SROM_READ | CR9_SRCS);
+ udelay(5);
/* Send the Read Command 110b */
- SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
- SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
- SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);
+ srom_clk_write(ioaddr, SROM_DATA_1);
+ srom_clk_write(ioaddr, SROM_DATA_1);
+ srom_clk_write(ioaddr, SROM_DATA_0);
/* Send the offset */
for (i = 5; i >= 0; i--) {
srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
- SROM_CLK_WRITE(srom_data, cr9_ioaddr);
+ srom_clk_write(ioaddr, srom_data);
}
- outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ dw32(DCR9, CR9_SROM_READ | CR9_SRCS);
+ udelay(5);
for (i = 16; i > 0; i--) {
- outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
+ dw32(DCR9, CR9_SROM_READ | CR9_SRCS | CR9_SRCLK);
udelay(5);
srom_data = (srom_data << 1) |
- ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);
- outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ ((dr32(DCR9) & CR9_CRDOUT) ? 1 : 0);
+ dw32(DCR9, CR9_SROM_READ | CR9_SRCS);
udelay(5);
}
- outl(CR9_SROM_READ, cr9_ioaddr);
+ dw32(DCR9, CR9_SROM_READ);
+ udelay(5);
return srom_data;
}
@@ -1620,13 +1638,14 @@ static u16 read_srom_word(long ioaddr, int offset)
* Auto sense the media mode
*/
-static u8 dmfe_sense_speed(struct dmfe_board_info * db)
+static u8 dmfe_sense_speed(struct dmfe_board_info *db)
{
+ void __iomem *ioaddr = db->ioaddr;
u8 ErrFlag = 0;
u16 phy_mode;
/* CR6 bit18=0, select 10/100M */
- update_cr6( (db->cr6_data & ~0x40000), db->ioaddr);
+ update_cr6(db->cr6_data & ~0x40000, ioaddr);
phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
@@ -1665,11 +1684,12 @@ static u8 dmfe_sense_speed(struct dmfe_board_info * db)
static void dmfe_set_phyxcer(struct dmfe_board_info *db)
{
+ void __iomem *ioaddr = db->ioaddr;
u16 phy_reg;
/* Select 10/100M phyxcer */
db->cr6_data &= ~0x40000;
- update_cr6(db->cr6_data, db->ioaddr);
+ update_cr6(db->cr6_data, ioaddr);
/* DM9009 Chip: Phyxcer reg18 bit12=0 */
if (db->chip_id == PCI_DM9009_ID) {
@@ -1765,18 +1785,15 @@ static void dmfe_process_mode(struct dmfe_board_info *db)
* Write a word to Phy register
*/
-static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
+static void phy_write(void __iomem *ioaddr, u8 phy_addr, u8 offset,
u16 phy_data, u32 chip_id)
{
u16 i;
- unsigned long ioaddr;
if (chip_id == PCI_DM9132_ID) {
- ioaddr = iobase + 0x80 + offset * 4;
- outw(phy_data, ioaddr);
+ dw16(0x80 + offset * 4, phy_data);
} else {
/* DM9102/DM9102A Chip */
- ioaddr = iobase + DCR9;
/* Send 33 synchronization clock to Phy controller */
for (i = 0; i < 35; i++)
@@ -1816,19 +1833,16 @@ static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
* Read a word data from phy register
*/
-static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
+static u16 phy_read(void __iomem *ioaddr, u8 phy_addr, u8 offset, u32 chip_id)
{
int i;
u16 phy_data;
- unsigned long ioaddr;
if (chip_id == PCI_DM9132_ID) {
/* DM9132 Chip */
- ioaddr = iobase + 0x80 + offset * 4;
- phy_data = inw(ioaddr);
+ phy_data = dr16(0x80 + offset * 4);
} else {
/* DM9102/DM9102A Chip */
- ioaddr = iobase + DCR9;
/* Send 33 synchronization clock to Phy controller */
for (i = 0; i < 35; i++)
@@ -1870,13 +1884,13 @@ static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
* Write one bit data to Phy Controller
*/
-static void phy_write_1bit(unsigned long ioaddr, u32 phy_data)
+static void phy_write_1bit(void __iomem *ioaddr, u32 phy_data)
{
- outl(phy_data, ioaddr); /* MII Clock Low */
+ dw32(DCR9, phy_data); /* MII Clock Low */
udelay(1);
- outl(phy_data | MDCLKH, ioaddr); /* MII Clock High */
+ dw32(DCR9, phy_data | MDCLKH); /* MII Clock High */
udelay(1);
- outl(phy_data, ioaddr); /* MII Clock Low */
+ dw32(DCR9, phy_data); /* MII Clock Low */
udelay(1);
}
@@ -1885,14 +1899,14 @@ static void phy_write_1bit(unsigned long ioaddr, u32 phy_data)
* Read one bit phy data from PHY controller
*/
-static u16 phy_read_1bit(unsigned long ioaddr)
+static u16 phy_read_1bit(void __iomem *ioaddr)
{
u16 phy_data;
- outl(0x50000, ioaddr);
+ dw32(DCR9, 0x50000);
udelay(1);
- phy_data = ( inl(ioaddr) >> 19 ) & 0x1;
- outl(0x40000, ioaddr);
+ phy_data = (dr32(DCR9) >> 19) & 0x1;
+ dw32(DCR9, 0x40000);
udelay(1);
return phy_data;
@@ -1978,7 +1992,7 @@ static void dmfe_parse_srom(struct dmfe_board_info * db)
/* Check DM9801 or DM9802 present or not */
db->HPNA_present = 0;
- update_cr6(db->cr6_data|0x40000, db->ioaddr);
+ update_cr6(db->cr6_data | 0x40000, db->ioaddr);
tmp_reg = phy_read(db->ioaddr, db->phy_addr, 3, db->chip_id);
if ( ( tmp_reg & 0xfff0 ) == 0xb900 ) {
/* DM9801 or DM9802 present */
@@ -2095,6 +2109,7 @@ static int dmfe_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pci_dev);
struct dmfe_board_info *db = netdev_priv(dev);
+ void __iomem *ioaddr = db->ioaddr;
u32 tmp;
/* Disable upper layer interface */
@@ -2102,11 +2117,11 @@ static int dmfe_suspend(struct pci_dev *pci_dev, pm_message_t state)
/* Disable Tx/Rx */
db->cr6_data &= ~(CR6_RXSC | CR6_TXSC);
- update_cr6(db->cr6_data, dev->base_addr);
+ update_cr6(db->cr6_data, ioaddr);
/* Disable Interrupt */
- outl(0, dev->base_addr + DCR7);
- outl(inl (dev->base_addr + DCR5), dev->base_addr + DCR5);
+ dw32(DCR7, 0);
+ dw32(DCR5, dr32(DCR5));
/* Fre RX buffers */
dmfe_free_rxbuffer(db);
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index fea3641d9398..c4f37aca2269 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -328,7 +328,7 @@ static void tulip_up(struct net_device *dev)
udelay(100);
if (tulip_debug > 1)
- netdev_dbg(dev, "tulip_up(), irq==%d\n", dev->irq);
+ netdev_dbg(dev, "tulip_up(), irq==%d\n", tp->pdev->irq);
iowrite32(tp->rx_ring_dma, ioaddr + CSR3);
iowrite32(tp->tx_ring_dma, ioaddr + CSR4);
@@ -515,11 +515,13 @@ media_picked:
static int
tulip_open(struct net_device *dev)
{
+ struct tulip_private *tp = netdev_priv(dev);
int retval;
tulip_init_ring (dev);
- retval = request_irq(dev->irq, tulip_interrupt, IRQF_SHARED, dev->name, dev);
+ retval = request_irq(tp->pdev->irq, tulip_interrupt, IRQF_SHARED,
+ dev->name, dev);
if (retval)
goto free_ring;
@@ -841,7 +843,7 @@ static int tulip_close (struct net_device *dev)
netdev_dbg(dev, "Shutting down ethercard, status was %02x\n",
ioread32 (ioaddr + CSR5));
- free_irq (dev->irq, dev);
+ free_irq (tp->pdev->irq, dev);
tulip_free_ring (dev);
@@ -1489,8 +1491,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task);
- dev->base_addr = (unsigned long)ioaddr;
-
#ifdef CONFIG_TULIP_MWI
if (!force_csr0 && (tp->flags & HAS_PCI_MWI))
tulip_mwi_config (pdev, dev);
@@ -1650,7 +1650,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
for (i = 0; i < 6; i++)
last_phys_addr[i] = dev->dev_addr[i];
last_irq = irq;
- dev->irq = irq;
/* The lower four bits are the media type. */
if (board_idx >= 0 && board_idx < MAX_UNITS) {
@@ -1858,7 +1857,8 @@ static int tulip_suspend (struct pci_dev *pdev, pm_message_t state)
tulip_down(dev);
netif_device_detach(dev);
- free_irq(dev->irq, dev);
+ /* FIXME: it needlessly adds an error path. */
+ free_irq(tp->pdev->irq, dev);
save_state:
pci_save_state(pdev);
@@ -1900,7 +1900,9 @@ static int tulip_resume(struct pci_dev *pdev)
return retval;
}
- if ((retval = request_irq(dev->irq, tulip_interrupt, IRQF_SHARED, dev->name, dev))) {
+ retval = request_irq(pdev->irq, tulip_interrupt, IRQF_SHARED,
+ dev->name, dev);
+ if (retval) {
pr_err("request_irq failed in resume\n");
return retval;
}
@@ -1960,11 +1962,14 @@ static void __devexit tulip_remove_one (struct pci_dev *pdev)
static void poll_tulip (struct net_device *dev)
{
+ struct tulip_private *tp = netdev_priv(dev);
+ const int irq = tp->pdev->irq;
+
/* disable_irq here is not very nice, but with the lockless
interrupt handler we have no other choice. */
- disable_irq(dev->irq);
- tulip_interrupt (dev->irq, dev);
- enable_irq(dev->irq);
+ disable_irq(irq);
+ tulip_interrupt (irq, dev);
+ enable_irq(irq);
}
#endif
diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c
index fc4001f6a5e4..75d45f8a37dc 100644
--- a/drivers/net/ethernet/dec/tulip/uli526x.c
+++ b/drivers/net/ethernet/dec/tulip/uli526x.c
@@ -42,6 +42,8 @@
#include <asm/dma.h>
#include <asm/uaccess.h>
+#define uw32(reg, val) iowrite32(val, ioaddr + (reg))
+#define ur32(reg) ioread32(ioaddr + (reg))
/* Board/System/Debug information/definition ---------------- */
#define PCI_ULI5261_ID 0x526110B9 /* ULi M5261 ID*/
@@ -110,14 +112,6 @@ do { \
#define SROM_V41_CODE 0x14
-#define SROM_CLK_WRITE(data, ioaddr) \
- outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \
- udelay(5); \
- outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr); \
- udelay(5); \
- outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr); \
- udelay(5);
-
/* Structure/enum declaration ------------------------------- */
struct tx_desc {
__le32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
@@ -132,12 +126,15 @@ struct rx_desc {
} __attribute__(( aligned(32) ));
struct uli526x_board_info {
- u32 chip_id; /* Chip vendor/Device ID */
+ struct uli_phy_ops {
+ void (*write)(struct uli526x_board_info *, u8, u8, u16);
+ u16 (*read)(struct uli526x_board_info *, u8, u8);
+ } phy;
struct net_device *next_dev; /* next device */
struct pci_dev *pdev; /* PCI device */
spinlock_t lock;
- long ioaddr; /* I/O base address */
+ void __iomem *ioaddr; /* I/O base address */
u32 cr0_data;
u32 cr5_data;
u32 cr6_data;
@@ -227,21 +224,21 @@ static netdev_tx_t uli526x_start_xmit(struct sk_buff *,
static int uli526x_stop(struct net_device *);
static void uli526x_set_filter_mode(struct net_device *);
static const struct ethtool_ops netdev_ethtool_ops;
-static u16 read_srom_word(long, int);
+static u16 read_srom_word(struct uli526x_board_info *, int);
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 net_device *, unsigned long);
+static void uli526x_descriptor_init(struct net_device *, void __iomem *);
static void allocate_rx_buffer(struct net_device *);
-static void update_cr6(u32, unsigned long);
+static void update_cr6(u32, void __iomem *);
static void send_filter_frame(struct net_device *, int);
-static u16 phy_read(unsigned long, u8, u8, u32);
-static u16 phy_readby_cr10(unsigned long, u8, u8);
-static void phy_write(unsigned long, u8, u8, u16, u32);
-static void phy_writeby_cr10(unsigned long, u8, u8, u16);
-static void phy_write_1bit(unsigned long, u32, u32);
-static u16 phy_read_1bit(unsigned long, u32);
+static u16 phy_readby_cr9(struct uli526x_board_info *, u8, u8);
+static u16 phy_readby_cr10(struct uli526x_board_info *, u8, u8);
+static void phy_writeby_cr9(struct uli526x_board_info *, u8, u8, u16);
+static void phy_writeby_cr10(struct uli526x_board_info *, u8, u8, u16);
+static void phy_write_1bit(struct uli526x_board_info *db, u32);
+static u16 phy_read_1bit(struct uli526x_board_info *db);
static u8 uli526x_sense_speed(struct uli526x_board_info *);
static void uli526x_process_mode(struct uli526x_board_info *);
static void uli526x_timer(unsigned long);
@@ -253,6 +250,18 @@ static void uli526x_free_rxbuffer(struct uli526x_board_info *);
static void uli526x_init(struct net_device *);
static void uli526x_set_phyxcer(struct uli526x_board_info *);
+static void srom_clk_write(struct uli526x_board_info *db, u32 data)
+{
+ void __iomem *ioaddr = db->ioaddr;
+
+ uw32(DCR9, data | CR9_SROM_READ | CR9_SRCS);
+ udelay(5);
+ uw32(DCR9, data | CR9_SROM_READ | CR9_SRCS | CR9_SRCLK);
+ udelay(5);
+ uw32(DCR9, data | CR9_SROM_READ | CR9_SRCS);
+ udelay(5);
+}
+
/* ULI526X network board routine ---------------------------- */
static const struct net_device_ops netdev_ops = {
@@ -277,6 +286,7 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
{
struct uli526x_board_info *db; /* board information structure */
struct net_device *dev;
+ void __iomem *ioaddr;
int i, err;
ULI526X_DBUG(0, "uli526x_init_one()", 0);
@@ -313,9 +323,9 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
goto err_out_disable;
}
- if (pci_request_regions(pdev, DRV_NAME)) {
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err < 0) {
pr_err("Failed to request PCI regions\n");
- err = -ENODEV;
goto err_out_disable;
}
@@ -323,32 +333,41 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
db = netdev_priv(dev);
/* Allocate Tx/Rx descriptor memory */
+ err = -ENOMEM;
+
db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
- if(db->desc_pool_ptr == NULL)
- {
- err = -ENOMEM;
- goto err_out_nomem;
- }
+ if (!db->desc_pool_ptr)
+ goto err_out_release;
+
db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
- if(db->buf_pool_ptr == NULL)
- {
- err = -ENOMEM;
- goto err_out_nomem;
- }
+ if (!db->buf_pool_ptr)
+ goto err_out_free_tx_desc;
db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
db->first_tx_desc_dma = db->desc_pool_dma_ptr;
db->buf_pool_start = db->buf_pool_ptr;
db->buf_pool_dma_start = db->buf_pool_dma_ptr;
- db->chip_id = ent->driver_data;
- db->ioaddr = pci_resource_start(pdev, 0);
+ switch (ent->driver_data) {
+ case PCI_ULI5263_ID:
+ db->phy.write = phy_writeby_cr10;
+ db->phy.read = phy_readby_cr10;
+ break;
+ default:
+ db->phy.write = phy_writeby_cr9;
+ db->phy.read = phy_readby_cr9;
+ break;
+ }
+
+ /* IO region. */
+ ioaddr = pci_iomap(pdev, 0, 0);
+ if (!ioaddr)
+ goto err_out_free_tx_buf;
+ db->ioaddr = ioaddr;
db->pdev = pdev;
db->init = 1;
- dev->base_addr = db->ioaddr;
- dev->irq = pdev->irq;
pci_set_drvdata(pdev, dev);
/* Register some necessary functions */
@@ -360,24 +379,24 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
/* read 64 word srom data */
for (i = 0; i < 64; i++)
- ((__le16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i));
+ ((__le16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db, i));
/* Set Node address */
if(((u16 *) db->srom)[0] == 0xffff || ((u16 *) db->srom)[0] == 0) /* SROM absent, so read MAC address from ID Table */
{
- outl(0x10000, db->ioaddr + DCR0); //Diagnosis mode
- outl(0x1c0, db->ioaddr + DCR13); //Reset dianostic pointer port
- outl(0, db->ioaddr + DCR14); //Clear reset port
- outl(0x10, db->ioaddr + DCR14); //Reset ID Table pointer
- outl(0, db->ioaddr + DCR14); //Clear reset port
- outl(0, db->ioaddr + DCR13); //Clear CR13
- outl(0x1b0, db->ioaddr + DCR13); //Select ID Table access port
+ uw32(DCR0, 0x10000); //Diagnosis mode
+ uw32(DCR13, 0x1c0); //Reset dianostic pointer port
+ uw32(DCR14, 0); //Clear reset port
+ uw32(DCR14, 0x10); //Reset ID Table pointer
+ uw32(DCR14, 0); //Clear reset port
+ uw32(DCR13, 0); //Clear CR13
+ uw32(DCR13, 0x1b0); //Select ID Table access port
//Read MAC address from CR14
for (i = 0; i < 6; i++)
- dev->dev_addr[i] = inl(db->ioaddr + DCR14);
+ dev->dev_addr[i] = ur32(DCR14);
//Read end
- outl(0, db->ioaddr + DCR13); //Clear CR13
- outl(0, db->ioaddr + DCR0); //Clear CR0
+ uw32(DCR13, 0); //Clear CR13
+ uw32(DCR0, 0); //Clear CR0
udelay(10);
}
else /*Exist SROM*/
@@ -387,26 +406,26 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
}
err = register_netdev (dev);
if (err)
- goto err_out_res;
+ goto err_out_unmap;
netdev_info(dev, "ULi M%04lx at pci%s, %pM, irq %d\n",
ent->driver_data >> 16, pci_name(pdev),
- dev->dev_addr, dev->irq);
+ dev->dev_addr, pdev->irq);
pci_set_master(pdev);
return 0;
-err_out_res:
+err_out_unmap:
+ pci_iounmap(pdev, db->ioaddr);
+err_out_free_tx_buf:
+ pci_free_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
+ db->buf_pool_ptr, db->buf_pool_dma_ptr);
+err_out_free_tx_desc:
+ pci_free_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20,
+ db->desc_pool_ptr, db->desc_pool_dma_ptr);
+err_out_release:
pci_release_regions(pdev);
-err_out_nomem:
- if(db->desc_pool_ptr)
- pci_free_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20,
- db->desc_pool_ptr, db->desc_pool_dma_ptr);
-
- if(db->buf_pool_ptr != NULL)
- pci_free_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
- db->buf_pool_ptr, db->buf_pool_dma_ptr);
err_out_disable:
pci_disable_device(pdev);
err_out_free:
@@ -422,19 +441,17 @@ static void __devexit uli526x_remove_one (struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct uli526x_board_info *db = netdev_priv(dev);
- ULI526X_DBUG(0, "uli526x_remove_one()", 0);
-
+ unregister_netdev(dev);
+ pci_iounmap(pdev, db->ioaddr);
pci_free_consistent(db->pdev, sizeof(struct tx_desc) *
DESC_ALL_CNT + 0x20, db->desc_pool_ptr,
db->desc_pool_dma_ptr);
pci_free_consistent(db->pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
db->buf_pool_ptr, db->buf_pool_dma_ptr);
- unregister_netdev(dev);
pci_release_regions(pdev);
- free_netdev(dev); /* free board information */
- pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
- ULI526X_DBUG(0, "uli526x_remove_one() exit", 0);
+ pci_set_drvdata(pdev, NULL);
+ free_netdev(dev);
}
@@ -468,7 +485,8 @@ static int uli526x_open(struct net_device *dev)
/* Initialize ULI526X board */
uli526x_init(dev);
- ret = request_irq(dev->irq, uli526x_interrupt, IRQF_SHARED, dev->name, dev);
+ ret = request_irq(db->pdev->irq, uli526x_interrupt, IRQF_SHARED,
+ dev->name, dev);
if (ret)
return ret;
@@ -496,57 +514,57 @@ static int uli526x_open(struct net_device *dev)
static void uli526x_init(struct net_device *dev)
{
struct uli526x_board_info *db = netdev_priv(dev);
- unsigned long ioaddr = db->ioaddr;
+ struct uli_phy_ops *phy = &db->phy;
+ void __iomem *ioaddr = db->ioaddr;
u8 phy_tmp;
u8 timeout;
- u16 phy_value;
u16 phy_reg_reset;
ULI526X_DBUG(0, "uli526x_init()", 0);
/* Reset M526x MAC controller */
- outl(ULI526X_RESET, ioaddr + DCR0); /* RESET MAC */
+ uw32(DCR0, ULI526X_RESET); /* RESET MAC */
udelay(100);
- outl(db->cr0_data, ioaddr + DCR0);
+ uw32(DCR0, db->cr0_data);
udelay(5);
/* Phy addr : In some boards,M5261/M5263 phy address != 1 */
db->phy_addr = 1;
- for(phy_tmp=0;phy_tmp<32;phy_tmp++)
- {
- phy_value=phy_read(db->ioaddr,phy_tmp,3,db->chip_id);//peer add
- if(phy_value != 0xffff&&phy_value!=0)
- {
+ for (phy_tmp = 0; phy_tmp < 32; phy_tmp++) {
+ u16 phy_value;
+
+ phy_value = phy->read(db, phy_tmp, 3); //peer add
+ if (phy_value != 0xffff && phy_value != 0) {
db->phy_addr = phy_tmp;
break;
}
}
- if(phy_tmp == 32)
+
+ if (phy_tmp == 32)
pr_warn("Can not find the phy address!!!\n");
/* Parser SROM and media mode */
db->media_mode = uli526x_media_mode;
/* phyxcer capability setting */
- phy_reg_reset = phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id);
+ phy_reg_reset = phy->read(db, db->phy_addr, 0);
phy_reg_reset = (phy_reg_reset | 0x8000);
- phy_write(db->ioaddr, db->phy_addr, 0, phy_reg_reset, db->chip_id);
+ phy->write(db, db->phy_addr, 0, phy_reg_reset);
/* See IEEE 802.3-2002.pdf (Section 2, Chapter "22.2.4 Management
* functions") or phy data sheet for details on phy reset
*/
udelay(500);
timeout = 10;
- while (timeout-- &&
- phy_read(db->ioaddr, db->phy_addr, 0, db->chip_id) & 0x8000)
- udelay(100);
+ while (timeout-- && phy->read(db, db->phy_addr, 0) & 0x8000)
+ udelay(100);
/* Process Phyxcer Media Mode */
uli526x_set_phyxcer(db);
/* Media Mode Process */
if ( !(db->media_mode & ULI526X_AUTO) )
- db->op_mode = db->media_mode; /* Force Mode */
+ db->op_mode = db->media_mode; /* Force Mode */
/* Initialize Transmit/Receive decriptor and CR3/4 */
uli526x_descriptor_init(dev, ioaddr);
@@ -559,10 +577,10 @@ static void uli526x_init(struct net_device *dev)
/* Init CR7, interrupt active bit */
db->cr7_data = CR7_DEFAULT;
- outl(db->cr7_data, ioaddr + DCR7);
+ uw32(DCR7, db->cr7_data);
/* Init CR15, Tx jabber and Rx watchdog timer */
- outl(db->cr15_data, ioaddr + DCR15);
+ uw32(DCR15, db->cr15_data);
/* Enable ULI526X Tx/Rx function */
db->cr6_data |= CR6_RXSC | CR6_TXSC;
@@ -579,6 +597,7 @@ static netdev_tx_t uli526x_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct uli526x_board_info *db = netdev_priv(dev);
+ void __iomem *ioaddr = db->ioaddr;
struct tx_desc *txptr;
unsigned long flags;
@@ -604,7 +623,7 @@ static netdev_tx_t uli526x_start_xmit(struct sk_buff *skb,
}
/* Disable NIC interrupt */
- outl(0, dev->base_addr + DCR7);
+ uw32(DCR7, 0);
/* transmit this packet */
txptr = db->tx_insert_ptr;
@@ -615,10 +634,10 @@ static netdev_tx_t uli526x_start_xmit(struct sk_buff *skb,
db->tx_insert_ptr = txptr->next_tx_desc;
/* Transmit Packet Process */
- if ( (db->tx_packet_cnt < TX_DESC_CNT) ) {
+ if (db->tx_packet_cnt < TX_DESC_CNT) {
txptr->tdes0 = cpu_to_le32(0x80000000); /* Set owner bit */
db->tx_packet_cnt++; /* Ready to send */
- outl(0x1, dev->base_addr + DCR1); /* Issue Tx polling */
+ uw32(DCR1, 0x1); /* Issue Tx polling */
dev->trans_start = jiffies; /* saved time stamp */
}
@@ -628,7 +647,7 @@ static netdev_tx_t uli526x_start_xmit(struct sk_buff *skb,
/* Restore CR7 to enable interrupt */
spin_unlock_irqrestore(&db->lock, flags);
- outl(db->cr7_data, dev->base_addr + DCR7);
+ uw32(DCR7, db->cr7_data);
/* free this SKB */
dev_kfree_skb(skb);
@@ -645,9 +664,7 @@ static netdev_tx_t uli526x_start_xmit(struct sk_buff *skb,
static int uli526x_stop(struct net_device *dev)
{
struct uli526x_board_info *db = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
-
- ULI526X_DBUG(0, "uli526x_stop", 0);
+ void __iomem *ioaddr = db->ioaddr;
/* disable system */
netif_stop_queue(dev);
@@ -656,12 +673,12 @@ static int uli526x_stop(struct net_device *dev)
del_timer_sync(&db->timer);
/* Reset & stop ULI526X board */
- outl(ULI526X_RESET, ioaddr + DCR0);
+ uw32(DCR0, ULI526X_RESET);
udelay(5);
- phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
+ db->phy.write(db, db->phy_addr, 0, 0x8000);
/* free interrupt */
- free_irq(dev->irq, dev);
+ free_irq(db->pdev->irq, dev);
/* free allocated rx buffer */
uli526x_free_rxbuffer(db);
@@ -679,18 +696,18 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct uli526x_board_info *db = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = db->ioaddr;
unsigned long flags;
spin_lock_irqsave(&db->lock, flags);
- outl(0, ioaddr + DCR7);
+ uw32(DCR7, 0);
/* Got ULI526X status */
- db->cr5_data = inl(ioaddr + DCR5);
- outl(db->cr5_data, ioaddr + DCR5);
+ db->cr5_data = ur32(DCR5);
+ uw32(DCR5, db->cr5_data);
if ( !(db->cr5_data & 0x180c1) ) {
/* Restore CR7 to enable interrupt mask */
- outl(db->cr7_data, ioaddr + DCR7);
+ uw32(DCR7, db->cr7_data);
spin_unlock_irqrestore(&db->lock, flags);
return IRQ_HANDLED;
}
@@ -718,7 +735,7 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id)
uli526x_free_tx_pkt(dev, db);
/* Restore CR7 to enable interrupt mask */
- outl(db->cr7_data, ioaddr + DCR7);
+ uw32(DCR7, db->cr7_data);
spin_unlock_irqrestore(&db->lock, flags);
return IRQ_HANDLED;
@@ -727,8 +744,10 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void uli526x_poll(struct net_device *dev)
{
+ struct uli526x_board_info *db = netdev_priv(dev);
+
/* ISR grabs the irqsave lock, so this should be safe */
- uli526x_interrupt(dev->irq, dev);
+ uli526x_interrupt(db->pdev->irq, dev);
}
#endif
@@ -962,12 +981,7 @@ static void netdev_get_drvinfo(struct net_device *dev,
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
- if (np->pdev)
- strlcpy(info->bus_info, pci_name(np->pdev),
- sizeof(info->bus_info));
- else
- sprintf(info->bus_info, "EISA 0x%lx %d",
- dev->base_addr, dev->irq);
+ strlcpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info));
}
static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) {
@@ -1007,18 +1021,20 @@ static const struct ethtool_ops netdev_ethtool_ops = {
static void uli526x_timer(unsigned long data)
{
- u32 tmp_cr8;
- unsigned char tmp_cr12=0;
struct net_device *dev = (struct net_device *) data;
struct uli526x_board_info *db = netdev_priv(dev);
+ struct uli_phy_ops *phy = &db->phy;
+ void __iomem *ioaddr = db->ioaddr;
unsigned long flags;
+ u8 tmp_cr12 = 0;
+ u32 tmp_cr8;
//ULI526X_DBUG(0, "uli526x_timer()", 0);
spin_lock_irqsave(&db->lock, flags);
/* Dynamic reset ULI526X : system error or transmit time-out */
- tmp_cr8 = inl(db->ioaddr + DCR8);
+ tmp_cr8 = ur32(DCR8);
if ( (db->interval_rx_cnt==0) && (tmp_cr8) ) {
db->reset_cr8++;
db->wait_reset = 1;
@@ -1028,7 +1044,7 @@ static void uli526x_timer(unsigned long data)
/* TX polling kick monitor */
if ( db->tx_packet_cnt &&
time_after(jiffies, dev_trans_start(dev) + ULI526X_TX_KICK) ) {
- outl(0x1, dev->base_addr + DCR1); // Tx polling again
+ uw32(DCR1, 0x1); // Tx polling again
// TX Timeout
if ( time_after(jiffies, dev_trans_start(dev) + ULI526X_TX_TIMEOUT) ) {
@@ -1049,7 +1065,7 @@ static void uli526x_timer(unsigned long data)
}
/* Link status check, Dynamic media type change */
- if((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)!=0)
+ if ((phy->read(db, db->phy_addr, 5) & 0x01e0)!=0)
tmp_cr12 = 3;
if ( !(tmp_cr12 & 0x3) && !db->link_failed ) {
@@ -1062,7 +1078,7 @@ static void uli526x_timer(unsigned long data)
/* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */
/* AUTO don't need */
if ( !(db->media_mode & 0x8) )
- phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id);
+ phy->write(db, db->phy_addr, 0, 0x1000);
/* AUTO mode, if INT phyxcer link failed, select EXT device */
if (db->media_mode & ULI526X_AUTO) {
@@ -1119,12 +1135,13 @@ static void uli526x_timer(unsigned long data)
static void uli526x_reset_prepare(struct net_device *dev)
{
struct uli526x_board_info *db = netdev_priv(dev);
+ void __iomem *ioaddr = db->ioaddr;
/* Sopt MAC controller */
db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */
- update_cr6(db->cr6_data, dev->base_addr);
- outl(0, dev->base_addr + DCR7); /* Disable Interrupt */
- outl(inl(dev->base_addr + DCR5), dev->base_addr + DCR5);
+ update_cr6(db->cr6_data, ioaddr);
+ uw32(DCR7, 0); /* Disable Interrupt */
+ uw32(DCR5, ur32(DCR5));
/* Disable upper layer interface */
netif_stop_queue(dev);
@@ -1289,7 +1306,7 @@ 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 net_device *dev, unsigned long ioaddr)
+static void uli526x_descriptor_init(struct net_device *dev, void __iomem *ioaddr)
{
struct uli526x_board_info *db = netdev_priv(dev);
struct tx_desc *tmp_tx;
@@ -1304,14 +1321,14 @@ static void uli526x_descriptor_init(struct net_device *dev, unsigned long ioaddr
/* tx descriptor start pointer */
db->tx_insert_ptr = db->first_tx_desc;
db->tx_remove_ptr = db->first_tx_desc;
- outl(db->first_tx_desc_dma, ioaddr + DCR4); /* TX DESC address */
+ uw32(DCR4, db->first_tx_desc_dma); /* TX DESC address */
/* rx descriptor start pointer */
db->first_rx_desc = (void *)db->first_tx_desc + sizeof(struct tx_desc) * TX_DESC_CNT;
db->first_rx_desc_dma = db->first_tx_desc_dma + sizeof(struct tx_desc) * TX_DESC_CNT;
db->rx_insert_ptr = db->first_rx_desc;
db->rx_ready_ptr = db->first_rx_desc;
- outl(db->first_rx_desc_dma, ioaddr + DCR3); /* RX DESC address */
+ uw32(DCR3, db->first_rx_desc_dma); /* RX DESC address */
/* Init Transmit chain */
tmp_buf = db->buf_pool_start;
@@ -1352,11 +1369,9 @@ static void uli526x_descriptor_init(struct net_device *dev, unsigned long ioaddr
* Update CR6 value
* Firstly stop ULI526X, then written value and start
*/
-
-static void update_cr6(u32 cr6_data, unsigned long ioaddr)
+static void update_cr6(u32 cr6_data, void __iomem *ioaddr)
{
-
- outl(cr6_data, ioaddr + DCR6);
+ uw32(DCR6, cr6_data);
udelay(5);
}
@@ -1375,6 +1390,7 @@ static void update_cr6(u32 cr6_data, unsigned long ioaddr)
static void send_filter_frame(struct net_device *dev, int mc_cnt)
{
struct uli526x_board_info *db = netdev_priv(dev);
+ void __iomem *ioaddr = db->ioaddr;
struct netdev_hw_addr *ha;
struct tx_desc *txptr;
u16 * addrptr;
@@ -1420,9 +1436,9 @@ static void send_filter_frame(struct net_device *dev, int mc_cnt)
/* Resource Empty */
db->tx_packet_cnt++;
txptr->tdes0 = cpu_to_le32(0x80000000);
- update_cr6(db->cr6_data | 0x2000, dev->base_addr);
- outl(0x1, dev->base_addr + DCR1); /* Issue Tx polling */
- update_cr6(db->cr6_data, dev->base_addr);
+ update_cr6(db->cr6_data | 0x2000, ioaddr);
+ uw32(DCR1, 0x1); /* Issue Tx polling */
+ update_cr6(db->cr6_data, ioaddr);
dev->trans_start = jiffies;
} else
netdev_err(dev, "No Tx resource - Send_filter_frame!\n");
@@ -1465,37 +1481,38 @@ static void allocate_rx_buffer(struct net_device *dev)
* Read one word data from the serial ROM
*/
-static u16 read_srom_word(long ioaddr, int offset)
+static u16 read_srom_word(struct uli526x_board_info *db, int offset)
{
- int i;
+ void __iomem *ioaddr = db->ioaddr;
u16 srom_data = 0;
- long cr9_ioaddr = ioaddr + DCR9;
+ int i;
- outl(CR9_SROM_READ, cr9_ioaddr);
- outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ uw32(DCR9, CR9_SROM_READ);
+ uw32(DCR9, CR9_SROM_READ | CR9_SRCS);
/* Send the Read Command 110b */
- SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
- SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
- SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);
+ srom_clk_write(db, SROM_DATA_1);
+ srom_clk_write(db, SROM_DATA_1);
+ srom_clk_write(db, SROM_DATA_0);
/* Send the offset */
for (i = 5; i >= 0; i--) {
srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
- SROM_CLK_WRITE(srom_data, cr9_ioaddr);
+ srom_clk_write(db, srom_data);
}
- outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ uw32(DCR9, CR9_SROM_READ | CR9_SRCS);
for (i = 16; i > 0; i--) {
- outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
+ uw32(DCR9, CR9_SROM_READ | CR9_SRCS | CR9_SRCLK);
udelay(5);
- srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);
- outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ srom_data = (srom_data << 1) |
+ ((ur32(DCR9) & CR9_CRDOUT) ? 1 : 0);
+ uw32(DCR9, CR9_SROM_READ | CR9_SRCS);
udelay(5);
}
- outl(CR9_SROM_READ, cr9_ioaddr);
+ uw32(DCR9, CR9_SROM_READ);
return srom_data;
}
@@ -1506,15 +1523,16 @@ static u16 read_srom_word(long ioaddr, int offset)
static u8 uli526x_sense_speed(struct uli526x_board_info * db)
{
+ struct uli_phy_ops *phy = &db->phy;
u8 ErrFlag = 0;
u16 phy_mode;
- phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
- phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
+ phy_mode = phy->read(db, db->phy_addr, 1);
+ phy_mode = phy->read(db, db->phy_addr, 1);
if ( (phy_mode & 0x24) == 0x24 ) {
- phy_mode = ((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)<<7);
+ phy_mode = ((phy->read(db, db->phy_addr, 5) & 0x01e0)<<7);
if(phy_mode&0x8000)
phy_mode = 0x8000;
else if(phy_mode&0x4000)
@@ -1549,10 +1567,11 @@ static u8 uli526x_sense_speed(struct uli526x_board_info * db)
static void uli526x_set_phyxcer(struct uli526x_board_info *db)
{
+ struct uli_phy_ops *phy = &db->phy;
u16 phy_reg;
/* Phyxcer capability setting */
- phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
+ phy_reg = phy->read(db, db->phy_addr, 4) & ~0x01e0;
if (db->media_mode & ULI526X_AUTO) {
/* AUTO Mode */
@@ -1573,10 +1592,10 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)
phy_reg|=db->PHY_reg4;
db->media_mode|=ULI526X_AUTO;
}
- phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
+ phy->write(db, db->phy_addr, 4, phy_reg);
/* Restart Auto-Negotiation */
- phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
+ phy->write(db, db->phy_addr, 0, 0x1200);
udelay(50);
}
@@ -1590,6 +1609,7 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)
static void uli526x_process_mode(struct uli526x_board_info *db)
{
+ struct uli_phy_ops *phy = &db->phy;
u16 phy_reg;
/* Full Duplex Mode Check */
@@ -1601,10 +1621,10 @@ static void uli526x_process_mode(struct uli526x_board_info *db)
update_cr6(db->cr6_data, db->ioaddr);
/* 10/100M phyxcer force mode need */
- if ( !(db->media_mode & 0x8)) {
+ if (!(db->media_mode & 0x8)) {
/* Forece Mode */
- phy_reg = phy_read(db->ioaddr, db->phy_addr, 6, db->chip_id);
- if ( !(phy_reg & 0x1) ) {
+ phy_reg = phy->read(db, db->phy_addr, 6);
+ if (!(phy_reg & 0x1)) {
/* parter without N-Way capability */
phy_reg = 0x0;
switch(db->op_mode) {
@@ -1613,148 +1633,126 @@ static void uli526x_process_mode(struct uli526x_board_info *db)
case ULI526X_100MHF: phy_reg = 0x2000; break;
case ULI526X_100MFD: phy_reg = 0x2100; break;
}
- phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
+ phy->write(db, db->phy_addr, 0, phy_reg);
}
}
}
-/*
- * Write a word to Phy register
- */
-
-static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id)
+/* M5261/M5263 Chip */
+static void phy_writeby_cr9(struct uli526x_board_info *db, u8 phy_addr,
+ u8 offset, u16 phy_data)
{
u16 i;
- unsigned long ioaddr;
-
- if(chip_id == PCI_ULI5263_ID)
- {
- phy_writeby_cr10(iobase, phy_addr, offset, phy_data);
- return;
- }
- /* M5261/M5263 Chip */
- ioaddr = iobase + DCR9;
/* Send 33 synchronization clock to Phy controller */
for (i = 0; i < 35; i++)
- phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(db, PHY_DATA_1);
/* Send start command(01) to Phy */
- phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
- phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(db, PHY_DATA_0);
+ phy_write_1bit(db, PHY_DATA_1);
/* Send write command(01) to Phy */
- phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
- phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(db, PHY_DATA_0);
+ phy_write_1bit(db, PHY_DATA_1);
/* Send Phy address */
for (i = 0x10; i > 0; i = i >> 1)
- phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+ phy_write_1bit(db, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
/* Send register address */
for (i = 0x10; i > 0; i = i >> 1)
- phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+ phy_write_1bit(db, offset & i ? PHY_DATA_1 : PHY_DATA_0);
/* written trasnition */
- phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
- phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(db, PHY_DATA_1);
+ phy_write_1bit(db, PHY_DATA_0);
/* Write a word data to PHY controller */
- for ( i = 0x8000; i > 0; i >>= 1)
- phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
-
+ for (i = 0x8000; i > 0; i >>= 1)
+ phy_write_1bit(db, phy_data & i ? PHY_DATA_1 : PHY_DATA_0);
}
-
-/*
- * Read a word data from phy register
- */
-
-static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
+static u16 phy_readby_cr9(struct uli526x_board_info *db, u8 phy_addr, u8 offset)
{
- int i;
u16 phy_data;
- unsigned long ioaddr;
-
- if(chip_id == PCI_ULI5263_ID)
- return phy_readby_cr10(iobase, phy_addr, offset);
- /* M5261/M5263 Chip */
- ioaddr = iobase + DCR9;
+ int i;
/* Send 33 synchronization clock to Phy controller */
for (i = 0; i < 35; i++)
- phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(db, PHY_DATA_1);
/* Send start command(01) to Phy */
- phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
- phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(db, PHY_DATA_0);
+ phy_write_1bit(db, PHY_DATA_1);
/* Send read command(10) to Phy */
- phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
- phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(db, PHY_DATA_1);
+ phy_write_1bit(db, PHY_DATA_0);
/* Send Phy address */
for (i = 0x10; i > 0; i = i >> 1)
- phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+ phy_write_1bit(db, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
/* Send register address */
for (i = 0x10; i > 0; i = i >> 1)
- phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
+ phy_write_1bit(db, offset & i ? PHY_DATA_1 : PHY_DATA_0);
/* Skip transition state */
- phy_read_1bit(ioaddr, chip_id);
+ phy_read_1bit(db);
/* read 16bit data */
for (phy_data = 0, i = 0; i < 16; i++) {
phy_data <<= 1;
- phy_data |= phy_read_1bit(ioaddr, chip_id);
+ phy_data |= phy_read_1bit(db);
}
return phy_data;
}
-static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset)
+static u16 phy_readby_cr10(struct uli526x_board_info *db, u8 phy_addr,
+ u8 offset)
{
- unsigned long ioaddr,cr10_value;
+ void __iomem *ioaddr = db->ioaddr;
+ u32 cr10_value = phy_addr;
- ioaddr = iobase + DCR10;
- cr10_value = phy_addr;
- cr10_value = (cr10_value<<5) + offset;
- cr10_value = (cr10_value<<16) + 0x08000000;
- outl(cr10_value,ioaddr);
+ cr10_value = (cr10_value << 5) + offset;
+ cr10_value = (cr10_value << 16) + 0x08000000;
+ uw32(DCR10, cr10_value);
udelay(1);
- while(1)
- {
- cr10_value = inl(ioaddr);
- if(cr10_value&0x10000000)
+ while (1) {
+ cr10_value = ur32(DCR10);
+ if (cr10_value & 0x10000000)
break;
}
return cr10_value & 0x0ffff;
}
-static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data)
+static void phy_writeby_cr10(struct uli526x_board_info *db, u8 phy_addr,
+ u8 offset, u16 phy_data)
{
- unsigned long ioaddr,cr10_value;
+ void __iomem *ioaddr = db->ioaddr;
+ u32 cr10_value = phy_addr;
- ioaddr = iobase + DCR10;
- cr10_value = phy_addr;
- cr10_value = (cr10_value<<5) + offset;
- cr10_value = (cr10_value<<16) + 0x04000000 + phy_data;
- outl(cr10_value,ioaddr);
+ cr10_value = (cr10_value << 5) + offset;
+ cr10_value = (cr10_value << 16) + 0x04000000 + phy_data;
+ uw32(DCR10, cr10_value);
udelay(1);
}
/*
* Write one bit data to Phy Controller
*/
-static void phy_write_1bit(unsigned long ioaddr, u32 phy_data, u32 chip_id)
+static void phy_write_1bit(struct uli526x_board_info *db, u32 data)
{
- outl(phy_data , ioaddr); /* MII Clock Low */
+ void __iomem *ioaddr = db->ioaddr;
+
+ uw32(DCR9, data); /* MII Clock Low */
udelay(1);
- outl(phy_data | MDCLKH, ioaddr); /* MII Clock High */
+ uw32(DCR9, data | MDCLKH); /* MII Clock High */
udelay(1);
- outl(phy_data , ioaddr); /* MII Clock Low */
+ uw32(DCR9, data); /* MII Clock Low */
udelay(1);
}
@@ -1763,14 +1761,15 @@ static void phy_write_1bit(unsigned long ioaddr, u32 phy_data, u32 chip_id)
* Read one bit phy data from PHY controller
*/
-static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id)
+static u16 phy_read_1bit(struct uli526x_board_info *db)
{
+ void __iomem *ioaddr = db->ioaddr;
u16 phy_data;
- outl(0x50000 , ioaddr);
+ uw32(DCR9, 0x50000);
udelay(1);
- phy_data = ( inl(ioaddr) >> 19 ) & 0x1;
- outl(0x40000 , ioaddr);
+ phy_data = (ur32(DCR9) >> 19) & 0x1;
+ uw32(DCR9, 0x40000);
udelay(1);
return phy_data;
diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c
index 2ac6fff0363a..4d1ffca83c82 100644
--- a/drivers/net/ethernet/dec/tulip/winbond-840.c
+++ b/drivers/net/ethernet/dec/tulip/winbond-840.c
@@ -400,9 +400,6 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
No hold time required! */
iowrite32(0x00000001, ioaddr + PCIBusCfg);
- dev->base_addr = (unsigned long)ioaddr;
- dev->irq = irq;
-
np = netdev_priv(dev);
np->pci_dev = pdev;
np->chip_id = chip_idx;
@@ -635,17 +632,18 @@ static int netdev_open(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->base_addr;
+ const int irq = np->pci_dev->irq;
int i;
iowrite32(0x00000001, ioaddr + PCIBusCfg); /* Reset */
netif_device_detach(dev);
- i = request_irq(dev->irq, intr_handler, IRQF_SHARED, dev->name, dev);
+ i = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev);
if (i)
goto out_err;
if (debug > 1)
- netdev_dbg(dev, "w89c840_open() irq %d\n", dev->irq);
+ netdev_dbg(dev, "w89c840_open() irq %d\n", irq);
if((i=alloc_ringdesc(dev)))
goto out_err;
@@ -932,6 +930,7 @@ static void tx_timeout(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->base_addr;
+ const int irq = np->pci_dev->irq;
dev_warn(&dev->dev, "Transmit timed out, status %08x, resetting...\n",
ioread32(ioaddr + IntrStatus));
@@ -951,7 +950,7 @@ static void tx_timeout(struct net_device *dev)
np->cur_tx, np->dirty_tx, np->tx_full, np->tx_q_bytes);
printk(KERN_DEBUG "Tx Descriptor addr %xh\n", ioread32(ioaddr+0x4C));
- disable_irq(dev->irq);
+ disable_irq(irq);
spin_lock_irq(&np->lock);
/*
* Under high load dirty_tx and the internal tx descriptor pointer
@@ -966,7 +965,7 @@ static void tx_timeout(struct net_device *dev)
init_rxtx_rings(dev);
init_registers(dev);
spin_unlock_irq(&np->lock);
- enable_irq(dev->irq);
+ enable_irq(irq);
netif_wake_queue(dev);
dev->trans_start = jiffies; /* prevent tx timeout */
@@ -1500,7 +1499,7 @@ static int netdev_close(struct net_device *dev)
iowrite32(0x0000, ioaddr + IntrEnable);
spin_unlock_irq(&np->lock);
- free_irq(dev->irq, dev);
+ free_irq(np->pci_dev->irq, dev);
wmb();
netif_device_attach(dev);
@@ -1589,7 +1588,7 @@ static int w840_suspend (struct pci_dev *pdev, pm_message_t state)
iowrite32(0, ioaddr + IntrEnable);
spin_unlock_irq(&np->lock);
- synchronize_irq(dev->irq);
+ synchronize_irq(np->pci_dev->irq);
netif_tx_disable(dev);
np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff;
diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c
index fdb329fe6e8e..138bf83bc98e 100644
--- a/drivers/net/ethernet/dec/tulip/xircom_cb.c
+++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c
@@ -41,7 +41,9 @@ MODULE_DESCRIPTION("Xircom Cardbus ethernet driver");
MODULE_AUTHOR("Arjan van de Ven <arjanv@redhat.com>");
MODULE_LICENSE("GPL");
-
+#define xw32(reg, val) iowrite32(val, ioaddr + (reg))
+#define xr32(reg) ioread32(ioaddr + (reg))
+#define xr8(reg) ioread8(ioaddr + (reg))
/* IO registers on the card, offsets */
#define CSR0 0x00
@@ -83,7 +85,7 @@ struct xircom_private {
struct sk_buff *tx_skb[4];
- unsigned long io_port;
+ void __iomem *ioaddr;
int open;
/* transmit_used is the rotating counter that indicates which transmit
@@ -137,7 +139,7 @@ static int link_status(struct xircom_private *card);
static DEFINE_PCI_DEVICE_TABLE(xircom_pci_table) = {
- {0x115D, 0x0003, PCI_ANY_ID, PCI_ANY_ID,},
+ { PCI_VDEVICE(XIRCOM, 0x0003), },
{0,},
};
MODULE_DEVICE_TABLE(pci, xircom_pci_table);
@@ -146,9 +148,7 @@ static struct pci_driver xircom_ops = {
.name = "xircom_cb",
.id_table = xircom_pci_table,
.probe = xircom_probe,
- .remove = xircom_remove,
- .suspend =NULL,
- .resume =NULL
+ .remove = __devexit_p(xircom_remove),
};
@@ -192,15 +192,18 @@ static const struct net_device_ops netdev_ops = {
*/
static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ struct device *d = &pdev->dev;
struct net_device *dev = NULL;
struct xircom_private *private;
unsigned long flags;
unsigned short tmp16;
+ int rc;
/* First do the PCI initialisation */
- if (pci_enable_device(pdev))
- return -ENODEV;
+ rc = pci_enable_device(pdev);
+ if (rc < 0)
+ goto out;
/* disable all powermanagement */
pci_write_config_dword(pdev, PCI_POWERMGMT, 0x0000);
@@ -211,11 +214,13 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
pci_read_config_word (pdev,PCI_STATUS, &tmp16);
pci_write_config_word (pdev, PCI_STATUS,tmp16);
- if (!request_region(pci_resource_start(pdev, 0), 128, "xircom_cb")) {
+ rc = pci_request_regions(pdev, "xircom_cb");
+ if (rc < 0) {
pr_err("%s: failed to allocate io-region\n", __func__);
- return -ENODEV;
+ goto err_disable;
}
+ rc = -ENOMEM;
/*
Before changing the hardware, allocate the memory.
This way, we can fail gracefully if not enough memory
@@ -223,17 +228,21 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
*/
dev = alloc_etherdev(sizeof(struct xircom_private));
if (!dev)
- goto device_fail;
+ goto err_release;
private = netdev_priv(dev);
/* Allocate the send/receive buffers */
- private->rx_buffer = pci_alloc_consistent(pdev,8192,&private->rx_dma_handle);
+ private->rx_buffer = dma_alloc_coherent(d, 8192,
+ &private->rx_dma_handle,
+ GFP_KERNEL);
if (private->rx_buffer == NULL) {
pr_err("%s: no memory for rx buffer\n", __func__);
goto rx_buf_fail;
}
- private->tx_buffer = pci_alloc_consistent(pdev,8192,&private->tx_dma_handle);
+ private->tx_buffer = dma_alloc_coherent(d, 8192,
+ &private->tx_dma_handle,
+ GFP_KERNEL);
if (private->tx_buffer == NULL) {
pr_err("%s: no memory for tx buffer\n", __func__);
goto tx_buf_fail;
@@ -244,10 +253,13 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
private->dev = dev;
private->pdev = pdev;
- private->io_port = pci_resource_start(pdev, 0);
+
+ /* IO range. */
+ private->ioaddr = pci_iomap(pdev, 0, 0);
+ if (!private->ioaddr)
+ goto reg_fail;
+
spin_lock_init(&private->lock);
- dev->irq = pdev->irq;
- dev->base_addr = private->io_port;
initialize_card(private);
read_mac_address(private);
@@ -256,9 +268,10 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
dev->netdev_ops = &netdev_ops;
pci_set_drvdata(pdev, dev);
- if (register_netdev(dev)) {
+ rc = register_netdev(dev);
+ if (rc < 0) {
pr_err("%s: netdevice registration failed\n", __func__);
- goto reg_fail;
+ goto err_unmap;
}
netdev_info(dev, "Xircom cardbus revision %i at irq %i\n",
@@ -273,17 +286,23 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
spin_unlock_irqrestore(&private->lock,flags);
trigger_receive(private);
+out:
+ return rc;
- return 0;
-
+err_unmap:
+ pci_iounmap(pdev, private->ioaddr);
reg_fail:
- kfree(private->tx_buffer);
+ pci_set_drvdata(pdev, NULL);
+ dma_free_coherent(d, 8192, private->tx_buffer, private->tx_dma_handle);
tx_buf_fail:
- kfree(private->rx_buffer);
+ dma_free_coherent(d, 8192, private->rx_buffer, private->rx_dma_handle);
rx_buf_fail:
free_netdev(dev);
-device_fail:
- return -ENODEV;
+err_release:
+ pci_release_regions(pdev);
+err_disable:
+ pci_disable_device(pdev);
+ goto out;
}
@@ -297,25 +316,28 @@ static void __devexit xircom_remove(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct xircom_private *card = netdev_priv(dev);
+ struct device *d = &pdev->dev;
- pci_free_consistent(pdev,8192,card->rx_buffer,card->rx_dma_handle);
- pci_free_consistent(pdev,8192,card->tx_buffer,card->tx_dma_handle);
-
- release_region(dev->base_addr, 128);
unregister_netdev(dev);
- free_netdev(dev);
+ pci_iounmap(pdev, card->ioaddr);
pci_set_drvdata(pdev, NULL);
+ dma_free_coherent(d, 8192, card->tx_buffer, card->tx_dma_handle);
+ dma_free_coherent(d, 8192, card->rx_buffer, card->rx_dma_handle);
+ free_netdev(dev);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
}
static irqreturn_t xircom_interrupt(int irq, void *dev_instance)
{
struct net_device *dev = (struct net_device *) dev_instance;
struct xircom_private *card = netdev_priv(dev);
+ void __iomem *ioaddr = card->ioaddr;
unsigned int status;
int i;
spin_lock(&card->lock);
- status = inl(card->io_port+CSR5);
+ status = xr32(CSR5);
#if defined DEBUG && DEBUG > 1
print_binary(status);
@@ -345,7 +367,7 @@ static irqreturn_t xircom_interrupt(int irq, void *dev_instance)
/* Clear all remaining interrupts */
status |= 0xffffffff; /* FIXME: make this clear only the
real existing bits */
- outl(status,card->io_port+CSR5);
+ xw32(CSR5, status);
for (i=0;i<NUMDESCRIPTORS;i++)
@@ -423,11 +445,11 @@ static netdev_tx_t xircom_start_xmit(struct sk_buff *skb,
static int xircom_open(struct net_device *dev)
{
struct xircom_private *xp = netdev_priv(dev);
+ const int irq = xp->pdev->irq;
int retval;
- netdev_info(dev, "xircom cardbus adaptor found, using irq %i\n",
- dev->irq);
- retval = request_irq(dev->irq, xircom_interrupt, IRQF_SHARED, dev->name, dev);
+ netdev_info(dev, "xircom cardbus adaptor found, using irq %i\n", irq);
+ retval = request_irq(irq, xircom_interrupt, IRQF_SHARED, dev->name, dev);
if (retval)
return retval;
@@ -459,7 +481,7 @@ static int xircom_close(struct net_device *dev)
spin_unlock_irqrestore(&card->lock,flags);
card->open = 0;
- free_irq(dev->irq,dev);
+ free_irq(card->pdev->irq, dev);
return 0;
@@ -469,35 +491,39 @@ static int xircom_close(struct net_device *dev)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void xircom_poll_controller(struct net_device *dev)
{
- disable_irq(dev->irq);
- xircom_interrupt(dev->irq, dev);
- enable_irq(dev->irq);
+ struct xircom_private *xp = netdev_priv(dev);
+ const int irq = xp->pdev->irq;
+
+ disable_irq(irq);
+ xircom_interrupt(irq, dev);
+ enable_irq(irq);
}
#endif
static void initialize_card(struct xircom_private *card)
{
- unsigned int val;
+ void __iomem *ioaddr = card->ioaddr;
unsigned long flags;
+ u32 val;
spin_lock_irqsave(&card->lock, flags);
/* First: reset the card */
- val = inl(card->io_port + CSR0);
+ val = xr32(CSR0);
val |= 0x01; /* Software reset */
- outl(val, card->io_port + CSR0);
+ xw32(CSR0, val);
udelay(100); /* give the card some time to reset */
- val = inl(card->io_port + CSR0);
+ val = xr32(CSR0);
val &= ~0x01; /* disable Software reset */
- outl(val, card->io_port + CSR0);
+ xw32(CSR0, val);
val = 0; /* Value 0x00 is a safe and conservative value
for the PCI configuration settings */
- outl(val, card->io_port + CSR0);
+ xw32(CSR0, val);
disable_all_interrupts(card);
@@ -515,10 +541,9 @@ ignored; I chose zero.
*/
static void trigger_transmit(struct xircom_private *card)
{
- unsigned int val;
+ void __iomem *ioaddr = card->ioaddr;
- val = 0;
- outl(val, card->io_port + CSR1);
+ xw32(CSR1, 0);
}
/*
@@ -530,10 +555,9 @@ ignored; I chose zero.
*/
static void trigger_receive(struct xircom_private *card)
{
- unsigned int val;
+ void __iomem *ioaddr = card->ioaddr;
- val = 0;
- outl(val, card->io_port + CSR2);
+ xw32(CSR2, 0);
}
/*
@@ -542,6 +566,7 @@ descriptors and programs the addresses into the card.
*/
static void setup_descriptors(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
u32 address;
int i;
@@ -571,7 +596,7 @@ static void setup_descriptors(struct xircom_private *card)
wmb();
/* Write the receive descriptor ring address to the card */
address = card->rx_dma_handle;
- outl(address, card->io_port + CSR3); /* Receive descr list address */
+ xw32(CSR3, address); /* Receive descr list address */
/* transmit descriptors */
@@ -596,7 +621,7 @@ static void setup_descriptors(struct xircom_private *card)
wmb();
/* wite the transmit descriptor ring to the card */
address = card->tx_dma_handle;
- outl(address, card->io_port + CSR4); /* xmit descr list address */
+ xw32(CSR4, address); /* xmit descr list address */
}
/*
@@ -605,11 +630,12 @@ valid by setting the address in the card to 0x00.
*/
static void remove_descriptors(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned int val;
val = 0;
- outl(val, card->io_port + CSR3); /* Receive descriptor address */
- outl(val, card->io_port + CSR4); /* Send descriptor address */
+ xw32(CSR3, val); /* Receive descriptor address */
+ xw32(CSR4, val); /* Send descriptor address */
}
/*
@@ -620,17 +646,17 @@ This function also clears the status-bit.
*/
static int link_status_changed(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned int val;
- val = inl(card->io_port + CSR5); /* Status register */
-
- if ((val & (1 << 27)) == 0) /* no change */
+ val = xr32(CSR5); /* Status register */
+ if (!(val & (1 << 27))) /* no change */
return 0;
/* clear the event by writing a 1 to the bit in the
status register. */
val = (1 << 27);
- outl(val, card->io_port + CSR5);
+ xw32(CSR5, val);
return 1;
}
@@ -642,11 +668,9 @@ in a non-stopped state.
*/
static int transmit_active(struct xircom_private *card)
{
- unsigned int val;
-
- val = inl(card->io_port + CSR5); /* Status register */
+ void __iomem *ioaddr = card->ioaddr;
- if ((val & (7 << 20)) == 0) /* transmitter disabled */
+ if (!(xr32(CSR5) & (7 << 20))) /* transmitter disabled */
return 0;
return 1;
@@ -658,11 +682,9 @@ in a non-stopped state.
*/
static int receive_active(struct xircom_private *card)
{
- unsigned int val;
-
- val = inl(card->io_port + CSR5); /* Status register */
+ void __iomem *ioaddr = card->ioaddr;
- if ((val & (7 << 17)) == 0) /* receiver disabled */
+ if (!(xr32(CSR5) & (7 << 17))) /* receiver disabled */
return 0;
return 1;
@@ -680,10 +702,11 @@ must be called with the lock held and interrupts disabled.
*/
static void activate_receiver(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned int val;
int counter;
- val = inl(card->io_port + CSR6); /* Operation mode */
+ val = xr32(CSR6); /* Operation mode */
/* If the "active" bit is set and the receiver is already
active, no need to do the expensive thing */
@@ -692,7 +715,7 @@ static void activate_receiver(struct xircom_private *card)
val = val & ~2; /* disable the receiver */
- outl(val, card->io_port + CSR6);
+ xw32(CSR6, val);
counter = 10;
while (counter > 0) {
@@ -706,9 +729,9 @@ static void activate_receiver(struct xircom_private *card)
}
/* enable the receiver */
- val = inl(card->io_port + CSR6); /* Operation mode */
- val = val | 2; /* enable the receiver */
- outl(val, card->io_port + CSR6);
+ val = xr32(CSR6); /* Operation mode */
+ val = val | 2; /* enable the receiver */
+ xw32(CSR6, val);
/* now wait for the card to activate again */
counter = 10;
@@ -733,12 +756,13 @@ must be called with the lock held and interrupts disabled.
*/
static void deactivate_receiver(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned int val;
int counter;
- val = inl(card->io_port + CSR6); /* Operation mode */
- val = val & ~2; /* disable the receiver */
- outl(val, card->io_port + CSR6);
+ val = xr32(CSR6); /* Operation mode */
+ val = val & ~2; /* disable the receiver */
+ xw32(CSR6, val);
counter = 10;
while (counter > 0) {
@@ -765,10 +789,11 @@ must be called with the lock held and interrupts disabled.
*/
static void activate_transmitter(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned int val;
int counter;
- val = inl(card->io_port + CSR6); /* Operation mode */
+ val = xr32(CSR6); /* Operation mode */
/* If the "active" bit is set and the receiver is already
active, no need to do the expensive thing */
@@ -776,7 +801,7 @@ static void activate_transmitter(struct xircom_private *card)
return;
val = val & ~(1 << 13); /* disable the transmitter */
- outl(val, card->io_port + CSR6);
+ xw32(CSR6, val);
counter = 10;
while (counter > 0) {
@@ -791,9 +816,9 @@ static void activate_transmitter(struct xircom_private *card)
}
/* enable the transmitter */
- val = inl(card->io_port + CSR6); /* Operation mode */
+ val = xr32(CSR6); /* Operation mode */
val = val | (1 << 13); /* enable the transmitter */
- outl(val, card->io_port + CSR6);
+ xw32(CSR6, val);
/* now wait for the card to activate again */
counter = 10;
@@ -818,12 +843,13 @@ must be called with the lock held and interrupts disabled.
*/
static void deactivate_transmitter(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned int val;
int counter;
- val = inl(card->io_port + CSR6); /* Operation mode */
+ val = xr32(CSR6); /* Operation mode */
val = val & ~2; /* disable the transmitter */
- outl(val, card->io_port + CSR6);
+ xw32(CSR6, val);
counter = 20;
while (counter > 0) {
@@ -846,11 +872,12 @@ must be called with the lock held and interrupts disabled.
*/
static void enable_transmit_interrupt(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned int val;
- val = inl(card->io_port + CSR7); /* Interrupt enable register */
- val |= 1; /* enable the transmit interrupt */
- outl(val, card->io_port + CSR7);
+ val = xr32(CSR7); /* Interrupt enable register */
+ val |= 1; /* enable the transmit interrupt */
+ xw32(CSR7, val);
}
@@ -861,11 +888,12 @@ must be called with the lock held and interrupts disabled.
*/
static void enable_receive_interrupt(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned int val;
- val = inl(card->io_port + CSR7); /* Interrupt enable register */
- val = val | (1 << 6); /* enable the receive interrupt */
- outl(val, card->io_port + CSR7);
+ val = xr32(CSR7); /* Interrupt enable register */
+ val = val | (1 << 6); /* enable the receive interrupt */
+ xw32(CSR7, val);
}
/*
@@ -875,11 +903,12 @@ must be called with the lock held and interrupts disabled.
*/
static void enable_link_interrupt(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned int val;
- val = inl(card->io_port + CSR7); /* Interrupt enable register */
- val = val | (1 << 27); /* enable the link status chage interrupt */
- outl(val, card->io_port + CSR7);
+ val = xr32(CSR7); /* Interrupt enable register */
+ val = val | (1 << 27); /* enable the link status chage interrupt */
+ xw32(CSR7, val);
}
@@ -891,10 +920,9 @@ must be called with the lock held and interrupts disabled.
*/
static void disable_all_interrupts(struct xircom_private *card)
{
- unsigned int val;
+ void __iomem *ioaddr = card->ioaddr;
- val = 0; /* disable all interrupts */
- outl(val, card->io_port + CSR7);
+ xw32(CSR7, 0);
}
/*
@@ -904,9 +932,10 @@ must be called with the lock held and interrupts disabled.
*/
static void enable_common_interrupts(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned int val;
- val = inl(card->io_port + CSR7); /* Interrupt enable register */
+ val = xr32(CSR7); /* Interrupt enable register */
val |= (1<<16); /* Normal Interrupt Summary */
val |= (1<<15); /* Abnormal Interrupt Summary */
val |= (1<<13); /* Fatal bus error */
@@ -915,7 +944,7 @@ static void enable_common_interrupts(struct xircom_private *card)
val |= (1<<5); /* Transmit Underflow */
val |= (1<<2); /* Transmit Buffer Unavailable */
val |= (1<<1); /* Transmit Process Stopped */
- outl(val, card->io_port + CSR7);
+ xw32(CSR7, val);
}
/*
@@ -925,11 +954,12 @@ must be called with the lock held and interrupts disabled.
*/
static int enable_promisc(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned int val;
- val = inl(card->io_port + CSR6);
+ val = xr32(CSR6);
val = val | (1 << 6);
- outl(val, card->io_port + CSR6);
+ xw32(CSR6, val);
return 1;
}
@@ -944,13 +974,16 @@ Must be called in locked state with interrupts disabled
*/
static int link_status(struct xircom_private *card)
{
- unsigned int val;
+ void __iomem *ioaddr = card->ioaddr;
+ u8 val;
- val = inb(card->io_port + CSR12);
+ val = xr8(CSR12);
- if (!(val&(1<<2))) /* bit 2 is 0 for 10mbit link, 1 for not an 10mbit link */
+ /* bit 2 is 0 for 10mbit link, 1 for not an 10mbit link */
+ if (!(val & (1 << 2)))
return 10;
- if (!(val&(1<<1))) /* bit 1 is 0 for 100mbit link, 1 for not an 100mbit link */
+ /* bit 1 is 0 for 100mbit link, 1 for not an 100mbit link */
+ if (!(val & (1 << 1)))
return 100;
/* If we get here -> no link at all */
@@ -969,29 +1002,31 @@ static int link_status(struct xircom_private *card)
*/
static void read_mac_address(struct xircom_private *card)
{
- unsigned char j, tuple, link, data_id, data_count;
+ void __iomem *ioaddr = card->ioaddr;
unsigned long flags;
+ u8 link;
int i;
spin_lock_irqsave(&card->lock, flags);
- outl(1 << 12, card->io_port + CSR9); /* enable boot rom access */
+ xw32(CSR9, 1 << 12); /* enable boot rom access */
for (i = 0x100; i < 0x1f7; i += link + 2) {
- outl(i, card->io_port + CSR10);
- tuple = inl(card->io_port + CSR9) & 0xff;
- outl(i + 1, card->io_port + CSR10);
- link = inl(card->io_port + CSR9) & 0xff;
- outl(i + 2, card->io_port + CSR10);
- data_id = inl(card->io_port + CSR9) & 0xff;
- outl(i + 3, card->io_port + CSR10);
- data_count = inl(card->io_port + CSR9) & 0xff;
+ u8 tuple, data_id, data_count;
+
+ xw32(CSR10, i);
+ tuple = xr32(CSR9);
+ xw32(CSR10, i + 1);
+ link = xr32(CSR9);
+ xw32(CSR10, i + 2);
+ data_id = xr32(CSR9);
+ xw32(CSR10, i + 3);
+ data_count = xr32(CSR9);
if ((tuple == 0x22) && (data_id == 0x04) && (data_count == 0x06)) {
- /*
- * This is it. We have the data we want.
- */
+ int j;
+
for (j = 0; j < 6; j++) {
- outl(i + j + 4, card->io_port + CSR10);
- card->dev->dev_addr[j] = inl(card->io_port + CSR9) & 0xff;
+ xw32(CSR10, i + j + 4);
+ card->dev->dev_addr[j] = xr32(CSR9) & 0xff;
}
break;
} else if (link == 0) {
@@ -1010,6 +1045,7 @@ static void read_mac_address(struct xircom_private *card)
*/
static void transceiver_voodoo(struct xircom_private *card)
{
+ void __iomem *ioaddr = card->ioaddr;
unsigned long flags;
/* disable all powermanagement */
@@ -1019,14 +1055,14 @@ static void transceiver_voodoo(struct xircom_private *card)
spin_lock_irqsave(&card->lock, flags);
- outl(0x0008, card->io_port + CSR15);
- udelay(25);
- outl(0xa8050000, card->io_port + CSR15);
- udelay(25);
- outl(0xa00f0000, card->io_port + CSR15);
- udelay(25);
+ xw32(CSR15, 0x0008);
+ udelay(25);
+ xw32(CSR15, 0xa8050000);
+ udelay(25);
+ xw32(CSR15, 0xa00f0000);
+ udelay(25);
- spin_unlock_irqrestore(&card->lock, flags);
+ spin_unlock_irqrestore(&card->lock, flags);
netif_start_queue(card->dev);
}
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
index 2e09edb9cdf8..a059f0c27e28 100644
--- a/drivers/net/ethernet/dlink/dl2k.c
+++ b/drivers/net/ethernet/dlink/dl2k.c
@@ -16,6 +16,13 @@
#include "dl2k.h"
#include <linux/dma-mapping.h>
+#define dw32(reg, val) iowrite32(val, ioaddr + (reg))
+#define dw16(reg, val) iowrite16(val, ioaddr + (reg))
+#define dw8(reg, val) iowrite8(val, ioaddr + (reg))
+#define dr32(reg) ioread32(ioaddr + (reg))
+#define dr16(reg) ioread16(ioaddr + (reg))
+#define dr8(reg) ioread8(ioaddr + (reg))
+
static char version[] __devinitdata =
KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n";
#define MAX_UNITS 8
@@ -49,8 +56,13 @@ module_param(tx_coalesce, int, 0); /* HW xmit count each TxDMAComplete */
/* Enable the default interrupts */
#define DEFAULT_INTR (RxDMAComplete | HostError | IntRequested | TxDMAComplete| \
UpdateStats | LinkEvent)
-#define EnableInt() \
-writew(DEFAULT_INTR, ioaddr + IntEnable)
+
+static void dl2k_enable_int(struct netdev_private *np)
+{
+ void __iomem *ioaddr = np->ioaddr;
+
+ dw16(IntEnable, DEFAULT_INTR);
+}
static const int max_intrloop = 50;
static const int multicast_filter_limit = 0x40;
@@ -73,7 +85,7 @@ static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static int rio_close (struct net_device *dev);
static int find_miiphy (struct net_device *dev);
static int parse_eeprom (struct net_device *dev);
-static int read_eeprom (long ioaddr, int eep_addr);
+static int read_eeprom (struct netdev_private *, int eep_addr);
static int mii_wait_link (struct net_device *dev, int wait);
static int mii_set_media (struct net_device *dev);
static int mii_get_media (struct net_device *dev);
@@ -106,7 +118,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
static int card_idx;
int chip_idx = ent->driver_data;
int err, irq;
- long ioaddr;
+ void __iomem *ioaddr;
static int version_printed;
void *ring_space;
dma_addr_t ring_dma;
@@ -124,26 +136,29 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_disable;
pci_set_master (pdev);
+
+ err = -ENOMEM;
+
dev = alloc_etherdev (sizeof (*np));
- if (!dev) {
- err = -ENOMEM;
+ if (!dev)
goto err_out_res;
- }
SET_NETDEV_DEV(dev, &pdev->dev);
-#ifdef MEM_MAPPING
- ioaddr = pci_resource_start (pdev, 1);
- ioaddr = (long) ioremap (ioaddr, RIO_IO_SIZE);
- if (!ioaddr) {
- err = -ENOMEM;
+ np = netdev_priv(dev);
+
+ /* IO registers range. */
+ ioaddr = pci_iomap(pdev, 0, 0);
+ if (!ioaddr)
goto err_out_dev;
- }
-#else
- ioaddr = pci_resource_start (pdev, 0);
+ np->eeprom_addr = ioaddr;
+
+#ifdef MEM_MAPPING
+ /* MM registers range. */
+ ioaddr = pci_iomap(pdev, 1, 0);
+ if (!ioaddr)
+ goto err_out_iounmap;
#endif
- dev->base_addr = ioaddr;
- dev->irq = irq;
- np = netdev_priv(dev);
+ np->ioaddr = ioaddr;
np->chip_id = chip_idx;
np->pdev = pdev;
spin_lock_init (&np->tx_lock);
@@ -239,7 +254,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_unmap_rx;
/* Fiber device? */
- np->phy_media = (readw(ioaddr + ASICCtrl) & PhyMedia) ? 1 : 0;
+ np->phy_media = (dr16(ASICCtrl) & PhyMedia) ? 1 : 0;
np->link_status = 0;
/* Set media and reset PHY */
if (np->phy_media) {
@@ -276,22 +291,20 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
printk(KERN_INFO "vlan(id):\t%d\n", np->vlan);
return 0;
- err_out_unmap_rx:
+err_out_unmap_rx:
pci_free_consistent (pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);
- err_out_unmap_tx:
+err_out_unmap_tx:
pci_free_consistent (pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);
- err_out_iounmap:
+err_out_iounmap:
#ifdef MEM_MAPPING
- iounmap ((void *) ioaddr);
-
- err_out_dev:
+ pci_iounmap(pdev, np->ioaddr);
#endif
+ pci_iounmap(pdev, np->eeprom_addr);
+err_out_dev:
free_netdev (dev);
-
- err_out_res:
+err_out_res:
pci_release_regions (pdev);
-
- err_out_disable:
+err_out_disable:
pci_disable_device (pdev);
return err;
}
@@ -299,11 +312,9 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
static int
find_miiphy (struct net_device *dev)
{
+ struct netdev_private *np = netdev_priv(dev);
int i, phy_found = 0;
- struct netdev_private *np;
- long ioaddr;
np = netdev_priv(dev);
- ioaddr = dev->base_addr;
np->phy_addr = 1;
for (i = 31; i >= 0; i--) {
@@ -323,26 +334,19 @@ find_miiphy (struct net_device *dev)
static int
parse_eeprom (struct net_device *dev)
{
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
int i, j;
- long ioaddr = dev->base_addr;
u8 sromdata[256];
u8 *psib;
u32 crc;
PSROM_t psrom = (PSROM_t) sromdata;
- struct netdev_private *np = netdev_priv(dev);
int cid, next;
-#ifdef MEM_MAPPING
- ioaddr = pci_resource_start (np->pdev, 0);
-#endif
- /* Read eeprom */
- for (i = 0; i < 128; i++) {
- ((__le16 *) sromdata)[i] = cpu_to_le16(read_eeprom (ioaddr, i));
- }
-#ifdef MEM_MAPPING
- ioaddr = dev->base_addr;
-#endif
+ for (i = 0; i < 128; i++)
+ ((__le16 *) sromdata)[i] = cpu_to_le16(read_eeprom(np, i));
+
if (np->pdev->vendor == PCI_VENDOR_ID_DLINK) { /* D-Link Only */
/* Check CRC */
crc = ~ether_crc_le (256 - 4, sromdata);
@@ -378,8 +382,7 @@ parse_eeprom (struct net_device *dev)
return 0;
case 2: /* Duplex Polarity */
np->duplex_polarity = psib[i];
- writeb (readb (ioaddr + PhyCtrl) | psib[i],
- ioaddr + PhyCtrl);
+ dw8(PhyCtrl, dr8(PhyCtrl) | psib[i]);
break;
case 3: /* Wake Polarity */
np->wake_polarity = psib[i];
@@ -407,59 +410,57 @@ static int
rio_open (struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = np->ioaddr;
+ const int irq = np->pdev->irq;
int i;
u16 macctrl;
- i = request_irq (dev->irq, rio_interrupt, IRQF_SHARED, dev->name, dev);
+ i = request_irq(irq, rio_interrupt, IRQF_SHARED, dev->name, dev);
if (i)
return i;
/* Reset all logic functions */
- writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset,
- ioaddr + ASICCtrl + 2);
+ dw16(ASICCtrl + 2,
+ GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset);
mdelay(10);
/* DebugCtrl bit 4, 5, 9 must set */
- writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);
+ dw32(DebugCtrl, dr32(DebugCtrl) | 0x0230);
/* Jumbo frame */
if (np->jumbo != 0)
- writew (MAX_JUMBO+14, ioaddr + MaxFrameSize);
+ dw16(MaxFrameSize, MAX_JUMBO+14);
alloc_list (dev);
/* Get station address */
for (i = 0; i < 6; i++)
- writeb (dev->dev_addr[i], ioaddr + StationAddr0 + i);
+ dw8(StationAddr0 + i, dev->dev_addr[i]);
set_multicast (dev);
if (np->coalesce) {
- writel (np->rx_coalesce | np->rx_timeout << 16,
- ioaddr + RxDMAIntCtrl);
+ dw32(RxDMAIntCtrl, np->rx_coalesce | np->rx_timeout << 16);
}
/* Set RIO to poll every N*320nsec. */
- writeb (0x20, ioaddr + RxDMAPollPeriod);
- writeb (0xff, ioaddr + TxDMAPollPeriod);
- writeb (0x30, ioaddr + RxDMABurstThresh);
- writeb (0x30, ioaddr + RxDMAUrgentThresh);
- writel (0x0007ffff, ioaddr + RmonStatMask);
+ dw8(RxDMAPollPeriod, 0x20);
+ dw8(TxDMAPollPeriod, 0xff);
+ dw8(RxDMABurstThresh, 0x30);
+ dw8(RxDMAUrgentThresh, 0x30);
+ dw32(RmonStatMask, 0x0007ffff);
/* clear statistics */
clear_stats (dev);
/* VLAN supported */
if (np->vlan) {
/* priority field in RxDMAIntCtrl */
- writel (readl(ioaddr + RxDMAIntCtrl) | 0x7 << 10,
- ioaddr + RxDMAIntCtrl);
+ dw32(RxDMAIntCtrl, dr32(RxDMAIntCtrl) | 0x7 << 10);
/* VLANId */
- writew (np->vlan, ioaddr + VLANId);
+ dw16(VLANId, np->vlan);
/* Length/Type should be 0x8100 */
- writel (0x8100 << 16 | np->vlan, ioaddr + VLANTag);
+ dw32(VLANTag, 0x8100 << 16 | np->vlan);
/* Enable AutoVLANuntagging, but disable AutoVLANtagging.
VLAN information tagged by TFC' VID, CFI fields. */
- writel (readl (ioaddr + MACCtrl) | AutoVLANuntagging,
- ioaddr + MACCtrl);
+ dw32(MACCtrl, dr32(MACCtrl) | AutoVLANuntagging);
}
init_timer (&np->timer);
@@ -469,20 +470,18 @@ rio_open (struct net_device *dev)
add_timer (&np->timer);
/* Start Tx/Rx */
- writel (readl (ioaddr + MACCtrl) | StatsEnable | RxEnable | TxEnable,
- ioaddr + MACCtrl);
+ dw32(MACCtrl, dr32(MACCtrl) | StatsEnable | RxEnable | TxEnable);
macctrl = 0;
macctrl |= (np->vlan) ? AutoVLANuntagging : 0;
macctrl |= (np->full_duplex) ? DuplexSelect : 0;
macctrl |= (np->tx_flow) ? TxFlowControlEnable : 0;
macctrl |= (np->rx_flow) ? RxFlowControlEnable : 0;
- writew(macctrl, ioaddr + MACCtrl);
+ dw16(MACCtrl, macctrl);
netif_start_queue (dev);
- /* Enable default interrupts */
- EnableInt ();
+ dl2k_enable_int(np);
return 0;
}
@@ -533,10 +532,11 @@ rio_timer (unsigned long data)
static void
rio_tx_timeout (struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n",
- dev->name, readl (ioaddr + TxStatus));
+ dev->name, dr32(TxStatus));
rio_free_tx(dev, 0);
dev->if_port = 0;
dev->trans_start = jiffies; /* prevent tx timeout */
@@ -547,6 +547,7 @@ static void
alloc_list (struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
int i;
np->cur_rx = np->cur_tx = 0;
@@ -594,24 +595,23 @@ alloc_list (struct net_device *dev)
}
/* Set RFDListPtr */
- writel (np->rx_ring_dma, dev->base_addr + RFDListPtr0);
- writel (0, dev->base_addr + RFDListPtr1);
+ dw32(RFDListPtr0, np->rx_ring_dma);
+ dw32(RFDListPtr1, 0);
}
static netdev_tx_t
start_xmit (struct sk_buff *skb, struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
struct netdev_desc *txdesc;
unsigned entry;
- u32 ioaddr;
u64 tfc_vlan_tag = 0;
if (np->link_status == 0) { /* Link Down */
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
- ioaddr = dev->base_addr;
entry = np->cur_tx % TX_RING_SIZE;
np->tx_skbuff[entry] = skb;
txdesc = &np->tx_ring[entry];
@@ -646,9 +646,9 @@ start_xmit (struct sk_buff *skb, struct net_device *dev)
(1 << FragCountShift));
/* TxDMAPollNow */
- writel (readl (ioaddr + DMACtrl) | 0x00001000, ioaddr + DMACtrl);
+ dw32(DMACtrl, dr32(DMACtrl) | 0x00001000);
/* Schedule ISR */
- writel(10000, ioaddr + CountDown);
+ dw32(CountDown, 10000);
np->cur_tx = (np->cur_tx + 1) % TX_RING_SIZE;
if ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE
< TX_QUEUE_LEN - 1 && np->speed != 10) {
@@ -658,10 +658,10 @@ start_xmit (struct sk_buff *skb, struct net_device *dev)
}
/* The first TFDListPtr */
- if (readl (dev->base_addr + TFDListPtr0) == 0) {
- writel (np->tx_ring_dma + entry * sizeof (struct netdev_desc),
- dev->base_addr + TFDListPtr0);
- writel (0, dev->base_addr + TFDListPtr1);
+ if (!dr32(TFDListPtr0)) {
+ dw32(TFDListPtr0, np->tx_ring_dma +
+ entry * sizeof (struct netdev_desc));
+ dw32(TFDListPtr1, 0);
}
return NETDEV_TX_OK;
@@ -671,17 +671,15 @@ static irqreturn_t
rio_interrupt (int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
- struct netdev_private *np;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
unsigned int_status;
- long ioaddr;
int cnt = max_intrloop;
int handled = 0;
- ioaddr = dev->base_addr;
- np = netdev_priv(dev);
while (1) {
- int_status = readw (ioaddr + IntStatus);
- writew (int_status, ioaddr + IntStatus);
+ int_status = dr16(IntStatus);
+ dw16(IntStatus, int_status);
int_status &= DEFAULT_INTR;
if (int_status == 0 || --cnt < 0)
break;
@@ -692,7 +690,7 @@ rio_interrupt (int irq, void *dev_instance)
/* TxDMAComplete interrupt */
if ((int_status & (TxDMAComplete|IntRequested))) {
int tx_status;
- tx_status = readl (ioaddr + TxStatus);
+ tx_status = dr32(TxStatus);
if (tx_status & 0x01)
tx_error (dev, tx_status);
/* Free used tx skbuffs */
@@ -705,7 +703,7 @@ rio_interrupt (int irq, void *dev_instance)
rio_error (dev, int_status);
}
if (np->cur_tx != np->old_tx)
- writel (100, ioaddr + CountDown);
+ dw32(CountDown, 100);
return IRQ_RETVAL(handled);
}
@@ -765,13 +763,11 @@ rio_free_tx (struct net_device *dev, int irq)
static void
tx_error (struct net_device *dev, int tx_status)
{
- struct netdev_private *np;
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
int frame_id;
int i;
- np = netdev_priv(dev);
-
frame_id = (tx_status & 0xffff0000);
printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n",
dev->name, tx_status, frame_id);
@@ -779,23 +775,21 @@ tx_error (struct net_device *dev, int tx_status)
/* Ttransmit Underrun */
if (tx_status & 0x10) {
np->stats.tx_fifo_errors++;
- writew (readw (ioaddr + TxStartThresh) + 0x10,
- ioaddr + TxStartThresh);
+ dw16(TxStartThresh, dr16(TxStartThresh) + 0x10);
/* Transmit Underrun need to set TxReset, DMARest, FIFOReset */
- writew (TxReset | DMAReset | FIFOReset | NetworkReset,
- ioaddr + ASICCtrl + 2);
+ dw16(ASICCtrl + 2,
+ TxReset | DMAReset | FIFOReset | NetworkReset);
/* Wait for ResetBusy bit clear */
for (i = 50; i > 0; i--) {
- if ((readw (ioaddr + ASICCtrl + 2) & ResetBusy) == 0)
+ if (!(dr16(ASICCtrl + 2) & ResetBusy))
break;
mdelay (1);
}
rio_free_tx (dev, 1);
/* Reset TFDListPtr */
- writel (np->tx_ring_dma +
- np->old_tx * sizeof (struct netdev_desc),
- dev->base_addr + TFDListPtr0);
- writel (0, dev->base_addr + TFDListPtr1);
+ dw32(TFDListPtr0, np->tx_ring_dma +
+ np->old_tx * sizeof (struct netdev_desc));
+ dw32(TFDListPtr1, 0);
/* Let TxStartThresh stay default value */
}
@@ -803,10 +797,10 @@ tx_error (struct net_device *dev, int tx_status)
if (tx_status & 0x04) {
np->stats.tx_fifo_errors++;
/* TxReset and clear FIFO */
- writew (TxReset | FIFOReset, ioaddr + ASICCtrl + 2);
+ dw16(ASICCtrl + 2, TxReset | FIFOReset);
/* Wait reset done */
for (i = 50; i > 0; i--) {
- if ((readw (ioaddr + ASICCtrl + 2) & ResetBusy) == 0)
+ if (!(dr16(ASICCtrl + 2) & ResetBusy))
break;
mdelay (1);
}
@@ -821,7 +815,7 @@ tx_error (struct net_device *dev, int tx_status)
np->stats.collisions++;
#endif
/* Restart the Tx */
- writel (readw (dev->base_addr + MACCtrl) | TxEnable, ioaddr + MACCtrl);
+ dw32(MACCtrl, dr16(MACCtrl) | TxEnable);
}
static int
@@ -931,8 +925,8 @@ receive_packet (struct net_device *dev)
static void
rio_error (struct net_device *dev, int int_status)
{
- long ioaddr = dev->base_addr;
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
u16 macctrl;
/* Link change event */
@@ -954,7 +948,7 @@ rio_error (struct net_device *dev, int int_status)
TxFlowControlEnable : 0;
macctrl |= (np->rx_flow) ?
RxFlowControlEnable : 0;
- writew(macctrl, ioaddr + MACCtrl);
+ dw16(MACCtrl, macctrl);
np->link_status = 1;
netif_carrier_on(dev);
} else {
@@ -974,7 +968,7 @@ rio_error (struct net_device *dev, int int_status)
if (int_status & HostError) {
printk (KERN_ERR "%s: HostError! IntStatus %4.4x.\n",
dev->name, int_status);
- writew (GlobalReset | HostReset, ioaddr + ASICCtrl + 2);
+ dw16(ASICCtrl + 2, GlobalReset | HostReset);
mdelay (500);
}
}
@@ -982,8 +976,8 @@ rio_error (struct net_device *dev, int int_status)
static struct net_device_stats *
get_stats (struct net_device *dev)
{
- long ioaddr = dev->base_addr;
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
#ifdef MEM_MAPPING
int i;
#endif
@@ -992,106 +986,107 @@ get_stats (struct net_device *dev)
/* All statistics registers need to be acknowledged,
else statistic overflow could cause problems */
- np->stats.rx_packets += readl (ioaddr + FramesRcvOk);
- np->stats.tx_packets += readl (ioaddr + FramesXmtOk);
- np->stats.rx_bytes += readl (ioaddr + OctetRcvOk);
- np->stats.tx_bytes += readl (ioaddr + OctetXmtOk);
+ np->stats.rx_packets += dr32(FramesRcvOk);
+ np->stats.tx_packets += dr32(FramesXmtOk);
+ np->stats.rx_bytes += dr32(OctetRcvOk);
+ np->stats.tx_bytes += dr32(OctetXmtOk);
- np->stats.multicast = readl (ioaddr + McstFramesRcvdOk);
- np->stats.collisions += readl (ioaddr + SingleColFrames)
- + readl (ioaddr + MultiColFrames);
+ np->stats.multicast = dr32(McstFramesRcvdOk);
+ np->stats.collisions += dr32(SingleColFrames)
+ + dr32(MultiColFrames);
/* detailed tx errors */
- stat_reg = readw (ioaddr + FramesAbortXSColls);
+ stat_reg = dr16(FramesAbortXSColls);
np->stats.tx_aborted_errors += stat_reg;
np->stats.tx_errors += stat_reg;
- stat_reg = readw (ioaddr + CarrierSenseErrors);
+ stat_reg = dr16(CarrierSenseErrors);
np->stats.tx_carrier_errors += stat_reg;
np->stats.tx_errors += stat_reg;
/* Clear all other statistic register. */
- readl (ioaddr + McstOctetXmtOk);
- readw (ioaddr + BcstFramesXmtdOk);
- readl (ioaddr + McstFramesXmtdOk);
- readw (ioaddr + BcstFramesRcvdOk);
- readw (ioaddr + MacControlFramesRcvd);
- readw (ioaddr + FrameTooLongErrors);
- readw (ioaddr + InRangeLengthErrors);
- readw (ioaddr + FramesCheckSeqErrors);
- readw (ioaddr + FramesLostRxErrors);
- readl (ioaddr + McstOctetXmtOk);
- readl (ioaddr + BcstOctetXmtOk);
- readl (ioaddr + McstFramesXmtdOk);
- readl (ioaddr + FramesWDeferredXmt);
- readl (ioaddr + LateCollisions);
- readw (ioaddr + BcstFramesXmtdOk);
- readw (ioaddr + MacControlFramesXmtd);
- readw (ioaddr + FramesWEXDeferal);
+ dr32(McstOctetXmtOk);
+ dr16(BcstFramesXmtdOk);
+ dr32(McstFramesXmtdOk);
+ dr16(BcstFramesRcvdOk);
+ dr16(MacControlFramesRcvd);
+ dr16(FrameTooLongErrors);
+ dr16(InRangeLengthErrors);
+ dr16(FramesCheckSeqErrors);
+ dr16(FramesLostRxErrors);
+ dr32(McstOctetXmtOk);
+ dr32(BcstOctetXmtOk);
+ dr32(McstFramesXmtdOk);
+ dr32(FramesWDeferredXmt);
+ dr32(LateCollisions);
+ dr16(BcstFramesXmtdOk);
+ dr16(MacControlFramesXmtd);
+ dr16(FramesWEXDeferal);
#ifdef MEM_MAPPING
for (i = 0x100; i <= 0x150; i += 4)
- readl (ioaddr + i);
+ dr32(i);
#endif
- readw (ioaddr + TxJumboFrames);
- readw (ioaddr + RxJumboFrames);
- readw (ioaddr + TCPCheckSumErrors);
- readw (ioaddr + UDPCheckSumErrors);
- readw (ioaddr + IPCheckSumErrors);
+ dr16(TxJumboFrames);
+ dr16(RxJumboFrames);
+ dr16(TCPCheckSumErrors);
+ dr16(UDPCheckSumErrors);
+ dr16(IPCheckSumErrors);
return &np->stats;
}
static int
clear_stats (struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
#ifdef MEM_MAPPING
int i;
#endif
/* All statistics registers need to be acknowledged,
else statistic overflow could cause problems */
- readl (ioaddr + FramesRcvOk);
- readl (ioaddr + FramesXmtOk);
- readl (ioaddr + OctetRcvOk);
- readl (ioaddr + OctetXmtOk);
-
- readl (ioaddr + McstFramesRcvdOk);
- readl (ioaddr + SingleColFrames);
- readl (ioaddr + MultiColFrames);
- readl (ioaddr + LateCollisions);
+ dr32(FramesRcvOk);
+ dr32(FramesXmtOk);
+ dr32(OctetRcvOk);
+ dr32(OctetXmtOk);
+
+ dr32(McstFramesRcvdOk);
+ dr32(SingleColFrames);
+ dr32(MultiColFrames);
+ dr32(LateCollisions);
/* detailed rx errors */
- readw (ioaddr + FrameTooLongErrors);
- readw (ioaddr + InRangeLengthErrors);
- readw (ioaddr + FramesCheckSeqErrors);
- readw (ioaddr + FramesLostRxErrors);
+ dr16(FrameTooLongErrors);
+ dr16(InRangeLengthErrors);
+ dr16(FramesCheckSeqErrors);
+ dr16(FramesLostRxErrors);
/* detailed tx errors */
- readw (ioaddr + FramesAbortXSColls);
- readw (ioaddr + CarrierSenseErrors);
+ dr16(FramesAbortXSColls);
+ dr16(CarrierSenseErrors);
/* Clear all other statistic register. */
- readl (ioaddr + McstOctetXmtOk);
- readw (ioaddr + BcstFramesXmtdOk);
- readl (ioaddr + McstFramesXmtdOk);
- readw (ioaddr + BcstFramesRcvdOk);
- readw (ioaddr + MacControlFramesRcvd);
- readl (ioaddr + McstOctetXmtOk);
- readl (ioaddr + BcstOctetXmtOk);
- readl (ioaddr + McstFramesXmtdOk);
- readl (ioaddr + FramesWDeferredXmt);
- readw (ioaddr + BcstFramesXmtdOk);
- readw (ioaddr + MacControlFramesXmtd);
- readw (ioaddr + FramesWEXDeferal);
+ dr32(McstOctetXmtOk);
+ dr16(BcstFramesXmtdOk);
+ dr32(McstFramesXmtdOk);
+ dr16(BcstFramesRcvdOk);
+ dr16(MacControlFramesRcvd);
+ dr32(McstOctetXmtOk);
+ dr32(BcstOctetXmtOk);
+ dr32(McstFramesXmtdOk);
+ dr32(FramesWDeferredXmt);
+ dr16(BcstFramesXmtdOk);
+ dr16(MacControlFramesXmtd);
+ dr16(FramesWEXDeferal);
#ifdef MEM_MAPPING
for (i = 0x100; i <= 0x150; i += 4)
- readl (ioaddr + i);
+ dr32(i);
#endif
- readw (ioaddr + TxJumboFrames);
- readw (ioaddr + RxJumboFrames);
- readw (ioaddr + TCPCheckSumErrors);
- readw (ioaddr + UDPCheckSumErrors);
- readw (ioaddr + IPCheckSumErrors);
+ dr16(TxJumboFrames);
+ dr16(RxJumboFrames);
+ dr16(TCPCheckSumErrors);
+ dr16(UDPCheckSumErrors);
+ dr16(IPCheckSumErrors);
return 0;
}
@@ -1114,10 +1109,10 @@ change_mtu (struct net_device *dev, int new_mtu)
static void
set_multicast (struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
u32 hash_table[2];
u16 rx_mode = 0;
- struct netdev_private *np = netdev_priv(dev);
hash_table[0] = hash_table[1] = 0;
/* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */
@@ -1153,9 +1148,9 @@ set_multicast (struct net_device *dev)
rx_mode |= ReceiveVLANMatch;
}
- writel (hash_table[0], ioaddr + HashTable0);
- writel (hash_table[1], ioaddr + HashTable1);
- writew (rx_mode, ioaddr + ReceiveMode);
+ dw32(HashTable0, hash_table[0]);
+ dw32(HashTable1, hash_table[1]);
+ dw16(ReceiveMode, rx_mode);
}
static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
@@ -1284,15 +1279,15 @@ rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
#define EEP_BUSY 0x8000
/* Read the EEPROM word */
/* We use I/O instruction to read/write eeprom to avoid fail on some machines */
-static int
-read_eeprom (long ioaddr, int eep_addr)
+static int read_eeprom(struct netdev_private *np, int eep_addr)
{
+ void __iomem *ioaddr = np->eeprom_addr;
int i = 1000;
- outw (EEP_READ | (eep_addr & 0xff), ioaddr + EepromCtrl);
+
+ dw16(EepromCtrl, EEP_READ | (eep_addr & 0xff));
while (i-- > 0) {
- if (!(inw (ioaddr + EepromCtrl) & EEP_BUSY)) {
- return inw (ioaddr + EepromData);
- }
+ if (!(dr16(EepromCtrl) & EEP_BUSY))
+ return dr16(EepromData);
}
return 0;
}
@@ -1302,38 +1297,40 @@ enum phy_ctrl_bits {
MII_DUPLEX = 0x08,
};
-#define mii_delay() readb(ioaddr)
+#define mii_delay() dr8(PhyCtrl)
static void
mii_sendbit (struct net_device *dev, u32 data)
{
- long ioaddr = dev->base_addr + PhyCtrl;
- data = (data) ? MII_DATA1 : 0;
- data |= MII_WRITE;
- data |= (readb (ioaddr) & 0xf8) | MII_WRITE;
- writeb (data, ioaddr);
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
+
+ data = ((data) ? MII_DATA1 : 0) | (dr8(PhyCtrl) & 0xf8) | MII_WRITE;
+ dw8(PhyCtrl, data);
mii_delay ();
- writeb (data | MII_CLK, ioaddr);
+ dw8(PhyCtrl, data | MII_CLK);
mii_delay ();
}
static int
mii_getbit (struct net_device *dev)
{
- long ioaddr = dev->base_addr + PhyCtrl;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
u8 data;
- data = (readb (ioaddr) & 0xf8) | MII_READ;
- writeb (data, ioaddr);
+ data = (dr8(PhyCtrl) & 0xf8) | MII_READ;
+ dw8(PhyCtrl, data);
mii_delay ();
- writeb (data | MII_CLK, ioaddr);
+ dw8(PhyCtrl, data | MII_CLK);
mii_delay ();
- return ((readb (ioaddr) >> 1) & 1);
+ return (dr8(PhyCtrl) >> 1) & 1;
}
static void
mii_send_bits (struct net_device *dev, u32 data, int len)
{
int i;
+
for (i = len - 1; i >= 0; i--) {
mii_sendbit (dev, data & (1 << i));
}
@@ -1687,28 +1684,29 @@ mii_set_media_pcs (struct net_device *dev)
static int
rio_close (struct net_device *dev)
{
- long ioaddr = dev->base_addr;
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->ioaddr;
+
+ struct pci_dev *pdev = np->pdev;
struct sk_buff *skb;
int i;
netif_stop_queue (dev);
/* Disable interrupts */
- writew (0, ioaddr + IntEnable);
+ dw16(IntEnable, 0);
/* Stop Tx and Rx logics */
- writel (TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl);
+ dw32(MACCtrl, TxDisable | RxDisable | StatsDisable);
- free_irq (dev->irq, dev);
+ free_irq(pdev->irq, dev);
del_timer_sync (&np->timer);
/* Free all the skbuffs in the queue. */
for (i = 0; i < RX_RING_SIZE; i++) {
skb = np->rx_skbuff[i];
if (skb) {
- pci_unmap_single(np->pdev,
- desc_to_dma(&np->rx_ring[i]),
+ pci_unmap_single(pdev, desc_to_dma(&np->rx_ring[i]),
skb->len, PCI_DMA_FROMDEVICE);
dev_kfree_skb (skb);
np->rx_skbuff[i] = NULL;
@@ -1719,8 +1717,7 @@ rio_close (struct net_device *dev)
for (i = 0; i < TX_RING_SIZE; i++) {
skb = np->tx_skbuff[i];
if (skb) {
- pci_unmap_single(np->pdev,
- desc_to_dma(&np->tx_ring[i]),
+ pci_unmap_single(pdev, desc_to_dma(&np->tx_ring[i]),
skb->len, PCI_DMA_TODEVICE);
dev_kfree_skb (skb);
np->tx_skbuff[i] = NULL;
@@ -1744,8 +1741,9 @@ rio_remove1 (struct pci_dev *pdev)
pci_free_consistent (pdev, TX_TOTAL_SIZE, np->tx_ring,
np->tx_ring_dma);
#ifdef MEM_MAPPING
- iounmap ((char *) (dev->base_addr));
+ pci_iounmap(pdev, np->ioaddr);
#endif
+ pci_iounmap(pdev, np->eeprom_addr);
free_netdev (dev);
pci_release_regions (pdev);
pci_disable_device (pdev);
diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h
index 30c2da3de548..3699565704c7 100644
--- a/drivers/net/ethernet/dlink/dl2k.h
+++ b/drivers/net/ethernet/dlink/dl2k.h
@@ -42,23 +42,6 @@
#define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct netdev_desc)
#define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct netdev_desc)
-/* This driver was written to use PCI memory space, however x86-oriented
- hardware often uses I/O space accesses. */
-#ifndef MEM_MAPPING
-#undef readb
-#undef readw
-#undef readl
-#undef writeb
-#undef writew
-#undef writel
-#define readb inb
-#define readw inw
-#define readl inl
-#define writeb outb
-#define writew outw
-#define writel outl
-#endif
-
/* Offsets to the device registers.
Unlike software-only systems, device drivers interact with complex hardware.
It's not useful to define symbolic names for every register bit in the
@@ -384,6 +367,8 @@ struct netdev_private {
dma_addr_t tx_ring_dma;
dma_addr_t rx_ring_dma;
struct pci_dev *pdev;
+ void __iomem *ioaddr;
+ void __iomem *eeprom_addr;
spinlock_t tx_lock;
spinlock_t rx_lock;
struct net_device_stats stats;
diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c
index d783f4f96ec0..d7bb52a7bda1 100644
--- a/drivers/net/ethernet/dlink/sundance.c
+++ b/drivers/net/ethernet/dlink/sundance.c
@@ -522,9 +522,6 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
cpu_to_le16(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET));
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- dev->base_addr = (unsigned long)ioaddr;
- dev->irq = irq;
-
np = netdev_priv(dev);
np->base = ioaddr;
np->pci_dev = pdev;
@@ -828,18 +825,19 @@ static int netdev_open(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->base;
+ const int irq = np->pci_dev->irq;
unsigned long flags;
int i;
/* Do we need to reset the chip??? */
- i = request_irq(dev->irq, intr_handler, IRQF_SHARED, dev->name, dev);
+ i = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev);
if (i)
return i;
if (netif_msg_ifup(np))
- printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
- dev->name, dev->irq);
+ printk(KERN_DEBUG "%s: netdev_open() irq %d\n", dev->name, irq);
+
init_ring(dev);
iowrite32(np->rx_ring_dma, ioaddr + RxListPtr);
@@ -1814,7 +1812,7 @@ static int netdev_close(struct net_device *dev)
}
#endif /* __i386__ debugging only */
- free_irq(dev->irq, dev);
+ free_irq(np->pci_dev->irq, dev);
del_timer_sync(&np->timer);
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index b276469f74e9..290b26f868c9 100644
--- a/drivers/net/ethernet/dnet.c
+++ b/drivers/net/ethernet/dnet.c
@@ -815,6 +815,7 @@ static const struct ethtool_ops dnet_ethtool_ops = {
.set_settings = dnet_set_settings,
.get_drvinfo = dnet_get_drvinfo,
.get_link = ethtool_op_get_link,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static const struct net_device_ops dnet_netdev_ops = {
diff --git a/drivers/net/ethernet/emulex/benet/Makefile b/drivers/net/ethernet/emulex/benet/Makefile
index a60cd8051135..1a91b276940d 100644
--- a/drivers/net/ethernet/emulex/benet/Makefile
+++ b/drivers/net/ethernet/emulex/benet/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_BE2NET) += be2net.o
-be2net-y := be_main.o be_cmds.o be_ethtool.o
+be2net-y := be_main.o be_cmds.o be_ethtool.o be_roce.o
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 9576ac002c23..c5c4c0e83bd1 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -32,8 +32,9 @@
#include <linux/u64_stats_sync.h>
#include "be_hw.h"
+#include "be_roce.h"
-#define DRV_VER "4.2.116u"
+#define DRV_VER "4.2.220u"
#define DRV_NAME "be2net"
#define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC"
#define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC"
@@ -102,7 +103,8 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */
#define MAX_TX_QS 8
-#define MAX_MSIX_VECTORS MAX_RSS_QS
+#define MAX_ROCE_EQS 5
+#define MAX_MSIX_VECTORS (MAX_RSS_QS + MAX_ROCE_EQS) /* RSS qs + RoCE */
#define BE_TX_BUDGET 256
#define BE_NAPI_WEIGHT 64
#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
@@ -162,6 +164,11 @@ static inline void queue_head_inc(struct be_queue_info *q)
index_inc(&q->head, q->len);
}
+static inline void index_dec(u16 *index, u16 limit)
+{
+ *index = MODULO((*index - 1), limit);
+}
+
static inline void queue_tail_inc(struct be_queue_info *q)
{
index_inc(&q->tail, q->len);
@@ -308,11 +315,33 @@ struct be_vf_cfg {
u32 tx_rate;
};
+enum vf_state {
+ ENABLED = 0,
+ ASSIGNED = 1
+};
+
#define BE_FLAGS_LINK_STATUS_INIT 1
#define BE_FLAGS_WORKER_SCHEDULED (1 << 3)
#define BE_UC_PMAC_COUNT 30
#define BE_VF_UC_PMAC_COUNT 2
+struct phy_info {
+ u8 transceiver;
+ u8 autoneg;
+ u8 fc_autoneg;
+ u8 port_type;
+ u16 phy_type;
+ u16 interface_type;
+ u32 misc_params;
+ u16 auto_speeds_supported;
+ u16 fixed_speeds_supported;
+ int link_speed;
+ int forced_port_speed;
+ u32 dac_cable_len;
+ u32 advertising;
+ u32 supported;
+};
+
struct be_adapter {
struct pci_dev *pdev;
struct net_device *netdev;
@@ -377,29 +406,41 @@ struct be_adapter {
u32 rx_fc; /* Rx flow control */
u32 tx_fc; /* Tx flow control */
bool stats_cmd_sent;
- int link_speed;
- u8 port_type;
- u8 transceiver;
- u8 autoneg;
u8 generation; /* BladeEngine ASIC generation */
+ u32 if_type;
+ struct {
+ u8 __iomem *base; /* Door Bell */
+ u32 size;
+ u32 total_size;
+ u64 io_addr;
+ } roce_db;
+ u32 num_msix_roce_vec;
+ struct ocrdma_dev *ocrdma_dev;
+ struct list_head entry;
+
u32 flash_status;
struct completion flash_compl;
- u32 num_vfs;
- u8 is_virtfn;
+ u32 num_vfs; /* Number of VFs provisioned by PF driver */
+ u32 dev_num_vfs; /* Number of VFs supported by HW */
+ u8 virtfn;
struct be_vf_cfg *vf_cfg;
bool be3_native;
u32 sli_family;
u8 hba_port_num;
u16 pvid;
+ struct phy_info phy;
u8 wol_cap;
bool wol;
u32 max_pmac_cnt; /* Max secondary UC MACs programmable */
u32 uc_macs; /* Count of secondary UC MAC programmed */
+ u32 msg_enable;
};
-#define be_physfn(adapter) (!adapter->is_virtfn)
+#define be_physfn(adapter) (!adapter->virtfn)
#define sriov_enabled(adapter) (adapter->num_vfs > 0)
+#define sriov_want(adapter) (adapter->dev_num_vfs && num_vfs && \
+ be_physfn(adapter))
#define for_all_vfs(adapter, vf_cfg, i) \
for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \
i++, vf_cfg++)
@@ -413,6 +454,10 @@ struct be_adapter {
#define lancer_chip(adapter) ((adapter->pdev->device == OC_DEVICE_ID3) || \
(adapter->pdev->device == OC_DEVICE_ID4))
+#define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \
+ adapter->sli_family == SKYHAWK_SLI_FAMILY) && \
+ (adapter->function_mode & RDMA_ENABLED))
+
extern const struct ethtool_ops be_ethtool_ops;
#define msix_enabled(adapter) (adapter->num_msix_vec > 0)
@@ -528,14 +573,6 @@ static inline u8 is_udp_pkt(struct sk_buff *skb)
return val;
}
-static inline void be_check_sriov_fn_type(struct be_adapter *adapter)
-{
- u32 sli_intf;
-
- pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
- adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
-}
-
static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
{
u32 addr;
@@ -577,10 +614,31 @@ static inline bool be_is_wol_excluded(struct be_adapter *adapter)
}
}
+static inline bool be_type_2_3(struct be_adapter *adapter)
+{
+ return (adapter->if_type == SLI_INTF_TYPE_2 ||
+ adapter->if_type == SLI_INTF_TYPE_3) ? true : false;
+}
+
extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
u16 num_popped);
extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
extern void be_parse_stats(struct be_adapter *adapter);
extern int be_load_fw(struct be_adapter *adapter, u8 *func);
extern bool be_is_wol_supported(struct be_adapter *adapter);
+extern bool be_pause_supported(struct be_adapter *adapter);
+extern u32 be_get_fw_log_level(struct be_adapter *adapter);
+
+/*
+ * internal function to initialize-cleanup roce device.
+ */
+extern void be_roce_dev_add(struct be_adapter *);
+extern void be_roce_dev_remove(struct be_adapter *);
+
+/*
+ * internal function to open-close roce device during ifup-ifdown.
+ */
+extern void be_roce_dev_open(struct be_adapter *);
+extern void be_roce_dev_close(struct be_adapter *);
+
#endif /* BE_H */
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 67b030d72df1..8d06ea381741 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -15,6 +15,7 @@
* Costa Mesa, CA 92626
*/
+#include <linux/module.h>
#include "be.h"
#include "be_cmds.h"
@@ -61,10 +62,21 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
compl->flags = 0;
}
+static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1)
+{
+ unsigned long addr;
+
+ addr = tag1;
+ addr = ((addr << 16) << 16) | tag0;
+ return (void *)addr;
+}
+
static int be_mcc_compl_process(struct be_adapter *adapter,
- struct be_mcc_compl *compl)
+ struct be_mcc_compl *compl)
{
u16 compl_status, extd_status;
+ struct be_cmd_resp_hdr *resp_hdr;
+ u8 opcode = 0, subsystem = 0;
/* Just swap the status to host endian; mcc tag is opaquely copied
* from mcc_wrb */
@@ -73,32 +85,36 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
CQE_STATUS_COMPL_MASK;
- if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) ||
- (compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) &&
- (compl->tag1 == CMD_SUBSYSTEM_COMMON)) {
+ resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
+
+ if (resp_hdr) {
+ opcode = resp_hdr->opcode;
+ subsystem = resp_hdr->subsystem;
+ }
+
+ if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
+ (opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
+ (subsystem == CMD_SUBSYSTEM_COMMON)) {
adapter->flash_status = compl_status;
complete(&adapter->flash_compl);
}
if (compl_status == MCC_STATUS_SUCCESS) {
- if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) ||
- (compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) &&
- (compl->tag1 == CMD_SUBSYSTEM_ETH)) {
+ if (((opcode == OPCODE_ETH_GET_STATISTICS) ||
+ (opcode == OPCODE_ETH_GET_PPORT_STATS)) &&
+ (subsystem == CMD_SUBSYSTEM_ETH)) {
be_parse_stats(adapter);
adapter->stats_cmd_sent = false;
}
- if (compl->tag0 ==
- OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) {
- struct be_mcc_wrb *mcc_wrb =
- queue_index_node(&adapter->mcc_obj.q,
- compl->tag1);
+ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
+ subsystem == CMD_SUBSYSTEM_COMMON) {
struct be_cmd_resp_get_cntl_addnl_attribs *resp =
- embedded_payload(mcc_wrb);
+ (void *)resp_hdr;
adapter->drv_stats.be_on_die_temperature =
resp->on_die_temperature;
}
} else {
- if (compl->tag0 == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
+ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
be_get_temp_freq = 0;
if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
@@ -108,13 +124,13 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
dev_warn(&adapter->pdev->dev, "This domain(VM) is not "
"permitted to execute this cmd (opcode %d)\n",
- compl->tag0);
+ opcode);
} else {
extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
CQE_STATUS_EXTD_MASK;
dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:"
"status %d, extd-status %d\n",
- compl->tag0, compl_status, extd_status);
+ opcode, compl_status, extd_status);
}
}
done:
@@ -126,7 +142,7 @@ static void be_async_link_state_process(struct be_adapter *adapter,
struct be_async_event_link_state *evt)
{
/* When link status changes, link speed must be re-queried from FW */
- adapter->link_speed = -1;
+ adapter->phy.link_speed = -1;
/* For the initial link status do not rely on the ASYNC event as
* it may not be received in some cases.
@@ -153,7 +169,7 @@ static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
{
if (evt->physical_port == adapter->port_num) {
/* qos_link_speed is in units of 10 Mbps */
- adapter->link_speed = evt->qos_link_speed * 10;
+ adapter->phy.link_speed = evt->qos_link_speed * 10;
}
}
@@ -286,7 +302,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
if (i == mcc_timeout) {
dev_err(&adapter->pdev->dev, "FW not responding\n");
adapter->fw_timeout = true;
- return -1;
+ return -EIO;
}
return status;
}
@@ -294,8 +310,26 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
/* Notify MCC requests and wait for completion */
static int be_mcc_notify_wait(struct be_adapter *adapter)
{
+ int status;
+ struct be_mcc_wrb *wrb;
+ struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
+ u16 index = mcc_obj->q.head;
+ struct be_cmd_resp_hdr *resp;
+
+ index_dec(&index, mcc_obj->q.len);
+ wrb = queue_index_node(&mcc_obj->q, index);
+
+ resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1);
+
be_mcc_notify(adapter);
- return be_mcc_wait_compl(adapter);
+
+ status = be_mcc_wait_compl(adapter);
+ if (status == -EIO)
+ goto out;
+
+ status = resp->status;
+out:
+ return status;
}
static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
@@ -435,14 +469,17 @@ static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
struct be_mcc_wrb *wrb, struct be_dma_mem *mem)
{
struct be_sge *sge;
+ unsigned long addr = (unsigned long)req_hdr;
+ u64 req_addr = addr;
req_hdr->opcode = opcode;
req_hdr->subsystem = subsystem;
req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
req_hdr->version = 0;
- wrb->tag0 = opcode;
- wrb->tag1 = subsystem;
+ wrb->tag0 = req_addr & 0xFFFFFFFF;
+ wrb->tag1 = upper_32_bits(req_addr);
+
wrb->payload_length = cmd_len;
if (mem) {
wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
@@ -1221,7 +1258,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size, wrb,
nonemb_cmd);
- req->cmd_params.params.pport_num = cpu_to_le16(adapter->port_num);
+ req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num);
req->cmd_params.params.reset_stats = 0;
be_mcc_notify(adapter);
@@ -1283,13 +1320,10 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_cntl_addnl_attribs *req;
- u16 mccq_index;
int status;
spin_lock_bh(&adapter->mcc_lock);
- mccq_index = adapter->mcc_obj.q.head;
-
wrb = wrb_from_mccq(adapter);
if (!wrb) {
status = -EBUSY;
@@ -1301,8 +1335,6 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req),
wrb, NULL);
- wrb->tag1 = mccq_index;
-
be_mcc_notify(adapter);
err:
@@ -1824,18 +1856,16 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
spin_unlock_bh(&adapter->mcc_lock);
if (!wait_for_completion_timeout(&adapter->flash_compl,
- msecs_to_jiffies(12000)))
+ msecs_to_jiffies(30000)))
status = -1;
else
status = adapter->flash_status;
resp = embedded_payload(wrb);
- if (!status) {
+ if (!status)
*data_written = le32_to_cpu(resp->actual_write_len);
- } else {
+ else
*addn_status = resp->additional_status;
- status = resp->status;
- }
return status;
@@ -1950,7 +1980,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL);
- req->params.op_type = cpu_to_le32(IMG_TYPE_REDBOOT);
+ req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT);
req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
req->params.offset = cpu_to_le32(offset);
req->params.data_buf_size = cpu_to_le32(0x4);
@@ -2136,8 +2166,7 @@ err:
return status;
}
-int be_cmd_get_phy_info(struct be_adapter *adapter,
- struct be_phy_info *phy_info)
+int be_cmd_get_phy_info(struct be_adapter *adapter)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_phy_info *req;
@@ -2170,9 +2199,15 @@ int be_cmd_get_phy_info(struct be_adapter *adapter,
if (!status) {
struct be_phy_info *resp_phy_info =
cmd.va + sizeof(struct be_cmd_req_hdr);
- phy_info->phy_type = le16_to_cpu(resp_phy_info->phy_type);
- phy_info->interface_type =
+ adapter->phy.phy_type = le16_to_cpu(resp_phy_info->phy_type);
+ adapter->phy.interface_type =
le16_to_cpu(resp_phy_info->interface_type);
+ adapter->phy.auto_speeds_supported =
+ le16_to_cpu(resp_phy_info->auto_speeds_supported);
+ adapter->phy.fixed_speeds_supported =
+ le16_to_cpu(resp_phy_info->fixed_speeds_supported);
+ adapter->phy.misc_params =
+ le32_to_cpu(resp_phy_info->misc_params);
}
pci_free_consistent(adapter->pdev, cmd.size,
cmd.va, cmd.dma);
@@ -2555,4 +2590,98 @@ err:
mutex_unlock(&adapter->mbox_lock);
pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
return status;
+
+}
+int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_get_ext_fat_caps *req;
+ int status;
+
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+
+ wrb = wrb_from_mbox(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = cmd->va;
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_EXT_FAT_CAPABILITES,
+ cmd->size, wrb, cmd);
+ req->parameter_type = cpu_to_le32(1);
+
+ status = be_mbox_notify_wait(adapter);
+err:
+ mutex_unlock(&adapter->mbox_lock);
+ return status;
+}
+
+int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd,
+ struct be_fat_conf_params *configs)
+{
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_set_ext_fat_caps *req;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = cmd->va;
+ memcpy(&req->set_params, configs, sizeof(struct be_fat_conf_params));
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_SET_EXT_FAT_CAPABILITES,
+ cmd->size, wrb, cmd);
+
+ status = be_mcc_notify_wait(adapter);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
+}
+
+int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
+ int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
+{
+ struct be_adapter *adapter = netdev_priv(netdev_handle);
+ struct be_mcc_wrb *wrb;
+ struct be_cmd_req_hdr *hdr = (struct be_cmd_req_hdr *) wrb_payload;
+ struct be_cmd_req_hdr *req;
+ struct be_cmd_resp_hdr *resp;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+ req = embedded_payload(wrb);
+ resp = embedded_payload(wrb);
+
+ be_wrb_cmd_hdr_prepare(req, hdr->subsystem,
+ hdr->opcode, wrb_payload_size, wrb, NULL);
+ memcpy(req, wrb_payload, wrb_payload_size);
+ be_dws_cpu_to_le(req, wrb_payload_size);
+
+ status = be_mcc_notify_wait(adapter);
+ if (cmd_status)
+ *cmd_status = (status & 0xffff);
+ if (ext_status)
+ *ext_status = 0;
+ memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
+ be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
}
+EXPORT_SYMBOL(be_roce_mcc_cmd);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index d5b680c56af0..9625bf420c16 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -189,6 +189,8 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_GET_PHY_DETAILS 102
#define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103
#define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121
+#define OPCODE_COMMON_GET_EXT_FAT_CAPABILITES 125
+#define OPCODE_COMMON_SET_EXT_FAT_CAPABILITES 126
#define OPCODE_COMMON_GET_MAC_LIST 147
#define OPCODE_COMMON_SET_MAC_LIST 148
#define OPCODE_COMMON_GET_HSW_CONFIG 152
@@ -225,8 +227,12 @@ struct be_cmd_req_hdr {
#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */
#define RESP_HDR_INFO_SUBSYS_SHIFT 8 /* bits 8 - 15 */
struct be_cmd_resp_hdr {
- u32 info; /* dword 0 */
- u32 status; /* dword 1 */
+ u8 opcode; /* dword 0 */
+ u8 subsystem; /* dword 0 */
+ u8 rsvd[2]; /* dword 0 */
+ u8 status; /* dword 1 */
+ u8 add_status; /* dword 1 */
+ u8 rsvd1[2]; /* dword 1 */
u32 response_length; /* dword 2 */
u32 actual_resp_len; /* dword 3 */
};
@@ -1056,6 +1062,7 @@ struct be_cmd_resp_modify_eq_delay {
/* The HW can come up in either of the following multi-channel modes
* based on the skew/IPL.
*/
+#define RDMA_ENABLED 0x4
#define FLEX10_MODE 0x400
#define VNIC_MODE 0x20000
#define UMC_ENABLED 0x1000000
@@ -1309,9 +1316,36 @@ enum {
PHY_TYPE_KX4_10GB,
PHY_TYPE_BASET_10GB,
PHY_TYPE_BASET_1GB,
+ PHY_TYPE_BASEX_1GB,
+ PHY_TYPE_SGMII,
PHY_TYPE_DISABLED = 255
};
+#define BE_SUPPORTED_SPEED_NONE 0
+#define BE_SUPPORTED_SPEED_10MBPS 1
+#define BE_SUPPORTED_SPEED_100MBPS 2
+#define BE_SUPPORTED_SPEED_1GBPS 4
+#define BE_SUPPORTED_SPEED_10GBPS 8
+
+#define BE_AN_EN 0x2
+#define BE_PAUSE_SYM_EN 0x80
+
+/* MAC speed valid values */
+#define SPEED_DEFAULT 0x0
+#define SPEED_FORCED_10GB 0x1
+#define SPEED_FORCED_1GB 0x2
+#define SPEED_AUTONEG_10GB 0x3
+#define SPEED_AUTONEG_1GB 0x4
+#define SPEED_AUTONEG_100MB 0x5
+#define SPEED_AUTONEG_10GB_1GB 0x6
+#define SPEED_AUTONEG_10GB_1GB_100MB 0x7
+#define SPEED_AUTONEG_1GB_100MB 0x8
+#define SPEED_AUTONEG_10MB 0x9
+#define SPEED_AUTONEG_1GB_100MB_10MB 0xa
+#define SPEED_AUTONEG_100MB_10MB 0xb
+#define SPEED_FORCED_100MB 0xc
+#define SPEED_FORCED_10MB 0xd
+
struct be_cmd_req_get_phy_info {
struct be_cmd_req_hdr hdr;
u8 rsvd0[24];
@@ -1321,7 +1355,11 @@ struct be_phy_info {
u16 phy_type;
u16 interface_type;
u32 misc_params;
- u32 future_use[4];
+ u16 ext_phy_details;
+ u16 rsvd;
+ u16 auto_speeds_supported;
+ u16 fixed_speeds_supported;
+ u32 future_use[2];
};
struct be_cmd_resp_get_phy_info {
@@ -1567,6 +1605,56 @@ static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
}
}
+
+/************** get fat capabilites *******************/
+#define MAX_MODULES 27
+#define MAX_MODES 4
+#define MODE_UART 0
+#define FW_LOG_LEVEL_DEFAULT 48
+#define FW_LOG_LEVEL_FATAL 64
+
+struct ext_fat_mode {
+ u8 mode;
+ u8 rsvd0;
+ u16 port_mask;
+ u32 dbg_lvl;
+ u64 fun_mask;
+} __packed;
+
+struct ext_fat_modules {
+ u8 modules_str[32];
+ u32 modules_id;
+ u32 num_modes;
+ struct ext_fat_mode trace_lvl[MAX_MODES];
+} __packed;
+
+struct be_fat_conf_params {
+ u32 max_log_entries;
+ u32 log_entry_size;
+ u8 log_type;
+ u8 max_log_funs;
+ u8 max_log_ports;
+ u8 rsvd0;
+ u32 supp_modes;
+ u32 num_modules;
+ struct ext_fat_modules module[MAX_MODULES];
+} __packed;
+
+struct be_cmd_req_get_ext_fat_caps {
+ struct be_cmd_req_hdr hdr;
+ u32 parameter_type;
+};
+
+struct be_cmd_resp_get_ext_fat_caps {
+ struct be_cmd_resp_hdr hdr;
+ struct be_fat_conf_params get_params;
+};
+
+struct be_cmd_req_set_ext_fat_caps {
+ struct be_cmd_req_hdr hdr;
+ struct be_fat_conf_params set_params;
+};
+
extern int be_pci_fnum_get(struct be_adapter *adapter);
extern int be_cmd_POST(struct be_adapter *adapter);
extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
@@ -1655,8 +1743,7 @@ extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
struct be_dma_mem *nonemb_cmd);
extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
u8 loopback_type, u8 enable);
-extern int be_cmd_get_phy_info(struct be_adapter *adapter,
- struct be_phy_info *phy_info);
+extern int be_cmd_get_phy_info(struct be_adapter *adapter);
extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
extern void be_detect_dump_ue(struct be_adapter *adapter);
extern int be_cmd_get_die_temperature(struct be_adapter *adapter);
@@ -1673,4 +1760,9 @@ extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
extern int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
u32 domain, u16 intf_id);
extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter);
+extern int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd);
+extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd,
+ struct be_fat_conf_params *cfgs);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index c1ff73cb0e62..63e51d476900 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -433,102 +433,193 @@ static int be_get_sset_count(struct net_device *netdev, int stringset)
}
}
+static u32 be_get_port_type(u32 phy_type, u32 dac_cable_len)
+{
+ u32 port;
+
+ switch (phy_type) {
+ case PHY_TYPE_BASET_1GB:
+ case PHY_TYPE_BASEX_1GB:
+ case PHY_TYPE_SGMII:
+ port = PORT_TP;
+ break;
+ case PHY_TYPE_SFP_PLUS_10GB:
+ port = dac_cable_len ? PORT_DA : PORT_FIBRE;
+ break;
+ case PHY_TYPE_XFP_10GB:
+ case PHY_TYPE_SFP_1GB:
+ port = PORT_FIBRE;
+ break;
+ case PHY_TYPE_BASET_10GB:
+ port = PORT_TP;
+ break;
+ default:
+ port = PORT_OTHER;
+ }
+
+ return port;
+}
+
+static u32 convert_to_et_setting(u32 if_type, u32 if_speeds)
+{
+ u32 val = 0;
+
+ switch (if_type) {
+ case PHY_TYPE_BASET_1GB:
+ case PHY_TYPE_BASEX_1GB:
+ case PHY_TYPE_SGMII:
+ val |= SUPPORTED_TP;
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
+ val |= SUPPORTED_1000baseT_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_100MBPS)
+ val |= SUPPORTED_100baseT_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_10MBPS)
+ val |= SUPPORTED_10baseT_Full;
+ break;
+ case PHY_TYPE_KX4_10GB:
+ val |= SUPPORTED_Backplane;
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
+ val |= SUPPORTED_1000baseKX_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)
+ val |= SUPPORTED_10000baseKX4_Full;
+ break;
+ case PHY_TYPE_KR_10GB:
+ val |= SUPPORTED_Backplane |
+ SUPPORTED_10000baseKR_Full;
+ break;
+ case PHY_TYPE_SFP_PLUS_10GB:
+ case PHY_TYPE_XFP_10GB:
+ case PHY_TYPE_SFP_1GB:
+ val |= SUPPORTED_FIBRE;
+ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)
+ val |= SUPPORTED_10000baseT_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
+ val |= SUPPORTED_1000baseT_Full;
+ break;
+ case PHY_TYPE_BASET_10GB:
+ val |= SUPPORTED_TP;
+ if (if_speeds & BE_SUPPORTED_SPEED_10GBPS)
+ val |= SUPPORTED_10000baseT_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_1GBPS)
+ val |= SUPPORTED_1000baseT_Full;
+ if (if_speeds & BE_SUPPORTED_SPEED_100MBPS)
+ val |= SUPPORTED_100baseT_Full;
+ break;
+ default:
+ val |= SUPPORTED_TP;
+ }
+
+ return val;
+}
+
+static int convert_to_et_speed(u32 be_speed)
+{
+ int et_speed = SPEED_10000;
+
+ switch (be_speed) {
+ case PHY_LINK_SPEED_10MBPS:
+ et_speed = SPEED_10;
+ break;
+ case PHY_LINK_SPEED_100MBPS:
+ et_speed = SPEED_100;
+ break;
+ case PHY_LINK_SPEED_1GBPS:
+ et_speed = SPEED_1000;
+ break;
+ case PHY_LINK_SPEED_10GBPS:
+ et_speed = SPEED_10000;
+ break;
+ }
+
+ return et_speed;
+}
+
+bool be_pause_supported(struct be_adapter *adapter)
+{
+ return (adapter->phy.interface_type == PHY_TYPE_SFP_PLUS_10GB ||
+ adapter->phy.interface_type == PHY_TYPE_XFP_10GB) ?
+ false : true;
+}
+
static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct be_adapter *adapter = netdev_priv(netdev);
- struct be_phy_info phy_info;
- u8 mac_speed = 0;
+ u8 port_speed = 0;
u16 link_speed = 0;
u8 link_status;
+ u32 et_speed = 0;
int status;
- if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
- status = be_cmd_link_status_query(adapter, &mac_speed,
- &link_speed, &link_status, 0);
- if (!status)
- be_link_status_update(adapter, link_status);
-
- /* link_speed is in units of 10 Mbps */
- if (link_speed) {
- ethtool_cmd_speed_set(ecmd, link_speed*10);
+ if (adapter->phy.link_speed < 0 || !(netdev->flags & IFF_UP)) {
+ if (adapter->phy.forced_port_speed < 0) {
+ status = be_cmd_link_status_query(adapter, &port_speed,
+ &link_speed, &link_status, 0);
+ if (!status)
+ be_link_status_update(adapter, link_status);
+ if (link_speed)
+ et_speed = link_speed * 10;
+ else if (link_status)
+ et_speed = convert_to_et_speed(port_speed);
} else {
- switch (mac_speed) {
- case PHY_LINK_SPEED_10MBPS:
- ethtool_cmd_speed_set(ecmd, SPEED_10);
- break;
- case PHY_LINK_SPEED_100MBPS:
- ethtool_cmd_speed_set(ecmd, SPEED_100);
- break;
- case PHY_LINK_SPEED_1GBPS:
- ethtool_cmd_speed_set(ecmd, SPEED_1000);
- break;
- case PHY_LINK_SPEED_10GBPS:
- ethtool_cmd_speed_set(ecmd, SPEED_10000);
- break;
- case PHY_LINK_SPEED_ZERO:
- ethtool_cmd_speed_set(ecmd, 0);
- break;
- }
+ et_speed = adapter->phy.forced_port_speed;
}
- status = be_cmd_get_phy_info(adapter, &phy_info);
- if (!status) {
- switch (phy_info.interface_type) {
- case PHY_TYPE_XFP_10GB:
- case PHY_TYPE_SFP_1GB:
- case PHY_TYPE_SFP_PLUS_10GB:
- ecmd->port = PORT_FIBRE;
- break;
- default:
- ecmd->port = PORT_TP;
- break;
- }
+ ethtool_cmd_speed_set(ecmd, et_speed);
+
+ status = be_cmd_get_phy_info(adapter);
+ if (status)
+ return status;
+
+ ecmd->supported =
+ convert_to_et_setting(adapter->phy.interface_type,
+ adapter->phy.auto_speeds_supported |
+ adapter->phy.fixed_speeds_supported);
+ ecmd->advertising =
+ convert_to_et_setting(adapter->phy.interface_type,
+ adapter->phy.auto_speeds_supported);
+
+ ecmd->port = be_get_port_type(adapter->phy.interface_type,
+ adapter->phy.dac_cable_len);
+
+ if (adapter->phy.auto_speeds_supported) {
+ ecmd->supported |= SUPPORTED_Autoneg;
+ ecmd->autoneg = AUTONEG_ENABLE;
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ }
- switch (phy_info.interface_type) {
- case PHY_TYPE_KR_10GB:
- case PHY_TYPE_KX4_10GB:
- ecmd->autoneg = AUTONEG_ENABLE;
+ if (be_pause_supported(adapter)) {
+ ecmd->supported |= SUPPORTED_Pause;
+ ecmd->advertising |= ADVERTISED_Pause;
+ }
+
+ switch (adapter->phy.interface_type) {
+ case PHY_TYPE_KR_10GB:
+ case PHY_TYPE_KX4_10GB:
ecmd->transceiver = XCVR_INTERNAL;
- break;
- default:
- ecmd->autoneg = AUTONEG_DISABLE;
- ecmd->transceiver = XCVR_EXTERNAL;
- break;
- }
+ break;
+ default:
+ ecmd->transceiver = XCVR_EXTERNAL;
+ break;
}
/* Save for future use */
- adapter->link_speed = ethtool_cmd_speed(ecmd);
- adapter->port_type = ecmd->port;
- adapter->transceiver = ecmd->transceiver;
- adapter->autoneg = ecmd->autoneg;
+ adapter->phy.link_speed = ethtool_cmd_speed(ecmd);
+ adapter->phy.port_type = ecmd->port;
+ adapter->phy.transceiver = ecmd->transceiver;
+ adapter->phy.autoneg = ecmd->autoneg;
+ adapter->phy.advertising = ecmd->advertising;
+ adapter->phy.supported = ecmd->supported;
} else {
- ethtool_cmd_speed_set(ecmd, adapter->link_speed);
- ecmd->port = adapter->port_type;
- ecmd->transceiver = adapter->transceiver;
- ecmd->autoneg = adapter->autoneg;
+ ethtool_cmd_speed_set(ecmd, adapter->phy.link_speed);
+ ecmd->port = adapter->phy.port_type;
+ ecmd->transceiver = adapter->phy.transceiver;
+ ecmd->autoneg = adapter->phy.autoneg;
+ ecmd->advertising = adapter->phy.advertising;
+ ecmd->supported = adapter->phy.supported;
}
- ecmd->duplex = DUPLEX_FULL;
+ ecmd->duplex = netif_carrier_ok(netdev) ? DUPLEX_FULL : DUPLEX_UNKNOWN;
ecmd->phy_address = adapter->port_num;
- switch (ecmd->port) {
- case PORT_FIBRE:
- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
- break;
- case PORT_TP:
- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP);
- break;
- case PORT_AUI:
- ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_AUI);
- break;
- }
-
- if (ecmd->autoneg) {
- ecmd->supported |= SUPPORTED_1000baseT_Full;
- ecmd->supported |= SUPPORTED_Autoneg;
- ecmd->advertising |= (ADVERTISED_10000baseT_Full |
- ADVERTISED_1000baseT_Full);
- }
return 0;
}
@@ -548,7 +639,7 @@ be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
struct be_adapter *adapter = netdev_priv(netdev);
be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause);
- ecmd->autoneg = 0;
+ ecmd->autoneg = adapter->phy.fc_autoneg;
}
static int
@@ -702,7 +793,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
}
}
- if (be_test_ddr_dma(adapter) != 0) {
+ if (!lancer_chip(adapter) && be_test_ddr_dma(adapter) != 0) {
data[3] = 1;
test->flags |= ETH_TEST_FL_FAILED;
}
@@ -787,6 +878,81 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
return status;
}
+static u32 be_get_msg_level(struct net_device *netdev)
+{
+ struct be_adapter *adapter = netdev_priv(netdev);
+
+ if (lancer_chip(adapter)) {
+ dev_err(&adapter->pdev->dev, "Operation not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ return adapter->msg_enable;
+}
+
+static void be_set_fw_log_level(struct be_adapter *adapter, u32 level)
+{
+ struct be_dma_mem extfat_cmd;
+ struct be_fat_conf_params *cfgs;
+ int status;
+ int i, j;
+
+ memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
+ extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
+ extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
+ &extfat_cmd.dma);
+ if (!extfat_cmd.va) {
+ dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
+ __func__);
+ goto err;
+ }
+ status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
+ if (!status) {
+ cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
+ sizeof(struct be_cmd_resp_hdr));
+ for (i = 0; i < cfgs->num_modules; i++) {
+ for (j = 0; j < cfgs->module[i].num_modes; j++) {
+ if (cfgs->module[i].trace_lvl[j].mode ==
+ MODE_UART)
+ cfgs->module[i].trace_lvl[j].dbg_lvl =
+ cpu_to_le32(level);
+ }
+ }
+ status = be_cmd_set_ext_fat_capabilites(adapter, &extfat_cmd,
+ cfgs);
+ if (status)
+ dev_err(&adapter->pdev->dev,
+ "Message level set failed\n");
+ } else {
+ dev_err(&adapter->pdev->dev, "Message level get failed\n");
+ }
+
+ pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va,
+ extfat_cmd.dma);
+err:
+ return;
+}
+
+static void be_set_msg_level(struct net_device *netdev, u32 level)
+{
+ struct be_adapter *adapter = netdev_priv(netdev);
+
+ if (lancer_chip(adapter)) {
+ dev_err(&adapter->pdev->dev, "Operation not supported\n");
+ return;
+ }
+
+ if (adapter->msg_enable == level)
+ return;
+
+ if ((level & NETIF_MSG_HW) != (adapter->msg_enable & NETIF_MSG_HW))
+ be_set_fw_log_level(adapter, level & NETIF_MSG_HW ?
+ FW_LOG_LEVEL_DEFAULT : FW_LOG_LEVEL_FATAL);
+ adapter->msg_enable = level;
+
+ return;
+}
+
const struct ethtool_ops be_ethtool_ops = {
.get_settings = be_get_settings,
.get_drvinfo = be_get_drvinfo,
@@ -802,6 +968,8 @@ const struct ethtool_ops be_ethtool_ops = {
.set_pauseparam = be_set_pauseparam,
.get_strings = be_get_stat_strings,
.set_phys_id = be_set_phys_id,
+ .get_msglevel = be_get_msg_level,
+ .set_msglevel = be_set_msg_level,
.get_sset_count = be_get_sset_count,
.get_ethtool_stats = be_get_ethtool_stats,
.get_regs_len = be_get_reg_len,
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index f2c89e3ccabd..d9fb0c501fa1 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -58,6 +58,8 @@
#define SLI_PORT_CONTROL_IP_MASK 0x08000000
+#define PCICFG_CUST_SCRATCHPAD_CSR 0x1EC
+
/********* Memory BAR register ************/
#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc
/* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
@@ -98,11 +100,13 @@
#define SLI_INTF_REV_SHIFT 4
#define SLI_INTF_FT_MASK 0x00000001
+#define SLI_INTF_TYPE_2 2
+#define SLI_INTF_TYPE_3 3
/* SLI family */
#define BE_SLI_FAMILY 0x0
#define LANCER_A0_SLI_FAMILY 0xA
-
+#define SKYHAWK_SLI_FAMILY 0x2
/********* ISR0 Register offset **********/
#define CEV_ISR0_OFFSET 0xC18
@@ -162,22 +166,23 @@
#define QUERY_FAT 1
/* Flashrom related descriptors */
+#define MAX_FLASH_COMP 32
#define IMAGE_TYPE_FIRMWARE 160
#define IMAGE_TYPE_BOOTCODE 224
#define IMAGE_TYPE_OPTIONROM 32
#define NUM_FLASHDIR_ENTRIES 32
-#define IMG_TYPE_ISCSI_ACTIVE 0
-#define IMG_TYPE_REDBOOT 1
-#define IMG_TYPE_BIOS 2
-#define IMG_TYPE_PXE_BIOS 3
-#define IMG_TYPE_FCOE_BIOS 8
-#define IMG_TYPE_ISCSI_BACKUP 9
-#define IMG_TYPE_FCOE_FW_ACTIVE 10
-#define IMG_TYPE_FCOE_FW_BACKUP 11
-#define IMG_TYPE_NCSI_FW 13
-#define IMG_TYPE_PHY_FW 99
+#define OPTYPE_ISCSI_ACTIVE 0
+#define OPTYPE_REDBOOT 1
+#define OPTYPE_BIOS 2
+#define OPTYPE_PXE_BIOS 3
+#define OPTYPE_FCOE_BIOS 8
+#define OPTYPE_ISCSI_BACKUP 9
+#define OPTYPE_FCOE_FW_ACTIVE 10
+#define OPTYPE_FCOE_FW_BACKUP 11
+#define OPTYPE_NCSI_FW 13
+#define OPTYPE_PHY_FW 99
#define TN_8022 13
#define ILLEGAL_IOCTL_REQ 2
@@ -223,6 +228,24 @@
#define FLASH_REDBOOT_START_g3 (262144)
#define FLASH_PHY_FW_START_g3 1310720
+#define IMAGE_NCSI 16
+#define IMAGE_OPTION_ROM_PXE 32
+#define IMAGE_OPTION_ROM_FCoE 33
+#define IMAGE_OPTION_ROM_ISCSI 34
+#define IMAGE_FLASHISM_JUMPVECTOR 48
+#define IMAGE_FLASH_ISM 49
+#define IMAGE_JUMP_VECTOR 50
+#define IMAGE_FIRMWARE_iSCSI 160
+#define IMAGE_FIRMWARE_COMP_iSCSI 161
+#define IMAGE_FIRMWARE_FCoE 162
+#define IMAGE_FIRMWARE_COMP_FCoE 163
+#define IMAGE_FIRMWARE_BACKUP_iSCSI 176
+#define IMAGE_FIRMWARE_BACKUP_COMP_iSCSI 177
+#define IMAGE_FIRMWARE_BACKUP_FCoE 178
+#define IMAGE_FIRMWARE_BACKUP_COMP_FCoE 179
+#define IMAGE_FIRMWARE_PHY 192
+#define IMAGE_BOOT_CODE 224
+
/************* Rx Packet Type Encoding **************/
#define BE_UNICAST_PACKET 0
#define BE_MULTICAST_PACKET 1
@@ -445,6 +468,7 @@ struct flash_comp {
unsigned long offset;
int optype;
int size;
+ int img_type;
};
struct image_hdr {
@@ -481,17 +505,19 @@ struct flash_section_hdr {
u32 format_rev;
u32 cksum;
u32 antidote;
- u32 build_no;
- u8 id_string[64];
- u32 active_entry_mask;
- u32 valid_entry_mask;
- u32 org_content_mask;
- u32 rsvd0;
- u32 rsvd1;
- u32 rsvd2;
- u32 rsvd3;
- u32 rsvd4;
-};
+ u32 num_images;
+ u8 id_string[128];
+ u32 rsvd[4];
+} __packed;
+
+struct flash_section_hdr_g2 {
+ u32 format_rev;
+ u32 cksum;
+ u32 antidote;
+ u32 build_num;
+ u8 id_string[128];
+ u32 rsvd[8];
+} __packed;
struct flash_section_entry {
u32 type;
@@ -503,10 +529,16 @@ struct flash_section_entry {
u32 rsvd0;
u32 rsvd1;
u8 ver_data[32];
-};
+} __packed;
struct flash_section_info {
u8 cookie[32];
struct flash_section_hdr fsec_hdr;
struct flash_section_entry fsec_entry[32];
-};
+} __packed;
+
+struct flash_section_info_g2 {
+ u8 cookie[32];
+ struct flash_section_hdr_g2 fsec_hdr;
+ struct flash_section_entry fsec_entry[32];
+} __packed;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 528a886bc2cd..08efd308d78a 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -421,6 +421,9 @@ void be_parse_stats(struct be_adapter *adapter)
populate_be2_stats(adapter);
}
+ if (lancer_chip(adapter))
+ goto done;
+
/* as erx_v1 is longer than v0, ok to use v1 defn for v0 access */
for_all_rx_queues(adapter, rxo, i) {
/* below erx HW counter can actually wrap around after
@@ -429,6 +432,8 @@ void be_parse_stats(struct be_adapter *adapter)
accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags,
(u16)erx->rx_drops_no_fragments[rxo->q.id]);
}
+done:
+ return;
}
static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
@@ -797,22 +802,30 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
if (adapter->promiscuous)
return 0;
- if (adapter->vlans_added <= adapter->max_vlans) {
- /* Construct VLAN Table to give to HW */
- for (i = 0; i < VLAN_N_VID; i++) {
- if (adapter->vlan_tag[i]) {
- vtag[ntags] = cpu_to_le16(i);
- ntags++;
- }
- }
- status = be_cmd_vlan_config(adapter, adapter->if_handle,
- vtag, ntags, 1, 0);
- } else {
- status = be_cmd_vlan_config(adapter, adapter->if_handle,
- NULL, 0, 1, 1);
+ if (adapter->vlans_added > adapter->max_vlans)
+ goto set_vlan_promisc;
+
+ /* Construct VLAN Table to give to HW */
+ for (i = 0; i < VLAN_N_VID; i++)
+ if (adapter->vlan_tag[i])
+ vtag[ntags++] = cpu_to_le16(i);
+
+ status = be_cmd_vlan_config(adapter, adapter->if_handle,
+ vtag, ntags, 1, 0);
+
+ /* Set to VLAN promisc mode as setting VLAN filter failed */
+ if (status) {
+ dev_info(&adapter->pdev->dev, "Exhausted VLAN HW filters.\n");
+ dev_info(&adapter->pdev->dev, "Disabling HW VLAN filtering.\n");
+ goto set_vlan_promisc;
}
return status;
+
+set_vlan_promisc:
+ status = be_cmd_vlan_config(adapter, adapter->if_handle,
+ NULL, 0, 1, 1);
+ return status;
}
static int be_vlan_add_vid(struct net_device *netdev, u16 vid)
@@ -862,6 +875,7 @@ ret:
static void be_set_rx_mode(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
+ int status;
if (netdev->flags & IFF_PROMISC) {
be_cmd_rx_filter(adapter, IFF_PROMISC, ON);
@@ -908,7 +922,14 @@ static void be_set_rx_mode(struct net_device *netdev)
}
}
- be_cmd_rx_filter(adapter, IFF_MULTICAST, ON);
+ status = be_cmd_rx_filter(adapter, IFF_MULTICAST, ON);
+
+ /* Set to MCAST promisc mode if setting MULTICAST address fails */
+ if (status) {
+ dev_info(&adapter->pdev->dev, "Exhausted multicast HW filters.\n");
+ dev_info(&adapter->pdev->dev, "Disabling HW multicast filtering.\n");
+ be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
+ }
done:
return;
}
@@ -1028,6 +1049,29 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
return status;
}
+static int be_find_vfs(struct be_adapter *adapter, int vf_state)
+{
+ struct pci_dev *dev, *pdev = adapter->pdev;
+ int vfs = 0, assigned_vfs = 0, pos, vf_fn;
+ u16 offset, stride;
+
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
+ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_OFFSET, &offset);
+ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_STRIDE, &stride);
+
+ dev = pci_get_device(pdev->vendor, PCI_ANY_ID, NULL);
+ while (dev) {
+ vf_fn = (pdev->devfn + offset + stride * vfs) & 0xFFFF;
+ if (dev->is_virtfn && dev->devfn == vf_fn) {
+ vfs++;
+ if (dev->dev_flags & PCI_DEV_FLAGS_ASSIGNED)
+ assigned_vfs++;
+ }
+ dev = pci_get_device(pdev->vendor, PCI_ANY_ID, dev);
+ }
+ return (vf_state == ASSIGNED) ? assigned_vfs : vfs;
+}
+
static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo)
{
struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]);
@@ -1238,6 +1282,7 @@ static void be_rx_compl_process(struct be_rx_obj *rxo,
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, netdev);
+ skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]);
if (netdev->features & NETIF_F_RXHASH)
skb->rxhash = rxcp->rss_hash;
@@ -1294,6 +1339,7 @@ void be_rx_compl_process_gro(struct be_rx_obj *rxo, struct napi_struct *napi,
skb->len = rxcp->pkt_size;
skb->data_len = rxcp->pkt_size;
skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]);
if (adapter->netdev->features & NETIF_F_RXHASH)
skb->rxhash = rxcp->rss_hash;
@@ -1555,7 +1601,9 @@ static int event_handle(struct be_eq_obj *eqo)
if (!num)
rearm = true;
- be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num);
+ if (num || msix_enabled(eqo->adapter))
+ be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num);
+
if (num)
napi_schedule(&eqo->napi);
@@ -1764,9 +1812,9 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
static int be_num_txqs_want(struct be_adapter *adapter)
{
- if (sriov_enabled(adapter) || be_is_mc(adapter) ||
- lancer_chip(adapter) || !be_physfn(adapter) ||
- adapter->generation == BE_GEN2)
+ if (sriov_want(adapter) || be_is_mc(adapter) ||
+ lancer_chip(adapter) || !be_physfn(adapter) ||
+ adapter->generation == BE_GEN2)
return 1;
else
return MAX_TX_QS;
@@ -2093,7 +2141,7 @@ 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) &&
+ !sriov_want(adapter) && be_physfn(adapter) &&
!be_is_mc(adapter))
return (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
else
@@ -2103,10 +2151,17 @@ static uint be_num_rss_want(struct be_adapter *adapter)
static void be_msix_enable(struct be_adapter *adapter)
{
#define BE_MIN_MSIX_VECTORS 1
- int i, status, num_vec;
+ int i, status, num_vec, num_roce_vec = 0;
/* If RSS queues are not used, need a vec for default RX Q */
num_vec = min(be_num_rss_want(adapter), num_online_cpus());
+ if (be_roce_supported(adapter)) {
+ num_roce_vec = min_t(u32, MAX_ROCE_MSIX_VECTORS,
+ (num_online_cpus() + 1));
+ num_roce_vec = min(num_roce_vec, MAX_ROCE_EQS);
+ num_vec += num_roce_vec;
+ num_vec = min(num_vec, MAX_MSIX_VECTORS);
+ }
num_vec = max(num_vec, BE_MIN_MSIX_VECTORS);
for (i = 0; i < num_vec; i++)
@@ -2123,55 +2178,18 @@ static void be_msix_enable(struct be_adapter *adapter)
}
return;
done:
- adapter->num_msix_vec = num_vec;
- return;
-}
-
-static int be_sriov_enable(struct be_adapter *adapter)
-{
- be_check_sriov_fn_type(adapter);
-
-#ifdef CONFIG_PCI_IOV
- if (be_physfn(adapter) && num_vfs) {
- int status, pos;
- u16 dev_vfs;
-
- pos = pci_find_ext_capability(adapter->pdev,
- PCI_EXT_CAP_ID_SRIOV);
- pci_read_config_word(adapter->pdev,
- pos + PCI_SRIOV_TOTAL_VF, &dev_vfs);
-
- adapter->num_vfs = min_t(u16, num_vfs, dev_vfs);
- if (adapter->num_vfs != num_vfs)
- dev_info(&adapter->pdev->dev,
- "Device supports %d VFs and not %d\n",
- adapter->num_vfs, num_vfs);
-
- status = pci_enable_sriov(adapter->pdev, adapter->num_vfs);
- if (status)
- adapter->num_vfs = 0;
-
- if (adapter->num_vfs) {
- adapter->vf_cfg = kcalloc(num_vfs,
- sizeof(struct be_vf_cfg),
- GFP_KERNEL);
- if (!adapter->vf_cfg)
- return -ENOMEM;
+ if (be_roce_supported(adapter)) {
+ if (num_vec > num_roce_vec) {
+ adapter->num_msix_vec = num_vec - num_roce_vec;
+ adapter->num_msix_roce_vec =
+ num_vec - adapter->num_msix_vec;
+ } else {
+ adapter->num_msix_vec = num_vec;
+ adapter->num_msix_roce_vec = 0;
}
- }
-#endif
- return 0;
-}
-
-static void be_sriov_disable(struct be_adapter *adapter)
-{
-#ifdef CONFIG_PCI_IOV
- if (sriov_enabled(adapter)) {
- pci_disable_sriov(adapter->pdev);
- kfree(adapter->vf_cfg);
- adapter->num_vfs = 0;
- }
-#endif
+ } else
+ adapter->num_msix_vec = num_vec;
+ return;
}
static inline int be_msix_vec_get(struct be_adapter *adapter,
@@ -2282,6 +2300,8 @@ static int be_close(struct net_device *netdev)
struct be_eq_obj *eqo;
int i;
+ be_roce_dev_close(adapter);
+
be_async_mcc_disable(adapter);
if (!lancer_chip(adapter))
@@ -2390,6 +2410,7 @@ static int be_open(struct net_device *netdev)
if (!status)
be_link_status_update(adapter, link_status);
+ be_roce_dev_open(adapter);
return 0;
err:
be_close(adapter->netdev);
@@ -2475,6 +2496,11 @@ static void be_vf_clear(struct be_adapter *adapter)
struct be_vf_cfg *vf_cfg;
u32 vf;
+ if (be_find_vfs(adapter, ASSIGNED)) {
+ dev_warn(&adapter->pdev->dev, "VFs are assigned to VMs\n");
+ goto done;
+ }
+
for_all_vfs(adapter, vf_cfg, vf) {
if (lancer_chip(adapter))
be_cmd_set_mac_list(adapter, NULL, 0, vf + 1);
@@ -2484,6 +2510,10 @@ static void be_vf_clear(struct be_adapter *adapter)
be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1);
}
+ pci_disable_sriov(adapter->pdev);
+done:
+ kfree(adapter->vf_cfg);
+ adapter->num_vfs = 0;
}
static int be_clear(struct be_adapter *adapter)
@@ -2513,29 +2543,60 @@ static int be_clear(struct be_adapter *adapter)
be_cmd_fw_clean(adapter);
be_msix_disable(adapter);
- kfree(adapter->pmac_id);
+ pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 0);
return 0;
}
-static void be_vf_setup_init(struct be_adapter *adapter)
+static int be_vf_setup_init(struct be_adapter *adapter)
{
struct be_vf_cfg *vf_cfg;
int vf;
+ adapter->vf_cfg = kcalloc(adapter->num_vfs, sizeof(*vf_cfg),
+ GFP_KERNEL);
+ if (!adapter->vf_cfg)
+ return -ENOMEM;
+
for_all_vfs(adapter, vf_cfg, vf) {
vf_cfg->if_handle = -1;
vf_cfg->pmac_id = -1;
}
+ return 0;
}
static int be_vf_setup(struct be_adapter *adapter)
{
struct be_vf_cfg *vf_cfg;
+ struct device *dev = &adapter->pdev->dev;
u32 cap_flags, en_flags, vf;
u16 def_vlan, lnk_speed;
- int status;
+ int status, enabled_vfs;
+
+ enabled_vfs = be_find_vfs(adapter, ENABLED);
+ if (enabled_vfs) {
+ dev_warn(dev, "%d VFs are already enabled\n", enabled_vfs);
+ dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs);
+ return 0;
+ }
+
+ if (num_vfs > adapter->dev_num_vfs) {
+ dev_warn(dev, "Device supports %d VFs and not %d\n",
+ adapter->dev_num_vfs, num_vfs);
+ num_vfs = adapter->dev_num_vfs;
+ }
- be_vf_setup_init(adapter);
+ status = pci_enable_sriov(adapter->pdev, num_vfs);
+ if (!status) {
+ adapter->num_vfs = num_vfs;
+ } else {
+ /* Platform doesn't support SRIOV though device supports it */
+ dev_warn(dev, "SRIOV enable failed\n");
+ return 0;
+ }
+
+ status = be_vf_setup_init(adapter);
+ if (status)
+ goto err;
cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
BE_IF_FLAGS_MULTICAST;
@@ -2546,9 +2607,11 @@ static int be_vf_setup(struct be_adapter *adapter)
goto err;
}
- status = be_vf_eth_addr_config(adapter);
- if (status)
- goto err;
+ if (!enabled_vfs) {
+ status = be_vf_eth_addr_config(adapter);
+ if (status)
+ goto err;
+ }
for_all_vfs(adapter, vf_cfg, vf) {
status = be_cmd_link_status_query(adapter, NULL, &lnk_speed,
@@ -2571,11 +2634,12 @@ err:
static void be_setup_init(struct be_adapter *adapter)
{
adapter->vlan_prio_bmap = 0xff;
- adapter->link_speed = -1;
+ adapter->phy.link_speed = -1;
adapter->if_handle = -1;
adapter->be3_native = false;
adapter->promiscuous = false;
adapter->eq_next_idx = 0;
+ adapter->phy.forced_port_speed = -1;
}
static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac)
@@ -2604,9 +2668,25 @@ do_none:
return status;
}
+/* Routine to query per function resource limits */
+static int be_get_config(struct be_adapter *adapter)
+{
+ int pos;
+ u16 dev_num_vfs;
+
+ pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV);
+ if (pos) {
+ pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF,
+ &dev_num_vfs);
+ adapter->dev_num_vfs = dev_num_vfs;
+ }
+ return 0;
+}
+
static int be_setup(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ struct device *dev = &adapter->pdev->dev;
u32 cap_flags, en_flags;
u32 tx_fc, rx_fc;
int status;
@@ -2614,6 +2694,8 @@ static int be_setup(struct be_adapter *adapter)
be_setup_init(adapter);
+ be_get_config(adapter);
+
be_cmd_req_native_mode(adapter);
be_msix_enable(adapter);
@@ -2680,36 +2762,33 @@ static int be_setup(struct be_adapter *adapter)
be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL);
- status = be_vid_config(adapter, false, 0);
- if (status)
- goto err;
+ be_vid_config(adapter, false, 0);
be_set_rx_mode(adapter->netdev);
- status = be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc);
- /* For Lancer: It is legal for this cmd to fail on VF */
- if (status && (be_physfn(adapter) || !lancer_chip(adapter)))
- goto err;
+ be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc);
- if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc) {
- status = be_cmd_set_flow_control(adapter, adapter->tx_fc,
+ if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc)
+ be_cmd_set_flow_control(adapter, adapter->tx_fc,
adapter->rx_fc);
- /* For Lancer: It is legal for this cmd to fail on VF */
- if (status && (be_physfn(adapter) || !lancer_chip(adapter)))
- goto err;
- }
pcie_set_readrq(adapter->pdev, 4096);
- if (sriov_enabled(adapter)) {
- status = be_vf_setup(adapter);
- if (status)
- goto err;
+ if (be_physfn(adapter) && num_vfs) {
+ if (adapter->dev_num_vfs)
+ be_vf_setup(adapter);
+ else
+ dev_warn(dev, "device doesn't support SRIOV\n");
}
+ be_cmd_get_phy_info(adapter);
+ if (be_pause_supported(adapter))
+ adapter->phy.fc_autoneg = 1;
+
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
adapter->flags |= BE_FLAGS_WORKER_SCHEDULED;
+ pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 1);
return 0;
err:
be_clear(adapter);
@@ -2731,6 +2810,8 @@ static void be_netpoll(struct net_device *netdev)
#endif
#define FW_FILE_HDR_SIGN "ServerEngines Corp. "
+char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
+
static bool be_flash_redboot(struct be_adapter *adapter,
const u8 *p, u32 img_start, int image_size,
int hdr_size)
@@ -2760,71 +2841,105 @@ static bool be_flash_redboot(struct be_adapter *adapter,
static bool phy_flashing_required(struct be_adapter *adapter)
{
- int status = 0;
- struct be_phy_info phy_info;
+ return (adapter->phy.phy_type == TN_8022 &&
+ adapter->phy.interface_type == PHY_TYPE_BASET_10GB);
+}
- status = be_cmd_get_phy_info(adapter, &phy_info);
- if (status)
- return false;
- if ((phy_info.phy_type == TN_8022) &&
- (phy_info.interface_type == PHY_TYPE_BASET_10GB)) {
- return true;
+static bool is_comp_in_ufi(struct be_adapter *adapter,
+ struct flash_section_info *fsec, int type)
+{
+ int i = 0, img_type = 0;
+ struct flash_section_info_g2 *fsec_g2 = NULL;
+
+ if (adapter->generation != BE_GEN3)
+ fsec_g2 = (struct flash_section_info_g2 *)fsec;
+
+ for (i = 0; i < MAX_FLASH_COMP; i++) {
+ if (fsec_g2)
+ img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type);
+ else
+ img_type = le32_to_cpu(fsec->fsec_entry[i].type);
+
+ if (img_type == type)
+ return true;
}
return false;
+
+}
+
+struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
+ int header_size,
+ const struct firmware *fw)
+{
+ struct flash_section_info *fsec = NULL;
+ const u8 *p = fw->data;
+
+ p += header_size;
+ while (p < (fw->data + fw->size)) {
+ fsec = (struct flash_section_info *)p;
+ if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie)))
+ return fsec;
+ p += 32;
+ }
+ return NULL;
}
static int be_flash_data(struct be_adapter *adapter,
- const struct firmware *fw,
- struct be_dma_mem *flash_cmd, int num_of_images)
+ const struct firmware *fw,
+ struct be_dma_mem *flash_cmd,
+ int num_of_images)
{
int status = 0, i, filehdr_size = 0;
+ int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
u32 total_bytes = 0, flash_op;
int num_bytes;
const u8 *p = fw->data;
struct be_cmd_write_flashrom *req = flash_cmd->va;
const struct flash_comp *pflashcomp;
- int num_comp;
-
- static const struct flash_comp gen3_flash_types[10] = {
- { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE,
- FLASH_IMAGE_MAX_SIZE_g3},
- { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT,
- FLASH_REDBOOT_IMAGE_MAX_SIZE_g3},
- { FLASH_iSCSI_BIOS_START_g3, IMG_TYPE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g3},
- { FLASH_PXE_BIOS_START_g3, IMG_TYPE_PXE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g3},
- { FLASH_FCoE_BIOS_START_g3, IMG_TYPE_FCOE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g3},
- { FLASH_iSCSI_BACKUP_IMAGE_START_g3, IMG_TYPE_ISCSI_BACKUP,
- FLASH_IMAGE_MAX_SIZE_g3},
- { FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE,
- FLASH_IMAGE_MAX_SIZE_g3},
- { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP,
- FLASH_IMAGE_MAX_SIZE_g3},
- { FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW,
- FLASH_NCSI_IMAGE_MAX_SIZE_g3},
- { FLASH_PHY_FW_START_g3, IMG_TYPE_PHY_FW,
- FLASH_PHY_FW_IMAGE_MAX_SIZE_g3}
+ int num_comp, hdr_size;
+ struct flash_section_info *fsec = NULL;
+
+ struct flash_comp gen3_flash_types[] = {
+ { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE,
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_iSCSI},
+ { FLASH_REDBOOT_START_g3, OPTYPE_REDBOOT,
+ FLASH_REDBOOT_IMAGE_MAX_SIZE_g3, IMAGE_BOOT_CODE},
+ { FLASH_iSCSI_BIOS_START_g3, OPTYPE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_ISCSI},
+ { FLASH_PXE_BIOS_START_g3, OPTYPE_PXE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_PXE},
+ { FLASH_FCoE_BIOS_START_g3, OPTYPE_FCOE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_FCoE},
+ { FLASH_iSCSI_BACKUP_IMAGE_START_g3, OPTYPE_ISCSI_BACKUP,
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_iSCSI},
+ { FLASH_FCoE_PRIMARY_IMAGE_START_g3, OPTYPE_FCOE_FW_ACTIVE,
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_FCoE},
+ { FLASH_FCoE_BACKUP_IMAGE_START_g3, OPTYPE_FCOE_FW_BACKUP,
+ FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_FCoE},
+ { FLASH_NCSI_START_g3, OPTYPE_NCSI_FW,
+ FLASH_NCSI_IMAGE_MAX_SIZE_g3, IMAGE_NCSI},
+ { FLASH_PHY_FW_START_g3, OPTYPE_PHY_FW,
+ FLASH_PHY_FW_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_PHY}
};
- static const struct flash_comp gen2_flash_types[8] = {
- { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE,
- FLASH_IMAGE_MAX_SIZE_g2},
- { FLASH_REDBOOT_START_g2, IMG_TYPE_REDBOOT,
- FLASH_REDBOOT_IMAGE_MAX_SIZE_g2},
- { FLASH_iSCSI_BIOS_START_g2, IMG_TYPE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g2},
- { FLASH_PXE_BIOS_START_g2, IMG_TYPE_PXE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g2},
- { FLASH_FCoE_BIOS_START_g2, IMG_TYPE_FCOE_BIOS,
- FLASH_BIOS_IMAGE_MAX_SIZE_g2},
- { FLASH_iSCSI_BACKUP_IMAGE_START_g2, IMG_TYPE_ISCSI_BACKUP,
- FLASH_IMAGE_MAX_SIZE_g2},
- { FLASH_FCoE_PRIMARY_IMAGE_START_g2, IMG_TYPE_FCOE_FW_ACTIVE,
- FLASH_IMAGE_MAX_SIZE_g2},
- { FLASH_FCoE_BACKUP_IMAGE_START_g2, IMG_TYPE_FCOE_FW_BACKUP,
- FLASH_IMAGE_MAX_SIZE_g2}
+
+ struct flash_comp gen2_flash_types[] = {
+ { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, OPTYPE_ISCSI_ACTIVE,
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_iSCSI},
+ { FLASH_REDBOOT_START_g2, OPTYPE_REDBOOT,
+ FLASH_REDBOOT_IMAGE_MAX_SIZE_g2, IMAGE_BOOT_CODE},
+ { FLASH_iSCSI_BIOS_START_g2, OPTYPE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_ISCSI},
+ { FLASH_PXE_BIOS_START_g2, OPTYPE_PXE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_PXE},
+ { FLASH_FCoE_BIOS_START_g2, OPTYPE_FCOE_BIOS,
+ FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_FCoE},
+ { FLASH_iSCSI_BACKUP_IMAGE_START_g2, OPTYPE_ISCSI_BACKUP,
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_iSCSI},
+ { FLASH_FCoE_PRIMARY_IMAGE_START_g2, OPTYPE_FCOE_FW_ACTIVE,
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_FCoE},
+ { FLASH_FCoE_BACKUP_IMAGE_START_g2, OPTYPE_FCOE_FW_BACKUP,
+ FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_FCoE}
};
if (adapter->generation == BE_GEN3) {
@@ -2836,22 +2951,37 @@ static int be_flash_data(struct be_adapter *adapter,
filehdr_size = sizeof(struct flash_file_hdr_g2);
num_comp = ARRAY_SIZE(gen2_flash_types);
}
+ /* Get flash section info*/
+ fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
+ if (!fsec) {
+ dev_err(&adapter->pdev->dev,
+ "Invalid Cookie. UFI corrupted ?\n");
+ return -1;
+ }
for (i = 0; i < num_comp; i++) {
- if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) &&
- memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
+ if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type))
+ continue;
+
+ if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) &&
+ memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
continue;
- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW) {
+
+ if (pflashcomp[i].optype == OPTYPE_PHY_FW) {
if (!phy_flashing_required(adapter))
continue;
}
- if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) &&
- (!be_flash_redboot(adapter, fw->data,
- pflashcomp[i].offset, pflashcomp[i].size, filehdr_size +
- (num_of_images * sizeof(struct image_hdr)))))
+
+ hdr_size = filehdr_size +
+ (num_of_images * sizeof(struct image_hdr));
+
+ if ((pflashcomp[i].optype == OPTYPE_REDBOOT) &&
+ (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset,
+ pflashcomp[i].size, hdr_size)))
continue;
+
+ /* Flash the component */
p = fw->data;
- p += filehdr_size + pflashcomp[i].offset
- + (num_of_images * sizeof(struct image_hdr));
+ p += filehdr_size + pflashcomp[i].offset + img_hdrs_size;
if (p + pflashcomp[i].size > fw->data + fw->size)
return -1;
total_bytes = pflashcomp[i].size;
@@ -2862,12 +2992,12 @@ static int be_flash_data(struct be_adapter *adapter,
num_bytes = total_bytes;
total_bytes -= num_bytes;
if (!total_bytes) {
- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW)
+ if (pflashcomp[i].optype == OPTYPE_PHY_FW)
flash_op = FLASHROM_OPER_PHY_FLASH;
else
flash_op = FLASHROM_OPER_FLASH;
} else {
- if (pflashcomp[i].optype == IMG_TYPE_PHY_FW)
+ if (pflashcomp[i].optype == OPTYPE_PHY_FW)
flash_op = FLASHROM_OPER_PHY_SAVE;
else
flash_op = FLASHROM_OPER_SAVE;
@@ -2879,7 +3009,7 @@ static int be_flash_data(struct be_adapter *adapter,
if (status) {
if ((status == ILLEGAL_IOCTL_REQ) &&
(pflashcomp[i].optype ==
- IMG_TYPE_PHY_FW))
+ OPTYPE_PHY_FW))
break;
dev_err(&adapter->pdev->dev,
"cmd to write to flash rom failed.\n");
@@ -3122,6 +3252,24 @@ static void be_unmap_pci_bars(struct be_adapter *adapter)
iounmap(adapter->csr);
if (adapter->db)
iounmap(adapter->db);
+ if (adapter->roce_db.base)
+ pci_iounmap(adapter->pdev, adapter->roce_db.base);
+}
+
+static int lancer_roce_map_pci_bars(struct be_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ u8 __iomem *addr;
+
+ addr = pci_iomap(pdev, 2, 0);
+ if (addr == NULL)
+ return -ENOMEM;
+
+ adapter->roce_db.base = addr;
+ adapter->roce_db.io_addr = pci_resource_start(pdev, 2);
+ adapter->roce_db.size = 8192;
+ adapter->roce_db.total_size = pci_resource_len(pdev, 2);
+ return 0;
}
static int be_map_pci_bars(struct be_adapter *adapter)
@@ -3130,11 +3278,18 @@ static int be_map_pci_bars(struct be_adapter *adapter)
int db_reg;
if (lancer_chip(adapter)) {
- addr = ioremap_nocache(pci_resource_start(adapter->pdev, 0),
- pci_resource_len(adapter->pdev, 0));
- if (addr == NULL)
- return -ENOMEM;
- adapter->db = addr;
+ if (be_type_2_3(adapter)) {
+ addr = ioremap_nocache(
+ pci_resource_start(adapter->pdev, 0),
+ pci_resource_len(adapter->pdev, 0));
+ if (addr == NULL)
+ return -ENOMEM;
+ adapter->db = addr;
+ }
+ if (adapter->if_type == SLI_INTF_TYPE_3) {
+ if (lancer_roce_map_pci_bars(adapter))
+ goto pci_map_err;
+ }
return 0;
}
@@ -3159,14 +3314,19 @@ static int be_map_pci_bars(struct be_adapter *adapter)
if (addr == NULL)
goto pci_map_err;
adapter->db = addr;
-
+ if (adapter->sli_family == SKYHAWK_SLI_FAMILY) {
+ adapter->roce_db.size = 4096;
+ adapter->roce_db.io_addr =
+ pci_resource_start(adapter->pdev, db_reg);
+ adapter->roce_db.total_size =
+ pci_resource_len(adapter->pdev, db_reg);
+ }
return 0;
pci_map_err:
be_unmap_pci_bars(adapter);
return -ENOMEM;
}
-
static void be_ctrl_cleanup(struct be_adapter *adapter)
{
struct be_dma_mem *mem = &adapter->mbox_mem_alloced;
@@ -3272,6 +3432,8 @@ static void __devexit be_remove(struct pci_dev *pdev)
if (!adapter)
return;
+ be_roce_dev_remove(adapter);
+
unregister_netdev(adapter->netdev);
be_clear(adapter);
@@ -3280,8 +3442,6 @@ static void __devexit be_remove(struct pci_dev *pdev)
be_ctrl_cleanup(adapter);
- be_sriov_disable(adapter);
-
pci_set_drvdata(pdev, NULL);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -3295,9 +3455,43 @@ bool be_is_wol_supported(struct be_adapter *adapter)
!be_is_wol_excluded(adapter)) ? true : false;
}
-static int be_get_config(struct be_adapter *adapter)
+u32 be_get_fw_log_level(struct be_adapter *adapter)
{
+ struct be_dma_mem extfat_cmd;
+ struct be_fat_conf_params *cfgs;
int status;
+ u32 level = 0;
+ int j;
+
+ memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
+ extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
+ extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
+ &extfat_cmd.dma);
+
+ if (!extfat_cmd.va) {
+ dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
+ __func__);
+ goto err;
+ }
+
+ status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
+ if (!status) {
+ cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
+ sizeof(struct be_cmd_resp_hdr));
+ for (j = 0; j < cfgs->module[0].num_modes; j++) {
+ if (cfgs->module[0].trace_lvl[j].mode == MODE_UART)
+ level = cfgs->module[0].trace_lvl[j].dbg_lvl;
+ }
+ }
+ pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va,
+ extfat_cmd.dma);
+err:
+ return level;
+}
+static int be_get_initial_config(struct be_adapter *adapter)
+{
+ int status;
+ u32 level;
status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
&adapter->function_mode, &adapter->function_caps);
@@ -3335,10 +3529,13 @@ static int be_get_config(struct be_adapter *adapter)
if (be_is_wol_supported(adapter))
adapter->wol = true;
+ level = be_get_fw_log_level(adapter);
+ adapter->msg_enable = level <= FW_LOG_LEVEL_DEFAULT ? NETIF_MSG_HW : 0;
+
return 0;
}
-static int be_dev_family_check(struct be_adapter *adapter)
+static int be_dev_type_check(struct be_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
u32 sli_intf = 0, if_type;
@@ -3350,17 +3547,27 @@ static int be_dev_family_check(struct be_adapter *adapter)
break;
case BE_DEVICE_ID2:
case OC_DEVICE_ID2:
- case OC_DEVICE_ID5:
adapter->generation = BE_GEN3;
break;
case OC_DEVICE_ID3:
case OC_DEVICE_ID4:
pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
+ SLI_INTF_IF_TYPE_SHIFT;
if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
SLI_INTF_IF_TYPE_SHIFT;
-
if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
- if_type != 0x02) {
+ !be_type_2_3(adapter)) {
+ dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
+ return -EINVAL;
+ }
+ adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
+ SLI_INTF_FAMILY_SHIFT);
+ adapter->generation = BE_GEN3;
+ break;
+ case OC_DEVICE_ID5:
+ pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ if ((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) {
dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
return -EINVAL;
}
@@ -3371,6 +3578,9 @@ static int be_dev_family_check(struct be_adapter *adapter)
default:
adapter->generation = 0;
}
+
+ pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+ adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
return 0;
}
@@ -3514,6 +3724,14 @@ reschedule:
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
}
+static bool be_reset_required(struct be_adapter *adapter)
+{
+ u32 reg;
+
+ pci_read_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, &reg);
+ return reg;
+}
+
static int __devinit be_probe(struct pci_dev *pdev,
const struct pci_device_id *pdev_id)
{
@@ -3539,7 +3757,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
adapter->pdev = pdev;
pci_set_drvdata(pdev, adapter);
- status = be_dev_family_check(adapter);
+ status = be_dev_type_check(adapter);
if (status)
goto free_netdev;
@@ -3557,13 +3775,9 @@ static int __devinit be_probe(struct pci_dev *pdev,
}
}
- status = be_sriov_enable(adapter);
- if (status)
- goto free_netdev;
-
status = be_ctrl_init(adapter);
if (status)
- goto disable_sriov;
+ goto free_netdev;
if (lancer_chip(adapter)) {
status = lancer_wait_ready(adapter);
@@ -3590,9 +3804,11 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status)
goto ctrl_clean;
- status = be_cmd_reset_function(adapter);
- if (status)
- goto ctrl_clean;
+ if (be_reset_required(adapter)) {
+ status = be_cmd_reset_function(adapter);
+ if (status)
+ goto ctrl_clean;
+ }
/* The INTR bit may be set in the card when probed by a kdump kernel
* after a crash.
@@ -3604,7 +3820,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status)
goto ctrl_clean;
- status = be_get_config(adapter);
+ status = be_get_initial_config(adapter);
if (status)
goto stats_clean;
@@ -3620,6 +3836,8 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status != 0)
goto unsetup;
+ be_roce_dev_add(adapter);
+
dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev),
adapter->port_num);
@@ -3633,8 +3851,6 @@ stats_clean:
be_stats_cleanup(adapter);
ctrl_clean:
be_ctrl_cleanup(adapter);
-disable_sriov:
- be_sriov_disable(adapter);
free_netdev:
free_netdev(netdev);
pci_set_drvdata(pdev, NULL);
@@ -3749,6 +3965,11 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
pci_disable_device(pdev);
+ /* The error could cause the FW to trigger a flash debug dump.
+ * Resetting the card while flash dump is in progress
+ * can cause it not to recover; wait for it to finish
+ */
+ ssleep(30);
return PCI_ERS_RESULT_NEED_RESET;
}
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c
new file mode 100644
index 000000000000..deecc44b3617
--- /dev/null
+++ b/drivers/net/ethernet/emulex/benet/be_roce.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2005 - 2011 Emulex
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ */
+
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/module.h>
+
+#include "be.h"
+#include "be_cmds.h"
+
+static struct ocrdma_driver *ocrdma_drv;
+static LIST_HEAD(be_adapter_list);
+static DEFINE_MUTEX(be_adapter_list_lock);
+
+static void _be_roce_dev_add(struct be_adapter *adapter)
+{
+ struct be_dev_info dev_info;
+ int i, num_vec;
+ struct pci_dev *pdev = adapter->pdev;
+
+ if (!ocrdma_drv)
+ return;
+ if (pdev->device == OC_DEVICE_ID5) {
+ /* only msix is supported on these devices */
+ if (!msix_enabled(adapter))
+ return;
+ /* DPP region address and length */
+ dev_info.dpp_unmapped_addr = pci_resource_start(pdev, 2);
+ dev_info.dpp_unmapped_len = pci_resource_len(pdev, 2);
+ } else {
+ dev_info.dpp_unmapped_addr = 0;
+ dev_info.dpp_unmapped_len = 0;
+ }
+ dev_info.pdev = adapter->pdev;
+ if (adapter->sli_family == SKYHAWK_SLI_FAMILY)
+ dev_info.db = adapter->db;
+ else
+ dev_info.db = adapter->roce_db.base;
+ dev_info.unmapped_db = adapter->roce_db.io_addr;
+ dev_info.db_page_size = adapter->roce_db.size;
+ dev_info.db_total_size = adapter->roce_db.total_size;
+ dev_info.netdev = adapter->netdev;
+ memcpy(dev_info.mac_addr, adapter->netdev->dev_addr, ETH_ALEN);
+ dev_info.dev_family = adapter->sli_family;
+ if (msix_enabled(adapter)) {
+ /* provide all the vectors, so that EQ creation response
+ * can decide which one to use.
+ */
+ num_vec = adapter->num_msix_vec + adapter->num_msix_roce_vec;
+ dev_info.intr_mode = BE_INTERRUPT_MODE_MSIX;
+ dev_info.msix.num_vectors = min(num_vec, MAX_ROCE_MSIX_VECTORS);
+ /* provide start index of the vector,
+ * so in case of linear usage,
+ * it can use the base as starting point.
+ */
+ dev_info.msix.start_vector = adapter->num_evt_qs;
+ for (i = 0; i < dev_info.msix.num_vectors; i++) {
+ dev_info.msix.vector_list[i] =
+ adapter->msix_entries[i].vector;
+ }
+ } else {
+ dev_info.msix.num_vectors = 0;
+ dev_info.intr_mode = BE_INTERRUPT_MODE_INTX;
+ }
+ adapter->ocrdma_dev = ocrdma_drv->add(&dev_info);
+}
+
+void be_roce_dev_add(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ INIT_LIST_HEAD(&adapter->entry);
+ mutex_lock(&be_adapter_list_lock);
+ list_add_tail(&adapter->entry, &be_adapter_list);
+
+ /* invoke add() routine of roce driver only if
+ * valid driver registered with add method and add() is not yet
+ * invoked on a given adapter.
+ */
+ _be_roce_dev_add(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_remove(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && ocrdma_drv->remove && adapter->ocrdma_dev)
+ ocrdma_drv->remove(adapter->ocrdma_dev);
+ adapter->ocrdma_dev = NULL;
+}
+
+void be_roce_dev_remove(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_remove(adapter);
+ list_del(&adapter->entry);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_open(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && adapter->ocrdma_dev &&
+ ocrdma_drv->state_change_handler)
+ ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 0);
+}
+
+void be_roce_dev_open(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_open(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+void _be_roce_dev_close(struct be_adapter *adapter)
+{
+ if (ocrdma_drv && adapter->ocrdma_dev &&
+ ocrdma_drv->state_change_handler)
+ ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 1);
+}
+
+void be_roce_dev_close(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ _be_roce_dev_close(adapter);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
+int be_roce_register_driver(struct ocrdma_driver *drv)
+{
+ struct be_adapter *dev;
+
+ mutex_lock(&be_adapter_list_lock);
+ if (ocrdma_drv) {
+ mutex_unlock(&be_adapter_list_lock);
+ return -EINVAL;
+ }
+ ocrdma_drv = drv;
+ list_for_each_entry(dev, &be_adapter_list, entry) {
+ struct net_device *netdev;
+ _be_roce_dev_add(dev);
+ netdev = dev->netdev;
+ if (netif_running(netdev) && netif_oper_up(netdev))
+ _be_roce_dev_open(dev);
+ }
+ mutex_unlock(&be_adapter_list_lock);
+ return 0;
+}
+EXPORT_SYMBOL(be_roce_register_driver);
+
+void be_roce_unregister_driver(struct ocrdma_driver *drv)
+{
+ struct be_adapter *dev;
+
+ mutex_lock(&be_adapter_list_lock);
+ list_for_each_entry(dev, &be_adapter_list, entry) {
+ if (dev->ocrdma_dev)
+ _be_roce_dev_remove(dev);
+ }
+ ocrdma_drv = NULL;
+ mutex_unlock(&be_adapter_list_lock);
+}
+EXPORT_SYMBOL(be_roce_unregister_driver);
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.h b/drivers/net/ethernet/emulex/benet/be_roce.h
new file mode 100644
index 000000000000..db4ea8081c07
--- /dev/null
+++ b/drivers/net/ethernet/emulex/benet/be_roce.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2005 - 2011 Emulex
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@emulex.com
+ *
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
+ */
+
+#ifndef BE_ROCE_H
+#define BE_ROCE_H
+
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+
+struct ocrdma_dev;
+
+enum be_interrupt_mode {
+ BE_INTERRUPT_MODE_MSIX = 0,
+ BE_INTERRUPT_MODE_INTX = 1,
+ BE_INTERRUPT_MODE_MSI = 2,
+};
+
+#define MAX_ROCE_MSIX_VECTORS 16
+struct be_dev_info {
+ u8 __iomem *db;
+ u64 unmapped_db;
+ u32 db_page_size;
+ u32 db_total_size;
+ u64 dpp_unmapped_addr;
+ u32 dpp_unmapped_len;
+ struct pci_dev *pdev;
+ struct net_device *netdev;
+ u8 mac_addr[ETH_ALEN];
+ u32 dev_family;
+ enum be_interrupt_mode intr_mode;
+ struct {
+ int num_vectors;
+ int start_vector;
+ u32 vector_list[MAX_ROCE_MSIX_VECTORS];
+ } msix;
+};
+
+/* ocrdma driver register's the callback functions with nic driver. */
+struct ocrdma_driver {
+ unsigned char name[32];
+ struct ocrdma_dev *(*add) (struct be_dev_info *dev_info);
+ void (*remove) (struct ocrdma_dev *);
+ void (*state_change_handler) (struct ocrdma_dev *, u32 new_state);
+};
+
+enum {
+ BE_DEV_UP = 0,
+ BE_DEV_DOWN = 1
+};
+
+/* APIs for RoCE driver to register callback handlers,
+ * which will be invoked when device is added, removed, ifup, ifdown
+ */
+int be_roce_register_driver(struct ocrdma_driver *drv);
+void be_roce_unregister_driver(struct ocrdma_driver *drv);
+
+/* API for RoCE driver to issue mailbox commands */
+int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
+ int wrb_payload_size, u16 *cmd_status, u16 *ext_status);
+
+#endif /* BE_ROCE_H */
diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c
index 1637b9862292..9d71c9cc300b 100644
--- a/drivers/net/ethernet/fealnx.c
+++ b/drivers/net/ethernet/fealnx.c
@@ -545,9 +545,6 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
/* Reset the chip to erase previous misconfiguration. */
iowrite32(0x00000001, ioaddr + BCR);
- dev->base_addr = (unsigned long)ioaddr;
- dev->irq = irq;
-
/* Make certain the descriptor lists are aligned. */
np = netdev_priv(dev);
np->mem = ioaddr;
@@ -832,11 +829,13 @@ static int netdev_open(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->mem;
- int i;
+ const int irq = np->pci_dev->irq;
+ int rc, i;
iowrite32(0x00000001, ioaddr + BCR); /* Reset */
- if (request_irq(dev->irq, intr_handler, IRQF_SHARED, dev->name, dev))
+ rc = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev);
+ if (rc)
return -EAGAIN;
for (i = 0; i < 3; i++)
@@ -924,8 +923,7 @@ static int netdev_open(struct net_device *dev)
np->reset_timer.data = (unsigned long) dev;
np->reset_timer.function = reset_timer;
np->reset_timer_armed = 0;
-
- return 0;
+ return rc;
}
@@ -1910,7 +1908,7 @@ static int netdev_close(struct net_device *dev)
del_timer_sync(&np->timer);
del_timer_sync(&np->reset_timer);
- free_irq(dev->irq, dev);
+ free_irq(np->pci_dev->irq, dev);
/* Free all the skbuffs in the Rx queue. */
for (i = 0; i < RX_RING_SIZE; i++) {
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index 4d3280ae56e8..ff7f4c5115a1 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -1163,6 +1163,7 @@ static const struct ethtool_ops fec_enet_ethtool_ops = {
.set_settings = fec_enet_set_settings,
.get_drvinfo = fec_enet_get_drvinfo,
.get_link = ethtool_op_get_link,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 7b34d8c698da..97f947b3d94a 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -811,6 +811,7 @@ static const struct ethtool_ops mpc52xx_fec_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_msglevel = mpc52xx_fec_get_msglevel,
.set_msglevel = mpc52xx_fec_set_msglevel,
+ .get_ts_info = ethtool_op_get_ts_info,
};
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 e4e6cd2c5f82..2b7633f766d9 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -963,6 +963,7 @@ static const struct ethtool_ops fs_ethtool_ops = {
.get_msglevel = fs_get_msglevel,
.set_msglevel = fs_set_msglevel,
.get_regs = fs_get_regs,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index e7bed5303997..0741aded9eb0 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -136,7 +136,7 @@ static void gfar_netpoll(struct net_device *dev);
int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit);
static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
- int amount_pull);
+ int amount_pull, struct napi_struct *napi);
void gfar_halt(struct net_device *dev);
static void gfar_halt_nodisable(struct net_device *dev);
void gfar_start(struct net_device *dev);
@@ -1082,7 +1082,7 @@ static int gfar_probe(struct platform_device *ofdev)
if (dev->features & NETIF_F_IP_CSUM ||
priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
- dev->hard_header_len += GMAC_FCB_LEN;
+ dev->needed_headroom = GMAC_FCB_LEN;
/* Program the isrg regs only if number of grps > 1 */
if (priv->num_grps > 1) {
@@ -2675,12 +2675,12 @@ static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
/* gfar_process_frame() -- handle one incoming packet if skb
* isn't NULL. */
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
- int amount_pull)
+ int amount_pull, struct napi_struct *napi)
{
struct gfar_private *priv = netdev_priv(dev);
struct rxfcb *fcb = NULL;
- int ret;
+ gro_result_t ret;
/* fcb is at the beginning if exists */
fcb = (struct rxfcb *)skb->data;
@@ -2719,9 +2719,9 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
__vlan_hwaccel_put_tag(skb, fcb->vlctl);
/* Send the packet up the stack */
- ret = netif_receive_skb(skb);
+ ret = napi_gro_receive(napi, skb);
- if (NET_RX_DROP == ret)
+ if (GRO_DROP == ret)
priv->extra_stats.kernel_dropped++;
return 0;
@@ -2783,7 +2783,8 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
skb_put(skb, pkt_len);
rx_queue->stats.rx_bytes += pkt_len;
skb_record_rx_queue(skb, rx_queue->qindex);
- gfar_process_frame(dev, skb, amount_pull);
+ gfar_process_frame(dev, skb, amount_pull,
+ &rx_queue->grp->napi);
} else {
netif_warn(priv, rx_err, dev, "Missing skb!\n");
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 4c9f8d487dbb..2136c7ff5e6d 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1210,4 +1210,7 @@ struct filer_table {
struct gfar_filer_entry fe[MAX_FILER_CACHE_IDX + 20];
};
+/* The gianfar_ptp module will set this variable */
+extern int gfar_phc_index;
+
#endif /* __GIANFAR_H */
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 8d74efd04bb9..8a025570d97e 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/net_tstamp.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
@@ -1739,6 +1740,34 @@ static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
return ret;
}
+int gfar_phc_index = -1;
+
+static int gfar_get_ts_info(struct net_device *dev,
+ struct ethtool_ts_info *info)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+
+ if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)) {
+ info->so_timestamping =
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE;
+ info->phc_index = -1;
+ return 0;
+ }
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->phc_index = gfar_phc_index;
+ info->tx_types =
+ (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+ info->rx_filters =
+ (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_ALL);
+ return 0;
+}
+
const struct ethtool_ops gfar_ethtool_ops = {
.get_settings = gfar_gsettings,
.set_settings = gfar_ssettings,
@@ -1761,4 +1790,5 @@ const struct ethtool_ops gfar_ethtool_ops = {
#endif
.set_rxnfc = gfar_set_nfc,
.get_rxnfc = gfar_get_nfc,
+ .get_ts_info = gfar_get_ts_info,
};
diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c
index 5fd620bec15c..c08e5d40fecb 100644
--- a/drivers/net/ethernet/freescale/gianfar_ptp.c
+++ b/drivers/net/ethernet/freescale/gianfar_ptp.c
@@ -515,6 +515,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
err = PTR_ERR(etsects->clock);
goto no_clock;
}
+ gfar_phc_clock = ptp_clock_index(etsects->clock);
dev_set_drvdata(&dev->dev, etsects);
@@ -538,6 +539,7 @@ static int gianfar_ptp_remove(struct platform_device *dev)
gfar_write(&etsects->regs->tmr_temask, 0);
gfar_write(&etsects->regs->tmr_ctrl, 0);
+ gfar_phc_clock = -1;
ptp_clock_unregister(etsects->clock);
iounmap(etsects->regs);
release_resource(etsects->rsrc);
diff --git a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
index a97257f91a3d..37b035306013 100644
--- a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
+++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
@@ -415,6 +415,7 @@ static const struct ethtool_ops uec_ethtool_ops = {
.get_ethtool_stats = uec_get_ethtool_stats,
.get_wol = uec_get_wol,
.set_wol = uec_set_wol,
+ .get_ts_info = ethtool_op_get_ts_info,
};
void uec_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/fujitsu/at1700.c b/drivers/net/ethernet/fujitsu/at1700.c
index 3d94797c8f9b..4b80dc4531ad 100644
--- a/drivers/net/ethernet/fujitsu/at1700.c
+++ b/drivers/net/ethernet/fujitsu/at1700.c
@@ -27,7 +27,7 @@
ATI provided their EEPROM configuration code header file.
Thanks to NIIBE Yutaka <gniibe@mri.co.jp> for bug fixes.
- MCA bus (AT1720) support by Rene Schmit <rene@bss.lu>
+ MCA bus (AT1720) support (now deleted) by Rene Schmit <rene@bss.lu>
Bugs:
The MB86965 has a design flaw that makes all probes unreliable. Not
@@ -38,7 +38,6 @@
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/mca-legacy.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -79,24 +78,6 @@ static unsigned at1700_probe_list[] __initdata = {
0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
};
-/*
- * MCA
- */
-#ifdef CONFIG_MCA_LEGACY
-static int at1700_ioaddr_pattern[] __initdata = {
- 0x00, 0x04, 0x01, 0x05, 0x02, 0x06, 0x03, 0x07
-};
-
-static int at1700_mca_probe_list[] __initdata = {
- 0x400, 0x1400, 0x2400, 0x3400, 0x4400, 0x5400, 0x6400, 0x7400, 0
-};
-
-static int at1700_irq_pattern[] __initdata = {
- 0x00, 0x00, 0x00, 0x30, 0x70, 0xb0, 0x00, 0x00,
- 0x00, 0xf0, 0x34, 0x74, 0xb4, 0x00, 0x00, 0xf4, 0x00
-};
-#endif
-
/* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG
#define NET_DEBUG 1
@@ -114,7 +95,6 @@ struct net_local {
uint tx_queue_ready:1; /* Tx queue is ready to be sent. */
uint rx_started:1; /* Packets are Rxing. */
uchar tx_queue; /* Number of packet on the Tx queue. */
- char mca_slot; /* -1 means ISA */
ushort tx_queue_len; /* Current length of the Tx queue. */
};
@@ -166,21 +146,6 @@ static void set_rx_mode(struct net_device *dev);
static void net_tx_timeout (struct net_device *dev);
-#ifdef CONFIG_MCA_LEGACY
-struct at1720_mca_adapters_struct {
- char* name;
- int id;
-};
-/* rEnE : maybe there are others I don't know off... */
-
-static struct at1720_mca_adapters_struct at1720_mca_adapters[] __initdata = {
- { "Allied Telesys AT1720AT", 0x6410 },
- { "Allied Telesys AT1720BT", 0x6413 },
- { "Allied Telesys AT1720T", 0x6416 },
- { NULL, 0 },
-};
-#endif
-
/* Check for a network adaptor of this type, and return '0' iff one exists.
If dev->base_addr == 0, probe all likely locations.
If dev->base_addr == 1, always return failure.
@@ -194,11 +159,6 @@ static int irq;
static void cleanup_card(struct net_device *dev)
{
-#ifdef CONFIG_MCA_LEGACY
- struct net_local *lp = netdev_priv(dev);
- if (lp->mca_slot >= 0)
- mca_mark_as_unused(lp->mca_slot);
-#endif
free_irq(dev->irq, NULL);
release_region(dev->base_addr, AT1700_IO_EXTENT);
}
@@ -273,7 +233,7 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
static const char fmv_irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
static const char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
- int slot, ret = -ENODEV;
+ int ret = -ENODEV;
struct net_local *lp = netdev_priv(dev);
if (!request_region(ioaddr, AT1700_IO_EXTENT, DRV_NAME))
@@ -288,64 +248,6 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
ioaddr, read_eeprom(ioaddr, 4), read_eeprom(ioaddr, 5),
read_eeprom(ioaddr, 6), inw(ioaddr + EEPROM_Ctrl));
#endif
-
-#ifdef CONFIG_MCA_LEGACY
- /* rEnE (rene@bss.lu): got this from 3c509 driver source , adapted for AT1720 */
-
- /* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch, heavily
- modified by Chris Beauregard (cpbeaure@csclub.uwaterloo.ca)
- to support standard MCA probing. */
-
- /* redone for multi-card detection by ZP Gu (zpg@castle.net) */
- /* now works as a module */
-
- if (MCA_bus) {
- int j;
- int l_i;
- u_char pos3, pos4;
-
- for (j = 0; at1720_mca_adapters[j].name != NULL; j ++) {
- slot = 0;
- while (slot != MCA_NOTFOUND) {
-
- slot = mca_find_unused_adapter( at1720_mca_adapters[j].id, slot );
- if (slot == MCA_NOTFOUND) break;
-
- /* if we get this far, an adapter has been detected and is
- enabled */
-
- pos3 = mca_read_stored_pos( slot, 3 );
- pos4 = mca_read_stored_pos( slot, 4 );
-
- for (l_i = 0; l_i < 8; l_i++)
- if (( pos3 & 0x07) == at1700_ioaddr_pattern[l_i])
- break;
- ioaddr = at1700_mca_probe_list[l_i];
-
- for (irq = 0; irq < 0x10; irq++)
- if (((((pos4>>4) & 0x0f) | (pos3 & 0xf0)) & 0xff) == at1700_irq_pattern[irq])
- break;
-
- /* probing for a card at a particular IO/IRQ */
- if ((dev->irq && dev->irq != irq) ||
- (dev->base_addr && dev->base_addr != ioaddr)) {
- slot++; /* probing next slot */
- continue;
- }
-
- dev->irq = irq;
-
- /* claim the slot */
- mca_set_adapter_name( slot, at1720_mca_adapters[j].name );
- mca_mark_as_used(slot);
-
- goto found;
- }
- }
- /* if we get here, we didn't find an MCA adapter - try ISA */
- }
-#endif
- slot = -1;
/* We must check for the EEPROM-config boards first, else accessing
IOCONFIG0 will move the board! */
if (at1700_probe_list[inb(ioaddr + IOCONFIG1) & 0x07] == ioaddr &&
@@ -360,11 +262,7 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
goto err_out;
}
-#ifdef CONFIG_MCA_LEGACY
-found:
-#endif
-
- /* Reset the internal state machines. */
+ /* Reset the internal state machines. */
outb(0, ioaddr + RESET);
if (is_at1700) {
@@ -380,11 +278,11 @@ found:
break;
}
if (i == 8) {
- goto err_mca;
+ goto err_out;
}
} else {
if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr)
- goto err_mca;
+ goto err_out;
irq = fmv_irqmap[(inb(ioaddr + IOCONFIG)>>6) & 0x03];
}
}
@@ -464,23 +362,17 @@ found:
spin_lock_init(&lp->lock);
lp->jumpered = is_fmv18x;
- lp->mca_slot = slot;
/* Snarf the interrupt vector now. */
ret = request_irq(irq, net_interrupt, 0, DRV_NAME, dev);
if (ret) {
printk(KERN_ERR "AT1700 at %#3x is unusable due to a "
"conflict on IRQ %d.\n",
ioaddr, irq);
- goto err_mca;
+ goto err_out;
}
return 0;
-err_mca:
-#ifdef CONFIG_MCA_LEGACY
- if (slot >= 0)
- mca_mark_as_unused(slot);
-#endif
err_out:
release_region(ioaddr, AT1700_IO_EXTENT);
return ret;
diff --git a/drivers/net/ethernet/i825xx/3c523.c b/drivers/net/ethernet/i825xx/3c523.c
deleted file mode 100644
index 8451ecd4c1ec..000000000000
--- a/drivers/net/ethernet/i825xx/3c523.c
+++ /dev/null
@@ -1,1312 +0,0 @@
-/*
- net-3-driver for the 3c523 Etherlink/MC card (i82586 Ethernet chip)
-
-
- This is an extension to the Linux operating system, and is covered by the
- same GNU General Public License that covers that work.
-
- Copyright 1995, 1996 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca)
-
- This is basically Michael Hipp's ni52 driver, with a new probing
- algorithm and some minor changes to the 82586 CA and reset routines.
- Thanks a lot Michael for a really clean i82586 implementation! Unless
- otherwise documented in ni52.c, any bugs are mine.
-
- Contrary to the Ethernet-HOWTO, this isn't based on the 3c507 driver in
- any way. The ni52 is a lot easier to modify.
-
- sources:
- ni52.c
-
- Crynwr packet driver collection was a great reference for my first
- attempt at this sucker. The 3c507 driver also helped, until I noticed
- that ni52.c was a lot nicer.
-
- EtherLink/MC: Micro Channel Ethernet Adapter Technical Reference
- Manual, courtesy of 3Com CardFacts, documents the 3c523-specific
- stuff. Information on CardFacts is found in the Ethernet HOWTO.
- Also see <a href="http://www.3com.com/">
-
- Microprocessor Communications Support Chips, T.J. Byers, ISBN
- 0-444-01224-9, has a section on the i82586. It tells you just enough
- to know that you really don't want to learn how to program the chip.
-
- The original device probe code was stolen from ps2esdi.c
-
- Known Problems:
- Since most of the code was stolen from ni52.c, you'll run across the
- same bugs in the 0.62 version of ni52.c, plus maybe a few because of
- the 3c523 idiosynchacies. The 3c523 has 16K of RAM though, so there
- shouldn't be the overrun problem that the 8K ni52 has.
-
- This driver is for a 16K adapter. It should work fine on the 64K
- adapters, but it will only use one of the 4 banks of RAM. Modifying
- this for the 64K version would require a lot of heinous bank
- switching, which I'm sure not interested in doing. If you try to
- implement a bank switching version, you'll basically have to remember
- what bank is enabled and do a switch every time you access a memory
- location that's not current. You'll also have to remap pointers on
- the driver side, because it only knows about 16K of the memory.
- Anyone desperate or masochistic enough to try?
-
- It seems to be stable now when multiple transmit buffers are used. I
- can't see any performance difference, but then I'm working on a 386SX.
-
- Multicast doesn't work. It doesn't even pretend to work. Don't use
- it. Don't compile your kernel with multicast support. I don't know
- why.
-
- Features:
- This driver is useable as a loadable module. If you try to specify an
- IRQ or a IO address (via insmod 3c523.o irq=xx io=0xyyy), it will
- search the MCA slots until it finds a 3c523 with the specified
- parameters.
-
- This driver does support multiple ethernet cards when used as a module
- (up to MAX_3C523_CARDS, the default being 4)
-
- This has been tested with both BNC and TP versions, internal and
- external transceivers. Haven't tested with the 64K version (that I
- know of).
-
- History:
- Jan 1st, 1996
- first public release
- Feb 4th, 1996
- update to 1.3.59, incorporated multicast diffs from ni52.c
- Feb 15th, 1996
- added shared irq support
- Apr 1999
- added support for multiple cards when used as a module
- added option to disable multicast as is causes problems
- Ganesh Sittampalam <ganesh.sittampalam@magdalen.oxford.ac.uk>
- Stuart Adamson <stuart.adamson@compsoc.net>
- Nov 2001
- added support for ethtool (jgarzik)
-
- $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $
- */
-
-#define DRV_NAME "3c523"
-#define DRV_VERSION "17-Nov-2001"
-
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/skbuff.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/mca-legacy.h>
-#include <linux/ethtool.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-
-#include <asm/uaccess.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-
-#include "3c523.h"
-
-/*************************************************************************/
-#define DEBUG /* debug on */
-#define SYSBUSVAL 0 /* 1 = 8 Bit, 0 = 16 bit - 3c523 only does 16 bit */
-#undef ELMC_MULTICAST /* Disable multicast support as it is somewhat seriously broken at the moment */
-
-#define make32(ptr16) (p->memtop + (short) (ptr16) )
-#define make24(ptr32) ((char *) (ptr32) - p->base)
-#define make16(ptr32) ((unsigned short) ((unsigned long) (ptr32) - (unsigned long) p->memtop ))
-
-/*************************************************************************/
-/*
- Tables to which we can map values in the configuration registers.
- */
-static int irq_table[] __initdata = {
- 12, 7, 3, 9
-};
-
-static int csr_table[] __initdata = {
- 0x300, 0x1300, 0x2300, 0x3300
-};
-
-static int shm_table[] __initdata = {
- 0x0c0000, 0x0c8000, 0x0d0000, 0x0d8000
-};
-
-/******************* how to calculate the buffers *****************************
-
-
- * IMPORTANT NOTE: if you configure only one NUM_XMIT_BUFFS, the driver works
- * --------------- in a different (more stable?) mode. Only in this mode it's
- * possible to configure the driver with 'NO_NOPCOMMANDS'
-
-sizeof(scp)=12; sizeof(scb)=16; sizeof(iscp)=8;
-sizeof(scp)+sizeof(iscp)+sizeof(scb) = 36 = INIT
-sizeof(rfd) = 24; sizeof(rbd) = 12;
-sizeof(tbd) = 8; sizeof(transmit_cmd) = 16;
-sizeof(nop_cmd) = 8;
-
- * if you don't know the driver, better do not change this values: */
-
-#define RECV_BUFF_SIZE 1524 /* slightly oversized */
-#define XMIT_BUFF_SIZE 1524 /* slightly oversized */
-#define NUM_XMIT_BUFFS 1 /* config for both, 8K and 16K shmem */
-#define NUM_RECV_BUFFS_8 4 /* config for 8K shared mem */
-#define NUM_RECV_BUFFS_16 9 /* config for 16K shared mem */
-
-#if (NUM_XMIT_BUFFS == 1)
-#define NO_NOPCOMMANDS /* only possible with NUM_XMIT_BUFFS=1 */
-#endif
-
-/**************************************************************************/
-
-#define DELAY(x) { mdelay(32 * x); }
-
-/* a much shorter delay: */
-#define DELAY_16(); { udelay(16) ; }
-
-/* wait for command with timeout: */
-#define WAIT_4_SCB_CMD() { int i; \
- for(i=0;i<1024;i++) { \
- if(!p->scb->cmd) break; \
- DELAY_16(); \
- if(i == 1023) { \
- pr_warning("%s:%d: scb_cmd timed out .. resetting i82586\n",\
- dev->name,__LINE__); \
- elmc_id_reset586(); } } }
-
-static irqreturn_t elmc_interrupt(int irq, void *dev_id);
-static int elmc_open(struct net_device *dev);
-static int elmc_close(struct net_device *dev);
-static netdev_tx_t elmc_send_packet(struct sk_buff *, struct net_device *);
-static struct net_device_stats *elmc_get_stats(struct net_device *dev);
-static void elmc_timeout(struct net_device *dev);
-#ifdef ELMC_MULTICAST
-static void set_multicast_list(struct net_device *dev);
-#endif
-static const struct ethtool_ops netdev_ethtool_ops;
-
-/* helper-functions */
-static int init586(struct net_device *dev);
-static int check586(struct net_device *dev, unsigned long where, unsigned size);
-static void alloc586(struct net_device *dev);
-static void startrecv586(struct net_device *dev);
-static void *alloc_rfa(struct net_device *dev, void *ptr);
-static void elmc_rcv_int(struct net_device *dev);
-static void elmc_xmt_int(struct net_device *dev);
-static void elmc_rnr_int(struct net_device *dev);
-
-struct priv {
- unsigned long base;
- char *memtop;
- unsigned long mapped_start; /* Start of ioremap */
- volatile struct rfd_struct *rfd_last, *rfd_top, *rfd_first;
- volatile struct scp_struct *scp; /* volatile is important */
- volatile struct iscp_struct *iscp; /* volatile is important */
- volatile struct scb_struct *scb; /* volatile is important */
- volatile struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS];
-#if (NUM_XMIT_BUFFS == 1)
- volatile struct transmit_cmd_struct *xmit_cmds[2];
- volatile struct nop_cmd_struct *nop_cmds[2];
-#else
- volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS];
- volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS];
-#endif
- volatile int nop_point, num_recv_buffs;
- volatile char *xmit_cbuffs[NUM_XMIT_BUFFS];
- volatile int xmit_count, xmit_last;
- volatile int slot;
-};
-
-#define elmc_attn586() {elmc_do_attn586(dev->base_addr,ELMC_CTRL_INTE);}
-#define elmc_reset586() {elmc_do_reset586(dev->base_addr,ELMC_CTRL_INTE);}
-
-/* with interrupts disabled - this will clear the interrupt bit in the
- 3c523 control register, and won't put it back. This effectively
- disables interrupts on the card. */
-#define elmc_id_attn586() {elmc_do_attn586(dev->base_addr,0);}
-#define elmc_id_reset586() {elmc_do_reset586(dev->base_addr,0);}
-
-/*************************************************************************/
-/*
- Do a Channel Attention on the 3c523. This is extremely board dependent.
- */
-static void elmc_do_attn586(int ioaddr, int ints)
-{
- /* the 3c523 requires a minimum of 500 ns. The delays here might be
- a little too large, and hence they may cut the performance of the
- card slightly. If someone who knows a little more about Linux
- timing would care to play with these, I'd appreciate it. */
-
- /* this bit masking stuff is crap. I'd rather have separate
- registers with strobe triggers for each of these functions. <sigh>
- Ya take what ya got. */
-
- outb(ELMC_CTRL_RST | 0x3 | ELMC_CTRL_CA | ints, ioaddr + ELMC_CTRL);
- DELAY_16(); /* > 500 ns */
- outb(ELMC_CTRL_RST | 0x3 | ints, ioaddr + ELMC_CTRL);
-}
-
-/*************************************************************************/
-/*
- Reset the 82586 on the 3c523. Also very board dependent.
- */
-static void elmc_do_reset586(int ioaddr, int ints)
-{
- /* toggle the RST bit low then high */
- outb(0x3 | ELMC_CTRL_LBK, ioaddr + ELMC_CTRL);
- DELAY_16(); /* > 500 ns */
- outb(ELMC_CTRL_RST | ELMC_CTRL_LBK | 0x3, ioaddr + ELMC_CTRL);
-
- elmc_do_attn586(ioaddr, ints);
-}
-
-/**********************************************
- * close device
- */
-
-static int elmc_close(struct net_device *dev)
-{
- netif_stop_queue(dev);
- elmc_id_reset586(); /* the hard way to stop the receiver */
- free_irq(dev->irq, dev);
- return 0;
-}
-
-/**********************************************
- * open device
- */
-
-static int elmc_open(struct net_device *dev)
-{
- int ret;
-
- elmc_id_attn586(); /* disable interrupts */
-
- ret = request_irq(dev->irq, elmc_interrupt, IRQF_SHARED,
- dev->name, dev);
- if (ret) {
- pr_err("%s: couldn't get irq %d\n", dev->name, dev->irq);
- elmc_id_reset586();
- return ret;
- }
- alloc586(dev);
- init586(dev);
- startrecv586(dev);
- netif_start_queue(dev);
- return 0; /* most done by init */
-}
-
-/**********************************************
- * Check to see if there's an 82586 out there.
- */
-
-static int __init check586(struct net_device *dev, unsigned long where, unsigned size)
-{
- struct priv *p = netdev_priv(dev);
- char *iscp_addrs[2];
- int i = 0;
-
- p->base = (unsigned long) isa_bus_to_virt((unsigned long)where) + size - 0x01000000;
- p->memtop = isa_bus_to_virt((unsigned long)where) + size;
- p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
- memset((char *) p->scp, 0, sizeof(struct scp_struct));
- p->scp->sysbus = SYSBUSVAL; /* 1 = 8Bit-Bus, 0 = 16 Bit */
-
- iscp_addrs[0] = isa_bus_to_virt((unsigned long)where);
- iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);
-
- for (i = 0; i < 2; i++) {
- p->iscp = (struct iscp_struct *) iscp_addrs[i];
- memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
-
- p->scp->iscp = make24(p->iscp);
- p->iscp->busy = 1;
-
- elmc_id_reset586();
-
- /* reset586 does an implicit CA */
-
- /* apparently, you sometimes have to kick the 82586 twice... */
- elmc_id_attn586();
- DELAY(1);
-
- if (p->iscp->busy) { /* i82586 clears 'busy' after successful init */
- return 0;
- }
- }
- return 1;
-}
-
-/******************************************************************
- * set iscp at the right place, called by elmc_probe and open586.
- */
-
-static void alloc586(struct net_device *dev)
-{
- struct priv *p = netdev_priv(dev);
-
- elmc_id_reset586();
- DELAY(2);
-
- p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
- p->scb = (struct scb_struct *) isa_bus_to_virt(dev->mem_start);
- p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct));
-
- memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
- memset((char *) p->scp, 0, sizeof(struct scp_struct));
-
- p->scp->iscp = make24(p->iscp);
- p->scp->sysbus = SYSBUSVAL;
- p->iscp->scb_offset = make16(p->scb);
-
- p->iscp->busy = 1;
- elmc_id_reset586();
- elmc_id_attn586();
-
- DELAY(2);
-
- if (p->iscp->busy)
- pr_err("%s: Init-Problems (alloc).\n", dev->name);
-
- memset((char *) p->scb, 0, sizeof(struct scb_struct));
-}
-
-/*****************************************************************/
-
-static int elmc_getinfo(char *buf, int slot, void *d)
-{
- int len = 0;
- struct net_device *dev = d;
-
- if (dev == NULL)
- return len;
-
- len += sprintf(buf + len, "Revision: 0x%x\n",
- inb(dev->base_addr + ELMC_REVISION) & 0xf);
- len += sprintf(buf + len, "IRQ: %d\n", dev->irq);
- len += sprintf(buf + len, "IO Address: %#lx-%#lx\n", dev->base_addr,
- dev->base_addr + ELMC_IO_EXTENT);
- len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start,
- dev->mem_end - 1);
- len += sprintf(buf + len, "Transceiver: %s\n", dev->if_port ?
- "External" : "Internal");
- len += sprintf(buf + len, "Device: %s\n", dev->name);
- len += sprintf(buf + len, "Hardware Address: %pM\n",
- dev->dev_addr);
-
- return len;
-} /* elmc_getinfo() */
-
-static const struct net_device_ops netdev_ops = {
- .ndo_open = elmc_open,
- .ndo_stop = elmc_close,
- .ndo_get_stats = elmc_get_stats,
- .ndo_start_xmit = elmc_send_packet,
- .ndo_tx_timeout = elmc_timeout,
-#ifdef ELMC_MULTICAST
- .ndo_set_rx_mode = set_multicast_list,
-#endif
- .ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
-};
-
-/*****************************************************************/
-
-static int __init do_elmc_probe(struct net_device *dev)
-{
- static int slot;
- int base_addr = dev->base_addr;
- int irq = dev->irq;
- u_char status = 0;
- u_char revision = 0;
- int i = 0;
- unsigned int size = 0;
- int retval;
- struct priv *pr = netdev_priv(dev);
-
- if (MCA_bus == 0) {
- return -ENODEV;
- }
- /* search through the slots for the 3c523. */
- slot = mca_find_adapter(ELMC_MCA_ID, 0);
- while (slot != -1) {
- status = mca_read_stored_pos(slot, 2);
-
- dev->irq=irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6];
- dev->base_addr=csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1];
-
- /*
- If we're trying to match a specified irq or IO address,
- we'll reject a match unless it's what we're looking for.
- Also reject it if the card is already in use.
- */
-
- if ((irq && irq != dev->irq) ||
- (base_addr && base_addr != dev->base_addr)) {
- slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
- continue;
- }
- if (!request_region(dev->base_addr, ELMC_IO_EXTENT, DRV_NAME)) {
- slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
- continue;
- }
-
- /* found what we're looking for... */
- break;
- }
-
- /* we didn't find any 3c523 in the slots we checked for */
- if (slot == MCA_NOTFOUND)
- return (base_addr || irq) ? -ENXIO : -ENODEV;
-
- mca_set_adapter_name(slot, "3Com 3c523 Etherlink/MC");
- mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev);
-
- /* if we get this far, adapter has been found - carry on */
- pr_info("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1);
-
- /* Now we extract configuration info from the card.
- The 3c523 provides information in two of the POS registers, but
- the second one is only needed if we want to tell the card what IRQ
- to use. I suspect that whoever sets the thing up initially would
- prefer we don't screw with those things.
-
- Note that we read the status info when we found the card...
-
- See 3c523.h for more details.
- */
-
- /* revision is stored in the first 4 bits of the revision register */
- revision = inb(dev->base_addr + ELMC_REVISION) & 0xf;
-
- /* according to docs, we read the interrupt and write it back to
- the IRQ select register, since the POST might not configure the IRQ
- properly. */
- switch (dev->irq) {
- case 3:
- mca_write_pos(slot, 3, 0x04);
- break;
- case 7:
- mca_write_pos(slot, 3, 0x02);
- break;
- case 9:
- mca_write_pos(slot, 3, 0x08);
- break;
- case 12:
- mca_write_pos(slot, 3, 0x01);
- break;
- }
-
- pr->slot = slot;
-
- pr_info("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
- dev->base_addr);
-
- /* Determine if we're using the on-board transceiver (i.e. coax) or
- an external one. The information is pretty much useless, but I
- guess it's worth brownie points. */
- dev->if_port = (status & ELMC_STATUS_DISABLE_THIN);
-
- /* The 3c523 has a 24K chunk of memory. The first 16K is the
- shared memory, while the last 8K is for the EtherStart BIOS ROM.
- Which we don't care much about here. We'll just tell Linux that
- we're using 16K. MCA won't permit address space conflicts caused
- by not mapping the other 8K. */
- dev->mem_start = shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3];
-
- /* We're using MCA, so it's a given that the information about memory
- size is correct. The Crynwr drivers do something like this. */
-
- elmc_id_reset586(); /* seems like a good idea before checking it... */
-
- size = 0x4000; /* check for 16K mem */
- if (!check586(dev, dev->mem_start, size)) {
- pr_err("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
- dev->mem_start);
- retval = -ENODEV;
- goto err_out;
- }
- dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */
-
- pr->memtop = isa_bus_to_virt(dev->mem_start) + size;
- pr->base = (unsigned long) isa_bus_to_virt(dev->mem_start) + size - 0x01000000;
- alloc586(dev);
-
- elmc_id_reset586(); /* make sure it doesn't generate spurious ints */
-
- /* set number of receive-buffs according to memsize */
- pr->num_recv_buffs = NUM_RECV_BUFFS_16;
-
- /* dump all the assorted information */
- pr_info("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
- dev->irq, dev->if_port ? "ex" : "in",
- dev->mem_start, dev->mem_end - 1);
-
- /* The hardware address for the 3c523 is stored in the first six
- bytes of the IO address. */
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = inb(dev->base_addr + i);
-
- pr_info("%s: hardware address %pM\n",
- dev->name, dev->dev_addr);
-
- dev->netdev_ops = &netdev_ops;
- dev->watchdog_timeo = HZ;
- dev->ethtool_ops = &netdev_ethtool_ops;
-
- /* note that we haven't actually requested the IRQ from the kernel.
- That gets done in elmc_open(). I'm not sure that's such a good idea,
- but it works, so I'll go with it. */
-
-#ifndef ELMC_MULTICAST
- dev->flags&=~IFF_MULTICAST; /* Multicast doesn't work */
-#endif
-
- retval = register_netdev(dev);
- if (retval)
- goto err_out;
-
- return 0;
-err_out:
- mca_set_adapter_procfn(slot, NULL, NULL);
- release_region(dev->base_addr, ELMC_IO_EXTENT);
- return retval;
-}
-
-#ifdef MODULE
-static void cleanup_card(struct net_device *dev)
-{
- mca_set_adapter_procfn(((struct priv *)netdev_priv(dev))->slot,
- NULL, NULL);
- release_region(dev->base_addr, ELMC_IO_EXTENT);
-}
-#else
-struct net_device * __init elmc_probe(int unit)
-{
- struct net_device *dev = alloc_etherdev(sizeof(struct priv));
- int err;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
-
- err = do_elmc_probe(dev);
- if (err)
- goto out;
- return dev;
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-#endif
-
-/**********************************************
- * init the chip (elmc-interrupt should be disabled?!)
- * needs a correct 'allocated' memory
- */
-
-static int init586(struct net_device *dev)
-{
- void *ptr;
- unsigned long s;
- int i, result = 0;
- struct priv *p = netdev_priv(dev);
- volatile struct configure_cmd_struct *cfg_cmd;
- volatile struct iasetup_cmd_struct *ias_cmd;
- volatile struct tdr_cmd_struct *tdr_cmd;
- volatile struct mcsetup_cmd_struct *mc_cmd;
- struct netdev_hw_addr *ha;
- int num_addrs = netdev_mc_count(dev);
-
- ptr = (void *) ((char *) p->scb + sizeof(struct scb_struct));
-
- cfg_cmd = (struct configure_cmd_struct *) ptr; /* configure-command */
- cfg_cmd->cmd_status = 0;
- cfg_cmd->cmd_cmd = CMD_CONFIGURE | CMD_LAST;
- cfg_cmd->cmd_link = 0xffff;
-
- cfg_cmd->byte_cnt = 0x0a; /* number of cfg bytes */
- cfg_cmd->fifo = 0x08; /* fifo-limit (8=tx:32/rx:64) */
- cfg_cmd->sav_bf = 0x40; /* hold or discard bad recv frames (bit 7) */
- cfg_cmd->adr_len = 0x2e; /* addr_len |!src_insert |pre-len |loopback */
- cfg_cmd->priority = 0x00;
- cfg_cmd->ifs = 0x60;
- cfg_cmd->time_low = 0x00;
- cfg_cmd->time_high = 0xf2;
- cfg_cmd->promisc = 0;
- if (dev->flags & (IFF_ALLMULTI | IFF_PROMISC))
- cfg_cmd->promisc = 1;
- cfg_cmd->carr_coll = 0x00;
-
- p->scb->cbl_offset = make16(cfg_cmd);
-
- p->scb->cmd = CUC_START; /* cmd.-unit start */
- elmc_id_attn586();
-
- s = jiffies; /* warning: only active with interrupts on !! */
- while (!(cfg_cmd->cmd_status & STAT_COMPL)) {
- if (time_after(jiffies, s + 30*HZ/100))
- break;
- }
-
- if ((cfg_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_COMPL | STAT_OK)) {
- pr_warning("%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status);
- return 1;
- }
- /*
- * individual address setup
- */
- ias_cmd = (struct iasetup_cmd_struct *) ptr;
-
- ias_cmd->cmd_status = 0;
- ias_cmd->cmd_cmd = CMD_IASETUP | CMD_LAST;
- ias_cmd->cmd_link = 0xffff;
-
- memcpy((char *) &ias_cmd->iaddr, (char *) dev->dev_addr, ETH_ALEN);
-
- p->scb->cbl_offset = make16(ias_cmd);
-
- p->scb->cmd = CUC_START; /* cmd.-unit start */
- elmc_id_attn586();
-
- s = jiffies;
- while (!(ias_cmd->cmd_status & STAT_COMPL)) {
- if (time_after(jiffies, s + 30*HZ/100))
- break;
- }
-
- if ((ias_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_OK | STAT_COMPL)) {
- pr_warning("%s (elmc): individual address setup command failed: %04x\n",
- dev->name, ias_cmd->cmd_status);
- return 1;
- }
- /*
- * TDR, wire check .. e.g. no resistor e.t.c
- */
- tdr_cmd = (struct tdr_cmd_struct *) ptr;
-
- tdr_cmd->cmd_status = 0;
- tdr_cmd->cmd_cmd = CMD_TDR | CMD_LAST;
- tdr_cmd->cmd_link = 0xffff;
- tdr_cmd->status = 0;
-
- p->scb->cbl_offset = make16(tdr_cmd);
-
- p->scb->cmd = CUC_START; /* cmd.-unit start */
- elmc_attn586();
-
- s = jiffies;
- while (!(tdr_cmd->cmd_status & STAT_COMPL)) {
- if (time_after(jiffies, s + 30*HZ/100)) {
- pr_warning("%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
- result = 1;
- break;
- }
- }
-
- if (!result) {
- DELAY(2); /* wait for result */
- result = tdr_cmd->status;
-
- p->scb->cmd = p->scb->status & STAT_MASK;
- elmc_id_attn586(); /* ack the interrupts */
-
- if (result & TDR_LNK_OK) {
- /* empty */
- } else if (result & TDR_XCVR_PRB) {
- pr_warning("%s: TDR: Transceiver problem!\n", dev->name);
- } else if (result & TDR_ET_OPN) {
- pr_warning("%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
- } else if (result & TDR_ET_SRT) {
- if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */
- pr_warning("%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
- } else {
- pr_warning("%s: TDR: Unknown status %04x\n", dev->name, result);
- }
- }
- /*
- * ack interrupts
- */
- p->scb->cmd = p->scb->status & STAT_MASK;
- elmc_id_attn586();
-
- /*
- * alloc nop/xmit-cmds
- */
-#if (NUM_XMIT_BUFFS == 1)
- for (i = 0; i < 2; i++) {
- p->nop_cmds[i] = (struct nop_cmd_struct *) ptr;
- p->nop_cmds[i]->cmd_cmd = CMD_NOP;
- p->nop_cmds[i]->cmd_status = 0;
- p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i]));
- ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
- }
- p->xmit_cmds[0] = (struct transmit_cmd_struct *) ptr; /* transmit cmd/buff 0 */
- ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
-#else
- for (i = 0; i < NUM_XMIT_BUFFS; i++) {
- p->nop_cmds[i] = (struct nop_cmd_struct *) ptr;
- p->nop_cmds[i]->cmd_cmd = CMD_NOP;
- p->nop_cmds[i]->cmd_status = 0;
- p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i]));
- ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
- p->xmit_cmds[i] = (struct transmit_cmd_struct *) ptr; /*transmit cmd/buff 0 */
- ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
- }
-#endif
-
- ptr = alloc_rfa(dev, (void *) ptr); /* init receive-frame-area */
-
- /*
- * Multicast setup
- */
-
- if (num_addrs) {
- /* I don't understand this: do we really need memory after the init? */
- int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
- if (len <= 0) {
- pr_err("%s: Ooooops, no memory for MC-Setup!\n", dev->name);
- } else {
- if (len < num_addrs) {
- num_addrs = len;
- pr_warning("%s: Sorry, can only apply %d MC-Address(es).\n",
- dev->name, num_addrs);
- }
- mc_cmd = (struct mcsetup_cmd_struct *) ptr;
- mc_cmd->cmd_status = 0;
- mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST;
- mc_cmd->cmd_link = 0xffff;
- mc_cmd->mc_cnt = num_addrs * 6;
- i = 0;
- netdev_for_each_mc_addr(ha, dev)
- memcpy((char *) mc_cmd->mc_list[i++],
- ha->addr, 6);
- p->scb->cbl_offset = make16(mc_cmd);
- p->scb->cmd = CUC_START;
- elmc_id_attn586();
- s = jiffies;
- while (!(mc_cmd->cmd_status & STAT_COMPL)) {
- if (time_after(jiffies, s + 30*HZ/100))
- break;
- }
- if (!(mc_cmd->cmd_status & STAT_COMPL)) {
- pr_warning("%s: Can't apply multicast-address-list.\n", dev->name);
- }
- }
- }
- /*
- * alloc xmit-buffs / init xmit_cmds
- */
- for (i = 0; i < NUM_XMIT_BUFFS; i++) {
- p->xmit_cbuffs[i] = (char *) ptr; /* char-buffs */
- ptr = (char *) ptr + XMIT_BUFF_SIZE;
- p->xmit_buffs[i] = (struct tbd_struct *) ptr; /* TBD */
- ptr = (char *) ptr + sizeof(struct tbd_struct);
- if ((void *) ptr > (void *) p->iscp) {
- pr_err("%s: not enough shared-mem for your configuration!\n", dev->name);
- return 1;
- }
- memset((char *) (p->xmit_cmds[i]), 0, sizeof(struct transmit_cmd_struct));
- memset((char *) (p->xmit_buffs[i]), 0, sizeof(struct tbd_struct));
- p->xmit_cmds[i]->cmd_status = STAT_COMPL;
- p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT;
- p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i]));
- p->xmit_buffs[i]->next = 0xffff;
- p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i]));
- }
-
- p->xmit_count = 0;
- p->xmit_last = 0;
-#ifndef NO_NOPCOMMANDS
- p->nop_point = 0;
-#endif
-
- /*
- * 'start transmitter' (nop-loop)
- */
-#ifndef NO_NOPCOMMANDS
- p->scb->cbl_offset = make16(p->nop_cmds[0]);
- p->scb->cmd = CUC_START;
- elmc_id_attn586();
- WAIT_4_SCB_CMD();
-#else
- p->xmit_cmds[0]->cmd_link = 0xffff;
- p->xmit_cmds[0]->cmd_cmd = CMD_XMIT | CMD_LAST | CMD_INT;
-#endif
-
- return 0;
-}
-
-/******************************************************
- * This is a helper routine for elmc_rnr_int() and init586().
- * It sets up the Receive Frame Area (RFA).
- */
-
-static void *alloc_rfa(struct net_device *dev, void *ptr)
-{
- volatile struct rfd_struct *rfd = (struct rfd_struct *) ptr;
- volatile struct rbd_struct *rbd;
- int i;
- struct priv *p = netdev_priv(dev);
-
- memset((char *) rfd, 0, sizeof(struct rfd_struct) * p->num_recv_buffs);
- p->rfd_first = rfd;
-
- for (i = 0; i < p->num_recv_buffs; i++) {
- rfd[i].next = make16(rfd + (i + 1) % p->num_recv_buffs);
- }
- rfd[p->num_recv_buffs - 1].last = RFD_SUSP; /* RU suspend */
-
- ptr = (void *) (rfd + p->num_recv_buffs);
-
- rbd = (struct rbd_struct *) ptr;
- ptr = (void *) (rbd + p->num_recv_buffs);
-
- /* clr descriptors */
- memset((char *) rbd, 0, sizeof(struct rbd_struct) * p->num_recv_buffs);
-
- for (i = 0; i < p->num_recv_buffs; i++) {
- rbd[i].next = make16((rbd + (i + 1) % p->num_recv_buffs));
- rbd[i].size = RECV_BUFF_SIZE;
- rbd[i].buffer = make24(ptr);
- ptr = (char *) ptr + RECV_BUFF_SIZE;
- }
-
- p->rfd_top = p->rfd_first;
- p->rfd_last = p->rfd_first + p->num_recv_buffs - 1;
-
- p->scb->rfa_offset = make16(p->rfd_first);
- p->rfd_first->rbd_offset = make16(rbd);
-
- return ptr;
-}
-
-
-/**************************************************
- * Interrupt Handler ...
- */
-
-static irqreturn_t
-elmc_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- unsigned short stat;
- struct priv *p;
-
- if (!netif_running(dev)) {
- /* The 3c523 has this habit of generating interrupts during the
- reset. I'm not sure if the ni52 has this same problem, but it's
- really annoying if we haven't finished initializing it. I was
- hoping all the elmc_id_* commands would disable this, but I
- might have missed a few. */
-
- elmc_id_attn586(); /* ack inter. and disable any more */
- return IRQ_HANDLED;
- } else if (!(ELMC_CTRL_INT & inb(dev->base_addr + ELMC_CTRL))) {
- /* wasn't this device */
- return IRQ_NONE;
- }
- /* reading ELMC_CTRL also clears the INT bit. */
-
- p = netdev_priv(dev);
-
- while ((stat = p->scb->status & STAT_MASK))
- {
- p->scb->cmd = stat;
- elmc_attn586(); /* ack inter. */
-
- if (stat & STAT_CX) {
- /* command with I-bit set complete */
- elmc_xmt_int(dev);
- }
- if (stat & STAT_FR) {
- /* received a frame */
- elmc_rcv_int(dev);
- }
-#ifndef NO_NOPCOMMANDS
- if (stat & STAT_CNA) {
- /* CU went 'not ready' */
- if (netif_running(dev)) {
- pr_warning("%s: oops! CU has left active state. stat: %04x/%04x.\n",
- dev->name, (int) stat, (int) p->scb->status);
- }
- }
-#endif
-
- if (stat & STAT_RNR) {
- /* RU went 'not ready' */
-
- if (p->scb->status & RU_SUSPEND) {
- /* special case: RU_SUSPEND */
-
- WAIT_4_SCB_CMD();
- p->scb->cmd = RUC_RESUME;
- elmc_attn586();
- } else {
- pr_warning("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n",
- dev->name, (int) stat, (int) p->scb->status);
- elmc_rnr_int(dev);
- }
- }
- WAIT_4_SCB_CMD(); /* wait for ack. (elmc_xmt_int can be faster than ack!!) */
- if (p->scb->cmd) { /* timed out? */
- break;
- }
- }
- return IRQ_HANDLED;
-}
-
-/*******************************************************
- * receive-interrupt
- */
-
-static void elmc_rcv_int(struct net_device *dev)
-{
- int status;
- unsigned short totlen;
- struct sk_buff *skb;
- struct rbd_struct *rbd;
- struct priv *p = netdev_priv(dev);
-
- for (; (status = p->rfd_top->status) & STAT_COMPL;) {
- rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
-
- if (status & STAT_OK) { /* frame received without error? */
- if ((totlen = rbd->status) & RBD_LAST) { /* the first and the last buffer? */
- totlen &= RBD_MASK; /* length of this frame */
- rbd->status = 0;
- skb = netdev_alloc_skb(dev, totlen + 2);
- if (skb != NULL) {
- skb_reserve(skb, 2); /* 16 byte alignment */
- skb_put(skb,totlen);
- skb_copy_to_linear_data(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen);
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += totlen;
- } else {
- dev->stats.rx_dropped++;
- }
- } else {
- pr_warning("%s: received oversized frame.\n", dev->name);
- dev->stats.rx_dropped++;
- }
- } else { /* frame !(ok), only with 'save-bad-frames' */
- pr_warning("%s: oops! rfd-error-status: %04x\n", dev->name, status);
- dev->stats.rx_errors++;
- }
- p->rfd_top->status = 0;
- p->rfd_top->last = RFD_SUSP;
- p->rfd_last->last = 0; /* delete RU_SUSP */
- p->rfd_last = p->rfd_top;
- p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */
- }
-}
-
-/**********************************************************
- * handle 'Receiver went not ready'.
- */
-
-static void elmc_rnr_int(struct net_device *dev)
-{
- struct priv *p = netdev_priv(dev);
-
- dev->stats.rx_errors++;
-
- WAIT_4_SCB_CMD(); /* wait for the last cmd */
- p->scb->cmd = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */
- elmc_attn586();
- WAIT_4_SCB_CMD(); /* wait for accept cmd. */
-
- alloc_rfa(dev, (char *) p->rfd_first);
- startrecv586(dev); /* restart RU */
-
- pr_warning("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);
-
-}
-
-/**********************************************************
- * handle xmit - interrupt
- */
-
-static void elmc_xmt_int(struct net_device *dev)
-{
- int status;
- struct priv *p = netdev_priv(dev);
-
- status = p->xmit_cmds[p->xmit_last]->cmd_status;
- if (!(status & STAT_COMPL)) {
- pr_warning("%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);
- }
- if (status & STAT_OK) {
- dev->stats.tx_packets++;
- dev->stats.collisions += (status & TCMD_MAXCOLLMASK);
- } else {
- dev->stats.tx_errors++;
- if (status & TCMD_LATECOLL) {
- pr_warning("%s: late collision detected.\n", dev->name);
- dev->stats.collisions++;
- } else if (status & TCMD_NOCARRIER) {
- dev->stats.tx_carrier_errors++;
- pr_warning("%s: no carrier detected.\n", dev->name);
- } else if (status & TCMD_LOSTCTS) {
- pr_warning("%s: loss of CTS detected.\n", dev->name);
- } else if (status & TCMD_UNDERRUN) {
- dev->stats.tx_fifo_errors++;
- pr_warning("%s: DMA underrun detected.\n", dev->name);
- } else if (status & TCMD_MAXCOLL) {
- pr_warning("%s: Max. collisions exceeded.\n", dev->name);
- dev->stats.collisions += 16;
- }
- }
-
-#if (NUM_XMIT_BUFFS != 1)
- if ((++p->xmit_last) == NUM_XMIT_BUFFS) {
- p->xmit_last = 0;
- }
-#endif
-
- netif_wake_queue(dev);
-}
-
-/***********************************************************
- * (re)start the receiver
- */
-
-static void startrecv586(struct net_device *dev)
-{
- struct priv *p = netdev_priv(dev);
-
- p->scb->rfa_offset = make16(p->rfd_first);
- p->scb->cmd = RUC_START;
- elmc_attn586(); /* start cmd. */
- WAIT_4_SCB_CMD(); /* wait for accept cmd. (no timeout!!) */
-}
-
-/******************************************************
- * timeout
- */
-
-static void elmc_timeout(struct net_device *dev)
-{
- struct priv *p = netdev_priv(dev);
- /* COMMAND-UNIT active? */
- if (p->scb->status & CU_ACTIVE) {
- pr_debug("%s: strange ... timeout with CU active?!?\n", dev->name);
- pr_debug("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name,
- (int)p->xmit_cmds[0]->cmd_status,
- (int)p->nop_cmds[0]->cmd_status,
- (int)p->nop_cmds[1]->cmd_status, (int)p->nop_point);
- p->scb->cmd = CUC_ABORT;
- elmc_attn586();
- WAIT_4_SCB_CMD();
- p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
- p->scb->cmd = CUC_START;
- elmc_attn586();
- WAIT_4_SCB_CMD();
- netif_wake_queue(dev);
- } else {
- pr_debug("%s: xmitter timed out, try to restart! stat: %04x\n",
- dev->name, p->scb->status);
- pr_debug("%s: command-stats: %04x %04x\n", dev->name,
- p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status);
- elmc_close(dev);
- elmc_open(dev);
- }
-}
-
-/******************************************************
- * send frame
- */
-
-static netdev_tx_t elmc_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
- int len;
- int i;
-#ifndef NO_NOPCOMMANDS
- int next_nop;
-#endif
- struct priv *p = netdev_priv(dev);
-
- netif_stop_queue(dev);
-
- len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
-
- if (len != skb->len)
- memset((char *) p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN);
- skb_copy_from_linear_data(skb, (char *) p->xmit_cbuffs[p->xmit_count], skb->len);
-
-#if (NUM_XMIT_BUFFS == 1)
-#ifdef NO_NOPCOMMANDS
- p->xmit_buffs[0]->size = TBD_LAST | len;
- for (i = 0; i < 16; i++) {
- p->scb->cbl_offset = make16(p->xmit_cmds[0]);
- p->scb->cmd = CUC_START;
- p->xmit_cmds[0]->cmd_status = 0;
- elmc_attn586();
- if (!i) {
- dev_kfree_skb(skb);
- }
- WAIT_4_SCB_CMD();
- if ((p->scb->status & CU_ACTIVE)) { /* test it, because CU sometimes doesn't start immediately */
- break;
- }
- if (p->xmit_cmds[0]->cmd_status) {
- break;
- }
- if (i == 15) {
- pr_warning("%s: Can't start transmit-command.\n", dev->name);
- }
- }
-#else
- next_nop = (p->nop_point + 1) & 0x1;
- p->xmit_buffs[0]->size = TBD_LAST | len;
-
- p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link
- = make16((p->nop_cmds[next_nop]));
- p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
-
- p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
- p->nop_point = next_nop;
- dev_kfree_skb(skb);
-#endif
-#else
- p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
- if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) {
- next_nop = 0;
- }
- p->xmit_cmds[p->xmit_count]->cmd_status = 0;
- p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link
- = make16((p->nop_cmds[next_nop]));
- p->nop_cmds[next_nop]->cmd_status = 0;
- p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
- p->xmit_count = next_nop;
- if (p->xmit_count != p->xmit_last)
- netif_wake_queue(dev);
- dev_kfree_skb(skb);
-#endif
- return NETDEV_TX_OK;
-}
-
-/*******************************************
- * Someone wanna have the statistics
- */
-
-static struct net_device_stats *elmc_get_stats(struct net_device *dev)
-{
- struct priv *p = netdev_priv(dev);
- unsigned short crc, aln, rsc, ovrn;
-
- crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */
- p->scb->crc_errs -= crc;
- aln = p->scb->aln_errs;
- p->scb->aln_errs -= aln;
- rsc = p->scb->rsc_errs;
- p->scb->rsc_errs -= rsc;
- ovrn = p->scb->ovrn_errs;
- p->scb->ovrn_errs -= ovrn;
-
- dev->stats.rx_crc_errors += crc;
- dev->stats.rx_fifo_errors += ovrn;
- dev->stats.rx_frame_errors += aln;
- dev->stats.rx_dropped += rsc;
-
- return &dev->stats;
-}
-
-/********************************************************
- * Set MC list ..
- */
-
-#ifdef ELMC_MULTICAST
-static void set_multicast_list(struct net_device *dev)
-{
- if (!dev->start) {
- /* without a running interface, promiscuous doesn't work */
- return;
- }
- dev->start = 0;
- alloc586(dev);
- init586(dev);
- startrecv586(dev);
- dev->start = 1;
-}
-#endif
-
-static void netdev_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, DRV_NAME);
- strcpy(info->version, DRV_VERSION);
- sprintf(info->bus_info, "MCA 0x%lx", dev->base_addr);
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
- .get_drvinfo = netdev_get_drvinfo,
-};
-
-#ifdef MODULE
-
-/* Increase if needed ;) */
-#define MAX_3C523_CARDS 4
-
-static struct net_device *dev_elmc[MAX_3C523_CARDS];
-static int irq[MAX_3C523_CARDS];
-static int io[MAX_3C523_CARDS];
-module_param_array(irq, int, NULL, 0);
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io, "EtherLink/MC I/O base address(es)");
-MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)");
-MODULE_LICENSE("GPL");
-
-int __init init_module(void)
-{
- int this_dev,found = 0;
-
- /* Loop until we either can't find any more cards, or we have MAX_3C523_CARDS */
- for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) {
- struct net_device *dev = alloc_etherdev(sizeof(struct priv));
- if (!dev)
- break;
- dev->irq=irq[this_dev];
- dev->base_addr=io[this_dev];
- if (do_elmc_probe(dev) == 0) {
- dev_elmc[this_dev] = dev;
- found++;
- continue;
- }
- free_netdev(dev);
- if (io[this_dev]==0)
- break;
- pr_warning("3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]);
- }
-
- if(found==0) {
- if (io[0]==0)
- pr_notice("3c523.c: No 3c523 cards found\n");
- return -ENXIO;
- } else return 0;
-}
-
-void __exit cleanup_module(void)
-{
- int this_dev;
- for (this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) {
- struct net_device *dev = dev_elmc[this_dev];
- if (dev) {
- unregister_netdev(dev);
- cleanup_card(dev);
- free_netdev(dev);
- }
- }
-}
-
-#endif /* MODULE */
diff --git a/drivers/net/ethernet/i825xx/3c523.h b/drivers/net/ethernet/i825xx/3c523.h
deleted file mode 100644
index 6956441687b9..000000000000
--- a/drivers/net/ethernet/i825xx/3c523.h
+++ /dev/null
@@ -1,355 +0,0 @@
-#ifndef _3c523_INCLUDE_
-#define _3c523_INCLUDE_
-/*
- This is basically a hacked version of ni52.h, for the 3c523
- Etherlink/MC.
-*/
-
-/*
- * Intel i82586 Ethernet definitions
- *
- * This is an extension to the Linux operating system, and is covered by the
- * same GNU General Public License that covers that work.
- *
- * Copyright 1995 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca)
- *
- * See 3c523.c for details.
- *
- * $Header: /home/chrisb/linux-1.2.13-3c523/drivers/net/RCS/3c523.h,v 1.6 1996/01/20 05:09:00 chrisb Exp chrisb $
- */
-
-/*
- * where to find the System Configuration Pointer (SCP)
- */
-#define SCP_DEFAULT_ADDRESS 0xfffff4
-
-
-/*
- * System Configuration Pointer Struct
- */
-
-struct scp_struct
-{
- unsigned short zero_dum0; /* has to be zero */
- unsigned char sysbus; /* 0=16Bit,1=8Bit */
- unsigned char zero_dum1; /* has to be zero for 586 */
- unsigned short zero_dum2;
- unsigned short zero_dum3;
- char *iscp; /* pointer to the iscp-block */
-};
-
-
-/*
- * Intermediate System Configuration Pointer (ISCP)
- */
-struct iscp_struct
-{
- unsigned char busy; /* 586 clears after successful init */
- unsigned char zero_dummy; /* hast to be zero */
- unsigned short scb_offset; /* pointeroffset to the scb_base */
- char *scb_base; /* base-address of all 16-bit offsets */
-};
-
-/*
- * System Control Block (SCB)
- */
-struct scb_struct
-{
- unsigned short status; /* status word */
- unsigned short cmd; /* command word */
- unsigned short cbl_offset; /* pointeroffset, command block list */
- unsigned short rfa_offset; /* pointeroffset, receive frame area */
- unsigned short crc_errs; /* CRC-Error counter */
- unsigned short aln_errs; /* alignmenterror counter */
- unsigned short rsc_errs; /* Resourceerror counter */
- unsigned short ovrn_errs; /* OVerrunerror counter */
-};
-
-/*
- * possible command values for the command word
- */
-#define RUC_MASK 0x0070 /* mask for RU commands */
-#define RUC_NOP 0x0000 /* NOP-command */
-#define RUC_START 0x0010 /* start RU */
-#define RUC_RESUME 0x0020 /* resume RU after suspend */
-#define RUC_SUSPEND 0x0030 /* suspend RU */
-#define RUC_ABORT 0x0040 /* abort receiver operation immediately */
-
-#define CUC_MASK 0x0700 /* mask for CU command */
-#define CUC_NOP 0x0000 /* NOP-command */
-#define CUC_START 0x0100 /* start execution of 1. cmd on the CBL */
-#define CUC_RESUME 0x0200 /* resume after suspend */
-#define CUC_SUSPEND 0x0300 /* Suspend CU */
-#define CUC_ABORT 0x0400 /* abort command operation immediately */
-
-#define ACK_MASK 0xf000 /* mask for ACK command */
-#define ACK_CX 0x8000 /* acknowledges STAT_CX */
-#define ACK_FR 0x4000 /* ack. STAT_FR */
-#define ACK_CNA 0x2000 /* ack. STAT_CNA */
-#define ACK_RNR 0x1000 /* ack. STAT_RNR */
-
-/*
- * possible status values for the status word
- */
-#define STAT_MASK 0xf000 /* mask for cause of interrupt */
-#define STAT_CX 0x8000 /* CU finished cmd with its I bit set */
-#define STAT_FR 0x4000 /* RU finished receiving a frame */
-#define STAT_CNA 0x2000 /* CU left active state */
-#define STAT_RNR 0x1000 /* RU left ready state */
-
-#define CU_STATUS 0x700 /* CU status, 0=idle */
-#define CU_SUSPEND 0x100 /* CU is suspended */
-#define CU_ACTIVE 0x200 /* CU is active */
-
-#define RU_STATUS 0x70 /* RU status, 0=idle */
-#define RU_SUSPEND 0x10 /* RU suspended */
-#define RU_NOSPACE 0x20 /* RU no resources */
-#define RU_READY 0x40 /* RU is ready */
-
-/*
- * Receive Frame Descriptor (RFD)
- */
-struct rfd_struct
-{
- unsigned short status; /* status word */
- unsigned short last; /* Bit15,Last Frame on List / Bit14,suspend */
- unsigned short next; /* linkoffset to next RFD */
- unsigned short rbd_offset; /* pointeroffset to RBD-buffer */
- unsigned char dest[6]; /* ethernet-address, destination */
- unsigned char source[6]; /* ethernet-address, source */
- unsigned short length; /* 802.3 frame-length */
- unsigned short zero_dummy; /* dummy */
-};
-
-#define RFD_LAST 0x8000 /* last: last rfd in the list */
-#define RFD_SUSP 0x4000 /* last: suspend RU after */
-#define RFD_ERRMASK 0x0fe1 /* status: errormask */
-#define RFD_MATCHADD 0x0002 /* status: Destinationaddress !matches IA */
-#define RFD_RNR 0x0200 /* status: receiver out of resources */
-
-/*
- * Receive Buffer Descriptor (RBD)
- */
-struct rbd_struct
-{
- unsigned short status; /* status word,number of used bytes in buff */
- unsigned short next; /* pointeroffset to next RBD */
- char *buffer; /* receive buffer address pointer */
- unsigned short size; /* size of this buffer */
- unsigned short zero_dummy; /* dummy */
-};
-
-#define RBD_LAST 0x8000 /* last buffer */
-#define RBD_USED 0x4000 /* this buffer has data */
-#define RBD_MASK 0x3fff /* size-mask for length */
-
-/*
- * Statusvalues for Commands/RFD
- */
-#define STAT_COMPL 0x8000 /* status: frame/command is complete */
-#define STAT_BUSY 0x4000 /* status: frame/command is busy */
-#define STAT_OK 0x2000 /* status: frame/command is ok */
-
-/*
- * Action-Commands
- */
-#define CMD_NOP 0x0000 /* NOP */
-#define CMD_IASETUP 0x0001 /* initial address setup command */
-#define CMD_CONFIGURE 0x0002 /* configure command */
-#define CMD_MCSETUP 0x0003 /* MC setup command */
-#define CMD_XMIT 0x0004 /* transmit command */
-#define CMD_TDR 0x0005 /* time domain reflectometer (TDR) command */
-#define CMD_DUMP 0x0006 /* dump command */
-#define CMD_DIAGNOSE 0x0007 /* diagnose command */
-
-/*
- * Action command bits
- */
-#define CMD_LAST 0x8000 /* indicates last command in the CBL */
-#define CMD_SUSPEND 0x4000 /* suspend CU after this CB */
-#define CMD_INT 0x2000 /* generate interrupt after execution */
-
-/*
- * NOP - command
- */
-struct nop_cmd_struct
-{
- unsigned short cmd_status; /* status of this command */
- unsigned short cmd_cmd; /* the command itself (+bits) */
- unsigned short cmd_link; /* offsetpointer to next command */
-};
-
-/*
- * IA Setup command
- */
-struct iasetup_cmd_struct
-{
- unsigned short cmd_status;
- unsigned short cmd_cmd;
- unsigned short cmd_link;
- unsigned char iaddr[6];
-};
-
-/*
- * Configure command
- */
-struct configure_cmd_struct
-{
- unsigned short cmd_status;
- unsigned short cmd_cmd;
- unsigned short cmd_link;
- unsigned char byte_cnt; /* size of the config-cmd */
- unsigned char fifo; /* fifo/recv monitor */
- unsigned char sav_bf; /* save bad frames (bit7=1)*/
- unsigned char adr_len; /* adr_len(0-2),al_loc(3),pream(4-5),loopbak(6-7)*/
- unsigned char priority; /* lin_prio(0-2),exp_prio(4-6),bof_metd(7) */
- unsigned char ifs; /* inter frame spacing */
- unsigned char time_low; /* slot time low */
- unsigned char time_high; /* slot time high(0-2) and max. retries(4-7) */
- unsigned char promisc; /* promisc-mode(0) , et al (1-7) */
- unsigned char carr_coll; /* carrier(0-3)/collision(4-7) stuff */
- unsigned char fram_len; /* minimal frame len */
- unsigned char dummy; /* dummy */
-};
-
-/*
- * Multicast Setup command
- */
-struct mcsetup_cmd_struct
-{
- unsigned short cmd_status;
- unsigned short cmd_cmd;
- unsigned short cmd_link;
- unsigned short mc_cnt; /* number of bytes in the MC-List */
- unsigned char mc_list[0][6]; /* pointer to 6 bytes entries */
-};
-
-/*
- * transmit command
- */
-struct transmit_cmd_struct
-{
- unsigned short cmd_status;
- unsigned short cmd_cmd;
- unsigned short cmd_link;
- unsigned short tbd_offset; /* pointeroffset to TBD */
- unsigned char dest[6]; /* destination address of the frame */
- unsigned short length; /* user defined: 802.3 length / Ether type */
-};
-
-#define TCMD_ERRMASK 0x0fa0
-#define TCMD_MAXCOLLMASK 0x000f
-#define TCMD_MAXCOLL 0x0020
-#define TCMD_HEARTBEAT 0x0040
-#define TCMD_DEFERRED 0x0080
-#define TCMD_UNDERRUN 0x0100
-#define TCMD_LOSTCTS 0x0200
-#define TCMD_NOCARRIER 0x0400
-#define TCMD_LATECOLL 0x0800
-
-struct tdr_cmd_struct
-{
- unsigned short cmd_status;
- unsigned short cmd_cmd;
- unsigned short cmd_link;
- unsigned short status;
-};
-
-#define TDR_LNK_OK 0x8000 /* No link problem identified */
-#define TDR_XCVR_PRB 0x4000 /* indicates a transceiver problem */
-#define TDR_ET_OPN 0x2000 /* open, no correct termination */
-#define TDR_ET_SRT 0x1000 /* TDR detected a short circuit */
-#define TDR_TIMEMASK 0x07ff /* mask for the time field */
-
-/*
- * Transmit Buffer Descriptor (TBD)
- */
-struct tbd_struct
-{
- unsigned short size; /* size + EOF-Flag(15) */
- unsigned short next; /* pointeroffset to next TBD */
- char *buffer; /* pointer to buffer */
-};
-
-#define TBD_LAST 0x8000 /* EOF-Flag, indicates last buffer in list */
-
-/*************************************************************************/
-/*
-Verbatim from the Crynwyr stuff:
-
- The 3c523 responds with adapter code 0x6042 at slot
-registers xxx0 and xxx1. The setup register is at xxx2 and
-contains the following bits:
-
-0: card enable
-2,1: csr address select
- 00 = 0300
- 01 = 1300
- 10 = 2300
- 11 = 3300
-4,3: shared memory address select
- 00 = 0c0000
- 01 = 0c8000
- 10 = 0d0000
- 11 = 0d8000
-5: set to disable on-board thinnet
-7,6: (read-only) shows selected irq
- 00 = 12
- 01 = 7
- 10 = 3
- 11 = 9
-
-The interrupt-select register is at xxx3 and uses one bit per irq.
-
-0: int 12
-1: int 7
-2: int 3
-3: int 9
-
- Again, the documentation stresses that the setup register
-should never be written. The interrupt-select register may be
-written with the value corresponding to bits 7.6 in
-the setup register to insure corret setup.
-*/
-
-/* Offsets from the base I/O address. */
-#define ELMC_SA 0 /* first 6 bytes are IEEE network address */
-#define ELMC_CTRL 6 /* control & status register */
-#define ELMC_REVISION 7 /* revision register, first 4 bits only */
-#define ELMC_IO_EXTENT 8
-
-/* these are the bit selects for the port register 2 */
-#define ELMC_STATUS_ENABLED 0x01
-#define ELMC_STATUS_CSR_SELECT 0x06
-#define ELMC_STATUS_MEMORY_SELECT 0x18
-#define ELMC_STATUS_DISABLE_THIN 0x20
-#define ELMC_STATUS_IRQ_SELECT 0xc0
-
-/* this is the card id used in the detection code. You might recognize
-it from @6042.adf */
-#define ELMC_MCA_ID 0x6042
-
-/*
- The following define the bits for the control & status register
-
- The bank select registers can be used if more than 16K of memory is
- on the card. For some stupid reason, bank 3 is the one for the
- bottom 16K, and the card defaults to bank 0. So we have to set the
- bank to 3 before the card will even think of operating. To get bank
- 3, set BS0 and BS1 to high (of course...)
-*/
-#define ELMC_CTRL_BS0 0x01 /* RW bank select */
-#define ELMC_CTRL_BS1 0x02 /* RW bank select */
-#define ELMC_CTRL_INTE 0x04 /* RW interrupt enable, assert high */
-#define ELMC_CTRL_INT 0x08 /* R interrupt active, assert high */
-/*#define ELMC_CTRL_* 0x10*/ /* reserved */
-#define ELMC_CTRL_LBK 0x20 /* RW loopback enable, assert high */
-#define ELMC_CTRL_CA 0x40 /* RW channel attention, assert high */
-#define ELMC_CTRL_RST 0x80 /* RW 82586 reset, assert low */
-
-/* some handy compound bits */
-
-/* normal operation should have bank 3 and RST high, ints enabled */
-#define ELMC_NORMAL (ELMC_CTRL_INTE|ELMC_CTRL_RST|0x3)
-
-#endif /* _3c523_INCLUDE_ */
diff --git a/drivers/net/ethernet/i825xx/3c527.c b/drivers/net/ethernet/i825xx/3c527.c
deleted file mode 100644
index 278e791afe00..000000000000
--- a/drivers/net/ethernet/i825xx/3c527.c
+++ /dev/null
@@ -1,1660 +0,0 @@
-/* 3c527.c: 3Com Etherlink/MC32 driver for Linux 2.4 and 2.6.
- *
- * (c) Copyright 1998 Red Hat Software Inc
- * Written by Alan Cox.
- * Further debugging by Carl Drougge.
- * Initial SMP support by Felipe W Damasio <felipewd@terra.com.br>
- * Heavily modified by Richard Procter <rnp@paradise.net.nz>
- *
- * Based on skeleton.c written 1993-94 by Donald Becker and ne2.c
- * (for the MCA stuff) written by Wim Dumon.
- *
- * Thanks to 3Com for making this possible by providing me with the
- * documentation.
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#define DRV_NAME "3c527"
-#define DRV_VERSION "0.7-SMP"
-#define DRV_RELDATE "2003/09/21"
-
-static const char *version =
-DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Procter <rnp@paradise.net.nz>\n";
-
-/**
- * DOC: Traps for the unwary
- *
- * The diagram (Figure 1-1) and the POS summary disagree with the
- * "Interrupt Level" section in the manual.
- *
- * The manual contradicts itself when describing the minimum number
- * buffers in the 'configure lists' command.
- * My card accepts a buffer config of 4/4.
- *
- * Setting the SAV BP bit does not save bad packets, but
- * only enables RX on-card stats collection.
- *
- * The documentation in places seems to miss things. In actual fact
- * I've always eventually found everything is documented, it just
- * requires careful study.
- *
- * DOC: Theory Of Operation
- *
- * The 3com 3c527 is a 32bit MCA bus mastering adapter with a large
- * amount of on board intelligence that housekeeps a somewhat dumber
- * Intel NIC. For performance we want to keep the transmit queue deep
- * as the card can transmit packets while fetching others from main
- * memory by bus master DMA. Transmission and reception are driven by
- * circular buffer queues.
- *
- * The mailboxes can be used for controlling how the card traverses
- * its buffer rings, but are used only for initial setup in this
- * implementation. The exec mailbox allows a variety of commands to
- * be executed. Each command must complete before the next is
- * executed. Primarily we use the exec mailbox for controlling the
- * multicast lists. We have to do a certain amount of interesting
- * hoop jumping as the multicast list changes can occur in interrupt
- * state when the card has an exec command pending. We defer such
- * events until the command completion interrupt.
- *
- * A copy break scheme (taken from 3c59x.c) is employed whereby
- * received frames exceeding a configurable length are passed
- * directly to the higher networking layers without incuring a copy,
- * in what amounts to a time/space trade-off.
- *
- * The card also keeps a large amount of statistical information
- * on-board. In a perfect world, these could be used safely at no
- * cost. However, lacking information to the contrary, processing
- * them without races would involve so much extra complexity as to
- * make it unworthwhile to do so. In the end, a hybrid SW/HW
- * implementation was made necessary --- see mc32_update_stats().
- *
- * DOC: Notes
- *
- * It should be possible to use two or more cards, but at this stage
- * only by loading two copies of the same module.
- *
- * The on-board 82586 NIC has trouble receiving multiple
- * back-to-back frames and so is likely to drop packets from fast
- * senders.
-**/
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_ether.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/mca-legacy.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/wait.h>
-#include <linux/ethtool.h>
-#include <linux/completion.h>
-#include <linux/bitops.h>
-#include <linux/semaphore.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include "3c527.h"
-
-MODULE_LICENSE("GPL");
-
-/*
- * The name of the card. Is used for messages and in the requests for
- * io regions, irqs and dma channels
- */
-static const char* cardname = DRV_NAME;
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 2
-#endif
-
-static unsigned int mc32_debug = NET_DEBUG;
-
-/* The number of low I/O ports used by the ethercard. */
-#define MC32_IO_EXTENT 8
-
-/* As implemented, values must be a power-of-2 -- 4/8/16/32 */
-#define TX_RING_LEN 32 /* Typically the card supports 37 */
-#define RX_RING_LEN 8 /* " " " */
-
-/* Copy break point, see above for details.
- * Setting to > 1512 effectively disables this feature. */
-#define RX_COPYBREAK 200 /* Value from 3c59x.c */
-
-/* Issue the 82586 workaround command - this is for "busy lans", but
- * basically means for all lans now days - has a performance (latency)
- * cost, but best set. */
-static const int WORKAROUND_82586=1;
-
-/* Pointers to buffers and their on-card records */
-struct mc32_ring_desc
-{
- volatile struct skb_header *p;
- struct sk_buff *skb;
-};
-
-/* Information that needs to be kept for each board. */
-struct mc32_local
-{
- int slot;
-
- u32 base;
- volatile struct mc32_mailbox *rx_box;
- volatile struct mc32_mailbox *tx_box;
- volatile struct mc32_mailbox *exec_box;
- volatile struct mc32_stats *stats; /* Start of on-card statistics */
- u16 tx_chain; /* Transmit list start offset */
- u16 rx_chain; /* Receive list start offset */
- u16 tx_len; /* Transmit list count */
- u16 rx_len; /* Receive list count */
-
- u16 xceiver_desired_state; /* HALTED or RUNNING */
- u16 cmd_nonblocking; /* Thread is uninterested in command result */
- u16 mc_reload_wait; /* A multicast load request is pending */
- u32 mc_list_valid; /* True when the mclist is set */
-
- struct mc32_ring_desc tx_ring[TX_RING_LEN]; /* Host Transmit ring */
- struct mc32_ring_desc rx_ring[RX_RING_LEN]; /* Host Receive ring */
-
- atomic_t tx_count; /* buffers left */
- atomic_t tx_ring_head; /* index to tx en-queue end */
- u16 tx_ring_tail; /* index to tx de-queue end */
-
- u16 rx_ring_tail; /* index to rx de-queue end */
-
- struct semaphore cmd_mutex; /* Serialises issuing of execute commands */
- struct completion execution_cmd; /* Card has completed an execute command */
- struct completion xceiver_cmd; /* Card has completed a tx or rx command */
-};
-
-/* The station (ethernet) address prefix, used for a sanity check. */
-#define SA_ADDR0 0x02
-#define SA_ADDR1 0x60
-#define SA_ADDR2 0xAC
-
-struct mca_adapters_t {
- unsigned int id;
- char *name;
-};
-
-static const struct mca_adapters_t mc32_adapters[] = {
- { 0x0041, "3COM EtherLink MC/32" },
- { 0x8EF5, "IBM High Performance Lan Adapter" },
- { 0x0000, NULL }
-};
-
-
-/* Macros for ring index manipulations */
-static inline u16 next_rx(u16 rx) { return (rx+1)&(RX_RING_LEN-1); };
-static inline u16 prev_rx(u16 rx) { return (rx-1)&(RX_RING_LEN-1); };
-
-static inline u16 next_tx(u16 tx) { return (tx+1)&(TX_RING_LEN-1); };
-
-
-/* Index to functions, as function prototypes. */
-static int mc32_probe1(struct net_device *dev, int ioaddr);
-static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len);
-static int mc32_open(struct net_device *dev);
-static void mc32_timeout(struct net_device *dev);
-static netdev_tx_t mc32_send_packet(struct sk_buff *skb,
- struct net_device *dev);
-static irqreturn_t mc32_interrupt(int irq, void *dev_id);
-static int mc32_close(struct net_device *dev);
-static struct net_device_stats *mc32_get_stats(struct net_device *dev);
-static void mc32_set_multicast_list(struct net_device *dev);
-static void mc32_reset_multicast_list(struct net_device *dev);
-static const struct ethtool_ops netdev_ethtool_ops;
-
-static void cleanup_card(struct net_device *dev)
-{
- struct mc32_local *lp = netdev_priv(dev);
- unsigned slot = lp->slot;
- mca_mark_as_unused(slot);
- mca_set_adapter_name(slot, NULL);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, MC32_IO_EXTENT);
-}
-
-/**
- * mc32_probe - Search for supported boards
- * @unit: interface number to use
- *
- * Because MCA bus is a real bus and we can scan for cards we could do a
- * single scan for all boards here. Right now we use the passed in device
- * structure and scan for only one board. This needs fixing for modules
- * in particular.
- */
-
-struct net_device *__init mc32_probe(int unit)
-{
- struct net_device *dev = alloc_etherdev(sizeof(struct mc32_local));
- static int current_mca_slot = -1;
- int i;
- int err;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- if (unit >= 0)
- sprintf(dev->name, "eth%d", unit);
-
- /* Do not check any supplied i/o locations.
- POS registers usually don't fail :) */
-
- /* MCA cards have POS registers.
- Autodetecting MCA cards is extremely simple.
- Just search for the card. */
-
- for(i = 0; (mc32_adapters[i].name != NULL); i++) {
- current_mca_slot =
- mca_find_unused_adapter(mc32_adapters[i].id, 0);
-
- if(current_mca_slot != MCA_NOTFOUND) {
- if(!mc32_probe1(dev, current_mca_slot))
- {
- mca_set_adapter_name(current_mca_slot,
- mc32_adapters[i].name);
- mca_mark_as_used(current_mca_slot);
- err = register_netdev(dev);
- if (err) {
- cleanup_card(dev);
- free_netdev(dev);
- dev = ERR_PTR(err);
- }
- return dev;
- }
-
- }
- }
- free_netdev(dev);
- return ERR_PTR(-ENODEV);
-}
-
-static const struct net_device_ops netdev_ops = {
- .ndo_open = mc32_open,
- .ndo_stop = mc32_close,
- .ndo_start_xmit = mc32_send_packet,
- .ndo_get_stats = mc32_get_stats,
- .ndo_set_rx_mode = mc32_set_multicast_list,
- .ndo_tx_timeout = mc32_timeout,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
-};
-
-/**
- * mc32_probe1 - Check a given slot for a board and test the card
- * @dev: Device structure to fill in
- * @slot: The MCA bus slot being used by this card
- *
- * Decode the slot data and configure the card structures. Having done this we
- * can reset the card and configure it. The card does a full self test cycle
- * in firmware so we have to wait for it to return and post us either a
- * failure case or some addresses we use to find the board internals.
- */
-
-static int __init mc32_probe1(struct net_device *dev, int slot)
-{
- static unsigned version_printed;
- int i, err;
- u8 POS;
- u32 base;
- struct mc32_local *lp = netdev_priv(dev);
- static const u16 mca_io_bases[] = {
- 0x7280,0x7290,
- 0x7680,0x7690,
- 0x7A80,0x7A90,
- 0x7E80,0x7E90
- };
- static const u32 mca_mem_bases[] = {
- 0x00C0000,
- 0x00C4000,
- 0x00C8000,
- 0x00CC000,
- 0x00D0000,
- 0x00D4000,
- 0x00D8000,
- 0x00DC000
- };
- static const char * const failures[] = {
- "Processor instruction",
- "Processor data bus",
- "Processor data bus",
- "Processor data bus",
- "Adapter bus",
- "ROM checksum",
- "Base RAM",
- "Extended RAM",
- "82586 internal loopback",
- "82586 initialisation failure",
- "Adapter list configuration error"
- };
-
- /* Time to play MCA games */
-
- if (mc32_debug && version_printed++ == 0)
- pr_debug("%s", version);
-
- pr_info("%s: %s found in slot %d: ", dev->name, cardname, slot);
-
- POS = mca_read_stored_pos(slot, 2);
-
- if(!(POS&1))
- {
- pr_cont("disabled.\n");
- return -ENODEV;
- }
-
- /* Fill in the 'dev' fields. */
- dev->base_addr = mca_io_bases[(POS>>1)&7];
- dev->mem_start = mca_mem_bases[(POS>>4)&7];
-
- POS = mca_read_stored_pos(slot, 4);
- if(!(POS&1))
- {
- pr_cont("memory window disabled.\n");
- return -ENODEV;
- }
-
- POS = mca_read_stored_pos(slot, 5);
-
- i=(POS>>4)&3;
- if(i==3)
- {
- pr_cont("invalid memory window.\n");
- return -ENODEV;
- }
-
- i*=16384;
- i+=16384;
-
- dev->mem_end=dev->mem_start + i;
-
- dev->irq = ((POS>>2)&3)+9;
-
- if(!request_region(dev->base_addr, MC32_IO_EXTENT, cardname))
- {
- pr_cont("io 0x%3lX, which is busy.\n", dev->base_addr);
- return -EBUSY;
- }
-
- pr_cont("io 0x%3lX irq %d mem 0x%lX (%dK)\n",
- dev->base_addr, dev->irq, dev->mem_start, i/1024);
-
-
- /* We ought to set the cache line size here.. */
-
-
- /*
- * Go PROM browsing
- */
-
- /* Retrieve and print the ethernet address. */
- for (i = 0; i < 6; i++)
- {
- mca_write_pos(slot, 6, i+12);
- mca_write_pos(slot, 7, 0);
-
- dev->dev_addr[i] = mca_read_pos(slot,3);
- }
-
- pr_info("%s: Address %pM ", dev->name, dev->dev_addr);
-
- mca_write_pos(slot, 6, 0);
- mca_write_pos(slot, 7, 0);
-
- POS = mca_read_stored_pos(slot, 4);
-
- if(POS&2)
- pr_cont(": BNC port selected.\n");
- else
- pr_cont(": AUI port selected.\n");
-
- POS=inb(dev->base_addr+HOST_CTRL);
- POS|=HOST_CTRL_ATTN|HOST_CTRL_RESET;
- POS&=~HOST_CTRL_INTE;
- outb(POS, dev->base_addr+HOST_CTRL);
- /* Reset adapter */
- udelay(100);
- /* Reset off */
- POS&=~(HOST_CTRL_ATTN|HOST_CTRL_RESET);
- outb(POS, dev->base_addr+HOST_CTRL);
-
- udelay(300);
-
- /*
- * Grab the IRQ
- */
-
- err = request_irq(dev->irq, mc32_interrupt, IRQF_SHARED, DRV_NAME, dev);
- if (err) {
- release_region(dev->base_addr, MC32_IO_EXTENT);
- pr_err("%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq);
- goto err_exit_ports;
- }
-
- memset(lp, 0, sizeof(struct mc32_local));
- lp->slot = slot;
-
- i=0;
-
- base = inb(dev->base_addr);
-
- while(base == 0xFF)
- {
- i++;
- if(i == 1000)
- {
- pr_err("%s: failed to boot adapter.\n", dev->name);
- err = -ENODEV;
- goto err_exit_irq;
- }
- udelay(1000);
- if(inb(dev->base_addr+2)&(1<<5))
- base = inb(dev->base_addr);
- }
-
- if(base>0)
- {
- if(base < 0x0C)
- pr_err("%s: %s%s.\n", dev->name, failures[base-1],
- base<0x0A?" test failure":"");
- else
- pr_err("%s: unknown failure %d.\n", dev->name, base);
- err = -ENODEV;
- goto err_exit_irq;
- }
-
- base=0;
- for(i=0;i<4;i++)
- {
- int n=0;
-
- while(!(inb(dev->base_addr+2)&(1<<5)))
- {
- n++;
- udelay(50);
- if(n>100)
- {
- pr_err("%s: mailbox read fail (%d).\n", dev->name, i);
- err = -ENODEV;
- goto err_exit_irq;
- }
- }
-
- base|=(inb(dev->base_addr)<<(8*i));
- }
-
- lp->exec_box=isa_bus_to_virt(dev->mem_start+base);
-
- base=lp->exec_box->data[1]<<16|lp->exec_box->data[0];
-
- lp->base = dev->mem_start+base;
-
- lp->rx_box=isa_bus_to_virt(lp->base + lp->exec_box->data[2]);
- lp->tx_box=isa_bus_to_virt(lp->base + lp->exec_box->data[3]);
-
- lp->stats = isa_bus_to_virt(lp->base + lp->exec_box->data[5]);
-
- /*
- * Descriptor chains (card relative)
- */
-
- lp->tx_chain = lp->exec_box->data[8]; /* Transmit list start offset */
- lp->rx_chain = lp->exec_box->data[10]; /* Receive list start offset */
- lp->tx_len = lp->exec_box->data[9]; /* Transmit list count */
- lp->rx_len = lp->exec_box->data[11]; /* Receive list count */
-
- sema_init(&lp->cmd_mutex, 0);
- init_completion(&lp->execution_cmd);
- init_completion(&lp->xceiver_cmd);
-
- pr_info("%s: Firmware Rev %d. %d RX buffers, %d TX buffers. Base of 0x%08X.\n",
- dev->name, lp->exec_box->data[12], lp->rx_len, lp->tx_len, lp->base);
-
- dev->netdev_ops = &netdev_ops;
- dev->watchdog_timeo = HZ*5; /* Board does all the work */
- dev->ethtool_ops = &netdev_ethtool_ops;
-
- return 0;
-
-err_exit_irq:
- free_irq(dev->irq, dev);
-err_exit_ports:
- release_region(dev->base_addr, MC32_IO_EXTENT);
- return err;
-}
-
-
-/**
- * mc32_ready_poll - wait until we can feed it a command
- * @dev: The device to wait for
- *
- * Wait until the card becomes ready to accept a command via the
- * command register. This tells us nothing about the completion
- * status of any pending commands and takes very little time at all.
- */
-
-static inline void mc32_ready_poll(struct net_device *dev)
-{
- int ioaddr = dev->base_addr;
- while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
-}
-
-
-/**
- * mc32_command_nowait - send a command non blocking
- * @dev: The 3c527 to issue the command to
- * @cmd: The command word to write to the mailbox
- * @data: A data block if the command expects one
- * @len: Length of the data block
- *
- * Send a command from interrupt state. If there is a command
- * currently being executed then we return an error of -1. It
- * simply isn't viable to wait around as commands may be
- * slow. This can theoretically be starved on SMP, but it's hard
- * to see a realistic situation. We do not wait for the command
- * to complete --- we rely on the interrupt handler to tidy up
- * after us.
- */
-
-static int mc32_command_nowait(struct net_device *dev, u16 cmd, void *data, int len)
-{
- struct mc32_local *lp = netdev_priv(dev);
- int ioaddr = dev->base_addr;
- int ret = -1;
-
- if (down_trylock(&lp->cmd_mutex) == 0)
- {
- lp->cmd_nonblocking=1;
- lp->exec_box->mbox=0;
- lp->exec_box->mbox=cmd;
- memcpy((void *)lp->exec_box->data, data, len);
- barrier(); /* the memcpy forgot the volatile so be sure */
-
- /* Send the command */
- mc32_ready_poll(dev);
- outb(1<<6, ioaddr+HOST_CMD);
-
- ret = 0;
-
- /* Interrupt handler will signal mutex on completion */
- }
-
- return ret;
-}
-
-
-/**
- * mc32_command - send a command and sleep until completion
- * @dev: The 3c527 card to issue the command to
- * @cmd: The command word to write to the mailbox
- * @data: A data block if the command expects one
- * @len: Length of the data block
- *
- * Sends exec commands in a user context. This permits us to wait around
- * for the replies and also to wait for the command buffer to complete
- * from a previous command before we execute our command. After our
- * command completes we will attempt any pending multicast reload
- * we blocked off by hogging the exec buffer.
- *
- * You feed the card a command, you wait, it interrupts you get a
- * reply. All well and good. The complication arises because you use
- * commands for filter list changes which come in at bh level from things
- * like IPV6 group stuff.
- */
-
-static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len)
-{
- struct mc32_local *lp = netdev_priv(dev);
- int ioaddr = dev->base_addr;
- int ret = 0;
-
- down(&lp->cmd_mutex);
-
- /*
- * My Turn
- */
-
- lp->cmd_nonblocking=0;
- lp->exec_box->mbox=0;
- lp->exec_box->mbox=cmd;
- memcpy((void *)lp->exec_box->data, data, len);
- barrier(); /* the memcpy forgot the volatile so be sure */
-
- mc32_ready_poll(dev);
- outb(1<<6, ioaddr+HOST_CMD);
-
- wait_for_completion(&lp->execution_cmd);
-
- if(lp->exec_box->mbox&(1<<13))
- ret = -1;
-
- up(&lp->cmd_mutex);
-
- /*
- * A multicast set got blocked - try it now
- */
-
- if(lp->mc_reload_wait)
- {
- mc32_reset_multicast_list(dev);
- }
-
- return ret;
-}
-
-
-/**
- * mc32_start_transceiver - tell board to restart tx/rx
- * @dev: The 3c527 card to issue the command to
- *
- * This may be called from the interrupt state, where it is used
- * to restart the rx ring if the card runs out of rx buffers.
- *
- * We must first check if it's ok to (re)start the transceiver. See
- * mc32_close for details.
- */
-
-static void mc32_start_transceiver(struct net_device *dev) {
-
- struct mc32_local *lp = netdev_priv(dev);
- int ioaddr = dev->base_addr;
-
- /* Ignore RX overflow on device closure */
- if (lp->xceiver_desired_state==HALTED)
- return;
-
- /* Give the card the offset to the post-EOL-bit RX descriptor */
- mc32_ready_poll(dev);
- lp->rx_box->mbox=0;
- lp->rx_box->data[0]=lp->rx_ring[prev_rx(lp->rx_ring_tail)].p->next;
- outb(HOST_CMD_START_RX, ioaddr+HOST_CMD);
-
- mc32_ready_poll(dev);
- lp->tx_box->mbox=0;
- outb(HOST_CMD_RESTRT_TX, ioaddr+HOST_CMD); /* card ignores this on RX restart */
-
- /* We are not interrupted on start completion */
-}
-
-
-/**
- * mc32_halt_transceiver - tell board to stop tx/rx
- * @dev: The 3c527 card to issue the command to
- *
- * We issue the commands to halt the card's transceiver. In fact,
- * after some experimenting we now simply tell the card to
- * suspend. When issuing aborts occasionally odd things happened.
- *
- * We then sleep until the card has notified us that both rx and
- * tx have been suspended.
- */
-
-static void mc32_halt_transceiver(struct net_device *dev)
-{
- struct mc32_local *lp = netdev_priv(dev);
- int ioaddr = dev->base_addr;
-
- mc32_ready_poll(dev);
- lp->rx_box->mbox=0;
- outb(HOST_CMD_SUSPND_RX, ioaddr+HOST_CMD);
- wait_for_completion(&lp->xceiver_cmd);
-
- mc32_ready_poll(dev);
- lp->tx_box->mbox=0;
- outb(HOST_CMD_SUSPND_TX, ioaddr+HOST_CMD);
- wait_for_completion(&lp->xceiver_cmd);
-}
-
-
-/**
- * mc32_load_rx_ring - load the ring of receive buffers
- * @dev: 3c527 to build the ring for
- *
- * This initialises the on-card and driver datastructures to
- * the point where mc32_start_transceiver() can be called.
- *
- * The card sets up the receive ring for us. We are required to use the
- * ring it provides, although the size of the ring is configurable.
- *
- * We allocate an sk_buff for each ring entry in turn and
- * initialise its house-keeping info. At the same time, we read
- * each 'next' pointer in our rx_ring array. This reduces slow
- * shared-memory reads and makes it easy to access predecessor
- * descriptors.
- *
- * We then set the end-of-list bit for the last entry so that the
- * card will know when it has run out of buffers.
- */
-
-static int mc32_load_rx_ring(struct net_device *dev)
-{
- struct mc32_local *lp = netdev_priv(dev);
- int i;
- u16 rx_base;
- volatile struct skb_header *p;
-
- rx_base=lp->rx_chain;
-
- for(i=0; i<RX_RING_LEN; i++) {
- lp->rx_ring[i].skb=alloc_skb(1532, GFP_KERNEL);
- if (lp->rx_ring[i].skb==NULL) {
- for (;i>=0;i--)
- kfree_skb(lp->rx_ring[i].skb);
- return -ENOBUFS;
- }
- skb_reserve(lp->rx_ring[i].skb, 18);
-
- p=isa_bus_to_virt(lp->base+rx_base);
-
- p->control=0;
- p->data=isa_virt_to_bus(lp->rx_ring[i].skb->data);
- p->status=0;
- p->length=1532;
-
- lp->rx_ring[i].p=p;
- rx_base=p->next;
- }
-
- lp->rx_ring[i-1].p->control |= CONTROL_EOL;
-
- lp->rx_ring_tail=0;
-
- return 0;
-}
-
-
-/**
- * mc32_flush_rx_ring - free the ring of receive buffers
- * @lp: Local data of 3c527 to flush the rx ring of
- *
- * Free the buffer for each ring slot. This may be called
- * before mc32_load_rx_ring(), eg. on error in mc32_open().
- * Requires rx skb pointers to point to a valid skb, or NULL.
- */
-
-static void mc32_flush_rx_ring(struct net_device *dev)
-{
- struct mc32_local *lp = netdev_priv(dev);
- int i;
-
- for(i=0; i < RX_RING_LEN; i++)
- {
- if (lp->rx_ring[i].skb) {
- dev_kfree_skb(lp->rx_ring[i].skb);
- lp->rx_ring[i].skb = NULL;
- }
- lp->rx_ring[i].p=NULL;
- }
-}
-
-
-/**
- * mc32_load_tx_ring - load transmit ring
- * @dev: The 3c527 card to issue the command to
- *
- * This sets up the host transmit data-structures.
- *
- * First, we obtain from the card it's current position in the tx
- * ring, so that we will know where to begin transmitting
- * packets.
- *
- * Then, we read the 'next' pointers from the on-card tx ring into
- * our tx_ring array to reduce slow shared-mem reads. Finally, we
- * intitalise the tx house keeping variables.
- *
- */
-
-static void mc32_load_tx_ring(struct net_device *dev)
-{
- struct mc32_local *lp = netdev_priv(dev);
- volatile struct skb_header *p;
- int i;
- u16 tx_base;
-
- tx_base=lp->tx_box->data[0];
-
- for(i=0 ; i<TX_RING_LEN ; i++)
- {
- p=isa_bus_to_virt(lp->base+tx_base);
- lp->tx_ring[i].p=p;
- lp->tx_ring[i].skb=NULL;
-
- tx_base=p->next;
- }
-
- /* -1 so that tx_ring_head cannot "lap" tx_ring_tail */
- /* see mc32_tx_ring */
-
- atomic_set(&lp->tx_count, TX_RING_LEN-1);
- atomic_set(&lp->tx_ring_head, 0);
- lp->tx_ring_tail=0;
-}
-
-
-/**
- * mc32_flush_tx_ring - free transmit ring
- * @lp: Local data of 3c527 to flush the tx ring of
- *
- * If the ring is non-empty, zip over the it, freeing any
- * allocated skb_buffs. The tx ring house-keeping variables are
- * then reset. Requires rx skb pointers to point to a valid skb,
- * or NULL.
- */
-
-static void mc32_flush_tx_ring(struct net_device *dev)
-{
- struct mc32_local *lp = netdev_priv(dev);
- int i;
-
- for (i=0; i < TX_RING_LEN; i++)
- {
- if (lp->tx_ring[i].skb)
- {
- dev_kfree_skb(lp->tx_ring[i].skb);
- lp->tx_ring[i].skb = NULL;
- }
- }
-
- atomic_set(&lp->tx_count, 0);
- atomic_set(&lp->tx_ring_head, 0);
- lp->tx_ring_tail=0;
-}
-
-
-/**
- * mc32_open - handle 'up' of card
- * @dev: device to open
- *
- * The user is trying to bring the card into ready state. This requires
- * a brief dialogue with the card. Firstly we enable interrupts and then
- * 'indications'. Without these enabled the card doesn't bother telling
- * us what it has done. This had me puzzled for a week.
- *
- * We configure the number of card descriptors, then load the network
- * address and multicast filters. Turn on the workaround mode. This
- * works around a bug in the 82586 - it asks the firmware to do
- * so. It has a performance (latency) hit but is needed on busy
- * [read most] lans. We load the ring with buffers then we kick it
- * all off.
- */
-
-static int mc32_open(struct net_device *dev)
-{
- int ioaddr = dev->base_addr;
- struct mc32_local *lp = netdev_priv(dev);
- u8 one=1;
- u8 regs;
- u16 descnumbuffs[2] = {TX_RING_LEN, RX_RING_LEN};
-
- /*
- * Interrupts enabled
- */
-
- regs=inb(ioaddr+HOST_CTRL);
- regs|=HOST_CTRL_INTE;
- outb(regs, ioaddr+HOST_CTRL);
-
- /*
- * Allow ourselves to issue commands
- */
-
- up(&lp->cmd_mutex);
-
-
- /*
- * Send the indications on command
- */
-
- mc32_command(dev, 4, &one, 2);
-
- /*
- * Poke it to make sure it's really dead.
- */
-
- mc32_halt_transceiver(dev);
- mc32_flush_tx_ring(dev);
-
- /*
- * Ask card to set up on-card descriptors to our spec
- */
-
- if(mc32_command(dev, 8, descnumbuffs, 4)) {
- pr_info("%s: %s rejected our buffer configuration!\n",
- dev->name, cardname);
- mc32_close(dev);
- return -ENOBUFS;
- }
-
- /* Report new configuration */
- mc32_command(dev, 6, NULL, 0);
-
- lp->tx_chain = lp->exec_box->data[8]; /* Transmit list start offset */
- lp->rx_chain = lp->exec_box->data[10]; /* Receive list start offset */
- lp->tx_len = lp->exec_box->data[9]; /* Transmit list count */
- lp->rx_len = lp->exec_box->data[11]; /* Receive list count */
-
- /* Set Network Address */
- mc32_command(dev, 1, dev->dev_addr, 6);
-
- /* Set the filters */
- mc32_set_multicast_list(dev);
-
- if (WORKAROUND_82586) {
- u16 zero_word=0;
- mc32_command(dev, 0x0D, &zero_word, 2); /* 82586 bug workaround on */
- }
-
- mc32_load_tx_ring(dev);
-
- if(mc32_load_rx_ring(dev))
- {
- mc32_close(dev);
- return -ENOBUFS;
- }
-
- lp->xceiver_desired_state = RUNNING;
-
- /* And finally, set the ball rolling... */
- mc32_start_transceiver(dev);
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-
-/**
- * mc32_timeout - handle a timeout from the network layer
- * @dev: 3c527 that timed out
- *
- * Handle a timeout on transmit from the 3c527. This normally means
- * bad things as the hardware handles cable timeouts and mess for
- * us.
- *
- */
-
-static void mc32_timeout(struct net_device *dev)
-{
- pr_warning("%s: transmit timed out?\n", dev->name);
- /* Try to restart the adaptor. */
- netif_wake_queue(dev);
-}
-
-
-/**
- * mc32_send_packet - queue a frame for transmit
- * @skb: buffer to transmit
- * @dev: 3c527 to send it out of
- *
- * Transmit a buffer. This normally means throwing the buffer onto
- * the transmit queue as the queue is quite large. If the queue is
- * full then we set tx_busy and return. Once the interrupt handler
- * gets messages telling it to reclaim transmit queue entries, we will
- * clear tx_busy and the kernel will start calling this again.
- *
- * We do not disable interrupts or acquire any locks; this can
- * run concurrently with mc32_tx_ring(), and the function itself
- * is serialised at a higher layer. However, similarly for the
- * card itself, we must ensure that we update tx_ring_head only
- * after we've established a valid packet on the tx ring (and
- * before we let the card "see" it, to prevent it racing with the
- * irq handler).
- *
- */
-
-static netdev_tx_t mc32_send_packet(struct sk_buff *skb,
- struct net_device *dev)
-{
- struct mc32_local *lp = netdev_priv(dev);
- u32 head = atomic_read(&lp->tx_ring_head);
-
- volatile struct skb_header *p, *np;
-
- netif_stop_queue(dev);
-
- if(atomic_read(&lp->tx_count)==0) {
- return NETDEV_TX_BUSY;
- }
-
- if (skb_padto(skb, ETH_ZLEN)) {
- netif_wake_queue(dev);
- return NETDEV_TX_OK;
- }
-
- atomic_dec(&lp->tx_count);
-
- /* P is the last sending/sent buffer as a pointer */
- p=lp->tx_ring[head].p;
-
- head = next_tx(head);
-
- /* NP is the buffer we will be loading */
- np=lp->tx_ring[head].p;
-
- /* We will need this to flush the buffer out */
- lp->tx_ring[head].skb=skb;
-
- np->length = unlikely(skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
- np->data = isa_virt_to_bus(skb->data);
- np->status = 0;
- np->control = CONTROL_EOP | CONTROL_EOL;
- wmb();
-
- /*
- * The new frame has been setup; we can now
- * let the interrupt handler and card "see" it
- */
-
- atomic_set(&lp->tx_ring_head, head);
- p->control &= ~CONTROL_EOL;
-
- netif_wake_queue(dev);
- return NETDEV_TX_OK;
-}
-
-
-/**
- * mc32_update_stats - pull off the on board statistics
- * @dev: 3c527 to service
- *
- *
- * Query and reset the on-card stats. There's the small possibility
- * of a race here, which would result in an underestimation of
- * actual errors. As such, we'd prefer to keep all our stats
- * collection in software. As a rule, we do. However it can't be
- * used for rx errors and collisions as, by default, the card discards
- * bad rx packets.
- *
- * Setting the SAV BP in the rx filter command supposedly
- * stops this behaviour. However, testing shows that it only seems to
- * enable the collation of on-card rx statistics --- the driver
- * never sees an RX descriptor with an error status set.
- *
- */
-
-static void mc32_update_stats(struct net_device *dev)
-{
- struct mc32_local *lp = netdev_priv(dev);
- volatile struct mc32_stats *st = lp->stats;
-
- u32 rx_errors=0;
-
- rx_errors+=dev->stats.rx_crc_errors +=st->rx_crc_errors;
- st->rx_crc_errors=0;
- rx_errors+=dev->stats.rx_fifo_errors +=st->rx_overrun_errors;
- st->rx_overrun_errors=0;
- rx_errors+=dev->stats.rx_frame_errors +=st->rx_alignment_errors;
- st->rx_alignment_errors=0;
- rx_errors+=dev->stats.rx_length_errors+=st->rx_tooshort_errors;
- st->rx_tooshort_errors=0;
- rx_errors+=dev->stats.rx_missed_errors+=st->rx_outofresource_errors;
- st->rx_outofresource_errors=0;
- dev->stats.rx_errors=rx_errors;
-
- /* Number of packets which saw one collision */
- dev->stats.collisions+=st->dataC[10];
- st->dataC[10]=0;
-
- /* Number of packets which saw 2--15 collisions */
- dev->stats.collisions+=st->dataC[11];
- st->dataC[11]=0;
-}
-
-
-/**
- * mc32_rx_ring - process the receive ring
- * @dev: 3c527 that needs its receive ring processing
- *
- *
- * We have received one or more indications from the card that a
- * receive has completed. The buffer ring thus contains dirty
- * entries. We walk the ring by iterating over the circular rx_ring
- * array, starting at the next dirty buffer (which happens to be the
- * one we finished up at last time around).
- *
- * For each completed packet, we will either copy it and pass it up
- * the stack or, if the packet is near MTU sized, we allocate
- * another buffer and flip the old one up the stack.
- *
- * We must succeed in keeping a buffer on the ring. If necessary we
- * will toss a received packet rather than lose a ring entry. Once
- * the first uncompleted descriptor is found, we move the
- * End-Of-List bit to include the buffers just processed.
- *
- */
-
-static void mc32_rx_ring(struct net_device *dev)
-{
- struct mc32_local *lp = netdev_priv(dev);
- volatile struct skb_header *p;
- u16 rx_ring_tail;
- u16 rx_old_tail;
- int x=0;
-
- rx_old_tail = rx_ring_tail = lp->rx_ring_tail;
-
- do
- {
- p=lp->rx_ring[rx_ring_tail].p;
-
- if(!(p->status & (1<<7))) { /* Not COMPLETED */
- break;
- }
- if(p->status & (1<<6)) /* COMPLETED_OK */
- {
-
- u16 length=p->length;
- struct sk_buff *skb;
- struct sk_buff *newskb;
-
- /* Try to save time by avoiding a copy on big frames */
-
- if ((length > RX_COPYBREAK) &&
- ((newskb = netdev_alloc_skb(dev, 1532)) != NULL))
- {
- skb=lp->rx_ring[rx_ring_tail].skb;
- skb_put(skb, length);
-
- skb_reserve(newskb,18);
- lp->rx_ring[rx_ring_tail].skb=newskb;
- p->data=isa_virt_to_bus(newskb->data);
- }
- else
- {
- skb = netdev_alloc_skb(dev, length + 2);
-
- if(skb==NULL) {
- dev->stats.rx_dropped++;
- goto dropped;
- }
-
- skb_reserve(skb,2);
- memcpy(skb_put(skb, length),
- lp->rx_ring[rx_ring_tail].skb->data, length);
- }
-
- skb->protocol=eth_type_trans(skb,dev);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += length;
- netif_rx(skb);
- }
-
- dropped:
- p->length = 1532;
- p->status = 0;
-
- rx_ring_tail=next_rx(rx_ring_tail);
- }
- while(x++<48);
-
- /* If there was actually a frame to be processed, place the EOL bit */
- /* at the descriptor prior to the one to be filled next */
-
- if (rx_ring_tail != rx_old_tail)
- {
- lp->rx_ring[prev_rx(rx_ring_tail)].p->control |= CONTROL_EOL;
- lp->rx_ring[prev_rx(rx_old_tail)].p->control &= ~CONTROL_EOL;
-
- lp->rx_ring_tail=rx_ring_tail;
- }
-}
-
-
-/**
- * mc32_tx_ring - process completed transmits
- * @dev: 3c527 that needs its transmit ring processing
- *
- *
- * This operates in a similar fashion to mc32_rx_ring. We iterate
- * over the transmit ring. For each descriptor which has been
- * processed by the card, we free its associated buffer and note
- * any errors. This continues until the transmit ring is emptied
- * or we reach a descriptor that hasn't yet been processed by the
- * card.
- *
- */
-
-static void mc32_tx_ring(struct net_device *dev)
-{
- struct mc32_local *lp = netdev_priv(dev);
- volatile struct skb_header *np;
-
- /*
- * We rely on head==tail to mean 'queue empty'.
- * This is why lp->tx_count=TX_RING_LEN-1: in order to prevent
- * tx_ring_head wrapping to tail and confusing a 'queue empty'
- * condition with 'queue full'
- */
-
- while (lp->tx_ring_tail != atomic_read(&lp->tx_ring_head))
- {
- u16 t;
-
- t=next_tx(lp->tx_ring_tail);
- np=lp->tx_ring[t].p;
-
- if(!(np->status & (1<<7)))
- {
- /* Not COMPLETED */
- break;
- }
- dev->stats.tx_packets++;
- if(!(np->status & (1<<6))) /* Not COMPLETED_OK */
- {
- dev->stats.tx_errors++;
-
- switch(np->status&0x0F)
- {
- case 1:
- dev->stats.tx_aborted_errors++;
- break; /* Max collisions */
- case 2:
- dev->stats.tx_fifo_errors++;
- break;
- case 3:
- dev->stats.tx_carrier_errors++;
- break;
- case 4:
- dev->stats.tx_window_errors++;
- break; /* CTS Lost */
- case 5:
- dev->stats.tx_aborted_errors++;
- break; /* Transmit timeout */
- }
- }
- /* Packets are sent in order - this is
- basically a FIFO queue of buffers matching
- the card ring */
- dev->stats.tx_bytes+=lp->tx_ring[t].skb->len;
- dev_kfree_skb_irq(lp->tx_ring[t].skb);
- lp->tx_ring[t].skb=NULL;
- atomic_inc(&lp->tx_count);
- netif_wake_queue(dev);
-
- lp->tx_ring_tail=t;
- }
-
-}
-
-
-/**
- * mc32_interrupt - handle an interrupt from a 3c527
- * @irq: Interrupt number
- * @dev_id: 3c527 that requires servicing
- * @regs: Registers (unused)
- *
- *
- * An interrupt is raised whenever the 3c527 writes to the command
- * register. This register contains the message it wishes to send us
- * packed into a single byte field. We keep reading status entries
- * until we have processed all the control items, but simply count
- * transmit and receive reports. When all reports are in we empty the
- * transceiver rings as appropriate. This saves the overhead of
- * multiple command requests.
- *
- * Because MCA is level-triggered, we shouldn't miss indications.
- * Therefore, we needn't ask the card to suspend interrupts within
- * this handler. The card receives an implicit acknowledgment of the
- * current interrupt when we read the command register.
- *
- */
-
-static irqreturn_t mc32_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- struct mc32_local *lp;
- int ioaddr, status, boguscount = 0;
- int rx_event = 0;
- int tx_event = 0;
-
- ioaddr = dev->base_addr;
- lp = netdev_priv(dev);
-
- /* See whats cooking */
-
- while((inb(ioaddr+HOST_STATUS)&HOST_STATUS_CWR) && boguscount++<2000)
- {
- status=inb(ioaddr+HOST_CMD);
-
- pr_debug("Status TX%d RX%d EX%d OV%d BC%d\n",
- (status&7), (status>>3)&7, (status>>6)&1,
- (status>>7)&1, boguscount);
-
- switch(status&7)
- {
- case 0:
- break;
- case 6: /* TX fail */
- case 2: /* TX ok */
- tx_event = 1;
- break;
- case 3: /* Halt */
- case 4: /* Abort */
- complete(&lp->xceiver_cmd);
- break;
- default:
- pr_notice("%s: strange tx ack %d\n", dev->name, status&7);
- }
- status>>=3;
- switch(status&7)
- {
- case 0:
- break;
- case 2: /* RX */
- rx_event=1;
- break;
- case 3: /* Halt */
- case 4: /* Abort */
- complete(&lp->xceiver_cmd);
- break;
- case 6:
- /* Out of RX buffers stat */
- /* Must restart rx */
- dev->stats.rx_dropped++;
- mc32_rx_ring(dev);
- mc32_start_transceiver(dev);
- break;
- default:
- pr_notice("%s: strange rx ack %d\n",
- dev->name, status&7);
- }
- status>>=3;
- if(status&1)
- {
- /*
- * No thread is waiting: we need to tidy
- * up ourself.
- */
-
- if (lp->cmd_nonblocking) {
- up(&lp->cmd_mutex);
- if (lp->mc_reload_wait)
- mc32_reset_multicast_list(dev);
- }
- else complete(&lp->execution_cmd);
- }
- if(status&2)
- {
- /*
- * We get interrupted once per
- * counter that is about to overflow.
- */
-
- mc32_update_stats(dev);
- }
- }
-
-
- /*
- * Process the transmit and receive rings
- */
-
- if(tx_event)
- mc32_tx_ring(dev);
-
- if(rx_event)
- mc32_rx_ring(dev);
-
- return IRQ_HANDLED;
-}
-
-
-/**
- * mc32_close - user configuring the 3c527 down
- * @dev: 3c527 card to shut down
- *
- * The 3c527 is a bus mastering device. We must be careful how we
- * shut it down. It may also be running shared interrupt so we have
- * to be sure to silence it properly
- *
- * We indicate that the card is closing to the rest of the
- * driver. Otherwise, it is possible that the card may run out
- * of receive buffers and restart the transceiver while we're
- * trying to close it.
- *
- * We abort any receive and transmits going on and then wait until
- * any pending exec commands have completed in other code threads.
- * In theory we can't get here while that is true, in practice I am
- * paranoid
- *
- * We turn off the interrupt enable for the board to be sure it can't
- * intefere with other devices.
- */
-
-static int mc32_close(struct net_device *dev)
-{
- struct mc32_local *lp = netdev_priv(dev);
- int ioaddr = dev->base_addr;
-
- u8 regs;
- u16 one=1;
-
- lp->xceiver_desired_state = HALTED;
- netif_stop_queue(dev);
-
- /*
- * Send the indications on command (handy debug check)
- */
-
- mc32_command(dev, 4, &one, 2);
-
- /* Shut down the transceiver */
-
- mc32_halt_transceiver(dev);
-
- /* Ensure we issue no more commands beyond this point */
-
- down(&lp->cmd_mutex);
-
- /* Ok the card is now stopping */
-
- regs=inb(ioaddr+HOST_CTRL);
- regs&=~HOST_CTRL_INTE;
- outb(regs, ioaddr+HOST_CTRL);
-
- mc32_flush_rx_ring(dev);
- mc32_flush_tx_ring(dev);
-
- mc32_update_stats(dev);
-
- return 0;
-}
-
-
-/**
- * mc32_get_stats - hand back stats to network layer
- * @dev: The 3c527 card to handle
- *
- * We've collected all the stats we can in software already. Now
- * it's time to update those kept on-card and return the lot.
- *
- */
-
-static struct net_device_stats *mc32_get_stats(struct net_device *dev)
-{
- mc32_update_stats(dev);
- return &dev->stats;
-}
-
-
-/**
- * do_mc32_set_multicast_list - attempt to update multicasts
- * @dev: 3c527 device to load the list on
- * @retry: indicates this is not the first call.
- *
- *
- * Actually set or clear the multicast filter for this adaptor. The
- * locking issues are handled by this routine. We have to track
- * state as it may take multiple calls to get the command sequence
- * completed. We just keep trying to schedule the loads until we
- * manage to process them all.
- *
- * num_addrs == -1 Promiscuous mode, receive all packets
- *
- * num_addrs == 0 Normal mode, clear multicast list
- *
- * num_addrs > 0 Multicast mode, receive normal and MC packets,
- * and do best-effort filtering.
- *
- * See mc32_update_stats() regards setting the SAV BP bit.
- *
- */
-
-static void do_mc32_set_multicast_list(struct net_device *dev, int retry)
-{
- struct mc32_local *lp = netdev_priv(dev);
- u16 filt = (1<<2); /* Save Bad Packets, for stats purposes */
-
- if ((dev->flags&IFF_PROMISC) ||
- (dev->flags&IFF_ALLMULTI) ||
- netdev_mc_count(dev) > 10)
- /* Enable promiscuous mode */
- filt |= 1;
- else if (!netdev_mc_empty(dev))
- {
- unsigned char block[62];
- unsigned char *bp;
- struct netdev_hw_addr *ha;
-
- if(retry==0)
- lp->mc_list_valid = 0;
- if(!lp->mc_list_valid)
- {
- block[1]=0;
- block[0]=netdev_mc_count(dev);
- bp=block+2;
-
- netdev_for_each_mc_addr(ha, dev) {
- memcpy(bp, ha->addr, 6);
- bp+=6;
- }
- if(mc32_command_nowait(dev, 2, block,
- 2+6*netdev_mc_count(dev))==-1)
- {
- lp->mc_reload_wait = 1;
- return;
- }
- lp->mc_list_valid=1;
- }
- }
-
- if(mc32_command_nowait(dev, 0, &filt, 2)==-1)
- {
- lp->mc_reload_wait = 1;
- }
- else {
- lp->mc_reload_wait = 0;
- }
-}
-
-
-/**
- * mc32_set_multicast_list - queue multicast list update
- * @dev: The 3c527 to use
- *
- * Commence loading the multicast list. This is called when the kernel
- * changes the lists. It will override any pending list we are trying to
- * load.
- */
-
-static void mc32_set_multicast_list(struct net_device *dev)
-{
- do_mc32_set_multicast_list(dev,0);
-}
-
-
-/**
- * mc32_reset_multicast_list - reset multicast list
- * @dev: The 3c527 to use
- *
- * Attempt the next step in loading the multicast lists. If this attempt
- * fails to complete then it will be scheduled and this function called
- * again later from elsewhere.
- */
-
-static void mc32_reset_multicast_list(struct net_device *dev)
-{
- do_mc32_set_multicast_list(dev,1);
-}
-
-static void netdev_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strcpy(info->driver, DRV_NAME);
- strcpy(info->version, DRV_VERSION);
- sprintf(info->bus_info, "MCA 0x%lx", dev->base_addr);
-}
-
-static u32 netdev_get_msglevel(struct net_device *dev)
-{
- return mc32_debug;
-}
-
-static void netdev_set_msglevel(struct net_device *dev, u32 level)
-{
- mc32_debug = level;
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
- .get_drvinfo = netdev_get_drvinfo,
- .get_msglevel = netdev_get_msglevel,
- .set_msglevel = netdev_set_msglevel,
-};
-
-#ifdef MODULE
-
-static struct net_device *this_device;
-
-/**
- * init_module - entry point
- *
- * Probe and locate a 3c527 card. This really should probe and locate
- * all the 3c527 cards in the machine not just one of them. Yes you can
- * insmod multiple modules for now but it's a hack.
- */
-
-int __init init_module(void)
-{
- this_device = mc32_probe(-1);
- if (IS_ERR(this_device))
- return PTR_ERR(this_device);
- return 0;
-}
-
-/**
- * cleanup_module - free resources for an unload
- *
- * Unloading time. We release the MCA bus resources and the interrupt
- * at which point everything is ready to unload. The card must be stopped
- * at this point or we would not have been called. When we unload we
- * leave the card stopped but not totally shut down. When the card is
- * initialized it must be rebooted or the rings reloaded before any
- * transmit operations are allowed to start scribbling into memory.
- */
-
-void __exit cleanup_module(void)
-{
- unregister_netdev(this_device);
- cleanup_card(this_device);
- free_netdev(this_device);
-}
-
-#endif /* MODULE */
diff --git a/drivers/net/ethernet/i825xx/3c527.h b/drivers/net/ethernet/i825xx/3c527.h
deleted file mode 100644
index d693b8d15cde..000000000000
--- a/drivers/net/ethernet/i825xx/3c527.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 3COM "EtherLink MC/32" Descriptions
- */
-
-/*
- * Registers
- */
-
-#define HOST_CMD 0
-#define HOST_CMD_START_RX (1<<3)
-#define HOST_CMD_SUSPND_RX (3<<3)
-#define HOST_CMD_RESTRT_RX (5<<3)
-
-#define HOST_CMD_SUSPND_TX 3
-#define HOST_CMD_RESTRT_TX 5
-
-
-#define HOST_STATUS 2
-#define HOST_STATUS_CRR (1<<6)
-#define HOST_STATUS_CWR (1<<5)
-
-
-#define HOST_CTRL 6
-#define HOST_CTRL_ATTN (1<<7)
-#define HOST_CTRL_RESET (1<<6)
-#define HOST_CTRL_INTE (1<<2)
-
-#define HOST_RAMPAGE 8
-
-#define HALTED 0
-#define RUNNING 1
-
-struct mc32_mailbox
-{
- u16 mbox;
- u16 data[1];
-} __packed;
-
-struct skb_header
-{
- u8 status;
- u8 control;
- u16 next; /* Do not change! */
- u16 length;
- u32 data;
-} __packed;
-
-struct mc32_stats
-{
- /* RX Errors */
- u32 rx_crc_errors;
- u32 rx_alignment_errors;
- u32 rx_overrun_errors;
- u32 rx_tooshort_errors;
- u32 rx_toolong_errors;
- u32 rx_outofresource_errors;
-
- u32 rx_discarded; /* via card pattern match filter */
-
- /* TX Errors */
- u32 tx_max_collisions;
- u32 tx_carrier_errors;
- u32 tx_underrun_errors;
- u32 tx_cts_errors;
- u32 tx_timeout_errors;
-
- /* various cruft */
- u32 dataA[6];
- u16 dataB[5];
- u32 dataC[14];
-} __packed;
-
-#define STATUS_MASK 0x0F
-#define COMPLETED (1<<7)
-#define COMPLETED_OK (1<<6)
-#define BUFFER_BUSY (1<<5)
-
-#define CONTROL_EOP (1<<7) /* End Of Packet */
-#define CONTROL_EOL (1<<6) /* End of List */
-
-#define MCA_MC32_ID 0x0041 /* Our MCA ident */
diff --git a/drivers/net/ethernet/i825xx/Kconfig b/drivers/net/ethernet/i825xx/Kconfig
index ca1ae985c6df..fed5080a6b62 100644
--- a/drivers/net/ethernet/i825xx/Kconfig
+++ b/drivers/net/ethernet/i825xx/Kconfig
@@ -43,28 +43,6 @@ config EL16
To compile this driver as a module, choose M here. The module
will be called 3c507.
-config ELMC
- tristate "3c523 \"EtherLink/MC\" support"
- depends on MCA_LEGACY
- ---help---
- 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>.
-
- To compile this driver as a module, choose M here. The module
- will be called 3c523.
-
-config ELMC_II
- tristate "3c527 \"EtherLink/MC 32\" support (EXPERIMENTAL)"
- depends on MCA && MCA_LEGACY
- ---help---
- 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>.
-
- To compile this driver as a module, choose M here. The module
- will be called 3c527.
-
config ARM_ETHER1
tristate "Acorn Ether1 support"
depends on ARM && ARCH_ACORN
diff --git a/drivers/net/ethernet/i825xx/Makefile b/drivers/net/ethernet/i825xx/Makefile
index f68a3694968a..6adff85e8ecc 100644
--- a/drivers/net/ethernet/i825xx/Makefile
+++ b/drivers/net/ethernet/i825xx/Makefile
@@ -7,8 +7,6 @@ obj-$(CONFIG_EEXPRESS) += eexpress.o
obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
obj-$(CONFIG_ELPLUS) += 3c505.o
obj-$(CONFIG_EL16) += 3c507.o
-obj-$(CONFIG_ELMC) += 3c523.o
-obj-$(CONFIG_ELMC_II) += 3c527.o
obj-$(CONFIG_LP486E) += lp486e.o
obj-$(CONFIG_NI52) += ni52.o
obj-$(CONFIG_SUN3_82586) += sun3_82586.o
diff --git a/drivers/net/ethernet/i825xx/eexpress.c b/drivers/net/ethernet/i825xx/eexpress.c
index cc2e66ad4436..7a6a2f04c5b1 100644
--- a/drivers/net/ethernet/i825xx/eexpress.c
+++ b/drivers/net/ethernet/i825xx/eexpress.c
@@ -9,7 +9,7 @@
* Many modifications, and currently maintained, by
* Philip Blundell <philb@gnu.org>
* Added the Compaq LTE Alan Cox <alan@lxorguk.ukuu.org.uk>
- * Added MCA support Adam Fritzler
+ * Added MCA support Adam Fritzler (now deleted)
*
* Note - this driver is experimental still - it has problems on faster
* machines. Someone needs to sit down and go through it line by line with
@@ -111,7 +111,6 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#include <linux/mca-legacy.h>
#include <linux/spinlock.h>
#include <linux/bitops.h>
#include <linux/jiffies.h>
@@ -227,16 +226,6 @@ static unsigned short start_code[] = {
/* maps irq number to EtherExpress magic value */
static char irqrmap[] = { 0,0,1,2,3,4,0,0,0,1,5,6,0,0,0,0 };
-#ifdef CONFIG_MCA_LEGACY
-/* mapping of the first four bits of the second POS register */
-static unsigned short mca_iomap[] = {
- 0x270, 0x260, 0x250, 0x240, 0x230, 0x220, 0x210, 0x200,
- 0x370, 0x360, 0x350, 0x340, 0x330, 0x320, 0x310, 0x300
-};
-/* bits 5-7 of the second POS register */
-static char mca_irqmap[] = { 12, 9, 3, 4, 5, 10, 11, 15 };
-#endif
-
/*
* Prototypes for Linux interface
*/
@@ -340,53 +329,6 @@ static int __init do_express_probe(struct net_device *dev)
dev->if_port = 0xff; /* not set */
-#ifdef CONFIG_MCA_LEGACY
- if (MCA_bus) {
- int slot = 0;
-
- /*
- * Only find one card at a time. Subsequent calls
- * will find others, however, proper multicard MCA
- * probing and setup can't be done with the
- * old-style Space.c init routines. -- ASF
- */
- while (slot != MCA_NOTFOUND) {
- int pos0, pos1;
-
- slot = mca_find_unused_adapter(0x628B, slot);
- if (slot == MCA_NOTFOUND)
- break;
-
- pos0 = mca_read_stored_pos(slot, 2);
- pos1 = mca_read_stored_pos(slot, 3);
- ioaddr = mca_iomap[pos1&0xf];
-
- dev->irq = mca_irqmap[(pos1>>4)&0x7];
-
- /*
- * XXX: Transceiver selection is done
- * differently on the MCA version.
- * How to get it to select something
- * other than external/AUI is currently
- * unknown. This code is just for looks. -- ASF
- */
- if ((pos0 & 0x7) == 0x1)
- dev->if_port = AUI;
- else if ((pos0 & 0x7) == 0x5) {
- if (pos1 & 0x80)
- dev->if_port = BNC;
- else
- dev->if_port = TPE;
- }
-
- mca_set_adapter_name(slot, "Intel EtherExpress 16 MCA");
- mca_set_adapter_procfn(slot, NULL, dev);
- mca_mark_as_used(slot);
-
- break;
- }
- }
-#endif
if (ioaddr&0xfe00) {
if (!request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress"))
return -EBUSY;
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index c9069a28832b..f4d2da0db1b1 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -3335,6 +3335,8 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
goto out_shutdown_ports;
}
+ /* Handle any events that might be pending. */
+ tasklet_hi_schedule(&adapter->neq_tasklet);
ret = 0;
goto out;
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 76213162fbe3..79b07ec6726f 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -7,7 +7,7 @@ config NET_VENDOR_INTEL
default y
depends on PCI || PCI_MSI || ISA || ISA_DMA_API || ARM || \
ARCH_ACORN || MCA || MCA_LEGACY || SNI_RM || SUN3 || \
- GSC || BVME6000 || MVME16x || ARCH_ENP2611 || \
+ GSC || BVME6000 || MVME16x || \
(ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR) || \
EXPERIMENTAL
---help---
@@ -120,6 +120,17 @@ config IGB_DCA
driver. DCA is a method for warming the CPU cache before data
is used, with the intent of lessening the impact of cache misses.
+config IGB_PTP
+ bool "PTP Hardware Clock (PHC)"
+ default y
+ depends on IGB && PTP_1588_CLOCK
+ ---help---
+ Say Y here if you want to use PTP Hardware Clock (PHC) in the
+ driver. Only the basic clock operations have been implemented.
+
+ Every timestamp and clock read operations must consult the
+ overflow counter to form a correct time value.
+
config IGBVF
tristate "Intel(R) 82576 Virtual Function Ethernet support"
depends on PCI
@@ -182,6 +193,14 @@ config IXGBE
To compile this driver as a module, choose M here. The module
will be called ixgbe.
+config IXGBE_HWMON
+ bool "Intel(R) 10GbE PCI Express adapters HWMON support"
+ default y
+ depends on IXGBE && HWMON && !(IXGBE=y && HWMON=m)
+ ---help---
+ Say Y if you want to expose the thermal sensor data on some of
+ our cards, via a hwmon sysfs interface.
+
config IXGBE_DCA
bool "Direct Cache Access (DCA) Support"
default y
@@ -201,6 +220,17 @@ config IXGBE_DCB
If unsure, say N.
+config IXGBE_PTP
+ bool "PTP Clock Support"
+ default n
+ depends on IXGBE && PTP_1588_CLOCK
+ ---help---
+ Say Y here if you want support for 1588 Timestamping with a
+ PHC device, using the PTP 1588 Clock support. This is
+ required to enable timestamping support for the device.
+
+ If unsure, say N.
+
config IXGBEVF
tristate "Intel(R) 82599 Virtual Function Ethernet support"
depends on PCI_MSI
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index e498effb85d9..ada720b42ff6 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -1759,6 +1759,7 @@ static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
skb->data, skb->len, PCI_DMA_TODEVICE));
/* check for mapping failure? */
cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
+ skb_tx_timestamp(skb);
}
static netdev_tx_t e100_xmit_frame(struct sk_buff *skb,
@@ -2733,6 +2734,7 @@ static const struct ethtool_ops e100_ethtool_ops = {
.set_phys_id = e100_set_phys_id,
.get_ethtool_stats = e100_get_ethtool_stats,
.get_sset_count = e100_get_sset_count,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 4348b6fd44fa..95731c841044 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -493,7 +493,11 @@ out:
static void e1000_down_and_stop(struct e1000_adapter *adapter)
{
set_bit(__E1000_DOWN, &adapter->flags);
- cancel_work_sync(&adapter->reset_task);
+
+ /* Only kill reset task if adapter is not resetting */
+ if (!test_bit(__E1000_RESETTING, &adapter->flags))
+ cancel_work_sync(&adapter->reset_task);
+
cancel_delayed_work_sync(&adapter->watchdog_task);
cancel_delayed_work_sync(&adapter->phy_info_task);
cancel_delayed_work_sync(&adapter->fifo_stall_task);
@@ -827,9 +831,10 @@ static int e1000_set_features(struct net_device *netdev,
if (changed & NETIF_F_HW_VLAN_RX)
e1000_vlan_mode(netdev, features);
- if (!(changed & NETIF_F_RXCSUM))
+ if (!(changed & (NETIF_F_RXCSUM | NETIF_F_RXALL)))
return 0;
+ netdev->features = features;
adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
if (netif_running(netdev))
@@ -1074,6 +1079,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
netdev->features |= netdev->hw_features;
netdev->hw_features |= NETIF_F_RXCSUM;
+ netdev->hw_features |= NETIF_F_RXALL;
netdev->hw_features |= NETIF_F_RXFCS;
if (pci_using_dac) {
@@ -1841,6 +1847,22 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
break;
}
+ /* 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(RCTL, rctl);
}
@@ -3243,6 +3265,8 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
nr_frags, mss);
if (count) {
+ skb_tx_timestamp(skb);
+
e1000_tx_queue(adapter, tx_ring, tx_flags, count);
/* Make sure there is space in the ring for the next send. */
e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
@@ -3380,7 +3404,7 @@ static void e1000_dump(struct e1000_adapter *adapter)
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 { __le64 a; __le64 b; };
struct my_u *u = (struct my_u *)tx_desc;
const char *type;
@@ -3424,7 +3448,7 @@ rx_ring_summary:
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 { __le64 a; __le64 b; };
struct my_u *u = (struct my_u *)rx_desc;
const char *type;
@@ -4046,7 +4070,11 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
/* errors is only valid for DD + EOP descriptors */
if (unlikely((status & E1000_RXD_STAT_EOP) &&
(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
- u8 last_byte = *(skb->data + length - 1);
+ u8 *mapped;
+ u8 last_byte;
+
+ mapped = page_address(buffer_info->page);
+ last_byte = *(mapped + length - 1);
if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
last_byte)) {
spin_lock_irqsave(&adapter->stats_lock,
@@ -4057,6 +4085,8 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
irq_flags);
length--;
} else {
+ if (netdev->features & NETIF_F_RXALL)
+ goto process_skb;
/* recycle both page and skb */
buffer_info->skb = skb;
/* an error means any chain goes out the window
@@ -4069,6 +4099,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
}
#define rxtop rx_ring->rx_skb_top
+process_skb:
if (!(status & E1000_RXD_STAT_EOP)) {
/* this descriptor is only the beginning (or middle) */
if (!rxtop) {
@@ -4276,12 +4307,15 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
flags);
length--;
} else {
+ if (netdev->features & NETIF_F_RXALL)
+ goto process_skb;
/* recycle */
buffer_info->skb = skb;
goto next_desc;
}
}
+process_skb:
total_rx_bytes += (length - 4); /* don't count FCS */
total_rx_packets++;
@@ -4365,30 +4399,6 @@ e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
break;
}
- /* Fix for errata 23, can't cross 64kB boundary */
- if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
- struct sk_buff *oldskb = skb;
- e_err(rx_err, "skb align check failed: %u bytes at "
- "%p\n", bufsz, skb->data);
- /* Try again, without freeing the previous */
- skb = netdev_alloc_skb_ip_align(netdev, bufsz);
- /* Failed allocation, critical failure */
- if (!skb) {
- dev_kfree_skb(oldskb);
- adapter->alloc_rx_buff_failed++;
- break;
- }
-
- if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
- /* give up */
- dev_kfree_skb(skb);
- dev_kfree_skb(oldskb);
- break; /* while (cleaned_count--) */
- }
-
- /* Use new allocation */
- dev_kfree_skb(oldskb);
- }
buffer_info->skb = skb;
buffer_info->length = adapter->rx_buffer_len;
check_page:
diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
index bac9dda31b6c..4dd18a1f45d2 100644
--- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c
+++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c
@@ -228,9 +228,7 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw)
/* FWSM register */
mac->has_fwsm = true;
/* ARC supported; valid only if manageability features are enabled. */
- mac->arc_subsystem_valid =
- (er32(FWSM) & E1000_FWSM_MODE_MASK)
- ? true : false;
+ mac->arc_subsystem_valid = !!(er32(FWSM) & E1000_FWSM_MODE_MASK);
/* Adaptive IFS not supported */
mac->adaptive_ifs = false;
@@ -766,6 +764,7 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
{
u32 ctrl;
s32 ret_val;
+ u16 kum_reg_data;
/*
* Prevent the PCI-E bus from sticking if there is no TLP connection
@@ -791,6 +790,13 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
ew32(CTRL, ctrl | E1000_CTRL_RST);
e1000_release_phy_80003es2lan(hw);
+ /* Disable IBIST slave mode (far-end loopback) */
+ e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+ &kum_reg_data);
+ kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+ e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+ kum_reg_data);
+
ret_val = e1000e_get_auto_rd_done(hw);
if (ret_val)
/* We don't want to continue accessing MAC registers. */
@@ -938,6 +944,14 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
else
reg |= (1 << 28);
ew32(TARC(1), reg);
+
+ /*
+ * Disable IPv6 extension header parsing because some malformed
+ * IPv6 headers can hang the Rx.
+ */
+ reg = er32(RFCTL);
+ reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
+ ew32(RFCTL, reg);
}
/**
@@ -1433,6 +1447,7 @@ static const struct e1000_mac_operations es2_mac_ops = {
/* setup_physical_interface dependent on media type */
.setup_led = e1000e_setup_led_generic,
.config_collision_dist = e1000e_config_collision_dist_generic,
+ .rar_set = e1000e_rar_set_generic,
};
static const struct e1000_phy_operations es2_phy_ops = {
diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c
index b3fdc6977f2e..36db4df09aed 100644
--- a/drivers/net/ethernet/intel/e1000e/82571.c
+++ b/drivers/net/ethernet/intel/e1000e/82571.c
@@ -295,9 +295,8 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
* ARC supported; valid only if manageability features are
* enabled.
*/
- mac->arc_subsystem_valid =
- (er32(FWSM) & E1000_FWSM_MODE_MASK)
- ? true : false;
+ mac->arc_subsystem_valid = !!(er32(FWSM) &
+ E1000_FWSM_MODE_MASK);
break;
case e1000_82574:
case e1000_82583:
@@ -798,7 +797,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
/* Check for pending operations. */
for (i = 0; i < E1000_FLASH_UPDATES; i++) {
usleep_range(1000, 2000);
- if ((er32(EECD) & E1000_EECD_FLUPD) == 0)
+ if (!(er32(EECD) & E1000_EECD_FLUPD))
break;
}
@@ -822,7 +821,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
for (i = 0; i < E1000_FLASH_UPDATES; i++) {
usleep_range(1000, 2000);
- if ((er32(EECD) & E1000_EECD_FLUPD) == 0)
+ if (!(er32(EECD) & E1000_EECD_FLUPD))
break;
}
@@ -1000,7 +999,7 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
**/
static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
{
- u32 ctrl, ctrl_ext;
+ u32 ctrl, ctrl_ext, eecd;
s32 ret_val;
/*
@@ -1073,6 +1072,16 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
*/
switch (hw->mac.type) {
+ case e1000_82571:
+ case e1000_82572:
+ /*
+ * REQ and GNT bits need to be cleared when using AUTO_RD
+ * to access the EEPROM.
+ */
+ eecd = er32(EECD);
+ eecd &= ~(E1000_EECD_REQ | E1000_EECD_GNT);
+ ew32(EECD, eecd);
+ break;
case e1000_82573:
case e1000_82574:
case e1000_82583:
@@ -1280,6 +1289,16 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
ew32(CTRL_EXT, reg);
}
+ /*
+ * Disable IPv6 extension header parsing because some malformed
+ * IPv6 headers can hang the Rx.
+ */
+ if (hw->mac.type <= e1000_82573) {
+ reg = er32(RFCTL);
+ reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
+ ew32(RFCTL, reg);
+ }
+
/* PCI-Ex Control Registers */
switch (hw->mac.type) {
case e1000_82574:
@@ -1763,7 +1782,8 @@ void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state)
* incoming packets directed to this port are dropped.
* Eventually the LAA will be in RAR[0] and RAR[14].
*/
- e1000e_rar_set(hw, hw->mac.addr, hw->mac.rar_entry_count - 1);
+ hw->mac.ops.rar_set(hw, hw->mac.addr,
+ hw->mac.rar_entry_count - 1);
}
/**
@@ -1927,6 +1947,7 @@ static const struct e1000_mac_operations e82571_mac_ops = {
.setup_led = e1000e_setup_led_generic,
.config_collision_dist = e1000e_config_collision_dist_generic,
.read_mac_addr = e1000_read_mac_addr_82571,
+ .rar_set = e1000e_rar_set_generic,
};
static const struct e1000_phy_operations e82_phy_ops_igp = {
@@ -2061,9 +2082,11 @@ const struct e1000_info e1000_82574_info = {
| FLAG_HAS_SMART_POWER_DOWN
| FLAG_HAS_AMT
| FLAG_HAS_CTRLEXT_ON_LOAD,
- .flags2 = FLAG2_CHECK_PHY_HANG
+ .flags2 = FLAG2_CHECK_PHY_HANG
| FLAG2_DISABLE_ASPM_L0S
- | FLAG2_NO_DISABLE_RX,
+ | FLAG2_DISABLE_ASPM_L1
+ | FLAG2_NO_DISABLE_RX
+ | FLAG2_DMA_BURST,
.pba = 32,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_82571,
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h
index 3a5025917163..351a4097b2ba 100644
--- a/drivers/net/ethernet/intel/e1000e/defines.h
+++ b/drivers/net/ethernet/intel/e1000e/defines.h
@@ -74,7 +74,9 @@
#define E1000_WUS_BC E1000_WUFC_BC
/* Extended Device Control */
+#define E1000_CTRL_EXT_LPCD 0x00000004 /* LCD Power Cycle Done */
#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */
+#define E1000_CTRL_EXT_FORCE_SMBUS 0x00000800 /* Force SMBus mode */
#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
@@ -573,6 +575,7 @@
#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
/* Link Partner Ability Register (Base Page) */
+#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP 100TX Full Dplx Capable */
#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
@@ -739,6 +742,7 @@
#define I82577_E_PHY_ID 0x01540050
#define I82578_E_PHY_ID 0x004DD040
#define I82579_E_PHY_ID 0x01540090
+#define I217_E_PHY_ID 0x015400A0
/* M88E1000 Specific Registers */
#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
@@ -850,4 +854,8 @@
/* SerDes Control */
#define E1000_GEN_POLL_TIMEOUT 640
+/* FW Semaphore */
+#define E1000_FWSM_WLOCK_MAC_MASK 0x0380
+#define E1000_FWSM_WLOCK_MAC_SHIFT 7
+
#endif /* _E1000_DEFINES_H_ */
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index b83897f76ee3..6e6fffb34581 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -206,6 +206,7 @@ enum e1000_boards {
board_ich10lan,
board_pchlan,
board_pch2lan,
+ board_pch_lpt,
};
struct e1000_ps_page {
@@ -528,6 +529,7 @@ extern const struct e1000_info e1000_ich9_info;
extern const struct e1000_info e1000_ich10_info;
extern const struct e1000_info e1000_pch_info;
extern const struct e1000_info e1000_pch2_info;
+extern const struct e1000_info e1000_pch_lpt_info;
extern const struct e1000_info e1000_es2_info;
extern s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
@@ -576,7 +578,7 @@ 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,
u8 *mc_addr_list,
u32 mc_addr_count);
-extern void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
+extern void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index);
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);
@@ -673,11 +675,21 @@ static inline s32 e1e_rphy(struct e1000_hw *hw, u32 offset, u16 *data)
return hw->phy.ops.read_reg(hw, offset, data);
}
+static inline s32 e1e_rphy_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return hw->phy.ops.read_reg_locked(hw, offset, data);
+}
+
static inline s32 e1e_wphy(struct e1000_hw *hw, u32 offset, u16 data)
{
return hw->phy.ops.write_reg(hw, offset, data);
}
+static inline s32 e1e_wphy_locked(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return hw->phy.ops.write_reg_locked(hw, offset, data);
+}
+
static inline s32 e1000_get_cable_length(struct e1000_hw *hw)
{
return hw->phy.ops.get_cable_length(hw);
@@ -735,9 +747,46 @@ static inline u32 __er32(struct e1000_hw *hw, unsigned long reg)
return readl(hw->hw_addr + reg);
}
+#define er32(reg) __er32(hw, E1000_##reg)
+
+/**
+ * __ew32_prepare - prepare to write to MAC CSR register on certain parts
+ * @hw: pointer to the HW structure
+ *
+ * When updating the MAC CSR registers, the Manageability Engine (ME) could
+ * be accessing the registers at the same time. Normally, this is handled in
+ * h/w by an arbiter but on some parts there is a bug that acknowledges Host
+ * accesses later than it should which could result in the register to have
+ * an incorrect value. Workaround this by checking the FWSM register which
+ * has bit 24 set while ME is accessing MAC CSR registers, wait if it is set
+ * and try again a number of times.
+ **/
+static inline s32 __ew32_prepare(struct e1000_hw *hw)
+{
+ s32 i = E1000_ICH_FWSM_PCIM2PCI_COUNT;
+
+ while ((er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI) && --i)
+ udelay(50);
+
+ return i;
+}
+
static inline void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val)
{
+ if (hw->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
+ __ew32_prepare(hw);
+
writel(val, hw->hw_addr + reg);
}
+#define ew32(reg, val) __ew32(hw, E1000_##reg, (val))
+
+#define e1e_flush() er32(STATUS)
+
+#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \
+ (__ew32((a), (reg + ((offset) << 2)), (value)))
+
+#define E1000_READ_REG_ARRAY(a, reg, offset) \
+ (readl((a)->hw_addr + reg + ((offset) << 2)))
+
#endif /* _E1000_H_ */
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index db35dd5d96de..d863075df7a4 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -259,8 +259,7 @@ static int e1000_set_settings(struct net_device *netdev,
* cannot be changed
*/
if (hw->phy.ops.check_reset_block(hw)) {
- e_err("Cannot change link characteristics when SoL/IDER is "
- "active.\n");
+ e_err("Cannot change link characteristics when SoL/IDER is active.\n");
return -EINVAL;
}
@@ -403,15 +402,15 @@ static void e1000_get_regs(struct net_device *netdev,
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[3] = er32(RDLEN(0));
+ regs_buff[4] = er32(RDH(0));
+ regs_buff[5] = er32(RDT(0));
regs_buff[6] = er32(RDTR);
regs_buff[7] = er32(TCTL);
- regs_buff[8] = er32(TDLEN);
- regs_buff[9] = er32(TDH);
- regs_buff[10] = er32(TDT);
+ regs_buff[8] = er32(TDLEN(0));
+ regs_buff[9] = er32(TDH(0));
+ regs_buff[10] = er32(TDT(0));
regs_buff[11] = er32(TIDV);
regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */
@@ -727,9 +726,8 @@ static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
(test[pat] & write));
val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset);
if (val != (test[pat] & write & mask)) {
- e_err("pattern test reg %04X failed: got 0x%08X "
- "expected 0x%08X\n", reg + offset, val,
- (test[pat] & write & mask));
+ e_err("pattern test reg %04X failed: got 0x%08X expected 0x%08X\n",
+ reg + offset, val, (test[pat] & write & mask));
*data = reg;
return 1;
}
@@ -744,8 +742,8 @@ static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
__ew32(&adapter->hw, reg, write & mask);
val = __er32(&adapter->hw, reg);
if ((write & mask) != (val & mask)) {
- e_err("set/check reg %04X test failed: got 0x%08X "
- "expected 0x%08X\n", reg, (val & mask), (write & mask));
+ e_err("set/check reg %04X test failed: got 0x%08X expected 0x%08X\n",
+ reg, (val & mask), (write & mask));
*data = reg;
return 1;
}
@@ -775,6 +773,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
u32 i;
u32 toggle;
u32 mask;
+ u32 wlock_mac = 0;
/*
* The status register is Read Only, so a write should fail.
@@ -797,8 +796,8 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
ew32(STATUS, toggle);
after = er32(STATUS) & toggle;
if (value != after) {
- e_err("failed STATUS register test got: 0x%08X expected: "
- "0x%08X\n", after, value);
+ e_err("failed STATUS register test got: 0x%08X expected: 0x%08X\n",
+ after, value);
*data = 1;
return 1;
}
@@ -813,15 +812,15 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
}
REG_PATTERN_TEST(E1000_RDTR, 0x0000FFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(E1000_RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(E1000_RDLEN, 0x000FFF80, 0x000FFFFF);
- REG_PATTERN_TEST(E1000_RDH, 0x0000FFFF, 0x0000FFFF);
- REG_PATTERN_TEST(E1000_RDT, 0x0000FFFF, 0x0000FFFF);
+ REG_PATTERN_TEST(E1000_RDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF);
+ REG_PATTERN_TEST(E1000_RDLEN(0), 0x000FFF80, 0x000FFFFF);
+ REG_PATTERN_TEST(E1000_RDH(0), 0x0000FFFF, 0x0000FFFF);
+ REG_PATTERN_TEST(E1000_RDT(0), 0x0000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(E1000_FCRTH, 0x0000FFF8, 0x0000FFF8);
REG_PATTERN_TEST(E1000_FCTTV, 0x0000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(E1000_TIPG, 0x3FFFFFFF, 0x3FFFFFFF);
- REG_PATTERN_TEST(E1000_TDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(E1000_TDLEN, 0x000FFF80, 0x000FFFFF);
+ REG_PATTERN_TEST(E1000_TDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF);
+ REG_PATTERN_TEST(E1000_TDLEN(0), 0x000FFF80, 0x000FFFFF);
REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x00000000);
@@ -830,29 +829,41 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
REG_SET_AND_CHECK(E1000_TCTL, 0xFFFFFFFF, 0x00000000);
REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF);
- REG_PATTERN_TEST(E1000_RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
+ REG_PATTERN_TEST(E1000_RDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF);
if (!(adapter->flags & FLAG_IS_ICH))
REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF);
- REG_PATTERN_TEST(E1000_TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
+ REG_PATTERN_TEST(E1000_TDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF);
mask = 0x8003FFFF;
switch (mac->type) {
case e1000_ich10lan:
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
mask |= (1 << 18);
break;
default:
break;
}
- for (i = 0; i < mac->rar_entry_count; i++)
+
+ if (mac->type == e1000_pch_lpt)
+ wlock_mac = (er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK) >>
+ E1000_FWSM_WLOCK_MAC_SHIFT;
+
+ for (i = 0; i < mac->rar_entry_count; i++) {
+ /* Cannot test write-protected SHRAL[n] registers */
+ if ((wlock_mac == 1) || (wlock_mac && (i > wlock_mac)))
+ continue;
+
REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1),
- mask, 0xFFFFFFFF);
+ mask, 0xFFFFFFFF);
+ }
for (i = 0; i < mac->mta_reg_count; i++)
REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF);
*data = 0;
+
return 0;
}
@@ -1104,11 +1115,11 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
- ew32(TDBAL, ((u64) tx_ring->dma & 0x00000000FFFFFFFF));
- ew32(TDBAH, ((u64) tx_ring->dma >> 32));
- ew32(TDLEN, tx_ring->count * sizeof(struct e1000_tx_desc));
- ew32(TDH, 0);
- ew32(TDT, 0);
+ ew32(TDBAL(0), ((u64) tx_ring->dma & 0x00000000FFFFFFFF));
+ ew32(TDBAH(0), ((u64) tx_ring->dma >> 32));
+ ew32(TDLEN(0), tx_ring->count * sizeof(struct e1000_tx_desc));
+ ew32(TDH(0), 0);
+ ew32(TDT(0), 0);
ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR |
E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT);
@@ -1168,11 +1179,11 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
rctl = er32(RCTL);
if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX))
ew32(RCTL, rctl & ~E1000_RCTL_EN);
- ew32(RDBAL, ((u64) rx_ring->dma & 0xFFFFFFFF));
- ew32(RDBAH, ((u64) rx_ring->dma >> 32));
- ew32(RDLEN, rx_ring->size);
- ew32(RDH, 0);
- ew32(RDT, 0);
+ ew32(RDBAL(0), ((u64) rx_ring->dma & 0xFFFFFFFF));
+ ew32(RDBAH(0), ((u64) rx_ring->dma >> 32));
+ ew32(RDLEN(0), rx_ring->size);
+ ew32(RDH(0), 0);
+ ew32(RDT(0), 0);
rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE |
E1000_RCTL_SBP | E1000_RCTL_SECRC |
@@ -1534,7 +1545,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
int ret_val = 0;
unsigned long time;
- ew32(RDT, rx_ring->count - 1);
+ ew32(RDT(0), rx_ring->count - 1);
/*
* Calculate the loop count based on the largest descriptor ring
@@ -1561,7 +1572,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
if (k == tx_ring->count)
k = 0;
}
- ew32(TDT, k);
+ ew32(TDT(0), k);
e1e_flush();
msleep(200);
time = jiffies; /* set the start time for the receive */
@@ -1791,8 +1802,7 @@ static void e1000_get_wol(struct net_device *netdev,
wol->supported &= ~WAKE_UCAST;
if (adapter->wol & E1000_WUFC_EX)
- e_err("Interface does not support directed (unicast) "
- "frame wake-up packets\n");
+ e_err("Interface does not support directed (unicast) frame wake-up packets\n");
}
if (adapter->wol & E1000_WUFC_EX)
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
index f82ecf536c8b..ed5b40985edb 100644
--- a/drivers/net/ethernet/intel/e1000e/hw.h
+++ b/drivers/net/ethernet/intel/e1000e/hw.h
@@ -36,16 +36,6 @@ struct e1000_adapter;
#include "defines.h"
-#define er32(reg) __er32(hw, E1000_##reg)
-#define ew32(reg,val) __ew32(hw, E1000_##reg, (val))
-#define e1e_flush() er32(STATUS)
-
-#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \
- (writel((value), ((a)->hw_addr + reg + ((offset) << 2))))
-
-#define E1000_READ_REG_ARRAY(a, reg, offset) \
- (readl((a)->hw_addr + reg + ((offset) << 2)))
-
enum e1e_registers {
E1000_CTRL = 0x00000, /* Device Control - RW */
E1000_STATUS = 0x00008, /* Device Status - RO */
@@ -61,6 +51,7 @@ enum e1e_registers {
E1000_FEXTNVM = 0x00028, /* Future Extended NVM - RW */
E1000_FCT = 0x00030, /* Flow Control Type - RW */
E1000_VET = 0x00038, /* VLAN Ether Type - RW */
+ E1000_FEXTNVM3 = 0x0003C, /* Future Extended NVM 3 - RW */
E1000_ICR = 0x000C0, /* Interrupt Cause Read - R/clr */
E1000_ITR = 0x000C4, /* Interrupt Throttling Rate - RW */
E1000_ICS = 0x000C8, /* Interrupt Cause Set - WO */
@@ -94,31 +85,40 @@ enum e1e_registers {
E1000_FCRTL = 0x02160, /* Flow Control Receive Threshold Low - RW */
E1000_FCRTH = 0x02168, /* Flow Control Receive Threshold High - RW */
E1000_PSRCTL = 0x02170, /* Packet Split Receive Control - RW */
- E1000_RDBAL = 0x02800, /* Rx Descriptor Base Address Low - RW */
- E1000_RDBAH = 0x02804, /* Rx Descriptor Base Address High - RW */
- E1000_RDLEN = 0x02808, /* Rx Descriptor Length - RW */
- E1000_RDH = 0x02810, /* Rx Descriptor Head - RW */
- E1000_RDT = 0x02818, /* Rx Descriptor Tail - RW */
- E1000_RDTR = 0x02820, /* Rx Delay Timer - RW */
- E1000_RXDCTL_BASE = 0x02828, /* Rx Descriptor Control - RW */
-#define E1000_RXDCTL(_n) (E1000_RXDCTL_BASE + (_n << 8))
- E1000_RADV = 0x0282C, /* Rx Interrupt Absolute Delay Timer - RW */
-
-/* Convenience macros
+/*
+ * Convenience macros
*
* Note: "_n" is the queue number of the register to be written to.
*
* Example usage:
- * E1000_RDBAL_REG(current_rx_queue)
- *
+ * E1000_RDBAL(current_rx_queue)
*/
-#define E1000_RDBAL_REG(_n) (E1000_RDBAL + (_n << 8))
+ E1000_RDBAL_BASE = 0x02800, /* Rx Descriptor Base Address Low - RW */
+#define E1000_RDBAL(_n) (E1000_RDBAL_BASE + (_n << 8))
+ E1000_RDBAH_BASE = 0x02804, /* Rx Descriptor Base Address High - RW */
+#define E1000_RDBAH(_n) (E1000_RDBAH_BASE + (_n << 8))
+ E1000_RDLEN_BASE = 0x02808, /* Rx Descriptor Length - RW */
+#define E1000_RDLEN(_n) (E1000_RDLEN_BASE + (_n << 8))
+ E1000_RDH_BASE = 0x02810, /* Rx Descriptor Head - RW */
+#define E1000_RDH(_n) (E1000_RDH_BASE + (_n << 8))
+ E1000_RDT_BASE = 0x02818, /* Rx Descriptor Tail - RW */
+#define E1000_RDT(_n) (E1000_RDT_BASE + (_n << 8))
+ E1000_RDTR = 0x02820, /* Rx Delay Timer - RW */
+ E1000_RXDCTL_BASE = 0x02828, /* Rx Descriptor Control - RW */
+#define E1000_RXDCTL(_n) (E1000_RXDCTL_BASE + (_n << 8))
+ E1000_RADV = 0x0282C, /* Rx Interrupt Absolute Delay Timer - RW */
+
E1000_KABGTXD = 0x03004, /* AFE Band Gap Transmit Ref Data */
- E1000_TDBAL = 0x03800, /* Tx Descriptor Base Address Low - RW */
- E1000_TDBAH = 0x03804, /* Tx Descriptor Base Address High - RW */
- E1000_TDLEN = 0x03808, /* Tx Descriptor Length - RW */
- E1000_TDH = 0x03810, /* Tx Descriptor Head - RW */
- E1000_TDT = 0x03818, /* Tx Descriptor Tail - RW */
+ E1000_TDBAL_BASE = 0x03800, /* Tx Descriptor Base Address Low - RW */
+#define E1000_TDBAL(_n) (E1000_TDBAL_BASE + (_n << 8))
+ E1000_TDBAH_BASE = 0x03804, /* Tx Descriptor Base Address High - RW */
+#define E1000_TDBAH(_n) (E1000_TDBAH_BASE + (_n << 8))
+ E1000_TDLEN_BASE = 0x03808, /* Tx Descriptor Length - RW */
+#define E1000_TDLEN(_n) (E1000_TDLEN_BASE + (_n << 8))
+ E1000_TDH_BASE = 0x03810, /* Tx Descriptor Head - RW */
+#define E1000_TDH(_n) (E1000_TDH_BASE + (_n << 8))
+ E1000_TDT_BASE = 0x03818, /* Tx Descriptor Tail - RW */
+#define E1000_TDT(_n) (E1000_TDT_BASE + (_n << 8))
E1000_TIDV = 0x03820, /* Tx Interrupt Delay Value - RW */
E1000_TXDCTL_BASE = 0x03828, /* Tx Descriptor Control - RW */
#define E1000_TXDCTL(_n) (E1000_TXDCTL_BASE + (_n << 8))
@@ -200,6 +200,14 @@ enum e1e_registers {
#define E1000_RA (E1000_RAL(0))
E1000_RAH_BASE = 0x05404, /* Receive Address High - RW */
#define E1000_RAH(_n) (E1000_RAH_BASE + ((_n) * 8))
+ E1000_SHRAL_PCH_LPT_BASE = 0x05408,
+#define E1000_SHRAL_PCH_LPT(_n) (E1000_SHRAL_PCH_LPT_BASE + ((_n) * 8))
+ E1000_SHRAH_PCH_LTP_BASE = 0x0540C,
+#define E1000_SHRAH_PCH_LPT(_n) (E1000_SHRAH_PCH_LTP_BASE + ((_n) * 8))
+ E1000_SHRAL_BASE = 0x05438, /* Shared Receive Address Low - RW */
+#define E1000_SHRAL(_n) (E1000_SHRAL_BASE + ((_n) * 8))
+ E1000_SHRAH_BASE = 0x0543C, /* Shared Receive Address High - RW */
+#define E1000_SHRAH(_n) (E1000_SHRAH_BASE + ((_n) * 8))
E1000_VFTA = 0x05600, /* VLAN Filter Table Array - RW Array */
E1000_WUC = 0x05800, /* Wakeup Control - RW */
E1000_WUFC = 0x05808, /* Wakeup Filter Control - RW */
@@ -402,6 +410,8 @@ enum e1e_registers {
#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0
#define E1000_DEV_ID_PCH2_LV_LM 0x1502
#define E1000_DEV_ID_PCH2_LV_V 0x1503
+#define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A
+#define E1000_DEV_ID_PCH_LPT_I217_V 0x153B
#define E1000_REVISION_4 4
@@ -422,6 +432,7 @@ enum e1000_mac_type {
e1000_ich10lan,
e1000_pchlan,
e1000_pch2lan,
+ e1000_pch_lpt,
};
enum e1000_media_type {
@@ -459,6 +470,7 @@ enum e1000_phy_type {
e1000_phy_82578,
e1000_phy_82577,
e1000_phy_82579,
+ e1000_phy_i217,
};
enum e1000_bus_width {
@@ -782,6 +794,7 @@ struct e1000_mac_operations {
s32 (*setup_led)(struct e1000_hw *);
void (*write_vfta)(struct e1000_hw *, u32, u32);
void (*config_collision_dist)(struct e1000_hw *);
+ void (*rar_set)(struct e1000_hw *, u8 *, u32);
s32 (*read_mac_addr)(struct e1000_hw *);
};
@@ -966,6 +979,7 @@ struct e1000_dev_spec_ich8lan {
struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
bool nvm_k1_enabled;
bool eee_disable;
+ u16 eee_lp_ability;
};
struct e1000_hw {
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index b461c24945e3..bbf70ba367da 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -105,6 +105,9 @@
#define E1000_FEXTNVM_SW_CONFIG 1
#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ */
+#define E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK 0x0C000000
+#define E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC 0x08000000
+
#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7
#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7
#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3
@@ -112,6 +115,8 @@
#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL
#define E1000_ICH_RAR_ENTRIES 7
+#define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */
+#define E1000_PCH_LPT_RAR_ENTRIES 12 /* RAR[0], SHRA[0-10] */
#define PHY_PAGE_SHIFT 5
#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
@@ -127,14 +132,22 @@
#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in milliseconds */
+/* SMBus Control Phy Register */
+#define CV_SMB_CTRL PHY_REG(769, 23)
+#define CV_SMB_CTRL_FORCE_SMBUS 0x0001
+
/* SMBus Address Phy Register */
#define HV_SMB_ADDR PHY_REG(768, 26)
#define HV_SMB_ADDR_MASK 0x007F
#define HV_SMB_ADDR_PEC_EN 0x0200
#define HV_SMB_ADDR_VALID 0x0080
+#define HV_SMB_ADDR_FREQ_MASK 0x1100
+#define HV_SMB_ADDR_FREQ_LOW_SHIFT 8
+#define HV_SMB_ADDR_FREQ_HIGH_SHIFT 12
/* PHY Power Management Control */
#define HV_PM_CTRL PHY_REG(770, 17)
+#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100
/* PHY Low Power Idle Control */
#define I82579_LPI_CTRL PHY_REG(772, 20)
@@ -147,11 +160,26 @@
#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 */
+#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */
+#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */
+#define I217_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE supported */
+
+/* Intel Rapid Start Technology Support */
+#define I217_PROXY_CTRL PHY_REG(BM_WUC_PAGE, 70)
+#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080
+#define I217_SxCTRL PHY_REG(BM_PORT_CTRL_PAGE, 28)
+#define I217_SxCTRL_MASK 0x1000
+#define I217_CGFREG PHY_REG(772, 29)
+#define I217_CGFREG_MASK 0x0002
+#define I217_MEMPWR PHY_REG(772, 26)
+#define I217_MEMPWR_MASK 0x0010
/* Strapping Option Register - RO */
#define E1000_STRAP 0x0000C
#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000
#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17
+#define E1000_STRAP_SMT_FREQ_MASK 0x00003000
+#define E1000_STRAP_SMT_FREQ_SHIFT 12
/* OEM Bits Phy Register */
#define HV_OEM_BITS PHY_REG(768, 25)
@@ -255,6 +283,8 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
+static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index);
+static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index);
static s32 e1000_k1_workaround_lv(struct e1000_hw *hw);
static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate);
@@ -283,18 +313,161 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 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)
+/**
+ * e1000_phy_is_accessible_pchlan - Check if able to access PHY registers
+ * @hw: pointer to the HW structure
+ *
+ * Test access to the PHY registers by reading the PHY ID registers. If
+ * the PHY ID is already known (e.g. resume path) compare it with known ID,
+ * otherwise assume the read PHY ID is correct if it is valid.
+ *
+ * Assumes the sw/fw/hw semaphore is already acquired.
+ **/
+static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
{
- u32 ctrl;
+ u16 phy_reg;
+ u32 phy_id;
- ctrl = er32(CTRL);
- ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
- ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
- ew32(CTRL, ctrl);
- e1e_flush();
- udelay(10);
- ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
- ew32(CTRL, ctrl);
+ e1e_rphy_locked(hw, PHY_ID1, &phy_reg);
+ phy_id = (u32)(phy_reg << 16);
+ e1e_rphy_locked(hw, PHY_ID2, &phy_reg);
+ phy_id |= (u32)(phy_reg & PHY_REVISION_MASK);
+
+ if (hw->phy.id) {
+ if (hw->phy.id == phy_id)
+ return true;
+ } else {
+ if ((phy_id != 0) && (phy_id != PHY_REVISION_MASK))
+ hw->phy.id = phy_id;
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds
+ * @hw: pointer to the HW structure
+ *
+ * Workarounds/flow necessary for PHY initialization during driver load
+ * and resume paths.
+ **/
+static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
+{
+ u32 mac_reg, fwsm = er32(FWSM);
+ s32 ret_val;
+ u16 phy_reg;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ e_dbg("Failed to initialize PHY flow\n");
+ return ret_val;
+ }
+
+ /*
+ * The MAC-PHY interconnect may be in SMBus mode. If the PHY is
+ * inaccessible and resetting the PHY is not blocked, toggle the
+ * LANPHYPC Value bit to force the interconnect to PCIe mode.
+ */
+ switch (hw->mac.type) {
+ case e1000_pch_lpt:
+ if (e1000_phy_is_accessible_pchlan(hw))
+ break;
+
+ /*
+ * Before toggling LANPHYPC, see if PHY is accessible by
+ * forcing MAC to SMBus mode first.
+ */
+ mac_reg = er32(CTRL_EXT);
+ mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
+ ew32(CTRL_EXT, mac_reg);
+
+ /* fall-through */
+ case e1000_pch2lan:
+ /*
+ * Gate automatic PHY configuration by hardware on
+ * non-managed 82579
+ */
+ if ((hw->mac.type == e1000_pch2lan) &&
+ !(fwsm & E1000_ICH_FWSM_FW_VALID))
+ e1000_gate_hw_phy_config_ich8lan(hw, true);
+
+ if (e1000_phy_is_accessible_pchlan(hw)) {
+ if (hw->mac.type == e1000_pch_lpt) {
+ /* Unforce SMBus mode in PHY */
+ e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg);
+ phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+ e1e_wphy_locked(hw, CV_SMB_CTRL, phy_reg);
+
+ /* Unforce SMBus mode in MAC */
+ mac_reg = er32(CTRL_EXT);
+ mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+ ew32(CTRL_EXT, mac_reg);
+ }
+ break;
+ }
+
+ /* fall-through */
+ case e1000_pchlan:
+ if ((hw->mac.type == e1000_pchlan) &&
+ (fwsm & E1000_ICH_FWSM_FW_VALID))
+ break;
+
+ if (hw->phy.ops.check_reset_block(hw)) {
+ e_dbg("Required LANPHYPC toggle blocked by ME\n");
+ break;
+ }
+
+ e_dbg("Toggling LANPHYPC\n");
+
+ /* Set Phy Config Counter to 50msec */
+ mac_reg = er32(FEXTNVM3);
+ mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
+ mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
+ ew32(FEXTNVM3, mac_reg);
+
+ /* Toggle LANPHYPC Value bit */
+ mac_reg = er32(CTRL);
+ mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE;
+ mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE;
+ ew32(CTRL, mac_reg);
+ e1e_flush();
+ udelay(10);
+ mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
+ ew32(CTRL, mac_reg);
+ e1e_flush();
+ if (hw->mac.type < e1000_pch_lpt) {
+ msleep(50);
+ } else {
+ u16 count = 20;
+ do {
+ usleep_range(5000, 10000);
+ } while (!(er32(CTRL_EXT) &
+ E1000_CTRL_EXT_LPCD) && count--);
+ }
+ break;
+ default:
+ break;
+ }
+
+ hw->phy.ops.release(hw);
+
+ /*
+ * 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);
+
+ /* 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);
+ }
+
+ return ret_val;
}
/**
@@ -324,70 +497,41 @@ 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;
- 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);
-
- /*
- * Gate automatic PHY configuration by hardware on
- * non-managed 82579
- */
- 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)
- return ret_val;
+ phy->id = e1000_phy_unknown;
- /* 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);
- }
- }
+ ret_val = e1000_init_phy_workarounds_pchlan(hw);
+ if (ret_val)
+ return ret_val;
- phy->id = e1000_phy_unknown;
- switch (hw->mac.type) {
- default:
- ret_val = e1000e_get_phy_id(hw);
- if (ret_val)
- return ret_val;
- if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
+ if (phy->id == e1000_phy_unknown)
+ switch (hw->mac.type) {
+ default:
+ ret_val = e1000e_get_phy_id(hw);
+ if (ret_val)
+ return ret_val;
+ if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
+ break;
+ /* fall-through */
+ case e1000_pch2lan:
+ case e1000_pch_lpt:
+ /*
+ * In case the PHY needs to be in mdio slow mode,
+ * set slow mode and try to get the PHY id again.
+ */
+ ret_val = e1000_set_mdio_slow_mode_hv(hw);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000e_get_phy_id(hw);
+ if (ret_val)
+ return ret_val;
break;
- /* fall-through */
- case e1000_pch2lan:
- /*
- * In case the PHY needs to be in mdio slow mode,
- * set slow mode and try to get the PHY id again.
- */
- ret_val = e1000_set_mdio_slow_mode_hv(hw);
- if (ret_val)
- return ret_val;
- ret_val = e1000e_get_phy_id(hw);
- if (ret_val)
- return ret_val;
- break;
- }
+ }
phy->type = e1000e_get_phy_type_from_id(phy->id);
switch (phy->type) {
case e1000_phy_82577:
case e1000_phy_82579:
+ case e1000_phy_i217:
phy->ops.check_polarity = e1000_check_polarity_82577;
phy->ops.force_speed_duplex =
e1000_phy_force_speed_duplex_82577;
@@ -572,7 +716,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
/* Adaptive IFS supported */
mac->adaptive_ifs = true;
- /* LED operations */
+ /* LED and other operations */
switch (mac->type) {
case e1000_ich8lan:
case e1000_ich9lan:
@@ -591,8 +735,12 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
mac->ops.led_on = e1000_led_on_ich8lan;
mac->ops.led_off = e1000_led_off_ich8lan;
break;
- case e1000_pchlan:
case e1000_pch2lan:
+ mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES;
+ mac->ops.rar_set = e1000_rar_set_pch2lan;
+ /* fall-through */
+ case e1000_pch_lpt:
+ case e1000_pchlan:
/* check management mode */
mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
/* ID LED init */
@@ -609,12 +757,20 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
break;
}
+ if (mac->type == e1000_pch_lpt) {
+ mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
+ mac->ops.rar_set = e1000_rar_set_pch_lpt;
+ }
+
/* Enable PCS Lock-loss workaround for ICH8 */
if (mac->type == e1000_ich8lan)
e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
- /* Gate automatic PHY configuration by hardware on managed 82579 */
- if ((mac->type == e1000_pch2lan) &&
+ /*
+ * Gate automatic PHY configuration by hardware on managed
+ * 82579 and i217
+ */
+ if ((mac->type == e1000_pch2lan || mac->type == e1000_pch_lpt) &&
(er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
e1000_gate_hw_phy_config_ich8lan(hw, true);
@@ -630,22 +786,50 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
**/
static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
{
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
s32 ret_val = 0;
u16 phy_reg;
- if (hw->phy.type != e1000_phy_82579)
+ if ((hw->phy.type != e1000_phy_82579) &&
+ (hw->phy.type != e1000_phy_i217))
return 0;
ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
if (ret_val)
return ret_val;
- if (hw->dev_spec.ich8lan.eee_disable)
+ if (dev_spec->eee_disable)
phy_reg &= ~I82579_LPI_CTRL_ENABLE_MASK;
else
phy_reg |= I82579_LPI_CTRL_ENABLE_MASK;
- return e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
+ ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
+ if (ret_val)
+ return ret_val;
+
+ if ((hw->phy.type == e1000_phy_i217) && !dev_spec->eee_disable) {
+ /* Save off link partner's EEE ability */
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR,
+ I217_EEE_LP_ABILITY);
+ if (ret_val)
+ goto release;
+ e1e_rphy_locked(hw, I82579_EMI_DATA, &dev_spec->eee_lp_ability);
+
+ /*
+ * EEE is not supported in 100Half, so ignore partner's EEE
+ * in 100 ability if full-duplex is not advertised.
+ */
+ e1e_rphy_locked(hw, PHY_LP_ABILITY, &phy_reg);
+ if (!(phy_reg & NWAY_LPAR_100TX_FD_CAPS))
+ dev_spec->eee_lp_ability &= ~I217_EEE_100_SUPPORTED;
+release:
+ hw->phy.ops.release(hw);
+ }
+
+ return 0;
}
/**
@@ -687,6 +871,9 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
return ret_val;
}
+ /* Clear link partner's EEE ability */
+ hw->dev_spec.ich8lan.eee_lp_ability = 0;
+
if (!link)
return 0; /* No link detected */
@@ -782,6 +969,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
break;
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
rc = e1000_init_phy_params_pchlan(hw);
break;
default:
@@ -967,6 +1155,145 @@ static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw)
}
/**
+ * e1000_rar_set_pch2lan - Set receive address register
+ * @hw: pointer to the HW structure
+ * @addr: pointer to the receive address
+ * @index: receive address array register
+ *
+ * Sets the receive address array register at index to the address passed
+ * in by addr. For 82579, RAR[0] is the base address register that is to
+ * contain the MAC address but RAR[1-6] are reserved for manageability (ME).
+ * Use SHRA[0-3] in place of those reserved for ME.
+ **/
+static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+ u32 rar_low, rar_high;
+
+ /*
+ * HW expects these in little endian so we reverse the byte order
+ * 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_high = ((u32)addr[4] | ((u32)addr[5] << 8));
+
+ /* If MAC address zero, no need to set the AV bit */
+ if (rar_low || rar_high)
+ rar_high |= E1000_RAH_AV;
+
+ if (index == 0) {
+ ew32(RAL(index), rar_low);
+ e1e_flush();
+ ew32(RAH(index), rar_high);
+ e1e_flush();
+ return;
+ }
+
+ if (index < hw->mac.rar_entry_count) {
+ s32 ret_val;
+
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
+ if (ret_val)
+ goto out;
+
+ ew32(SHRAL(index - 1), rar_low);
+ e1e_flush();
+ ew32(SHRAH(index - 1), rar_high);
+ e1e_flush();
+
+ e1000_release_swflag_ich8lan(hw);
+
+ /* verify the register updates */
+ if ((er32(SHRAL(index - 1)) == rar_low) &&
+ (er32(SHRAH(index - 1)) == rar_high))
+ return;
+
+ e_dbg("SHRA[%d] might be locked by ME - FWSM=0x%8.8x\n",
+ (index - 1), er32(FWSM));
+ }
+
+out:
+ e_dbg("Failed to write receive address at index %d\n", index);
+}
+
+/**
+ * e1000_rar_set_pch_lpt - Set receive address registers
+ * @hw: pointer to the HW structure
+ * @addr: pointer to the receive address
+ * @index: receive address array register
+ *
+ * Sets the receive address register array at index to the address passed
+ * in by addr. For LPT, RAR[0] is the base address register that is to
+ * contain the MAC address. SHRA[0-10] are the shared receive address
+ * registers that are shared between the Host and manageability engine (ME).
+ **/
+static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+ u32 rar_low, rar_high;
+ u32 wlock_mac;
+
+ /*
+ * HW expects these in little endian so we reverse the byte order
+ * 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_high = ((u32)addr[4] | ((u32)addr[5] << 8));
+
+ /* If MAC address zero, no need to set the AV bit */
+ if (rar_low || rar_high)
+ rar_high |= E1000_RAH_AV;
+
+ if (index == 0) {
+ ew32(RAL(index), rar_low);
+ e1e_flush();
+ ew32(RAH(index), rar_high);
+ e1e_flush();
+ return;
+ }
+
+ /*
+ * The manageability engine (ME) can lock certain SHRAR registers that
+ * it is using - those registers are unavailable for use.
+ */
+ if (index < hw->mac.rar_entry_count) {
+ wlock_mac = er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK;
+ wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT;
+
+ /* Check if all SHRAR registers are locked */
+ if (wlock_mac == 1)
+ goto out;
+
+ if ((wlock_mac == 0) || (index <= wlock_mac)) {
+ s32 ret_val;
+
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
+
+ if (ret_val)
+ goto out;
+
+ ew32(SHRAL_PCH_LPT(index - 1), rar_low);
+ e1e_flush();
+ ew32(SHRAH_PCH_LPT(index - 1), rar_high);
+ e1e_flush();
+
+ e1000_release_swflag_ich8lan(hw);
+
+ /* verify the register updates */
+ if ((er32(SHRAL_PCH_LPT(index - 1)) == rar_low) &&
+ (er32(SHRAH_PCH_LPT(index - 1)) == rar_high))
+ return;
+ }
+ }
+
+out:
+ e_dbg("Failed to write receive address at index %d\n", index);
+}
+
+/**
* e1000_check_reset_block_ich8lan - Check if PHY reset is blocked
* @hw: pointer to the HW structure
*
@@ -994,6 +1321,8 @@ static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
{
u16 phy_data;
u32 strap = er32(STRAP);
+ u32 freq = (strap & E1000_STRAP_SMT_FREQ_MASK) >>
+ E1000_STRAP_SMT_FREQ_SHIFT;
s32 ret_val = 0;
strap &= E1000_STRAP_SMBUS_ADDRESS_MASK;
@@ -1006,6 +1335,19 @@ static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT);
phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
+ if (hw->phy.type == e1000_phy_i217) {
+ /* Restore SMBus frequency */
+ if (freq--) {
+ phy_data &= ~HV_SMB_ADDR_FREQ_MASK;
+ phy_data |= (freq & (1 << 0)) <<
+ HV_SMB_ADDR_FREQ_LOW_SHIFT;
+ phy_data |= (freq & (1 << 1)) <<
+ (HV_SMB_ADDR_FREQ_HIGH_SHIFT - 1);
+ } else {
+ e_dbg("Unsupported SMB frequency in PHY\n");
+ }
+ }
+
return e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data);
}
@@ -1043,6 +1385,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
/* Fall-thru */
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
break;
default:
@@ -1062,10 +1405,9 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
* extended configuration before SW configuration
*/
data = er32(EXTCNF_CTRL);
- if (!(hw->mac.type == e1000_pch2lan)) {
- if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
- goto release;
- }
+ if ((hw->mac.type < e1000_pch2lan) &&
+ (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE))
+ goto release;
cnf_size = er32(EXTCNF_SIZE);
cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
@@ -1076,9 +1418,9 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
- if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
- (hw->mac.type == e1000_pchlan)) ||
- (hw->mac.type == e1000_pch2lan)) {
+ if (((hw->mac.type == e1000_pchlan) &&
+ !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) ||
+ (hw->mac.type > e1000_pchlan)) {
/*
* HW configures the SMBus address and LEDs when the
* OEM and LCD Write Enable bits are set in the NVM.
@@ -1121,8 +1463,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
reg_addr &= PHY_REG_MASK;
reg_addr |= phy_page;
- ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr,
- reg_data);
+ ret_val = e1e_wphy_locked(hw, (u32)reg_addr, reg_data);
if (ret_val)
goto release;
}
@@ -1159,8 +1500,8 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
/* Disable K1 when link is 1Gbps, otherwise use the NVM setting */
if (link) {
if (hw->phy.type == e1000_phy_82578) {
- ret_val = hw->phy.ops.read_reg_locked(hw, BM_CS_STATUS,
- &status_reg);
+ ret_val = e1e_rphy_locked(hw, BM_CS_STATUS,
+ &status_reg);
if (ret_val)
goto release;
@@ -1175,8 +1516,7 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
}
if (hw->phy.type == e1000_phy_82577) {
- ret_val = hw->phy.ops.read_reg_locked(hw, HV_M_STATUS,
- &status_reg);
+ ret_val = e1e_rphy_locked(hw, HV_M_STATUS, &status_reg);
if (ret_val)
goto release;
@@ -1191,15 +1531,13 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
}
/* Link stall fix for link up */
- ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
- 0x0100);
+ ret_val = e1e_wphy_locked(hw, PHY_REG(770, 19), 0x0100);
if (ret_val)
goto release;
} else {
/* Link stall fix for link down */
- ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
- 0x4100);
+ ret_val = e1e_wphy_locked(hw, PHY_REG(770, 19), 0x4100);
if (ret_val)
goto release;
}
@@ -1279,14 +1617,14 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
u32 mac_reg;
u16 oem_reg;
- if ((hw->mac.type != e1000_pch2lan) && (hw->mac.type != e1000_pchlan))
+ if (hw->mac.type < e1000_pchlan)
return ret_val;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;
- if (!(hw->mac.type == e1000_pch2lan)) {
+ if (hw->mac.type == e1000_pchlan) {
mac_reg = er32(EXTCNF_CTRL);
if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
goto release;
@@ -1298,7 +1636,7 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
mac_reg = er32(PHY_CTRL);
- ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg);
+ ret_val = e1e_rphy_locked(hw, HV_OEM_BITS, &oem_reg);
if (ret_val)
goto release;
@@ -1325,7 +1663,7 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
!hw->phy.ops.check_reset_block(hw))
oem_reg |= HV_OEM_BITS_RESTART_AN;
- ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg);
+ ret_val = e1e_wphy_locked(hw, HV_OEM_BITS, oem_reg);
release:
hw->phy.ops.release(hw);
@@ -1421,11 +1759,10 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;
- ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data);
+ ret_val = e1e_rphy_locked(hw, BM_PORT_GEN_CFG, &phy_data);
if (ret_val)
goto release;
- ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG,
- phy_data & 0x00FF);
+ ret_val = e1e_wphy_locked(hw, BM_PORT_GEN_CFG, phy_data & 0x00FF);
release:
hw->phy.ops.release(hw);
@@ -1484,7 +1821,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
u32 mac_reg;
u16 i;
- if (hw->mac.type != e1000_pch2lan)
+ if (hw->mac.type < e1000_pch2lan)
return 0;
/* disable Rx path while enabling/disabling workaround */
@@ -1657,20 +1994,18 @@ static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw)
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);
+ ret_val = e1e_wphy_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);
+ ret_val = e1e_wphy_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);
+ ret_val = e1e_wphy_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);
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_DATA, 0x0005);
release:
hw->phy.ops.release(hw);
@@ -1708,8 +2043,18 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
return ret_val;
if (status_reg & HV_M_STATUS_SPEED_1000) {
+ u16 pm_phy_reg;
+
mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
+ /* LV 1G Packet drop issue wa */
+ ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg);
+ if (ret_val)
+ return ret_val;
+ pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA;
+ ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg);
+ if (ret_val)
+ return ret_val;
} else {
mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
@@ -1733,7 +2078,7 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate)
{
u32 extcnf_ctrl;
- if (hw->mac.type != e1000_pch2lan)
+ if (hw->mac.type < e1000_pch2lan)
return;
extcnf_ctrl = er32(EXTCNF_CTRL);
@@ -1835,12 +2180,10 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
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_LPI_UPDATE_TIMER);
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR,
+ I82579_LPI_UPDATE_TIMER);
if (!ret_val)
- ret_val = hw->phy.ops.write_reg_locked(hw,
- I82579_EMI_DATA,
- 0x1387);
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_DATA, 0x1387);
hw->phy.ops.release(hw);
}
@@ -2213,7 +2556,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
/* Check if the flash descriptor is valid */
- if (hsfsts.hsf_status.fldesvalid == 0) {
+ if (!hsfsts.hsf_status.fldesvalid) {
e_dbg("Flash descriptor invalid. SW Sequencing must be used.\n");
return -E1000_ERR_NVM;
}
@@ -2233,7 +2576,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
* completed.
*/
- if (hsfsts.hsf_status.flcinprog == 0) {
+ if (!hsfsts.hsf_status.flcinprog) {
/*
* There is no cycle running at present,
* so we can start a cycle.
@@ -2251,7 +2594,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
*/
for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) {
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcinprog == 0) {
+ if (!hsfsts.hsf_status.flcinprog) {
ret_val = 0;
break;
}
@@ -2293,12 +2636,12 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
/* wait till FDONE bit is set to 1 */
do {
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcdone == 1)
+ if (hsfsts.hsf_status.flcdone)
break;
udelay(1);
} while (i++ < timeout);
- if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0)
+ if (hsfsts.hsf_status.flcdone && !hsfsts.hsf_status.flcerr)
return 0;
return -E1000_ERR_NVM;
@@ -2409,10 +2752,10 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
* ICH_FLASH_CYCLE_REPEAT_COUNT times.
*/
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1) {
+ if (hsfsts.hsf_status.flcerr) {
/* Repeat for some time before giving up. */
continue;
- } else if (hsfsts.hsf_status.flcdone == 0) {
+ } else if (!hsfsts.hsf_status.flcdone) {
e_dbg("Timeout error - flash cycle did not complete.\n");
break;
}
@@ -2642,7 +2985,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- if ((data & 0x40) == 0) {
+ if (!(data & 0x40)) {
data |= 0x40;
ret_val = e1000_write_nvm(hw, 0x19, 1, &data);
if (ret_val)
@@ -2760,10 +3103,10 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
* try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
*/
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1)
+ if (hsfsts.hsf_status.flcerr)
/* Repeat for some time before giving up. */
continue;
- if (hsfsts.hsf_status.flcdone == 0) {
+ if (!hsfsts.hsf_status.flcdone) {
e_dbg("Timeout error - flash cycle did not complete.\n");
break;
}
@@ -2915,10 +3258,10 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
* a few more times else Done
*/
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1)
+ if (hsfsts.hsf_status.flcerr)
/* repeat for some time before giving up */
continue;
- else if (hsfsts.hsf_status.flcdone == 0)
+ else if (!hsfsts.hsf_status.flcdone)
return ret_val;
} while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT);
}
@@ -3060,8 +3403,8 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
{
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
- u16 reg;
- u32 ctrl, kab;
+ u16 kum_cfg;
+ u32 ctrl, reg;
s32 ret_val;
/*
@@ -3095,12 +3438,12 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
}
if (hw->mac.type == e1000_pchlan) {
- /* Save the NVM K1 bit setting*/
- ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &reg);
+ /* Save the NVM K1 bit setting */
+ ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &kum_cfg);
if (ret_val)
return ret_val;
- if (reg & E1000_NVM_K1_ENABLE)
+ if (kum_cfg & E1000_NVM_K1_ENABLE)
dev_spec->nvm_k1_enabled = true;
else
dev_spec->nvm_k1_enabled = false;
@@ -3130,6 +3473,14 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
/* cannot issue a flush here because it hangs the hardware */
msleep(20);
+ /* Set Phy Config Counter to 50msec */
+ if (hw->mac.type == e1000_pch2lan) {
+ reg = er32(FEXTNVM3);
+ reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
+ reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
+ ew32(FEXTNVM3, reg);
+ }
+
if (!ret_val)
clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state);
@@ -3154,9 +3505,9 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ew32(IMC, 0xffffffff);
er32(ICR);
- kab = er32(KABGTXD);
- kab |= E1000_KABGTXD_BGSQLBIAS;
- ew32(KABGTXD, kab);
+ reg = er32(KABGTXD);
+ reg |= E1000_KABGTXD_BGSQLBIAS;
+ ew32(KABGTXD, reg);
return 0;
}
@@ -3309,6 +3660,13 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
*/
reg = er32(RFCTL);
reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS);
+
+ /*
+ * Disable IPv6 extension header parsing because some malformed
+ * IPv6 headers can hang the Rx.
+ */
+ if (hw->mac.type == e1000_ich8lan)
+ reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
ew32(RFCTL, reg);
}
@@ -3359,6 +3717,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
ew32(FCTTV, hw->fc.pause_time);
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
+ (hw->phy.type == e1000_phy_i217) ||
(hw->phy.type == e1000_phy_82577)) {
ew32(FCRTV_PCH, hw->fc.refresh_time);
@@ -3422,6 +3781,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
break;
case e1000_phy_82577:
case e1000_phy_82579:
+ case e1000_phy_i217:
ret_val = e1000_copper_link_setup_82577(hw);
if (ret_val)
return ret_val;
@@ -3668,14 +4028,88 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
* 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.
+ * Parts that support (and are linked to a partner which support) EEE in
+ * 100Mbps should disable LPLU since 100Mbps w/ EEE requires less power
+ * than 10Mbps w/o EEE.
**/
void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
{
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
u32 phy_ctrl;
s32 ret_val;
phy_ctrl = er32(PHY_CTRL);
phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE;
+ if (hw->phy.type == e1000_phy_i217) {
+ u16 phy_reg;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+
+ if (!dev_spec->eee_disable) {
+ u16 eee_advert;
+
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR,
+ I217_EEE_ADVERTISEMENT);
+ if (ret_val)
+ goto release;
+ e1e_rphy_locked(hw, I82579_EMI_DATA, &eee_advert);
+
+ /*
+ * Disable LPLU if both link partners support 100BaseT
+ * EEE and 100Full is advertised on both ends of the
+ * link.
+ */
+ if ((eee_advert & I217_EEE_100_SUPPORTED) &&
+ (dev_spec->eee_lp_ability &
+ I217_EEE_100_SUPPORTED) &&
+ (hw->phy.autoneg_advertised & ADVERTISE_100_FULL))
+ phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU |
+ E1000_PHY_CTRL_NOND0A_LPLU);
+ }
+
+ /*
+ * For i217 Intel Rapid Start Technology support,
+ * when the system is going into Sx and no manageability engine
+ * is present, the driver must configure proxy to reset only on
+ * power good. LPI (Low Power Idle) state must also reset only
+ * on power good, as well as the MTA (Multicast table array).
+ * The SMBus release must also be disabled on LCD reset.
+ */
+ if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
+
+ /* Enable proxy to reset only on power good. */
+ e1e_rphy_locked(hw, I217_PROXY_CTRL, &phy_reg);
+ phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE;
+ e1e_wphy_locked(hw, I217_PROXY_CTRL, phy_reg);
+
+ /*
+ * Set bit enable LPI (EEE) to reset only on
+ * power good.
+ */
+ e1e_rphy_locked(hw, I217_SxCTRL, &phy_reg);
+ phy_reg |= I217_SxCTRL_MASK;
+ e1e_wphy_locked(hw, I217_SxCTRL, phy_reg);
+
+ /* Disable the SMB release on LCD reset. */
+ e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg);
+ phy_reg &= ~I217_MEMPWR;
+ e1e_wphy_locked(hw, I217_MEMPWR, phy_reg);
+ }
+
+ /*
+ * Enable MTA to reset for Intel Rapid Start Technology
+ * Support
+ */
+ e1e_rphy_locked(hw, I217_CGFREG, &phy_reg);
+ phy_reg |= I217_CGFREG_MASK;
+ e1e_wphy_locked(hw, I217_CGFREG, phy_reg);
+
+release:
+ hw->phy.ops.release(hw);
+ }
+out:
ew32(PHY_CTRL, phy_ctrl);
if (hw->mac.type == e1000_ich8lan)
@@ -3704,44 +4138,61 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
* on which PHY resets are not blocked, if the PHY registers cannot be
* accessed properly by the s/w toggle the LANPHYPC value to power cycle
* the PHY.
+ * On i217, setup Intel Rapid Start Technology.
**/
void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
{
- u16 phy_id1, phy_id2;
s32 ret_val;
- if ((hw->mac.type != e1000_pch2lan) ||
- hw->phy.ops.check_reset_block(hw))
+ if (hw->mac.type < e1000_pch2lan)
return;
- ret_val = hw->phy.ops.acquire(hw);
+ ret_val = e1000_init_phy_workarounds_pchlan(hw);
if (ret_val) {
- e_dbg("Failed to acquire PHY semaphore in resume\n");
+ e_dbg("Failed to init PHY flow ret_val=%d\n", ret_val);
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;
-
- if (hw->phy.id == ((u32)(phy_id1 << 16) |
- (u32)(phy_id2 & PHY_REVISION_MASK)))
- goto release;
+ /*
+ * For i217 Intel Rapid Start Technology support when the system
+ * is transitioning from Sx and no manageability engine is present
+ * configure SMBus to restore on reset, disable proxy, and enable
+ * the reset on MTA (Multicast table array).
+ */
+ if (hw->phy.type == e1000_phy_i217) {
+ u16 phy_reg;
- e1000_toggle_lanphypc_value_ich8lan(hw);
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ e_dbg("Failed to setup iRST\n");
+ return;
+ }
- hw->phy.ops.release(hw);
- msleep(50);
- e1000_phy_hw_reset(hw);
- msleep(50);
- return;
+ if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
+ /*
+ * Restore clear on SMB if no manageability engine
+ * is present
+ */
+ ret_val = e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg);
+ if (ret_val)
+ goto release;
+ phy_reg |= I217_MEMPWR_MASK;
+ e1e_wphy_locked(hw, I217_MEMPWR, phy_reg);
+ /* Disable Proxy */
+ e1e_wphy_locked(hw, I217_PROXY_CTRL, 0);
+ }
+ /* Enable reset on MTA */
+ ret_val = e1e_rphy_locked(hw, I217_CGFREG, &phy_reg);
+ if (ret_val)
+ goto release;
+ phy_reg &= ~I217_CGFREG_MASK;
+ e1e_wphy_locked(hw, I217_CGFREG, phy_reg);
release:
- hw->phy.ops.release(hw);
+ if (ret_val)
+ e_dbg("Error %d in resume workarounds\n", ret_val);
+ hw->phy.ops.release(hw);
+ }
}
/**
@@ -3921,7 +4372,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
/* If EEPROM is not marked present, init the IGP 3 PHY manually */
if (hw->mac.type <= e1000_ich9lan) {
- if (((er32(EECD) & E1000_EECD_PRES) == 0) &&
+ if (!(er32(EECD) & E1000_EECD_PRES) &&
(hw->phy.type == e1000_phy_igp_3)) {
e1000e_phy_init_script_igp3(hw);
}
@@ -3982,6 +4433,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
/* Clear PHY statistics registers */
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
+ (hw->phy.type == e1000_phy_i217) ||
(hw->phy.type == e1000_phy_82577)) {
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
@@ -4026,6 +4478,7 @@ static const struct e1000_mac_operations ich8_mac_ops = {
.setup_physical_interface= e1000_setup_copper_link_ich8lan,
/* id_led_init dependent on mac type */
.config_collision_dist = e1000e_config_collision_dist_generic,
+ .rar_set = e1000e_rar_set_generic,
};
static const struct e1000_phy_operations ich8_phy_ops = {
@@ -4140,3 +4593,22 @@ const struct e1000_info e1000_pch2_info = {
.phy_ops = &ich8_phy_ops,
.nvm_ops = &ich8_nvm_ops,
};
+
+const struct e1000_info e1000_pch_lpt_info = {
+ .mac = e1000_pch_lpt,
+ .flags = FLAG_IS_ICH
+ | FLAG_HAS_WOL
+ | FLAG_HAS_CTRLEXT_ON_LOAD
+ | FLAG_HAS_AMT
+ | FLAG_HAS_FLASH
+ | FLAG_HAS_JUMBO_FRAMES
+ | FLAG_APME_IN_WUC,
+ .flags2 = FLAG2_HAS_PHY_STATS
+ | FLAG2_HAS_EEE,
+ .pba = 26,
+ .max_hw_frame_size = DEFAULT_JUMBO,
+ .get_variants = e1000_get_variants_ich8lan,
+ .mac_ops = &ich8_mac_ops,
+ .phy_ops = &ich8_phy_ops,
+ .nvm_ops = &ich8_nvm_ops,
+};
diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c
index decad98c1059..026e8b3ab52e 100644
--- a/drivers/net/ethernet/intel/e1000e/mac.c
+++ b/drivers/net/ethernet/intel/e1000e/mac.c
@@ -143,12 +143,12 @@ void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
/* Setup the receive address */
e_dbg("Programming MAC Address into RAR[0]\n");
- e1000e_rar_set(hw, hw->mac.addr, 0);
+ hw->mac.ops.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);
for (i = 1; i < rar_count; i++)
- e1000e_rar_set(hw, mac_addr, i);
+ hw->mac.ops.rar_set(hw, mac_addr, i);
}
/**
@@ -215,13 +215,13 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
* same as the normal permanent MAC address stored by the HW into the
* RAR. Do this by mapping this address into RAR0.
*/
- e1000e_rar_set(hw, alt_mac_addr, 0);
+ hw->mac.ops.rar_set(hw, alt_mac_addr, 0);
return 0;
}
/**
- * e1000e_rar_set - Set receive address register
+ * e1000e_rar_set_generic - Set receive address register
* @hw: pointer to the HW structure
* @addr: pointer to the receive address
* @index: receive address array register
@@ -229,7 +229,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
* Sets the receive address array register at index to the address passed
* in by addr.
**/
-void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
+void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
{
u32 rar_low, rar_high;
@@ -681,7 +681,7 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
return ret_val;
}
- if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
+ if (!(nvm_data & NVM_WORD0F_PAUSE_MASK))
hw->fc.requested_mode = e1000_fc_none;
else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == NVM_WORD0F_ASM_DIR)
hw->fc.requested_mode = e1000_fc_tx_pause;
diff --git a/drivers/net/ethernet/intel/e1000e/manage.c b/drivers/net/ethernet/intel/e1000e/manage.c
index 473f8e711510..bacc950fc684 100644
--- a/drivers/net/ethernet/intel/e1000e/manage.c
+++ b/drivers/net/ethernet/intel/e1000e/manage.c
@@ -85,7 +85,7 @@ static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
/* Check that the host interface is enabled. */
hicr = er32(HICR);
- if ((hicr & E1000_HICR_EN) == 0) {
+ if (!(hicr & E1000_HICR_EN)) {
e_dbg("E1000_HOST_EN bit disabled.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 9520a6ac1f30..a4b0435b00dc 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -56,7 +56,7 @@
#define DRV_EXTRAVERSION "-k"
-#define DRV_VERSION "1.9.5" DRV_EXTRAVERSION
+#define DRV_VERSION "2.0.0" DRV_EXTRAVERSION
char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION;
@@ -79,6 +79,7 @@ static const struct e1000_info *e1000_info_tbl[] = {
[board_ich10lan] = &e1000_ich10_info,
[board_pchlan] = &e1000_pch_info,
[board_pch2lan] = &e1000_pch2_info,
+ [board_pch_lpt] = &e1000_pch_lpt_info,
};
struct e1000_reg_info {
@@ -110,14 +111,14 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = {
/* Rx Registers */
{E1000_RCTL, "RCTL"},
- {E1000_RDLEN, "RDLEN"},
- {E1000_RDH, "RDH"},
- {E1000_RDT, "RDT"},
+ {E1000_RDLEN(0), "RDLEN"},
+ {E1000_RDH(0), "RDH"},
+ {E1000_RDT(0), "RDT"},
{E1000_RDTR, "RDTR"},
{E1000_RXDCTL(0), "RXDCTL"},
{E1000_ERT, "ERT"},
- {E1000_RDBAL, "RDBAL"},
- {E1000_RDBAH, "RDBAH"},
+ {E1000_RDBAL(0), "RDBAL"},
+ {E1000_RDBAH(0), "RDBAH"},
{E1000_RDFH, "RDFH"},
{E1000_RDFT, "RDFT"},
{E1000_RDFHS, "RDFHS"},
@@ -126,11 +127,11 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = {
/* Tx Registers */
{E1000_TCTL, "TCTL"},
- {E1000_TDBAL, "TDBAL"},
- {E1000_TDBAH, "TDBAH"},
- {E1000_TDLEN, "TDLEN"},
- {E1000_TDH, "TDH"},
- {E1000_TDT, "TDT"},
+ {E1000_TDBAL(0), "TDBAL"},
+ {E1000_TDBAH(0), "TDBAH"},
+ {E1000_TDLEN(0), "TDLEN"},
+ {E1000_TDH(0), "TDH"},
+ {E1000_TDT(0), "TDT"},
{E1000_TIDV, "TIDV"},
{E1000_TXDCTL(0), "TXDCTL"},
{E1000_TADV, "TADV"},
@@ -538,43 +539,15 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
adapter->hw_csum_good++;
}
-/**
- * e1000e_update_tail_wa - helper function for e1000e_update_[rt]dt_wa()
- * @hw: pointer to the HW structure
- * @tail: address of tail descriptor register
- * @i: value to write to tail descriptor register
- *
- * When updating the tail register, the ME could be accessing Host CSR
- * registers at the same time. Normally, this is handled in h/w by an
- * arbiter but on some parts there is a bug that acknowledges Host accesses
- * later than it should which could result in the descriptor register to
- * have an incorrect value. Workaround this by checking the FWSM register
- * 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, void __iomem *tail,
- unsigned int i)
-{
- unsigned int j = 0;
-
- while ((j++ < E1000_ICH_FWSM_PCIM2PCI_COUNT) &&
- (er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI))
- udelay(50);
-
- writel(i, tail);
-
- if ((j == E1000_ICH_FWSM_PCIM2PCI_COUNT) && (i != readl(tail)))
- return E1000_ERR_SWFW_SYNC;
-
- return 0;
-}
-
static void e1000e_update_rdt_wa(struct e1000_ring *rx_ring, unsigned int i)
{
struct e1000_adapter *adapter = rx_ring->adapter;
struct e1000_hw *hw = &adapter->hw;
+ s32 ret_val = __ew32_prepare(hw);
- if (e1000e_update_tail_wa(hw, rx_ring->tail, i)) {
+ writel(i, rx_ring->tail);
+
+ if (unlikely(!ret_val && (i != readl(rx_ring->tail)))) {
u32 rctl = er32(RCTL);
ew32(RCTL, rctl & ~E1000_RCTL_EN);
e_err("ME firmware caused invalid RDT - resetting\n");
@@ -586,8 +559,11 @@ static void e1000e_update_tdt_wa(struct e1000_ring *tx_ring, unsigned int i)
{
struct e1000_adapter *adapter = tx_ring->adapter;
struct e1000_hw *hw = &adapter->hw;
+ s32 ret_val = __ew32_prepare(hw);
+
+ writel(i, tx_ring->tail);
- if (e1000e_update_tail_wa(hw, tx_ring->tail, i)) {
+ if (unlikely(!ret_val && (i != readl(tx_ring->tail)))) {
u32 tctl = er32(TCTL);
ew32(TCTL, tctl & ~E1000_TCTL_EN);
e_err("ME firmware caused invalid TDT - resetting\n");
@@ -1053,7 +1029,8 @@ static void e1000_print_hw_hang(struct work_struct *work)
if (!adapter->tx_hang_recheck &&
(adapter->flags2 & FLAG2_DMA_BURST)) {
- /* May be block on write-back, flush and detect again
+ /*
+ * May be block on write-back, flush and detect again
* flush pending descriptor writebacks to memory
*/
ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
@@ -1108,6 +1085,10 @@ static void e1000_print_hw_hang(struct work_struct *work)
phy_1000t_status,
phy_ext_status,
pci_status);
+
+ /* Suggest workaround for known h/w issue */
+ if ((hw->mac.type == e1000_pchlan) && (er32(CTRL) & E1000_CTRL_TFCE))
+ e_err("Try turning off Tx pause (flow control) via ethtool\n");
}
/**
@@ -1645,7 +1626,10 @@ static void e1000_clean_rx_ring(struct e1000_ring *rx_ring)
adapter->flags2 &= ~FLAG2_IS_DISCARDING;
writel(0, rx_ring->head);
- writel(0, rx_ring->tail);
+ if (rx_ring->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
+ e1000e_update_rdt_wa(rx_ring, 0);
+ else
+ writel(0, rx_ring->tail);
}
static void e1000e_downshift_workaround(struct work_struct *work)
@@ -2318,7 +2302,10 @@ static void e1000_clean_tx_ring(struct e1000_ring *tx_ring)
tx_ring->next_to_clean = 0;
writel(0, tx_ring->head);
- writel(0, tx_ring->tail);
+ if (tx_ring->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
+ e1000e_update_tdt_wa(tx_ring, 0);
+ else
+ writel(0, tx_ring->tail);
}
/**
@@ -2530,33 +2517,31 @@ err:
}
/**
- * e1000_clean - NAPI Rx polling callback
+ * e1000e_poll - NAPI Rx polling callback
* @napi: struct associated with this polling callback
- * @budget: amount of packets driver is allowed to process this poll
+ * @weight: number of packets driver is allowed to process this poll
**/
-static int e1000_clean(struct napi_struct *napi, int budget)
+static int e1000e_poll(struct napi_struct *napi, int weight)
{
- struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
+ struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter,
+ napi);
struct e1000_hw *hw = &adapter->hw;
struct net_device *poll_dev = adapter->netdev;
int tx_cleaned = 1, work_done = 0;
adapter = netdev_priv(poll_dev);
- if (adapter->msix_entries &&
- !(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val))
- goto clean_rx;
-
- tx_cleaned = e1000_clean_tx_irq(adapter->tx_ring);
+ if (!adapter->msix_entries ||
+ (adapter->rx_ring->ims_val & adapter->tx_ring->ims_val))
+ tx_cleaned = e1000_clean_tx_irq(adapter->tx_ring);
-clean_rx:
- adapter->clean_rx(adapter->rx_ring, &work_done, budget);
+ adapter->clean_rx(adapter->rx_ring, &work_done, weight);
if (!tx_cleaned)
- work_done = budget;
+ work_done = weight;
- /* If budget not fully consumed, exit the polling mode */
- if (work_done < budget) {
+ /* If weight not fully consumed, exit the polling mode */
+ if (work_done < weight) {
if (adapter->itr_setting & 3)
e1000_set_itr(adapter);
napi_complete(napi);
@@ -2800,13 +2785,13 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
/* Setup the HW Tx Head and Tail descriptor pointers */
tdba = tx_ring->dma;
tdlen = tx_ring->count * sizeof(struct e1000_tx_desc);
- ew32(TDBAL, (tdba & DMA_BIT_MASK(32)));
- ew32(TDBAH, (tdba >> 32));
- ew32(TDLEN, tdlen);
- ew32(TDH, 0);
- ew32(TDT, 0);
- tx_ring->head = adapter->hw.hw_addr + E1000_TDH;
- tx_ring->tail = adapter->hw.hw_addr + E1000_TDT;
+ ew32(TDBAL(0), (tdba & DMA_BIT_MASK(32)));
+ ew32(TDBAH(0), (tdba >> 32));
+ ew32(TDLEN(0), tdlen);
+ ew32(TDH(0), 0);
+ ew32(TDT(0), 0);
+ tx_ring->head = adapter->hw.hw_addr + E1000_TDH(0);
+ tx_ring->tail = adapter->hw.hw_addr + E1000_TDT(0);
/* Set the Tx Interrupt Delay register */
ew32(TIDV, adapter->tx_int_delay);
@@ -2879,8 +2864,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
u32 rctl, rfctl;
u32 pages = 0;
- /* Workaround Si errata on 82579 - configure jumbo frame flow */
- if (hw->mac.type == e1000_pch2lan) {
+ /* Workaround Si errata on PCHx - configure jumbo frame flow */
+ if (hw->mac.type >= e1000_pch2lan) {
s32 ret_val;
if (adapter->netdev->mtu > ETH_DATA_LEN)
@@ -2955,6 +2940,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
/* Enable Extended Status in all Receive Descriptors */
rfctl = er32(RFCTL);
rfctl |= E1000_RFCTL_EXTEN;
+ ew32(RFCTL, rfctl);
/*
* 82571 and greater support packet-split where the protocol
@@ -2980,13 +2966,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
if (adapter->rx_ps_pages) {
u32 psrctl = 0;
- /*
- * disable packet split support for IPv6 extension headers,
- * because some malformed IPv6 headers can hang the Rx
- */
- rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
- E1000_RFCTL_NEW_IPV6_EXT_DIS);
-
/* Enable Packet split descriptors */
rctl |= E1000_RCTL_DTYP_PS;
@@ -3025,7 +3004,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
*/
}
- ew32(RFCTL, rfctl);
ew32(RCTL, rctl);
/* just started the receive unit, no need to restart */
adapter->flags &= ~FLAG_RX_RESTART_NOW;
@@ -3110,13 +3088,13 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
* the Base and Length of the Rx Descriptor Ring
*/
rdba = rx_ring->dma;
- ew32(RDBAL, (rdba & DMA_BIT_MASK(32)));
- ew32(RDBAH, (rdba >> 32));
- ew32(RDLEN, rdlen);
- ew32(RDH, 0);
- ew32(RDT, 0);
- rx_ring->head = adapter->hw.hw_addr + E1000_RDH;
- rx_ring->tail = adapter->hw.hw_addr + E1000_RDT;
+ ew32(RDBAL(0), (rdba & DMA_BIT_MASK(32)));
+ ew32(RDBAH(0), (rdba >> 32));
+ ew32(RDLEN(0), rdlen);
+ ew32(RDH(0), 0);
+ ew32(RDT(0), 0);
+ rx_ring->head = adapter->hw.hw_addr + E1000_RDH(0);
+ rx_ring->tail = adapter->hw.hw_addr + E1000_RDT(0);
/* Enable Receive Checksum Offload for TCP and UDP */
rxcsum = er32(RXCSUM);
@@ -3229,7 +3207,7 @@ static int e1000e_write_uc_addr_list(struct net_device *netdev)
netdev_for_each_uc_addr(ha, netdev) {
if (!rar_entries)
break;
- e1000e_rar_set(hw, ha->addr, rar_entries--);
+ hw->mac.ops.rar_set(hw, ha->addr, rar_entries--);
count++;
}
}
@@ -3510,6 +3488,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
fc->refresh_time = 0x1000;
break;
case e1000_pch2lan:
+ case e1000_pch_lpt:
fc->high_water = 0x05C20;
fc->low_water = 0x05048;
fc->pause_time = 0x0650;
@@ -4038,6 +4017,7 @@ static int e1000_close(struct net_device *netdev)
static int e1000_set_mac(struct net_device *netdev, void *p)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
@@ -4046,7 +4026,7 @@ static int e1000_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);
- e1000e_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
+ hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) {
/* activate the work around */
@@ -4060,9 +4040,8 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
* are dropped. Eventually the LAA will be in RAR[0] and
* RAR[14]
*/
- e1000e_rar_set(&adapter->hw,
- adapter->hw.mac.addr,
- adapter->hw.mac.rar_entry_count - 1);
+ hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr,
+ adapter->hw.mac.rar_entry_count - 1);
}
return 0;
@@ -4641,7 +4620,7 @@ link_up:
* reset from the other port. Set the appropriate LAA in RAR[0]
*/
if (e1000e_get_laa_state_82571(hw))
- e1000e_rar_set(hw, adapter->hw.mac.addr, 0);
+ hw->mac.ops.rar_set(hw, adapter->hw.mac.addr, 0);
if (adapter->flags2 & FLAG2_CHECK_PHY_HANG)
e1000e_check_82574_phy_workaround(adapter);
@@ -5151,6 +5130,8 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
/* if count is 0 then mapping error has occurred */
count = e1000_tx_map(tx_ring, skb, first, max_per_txd, nr_frags, mss);
if (count) {
+ skb_tx_timestamp(skb);
+
netdev_sent_queue(netdev, skb->len);
e1000_tx_queue(tx_ring, tx_flags, count);
/* Make sure there is space in the ring for the next send. */
@@ -5285,22 +5266,14 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
return -EINVAL;
}
- /* Jumbo frame workaround on 82579 requires CRC be stripped */
- if ((adapter->hw.mac.type == e1000_pch2lan) &&
+ /* Jumbo frame workaround on 82579 and newer requires CRC be stripped */
+ if ((adapter->hw.mac.type >= e1000_pch2lan) &&
!(adapter->flags2 & FLAG2_CRC_STRIPPING) &&
(new_mtu > ETH_DATA_LEN)) {
- e_err("Jumbo Frames not supported on 82579 when CRC stripping is disabled.\n");
+ e_err("Jumbo Frames not supported on this device when CRC stripping is disabled.\n");
return -EINVAL;
}
- /* 82573 Errata 17 */
- if (((adapter->hw.mac.type == e1000_82573) ||
- (adapter->hw.mac.type == e1000_82574)) &&
- (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN)) {
- adapter->flags2 |= FLAG2_DISABLE_ASPM_L1;
- e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L1);
- }
-
while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
usleep_range(1000, 2000);
/* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */
@@ -5694,7 +5667,7 @@ static int __e1000_resume(struct pci_dev *pdev)
return err;
}
- if (hw->mac.type == e1000_pch2lan)
+ if (hw->mac.type >= e1000_pch2lan)
e1000_resume_workarounds_pchlan(&adapter->hw);
e1000e_power_up_phy(adapter);
@@ -6226,7 +6199,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
netdev->netdev_ops = &e1000e_netdev_ops;
e1000e_set_ethtool_ops(netdev);
netdev->watchdog_timeo = 5 * HZ;
- netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
+ netif_napi_add(netdev, &adapter->napi, e1000e_poll, 64);
strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
netdev->mem_start = mmio_start;
@@ -6593,6 +6566,9 @@ 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 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_LM), board_pch_lpt },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_V), board_pch_lpt },
+
{ 0, 0, 0, 0, 0, 0, 0 } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
diff --git a/drivers/net/ethernet/intel/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c
index 16adeb9418a8..55cc1565bc2f 100644
--- a/drivers/net/ethernet/intel/e1000e/param.c
+++ b/drivers/net/ethernet/intel/e1000e/param.c
@@ -166,8 +166,8 @@ E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lea
*
* Default Value: 1 (enabled)
*/
-E1000_PARAM(CrcStripping, "Enable CRC Stripping, disable if your BMC needs " \
- "the CRC");
+E1000_PARAM(CrcStripping,
+ "Enable CRC Stripping, disable if your BMC needs the CRC");
struct e1000_option {
enum { enable_option, range_option, list_option } type;
@@ -347,8 +347,8 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
/*
* Make sure a message is printed for non-special
- * values. And in case of an invalid option, display
- * warning, use default and got through itr/itr_setting
+ * values. And in case of an invalid option, display
+ * warning, use default and go through itr/itr_setting
* adjustment logic below
*/
if ((adapter->itr > 4) &&
@@ -365,7 +365,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
* Make sure a message is printed for non-special
* default values
*/
- if (adapter->itr > 40)
+ if (adapter->itr > 4)
e_info("%s set to default %d\n", opt.name,
adapter->itr);
}
diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
index 35b45578c604..0334d013bc3c 100644
--- a/drivers/net/ethernet/intel/e1000e/phy.c
+++ b/drivers/net/ethernet/intel/e1000e/phy.c
@@ -639,6 +639,45 @@ s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
}
/**
+ * e1000_set_master_slave_mode - Setup PHY for Master/slave mode
+ * @hw: pointer to the HW structure
+ *
+ * Sets up Master/slave mode
+ **/
+static s32 e1000_set_master_slave_mode(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ u16 phy_data;
+
+ /* Resolve Master/Slave mode */
+ ret_val = e1e_rphy(hw, PHY_1000T_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* load defaults for future use */
+ hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ?
+ ((phy_data & CR_1000T_MS_VALUE) ?
+ e1000_ms_force_master : e1000_ms_force_slave) : e1000_ms_auto;
+
+ switch (hw->phy.ms_type) {
+ case e1000_ms_force_master:
+ phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_force_slave:
+ phy_data |= CR_1000T_MS_ENABLE;
+ phy_data &= ~(CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_auto:
+ phy_data &= ~CR_1000T_MS_ENABLE;
+ /* fall-through */
+ default:
+ break;
+ }
+
+ return e1e_wphy(hw, PHY_1000T_CTRL, phy_data);
+}
+
+/**
* e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
* @hw: pointer to the HW structure
*
@@ -659,7 +698,11 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
/* Enable downshift */
phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
- return e1e_wphy(hw, I82577_CFG_REG, phy_data);
+ ret_val = e1e_wphy(hw, I82577_CFG_REG, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ return e1000_set_master_slave_mode(hw);
}
/**
@@ -718,12 +761,28 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
* 1 - Enabled
*/
phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
- if (phy->disable_polarity_correction == 1)
+ if (phy->disable_polarity_correction)
phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
/* Enable downshift on BM (disabled by default) */
- if (phy->type == e1000_phy_bm)
+ if (phy->type == e1000_phy_bm) {
+ /* For 82574/82583, first disable then enable downshift */
+ if (phy->id == BME1000_E_PHY_ID_R2) {
+ phy_data &= ~BME1000_PSCR_ENABLE_DOWNSHIFT;
+ ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ /* Commit the changes. */
+ ret_val = e1000e_commit_phy(hw);
+ if (ret_val) {
+ e_dbg("Error committing the PHY changes\n");
+ return ret_val;
+ }
+ }
+
phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT;
+ }
ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
if (ret_val)
@@ -879,31 +938,7 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
return ret_val;
}
- ret_val = e1e_rphy(hw, PHY_1000T_CTRL, &data);
- if (ret_val)
- return ret_val;
-
- /* load defaults for future use */
- phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ?
- ((data & CR_1000T_MS_VALUE) ?
- e1000_ms_force_master :
- e1000_ms_force_slave) :
- e1000_ms_auto;
-
- switch (phy->ms_type) {
- case e1000_ms_force_master:
- data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
- break;
- case e1000_ms_force_slave:
- data |= CR_1000T_MS_ENABLE;
- data &= ~(CR_1000T_MS_VALUE);
- break;
- case e1000_ms_auto:
- data &= ~CR_1000T_MS_ENABLE;
- default:
- break;
- }
- ret_val = e1e_wphy(hw, PHY_1000T_CTRL, data);
+ ret_val = e1000_set_master_slave_mode(hw);
}
return ret_val;
@@ -1090,7 +1125,7 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
* If autoneg_advertised is zero, we assume it was not defaulted
* by the calling code so we set to advertise full capability.
*/
- if (phy->autoneg_advertised == 0)
+ if (!phy->autoneg_advertised)
phy->autoneg_advertised = phy->autoneg_mask;
e_dbg("Reconfiguring auto-neg advertisement params\n");
@@ -1596,7 +1631,7 @@ s32 e1000e_check_downshift(struct e1000_hw *hw)
ret_val = e1e_rphy(hw, offset, &phy_data);
if (!ret_val)
- phy->speed_downgraded = (phy_data & mask);
+ phy->speed_downgraded = !!(phy_data & mask);
return ret_val;
}
@@ -1925,8 +1960,8 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- phy->polarity_correction = (phy_data &
- M88E1000_PSCR_POLARITY_REVERSAL);
+ phy->polarity_correction = !!(phy_data &
+ M88E1000_PSCR_POLARITY_REVERSAL);
ret_val = e1000_check_polarity_m88(hw);
if (ret_val)
@@ -1936,7 +1971,7 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX);
+ phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX);
if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
ret_val = e1000_get_cable_length(hw);
@@ -1999,7 +2034,7 @@ s32 e1000e_get_phy_info_igp(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- phy->is_mdix = (data & IGP01E1000_PSSR_MDIX);
+ phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX);
if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
IGP01E1000_PSSR_SPEED_1000MBPS) {
@@ -2052,8 +2087,7 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data);
if (ret_val)
return ret_val;
- phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE)
- ? false : true;
+ phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE);
if (phy->polarity_correction) {
ret_val = e1000_check_polarity_ife(hw);
@@ -2070,7 +2104,7 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? true : false;
+ phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS);
/* The following parameters are undefined for 10/100 operation. */
phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
@@ -2320,6 +2354,9 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id)
case I82579_E_PHY_ID:
phy_type = e1000_phy_82579;
break;
+ case I217_E_PHY_ID:
+ phy_type = e1000_phy_i217;
+ break;
default:
phy_type = e1000_phy_unknown;
break;
@@ -2979,7 +3016,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
if ((hw->phy.type == e1000_phy_82578) &&
(hw->phy.revision >= 1) &&
(hw->phy.addr == 2) &&
- ((MAX_PHY_REG_ADDRESS & reg) == 0) && (data & (1 << 11))) {
+ !(MAX_PHY_REG_ADDRESS & reg) && (data & (1 << 11))) {
u16 data2 = 0x7EFF;
ret_val = e1000_access_phy_debug_regs_hv(hw,
(1 << 6) | 0x3,
@@ -3265,7 +3302,7 @@ s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? true : false;
+ phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX);
if ((data & I82577_PHY_STATUS2_SPEED_MASK) ==
I82577_PHY_STATUS2_SPEED_1000MBPS) {
diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile
index 6565c463185c..97c197fd4a8e 100644
--- a/drivers/net/ethernet/intel/igb/Makefile
+++ b/drivers/net/ethernet/intel/igb/Makefile
@@ -33,5 +33,7 @@
obj-$(CONFIG_IGB) += igb.o
igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
- e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o
+ e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \
+ e1000_i210.o
+igb-$(CONFIG_IGB_PTP) += igb_ptp.o
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index 08bdc33715ee..e65083958421 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -36,6 +36,7 @@
#include "e1000_mac.h"
#include "e1000_82575.h"
+#include "e1000_i210.h"
static s32 igb_get_invariants_82575(struct e1000_hw *);
static s32 igb_acquire_phy_82575(struct e1000_hw *);
@@ -52,6 +53,8 @@ static s32 igb_write_phy_reg_82580(struct e1000_hw *, u32, u16);
static s32 igb_reset_hw_82575(struct e1000_hw *);
static s32 igb_reset_hw_82580(struct e1000_hw *);
static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *, bool);
+static s32 igb_set_d0_lplu_state_82580(struct e1000_hw *, bool);
+static s32 igb_set_d3_lplu_state_82580(struct e1000_hw *, bool);
static s32 igb_setup_copper_link_82575(struct e1000_hw *);
static s32 igb_setup_serdes_link_82575(struct e1000_hw *);
static s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16);
@@ -96,6 +99,8 @@ static bool igb_sgmii_uses_mdio_82575(struct e1000_hw *hw)
break;
case e1000_82580:
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
reg = rd32(E1000_MDICNFG);
ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO);
break;
@@ -150,6 +155,17 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
case E1000_DEV_ID_I350_SGMII:
mac->type = e1000_i350;
break;
+ case E1000_DEV_ID_I210_COPPER:
+ case E1000_DEV_ID_I210_COPPER_OEM1:
+ case E1000_DEV_ID_I210_COPPER_IT:
+ case E1000_DEV_ID_I210_FIBER:
+ case E1000_DEV_ID_I210_SERDES:
+ case E1000_DEV_ID_I210_SGMII:
+ mac->type = e1000_i210;
+ break;
+ case E1000_DEV_ID_I211_COPPER:
+ mac->type = e1000_i211;
+ break;
default:
return -E1000_ERR_MAC_INIT;
break;
@@ -182,26 +198,44 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
/* Set mta register count */
mac->mta_reg_count = 128;
/* Set rar entry count */
- mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
- if (mac->type == e1000_82576)
+ switch (mac->type) {
+ case e1000_82576:
mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
- if (mac->type == e1000_82580)
+ break;
+ case e1000_82580:
mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
- if (mac->type == e1000_i350)
+ break;
+ case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
+ break;
+ default:
+ mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
+ break;
+ }
/* reset */
if (mac->type >= e1000_82580)
mac->ops.reset_hw = igb_reset_hw_82580;
else
mac->ops.reset_hw = igb_reset_hw_82575;
+
+ if (mac->type >= e1000_i210) {
+ mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_i210;
+ mac->ops.release_swfw_sync = igb_release_swfw_sync_i210;
+ } else {
+ mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_82575;
+ mac->ops.release_swfw_sync = igb_release_swfw_sync_82575;
+ }
+
/* Set if part includes ASF firmware */
mac->asf_firmware_present = true;
/* Set if manageability features are enabled. */
mac->arc_subsystem_valid =
(rd32(E1000_FWSM) & E1000_FWSM_MODE_MASK)
? true : false;
- /* enable EEE on i350 parts */
- if (mac->type == e1000_i350)
+ /* enable EEE on i350 parts and later parts */
+ if (mac->type >= e1000_i350)
dev_spec->eee_disable = false;
else
dev_spec->eee_disable = true;
@@ -213,26 +247,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
/* NVM initialization */
eecd = rd32(E1000_EECD);
-
- nvm->opcode_bits = 8;
- nvm->delay_usec = 1;
- switch (nvm->override) {
- case e1000_nvm_override_spi_large:
- nvm->page_size = 32;
- nvm->address_bits = 16;
- break;
- case e1000_nvm_override_spi_small:
- nvm->page_size = 8;
- nvm->address_bits = 8;
- break;
- default:
- nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
- nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
- break;
- }
-
- nvm->type = e1000_nvm_eeprom_spi;
-
size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
E1000_EECD_SIZE_EX_SHIFT);
@@ -242,6 +256,33 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
*/
size += NVM_WORD_SIZE_BASE_SHIFT;
+ nvm->word_size = 1 << size;
+ if (hw->mac.type < e1000_i210) {
+ nvm->opcode_bits = 8;
+ nvm->delay_usec = 1;
+ switch (nvm->override) {
+ case e1000_nvm_override_spi_large:
+ nvm->page_size = 32;
+ nvm->address_bits = 16;
+ break;
+ case e1000_nvm_override_spi_small:
+ nvm->page_size = 8;
+ nvm->address_bits = 8;
+ break;
+ default:
+ nvm->page_size = eecd
+ & E1000_EECD_ADDR_BITS ? 32 : 8;
+ nvm->address_bits = eecd
+ & E1000_EECD_ADDR_BITS ? 16 : 8;
+ break;
+ }
+ if (nvm->word_size == (1 << 15))
+ nvm->page_size = 128;
+
+ nvm->type = e1000_nvm_eeprom_spi;
+ } else
+ nvm->type = e1000_nvm_flash_hw;
+
/*
* Check for invalid size
*/
@@ -249,32 +290,60 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
pr_notice("The NVM size is not valid, defaulting to 32K\n");
size = 15;
}
- nvm->word_size = 1 << size;
- if (nvm->word_size == (1 << 15))
- nvm->page_size = 128;
/* NVM Function Pointers */
- nvm->ops.acquire = igb_acquire_nvm_82575;
- if (nvm->word_size < (1 << 15))
- nvm->ops.read = igb_read_nvm_eerd;
- else
- nvm->ops.read = igb_read_nvm_spi;
-
- nvm->ops.release = igb_release_nvm_82575;
switch (hw->mac.type) {
case e1000_82580:
nvm->ops.validate = igb_validate_nvm_checksum_82580;
nvm->ops.update = igb_update_nvm_checksum_82580;
+ nvm->ops.acquire = igb_acquire_nvm_82575;
+ nvm->ops.release = igb_release_nvm_82575;
+ if (nvm->word_size < (1 << 15))
+ nvm->ops.read = igb_read_nvm_eerd;
+ else
+ nvm->ops.read = igb_read_nvm_spi;
+ nvm->ops.write = igb_write_nvm_spi;
break;
case e1000_i350:
nvm->ops.validate = igb_validate_nvm_checksum_i350;
nvm->ops.update = igb_update_nvm_checksum_i350;
+ nvm->ops.acquire = igb_acquire_nvm_82575;
+ nvm->ops.release = igb_release_nvm_82575;
+ if (nvm->word_size < (1 << 15))
+ nvm->ops.read = igb_read_nvm_eerd;
+ else
+ nvm->ops.read = igb_read_nvm_spi;
+ nvm->ops.write = igb_write_nvm_spi;
+ break;
+ case e1000_i210:
+ nvm->ops.validate = igb_validate_nvm_checksum_i210;
+ nvm->ops.update = igb_update_nvm_checksum_i210;
+ nvm->ops.acquire = igb_acquire_nvm_i210;
+ nvm->ops.release = igb_release_nvm_i210;
+ nvm->ops.read = igb_read_nvm_srrd_i210;
+ nvm->ops.valid_led_default = igb_valid_led_default_i210;
+ break;
+ case e1000_i211:
+ nvm->ops.acquire = igb_acquire_nvm_i210;
+ nvm->ops.release = igb_release_nvm_i210;
+ nvm->ops.read = igb_read_nvm_i211;
+ nvm->ops.valid_led_default = igb_valid_led_default_i210;
+ nvm->ops.validate = NULL;
+ nvm->ops.update = NULL;
+ nvm->ops.write = NULL;
break;
default:
nvm->ops.validate = igb_validate_nvm_checksum;
nvm->ops.update = igb_update_nvm_checksum;
+ nvm->ops.acquire = igb_acquire_nvm_82575;
+ nvm->ops.release = igb_release_nvm_82575;
+ if (nvm->word_size < (1 << 15))
+ nvm->ops.read = igb_read_nvm_eerd;
+ else
+ nvm->ops.read = igb_read_nvm_spi;
+ nvm->ops.write = igb_write_nvm_spi;
+ break;
}
- nvm->ops.write = igb_write_nvm_spi;
/* if part supports SR-IOV then initialize mailbox parameters */
switch (mac->type) {
@@ -312,9 +381,13 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
if (igb_sgmii_active_82575(hw) && !igb_sgmii_uses_mdio_82575(hw)) {
phy->ops.read_reg = igb_read_phy_reg_sgmii_82575;
phy->ops.write_reg = igb_write_phy_reg_sgmii_82575;
- } else if (hw->mac.type >= e1000_82580) {
+ } else if ((hw->mac.type == e1000_82580)
+ || (hw->mac.type == e1000_i350)) {
phy->ops.read_reg = igb_read_phy_reg_82580;
phy->ops.write_reg = igb_write_phy_reg_82580;
+ } else if (hw->phy.type >= e1000_phy_i210) {
+ phy->ops.read_reg = igb_read_phy_reg_gs40g;
+ phy->ops.write_reg = igb_write_phy_reg_gs40g;
} else {
phy->ops.read_reg = igb_read_phy_reg_igp;
phy->ops.write_reg = igb_write_phy_reg_igp;
@@ -343,6 +416,14 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
else
phy->ops.get_cable_length = igb_get_cable_length_m88;
+ if (phy->id == I210_I_PHY_ID) {
+ phy->ops.get_cable_length =
+ igb_get_cable_length_m88_gen2;
+ phy->ops.set_d0_lplu_state =
+ igb_set_d0_lplu_state_82580;
+ phy->ops.set_d3_lplu_state =
+ igb_set_d3_lplu_state_82580;
+ }
phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
break;
case IGP03E1000_E_PHY_ID:
@@ -359,6 +440,17 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_82580;
phy->ops.get_cable_length = igb_get_cable_length_82580;
phy->ops.get_phy_info = igb_get_phy_info_82580;
+ phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580;
+ phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580;
+ break;
+ case I210_I_PHY_ID:
+ phy->type = e1000_phy_i210;
+ phy->ops.get_phy_info = igb_get_phy_info_m88;
+ phy->ops.check_polarity = igb_check_polarity_m88;
+ phy->ops.get_cable_length = igb_get_cable_length_m88_gen2;
+ phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580;
+ phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580;
+ phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
break;
default:
return -E1000_ERR_PHY;
@@ -385,7 +477,7 @@ static s32 igb_acquire_phy_82575(struct e1000_hw *hw)
else if (hw->bus.func == E1000_FUNC_3)
mask = E1000_SWFW_PHY3_SM;
- return igb_acquire_swfw_sync_82575(hw, mask);
+ return hw->mac.ops.acquire_swfw_sync(hw, mask);
}
/**
@@ -406,7 +498,7 @@ static void igb_release_phy_82575(struct e1000_hw *hw)
else if (hw->bus.func == E1000_FUNC_3)
mask = E1000_SWFW_PHY3_SM;
- igb_release_swfw_sync_82575(hw, mask);
+ hw->mac.ops.release_swfw_sync(hw, mask);
}
/**
@@ -510,6 +602,8 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw)
break;
case e1000_82580:
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
mdic = rd32(E1000_MDICNFG);
mdic &= E1000_MDICNFG_PHY_MASK;
phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT;
@@ -674,6 +768,96 @@ out:
}
/**
+ * igb_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state
+ * @hw: pointer to the HW structure
+ * @active: true to enable LPLU, false to disable
+ *
+ * Sets the LPLU D0 state according to the active flag. When
+ * activating LPLU this function also disables smart speed
+ * and vice versa. LPLU will not be activated unless the
+ * device autonegotiation advertisement meets standards of
+ * either 10 or 10/100 or 10/100/1000 at all duplexes.
+ * This is a function pointer entry point only called by
+ * PHY setup routines.
+ **/
+static s32 igb_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val = 0;
+ u16 data;
+
+ data = rd32(E1000_82580_PHY_POWER_MGMT);
+
+ if (active) {
+ data |= E1000_82580_PM_D0_LPLU;
+
+ /* When LPLU is enabled, we should disable SmartSpeed */
+ data &= ~E1000_82580_PM_SPD;
+ } else {
+ data &= ~E1000_82580_PM_D0_LPLU;
+
+ /*
+ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+ * SmartSpeed, so performance is maintained.
+ */
+ if (phy->smart_speed == e1000_smart_speed_on)
+ data |= E1000_82580_PM_SPD;
+ else if (phy->smart_speed == e1000_smart_speed_off)
+ data &= ~E1000_82580_PM_SPD; }
+
+ wr32(E1000_82580_PHY_POWER_MGMT, data);
+ return ret_val;
+}
+
+/**
+ * igb_set_d3_lplu_state_82580 - Sets low power link up state for D3
+ * @hw: pointer to the HW structure
+ * @active: boolean used to enable/disable lplu
+ *
+ * Success returns 0, Failure returns 1
+ *
+ * The low power link up (lplu) state is set to the power management level D3
+ * and SmartSpeed is disabled when active is true, else clear lplu for D3
+ * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
+ * is used during Dx states where the power conservation is most important.
+ * During driver activity, SmartSpeed should be enabled so performance is
+ * maintained.
+ **/
+s32 igb_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val = 0;
+ u16 data;
+
+ data = rd32(E1000_82580_PHY_POWER_MGMT);
+
+ if (!active) {
+ data &= ~E1000_82580_PM_D3_LPLU;
+ /*
+ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+ * SmartSpeed, so performance is maintained.
+ */
+ if (phy->smart_speed == e1000_smart_speed_on)
+ data |= E1000_82580_PM_SPD;
+ else if (phy->smart_speed == e1000_smart_speed_off)
+ data &= ~E1000_82580_PM_SPD;
+ } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
+ (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
+ (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
+ data |= E1000_82580_PM_D3_LPLU;
+ /* When LPLU is enabled, we should disable SmartSpeed */
+ data &= ~E1000_82580_PM_SPD;
+ }
+
+ wr32(E1000_82580_PHY_POWER_MGMT, data);
+ return ret_val;
+}
+
+/**
* igb_acquire_nvm_82575 - Request for access to EEPROM
* @hw: pointer to the HW structure
*
@@ -686,14 +870,14 @@ static s32 igb_acquire_nvm_82575(struct e1000_hw *hw)
{
s32 ret_val;
- ret_val = igb_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
+ ret_val = hw->mac.ops.acquire_swfw_sync(hw, E1000_SWFW_EEP_SM);
if (ret_val)
goto out;
ret_val = igb_acquire_nvm(hw);
if (ret_val)
- igb_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
+ hw->mac.ops.release_swfw_sync(hw, E1000_SWFW_EEP_SM);
out:
return ret_val;
@@ -709,7 +893,7 @@ out:
static void igb_release_nvm_82575(struct e1000_hw *hw)
{
igb_release_nvm(hw);
- igb_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
+ hw->mac.ops.release_swfw_sync(hw, E1000_SWFW_EEP_SM);
}
/**
@@ -1080,7 +1264,6 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw)
* is no link.
*/
igb_clear_hw_cntrs_82575(hw);
-
return ret_val;
}
@@ -1117,6 +1300,7 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
}
}
switch (hw->phy.type) {
+ case e1000_phy_i210:
case e1000_phy_m88:
if (hw->phy.id == I347AT4_E_PHY_ID ||
hw->phy.id == M88E1112_E_PHY_ID)
@@ -1757,7 +1941,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw)
/* Determine whether or not a global dev reset is requested */
if (global_device_reset &&
- igb_acquire_swfw_sync_82575(hw, swmbsw_mask))
+ hw->mac.ops.acquire_swfw_sync(hw, swmbsw_mask))
global_device_reset = false;
if (global_device_reset &&
@@ -1803,7 +1987,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw)
/* Release semaphore */
if (global_device_reset)
- igb_release_swfw_sync_82575(hw, swmbsw_mask);
+ hw->mac.ops.release_swfw_sync(hw, swmbsw_mask);
return ret_val;
}
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h
index b927d79ab536..e85c453f5428 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.h
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.h
@@ -55,10 +55,11 @@ extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
#define E1000_SRRCTL_DROP_EN 0x80000000
#define E1000_SRRCTL_TIMESTAMP 0x40000000
+
#define E1000_MRQC_ENABLE_RSS_4Q 0x00000002
#define E1000_MRQC_ENABLE_VMDQ 0x00000003
-#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005
#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
+#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005
#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index 89eb1f85b9fa..ec7e4fe3e3ee 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -301,6 +301,8 @@
* transactions */
#define E1000_DMACR_DMAC_LX_SHIFT 28
#define E1000_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */
+/* DMA Coalescing BMC-to-OS Watchdog Enable */
+#define E1000_DMACR_DC_BMC2OSW_EN 0x00008000
#define E1000_DMCTXTH_DMCTTHR_MASK 0x00000FFF /* DMA Coalescing Transmit
* Threshold */
@@ -458,6 +460,7 @@
#define E1000_ERR_INVALID_ARGUMENT 16
#define E1000_ERR_NO_SPACE 17
#define E1000_ERR_NVM_PBA_SECTION 18
+#define E1000_ERR_INVM_VALUE_NOT_FOUND 19
/* Loop limit on how long we wait for auto-negotiation to complete */
#define COPPER_LINK_UP_LIMIT 10
@@ -595,6 +598,25 @@
#define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
#define E1000_EECD_SIZE_EX_SHIFT 11
+#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */
+#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/
+#define E1000_FLUDONE_ATTEMPTS 20000
+#define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */
+#define E1000_I210_FIFO_SEL_RX 0x00
+#define E1000_I210_FIFO_SEL_TX_QAV(_i) (0x02 + (_i))
+#define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0)
+#define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06
+#define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01
+#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */
+#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/
+#define E1000_FLUDONE_ATTEMPTS 20000
+#define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */
+#define E1000_I210_FIFO_SEL_RX 0x00
+#define E1000_I210_FIFO_SEL_TX_QAV(_i) (0x02 + (_i))
+#define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0)
+#define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06
+#define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01
+
/* Offset to data in NVM read/write registers */
#define E1000_NVM_RW_REG_DATA 16
@@ -613,6 +635,16 @@
#define NVM_CHECKSUM_REG 0x003F
#define NVM_COMPATIBILITY_REG_3 0x0003
#define NVM_COMPATIBILITY_BIT_MASK 0x8000
+#define NVM_MAC_ADDR 0x0000
+#define NVM_SUB_DEV_ID 0x000B
+#define NVM_SUB_VEN_ID 0x000C
+#define NVM_DEV_ID 0x000D
+#define NVM_VEN_ID 0x000E
+#define NVM_INIT_CTRL_2 0x000F
+#define NVM_INIT_CTRL_4 0x0013
+#define NVM_LED_1_CFG 0x001C
+#define NVM_LED_0_2_CFG 0x001F
+
#define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */
#define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */
@@ -639,6 +671,7 @@
#define NVM_PBA_OFFSET_0 8
#define NVM_PBA_OFFSET_1 9
+#define NVM_RESERVED_WORD 0xFFFF
#define NVM_PBA_PTR_GUARD 0xFAFA
#define NVM_WORD_SIZE_BASE_SHIFT 6
@@ -696,6 +729,7 @@
#define I82580_I_PHY_ID 0x015403A0
#define I350_I_PHY_ID 0x015403B0
#define M88_VENDOR 0x0141
+#define I210_I_PHY_ID 0x01410C00
/* M88E1000 Specific Registers */
#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
@@ -815,6 +849,7 @@
#define E1000_IPCNFG_EEE_100M_AN 0x00000004 /* EEE Enable 100M AN */
#define E1000_EEER_TX_LPI_EN 0x00010000 /* EEE Tx LPI Enable */
#define E1000_EEER_RX_LPI_EN 0x00020000 /* EEE Rx LPI Enable */
+#define E1000_EEER_FRC_AN 0x10000000 /* Enable EEE in loopback */
#define E1000_EEER_LPI_FC 0x00040000 /* EEE Enable on FC */
/* SerDes Control */
diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h
index f67cbd3fa307..c2a51dcda550 100644
--- a/drivers/net/ethernet/intel/igb/e1000_hw.h
+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
@@ -63,6 +63,13 @@ struct e1000_hw;
#define E1000_DEV_ID_I350_FIBER 0x1522
#define E1000_DEV_ID_I350_SERDES 0x1523
#define E1000_DEV_ID_I350_SGMII 0x1524
+#define E1000_DEV_ID_I210_COPPER 0x1533
+#define E1000_DEV_ID_I210_COPPER_OEM1 0x1534
+#define E1000_DEV_ID_I210_COPPER_IT 0x1535
+#define E1000_DEV_ID_I210_FIBER 0x1536
+#define E1000_DEV_ID_I210_SERDES 0x1537
+#define E1000_DEV_ID_I210_SGMII 0x1538
+#define E1000_DEV_ID_I211_COPPER 0x1539
#define E1000_REVISION_2 2
#define E1000_REVISION_4 4
@@ -83,6 +90,8 @@ enum e1000_mac_type {
e1000_82576,
e1000_82580,
e1000_i350,
+ e1000_i210,
+ e1000_i211,
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
};
@@ -117,6 +126,7 @@ enum e1000_phy_type {
e1000_phy_igp_3,
e1000_phy_ife,
e1000_phy_82580,
+ e1000_phy_i210,
};
enum e1000_bus_type {
@@ -313,6 +323,9 @@ struct e1000_mac_operations {
void (*rar_set)(struct e1000_hw *, u8 *, u32);
s32 (*read_mac_addr)(struct e1000_hw *);
s32 (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *);
+ s32 (*acquire_swfw_sync)(struct e1000_hw *, u16);
+ void (*release_swfw_sync)(struct e1000_hw *, u16);
+
};
struct e1000_phy_operations {
@@ -338,6 +351,7 @@ struct e1000_nvm_operations {
s32 (*write)(struct e1000_hw *, u16, u16, u16 *);
s32 (*update)(struct e1000_hw *);
s32 (*validate)(struct e1000_hw *);
+ s32 (*valid_led_default)(struct e1000_hw *, u16 *);
};
struct e1000_info {
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c
new file mode 100644
index 000000000000..77a5f939bc74
--- /dev/null
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.c
@@ -0,0 +1,603 @@
+/*******************************************************************************
+
+ Intel(R) Gigabit Ethernet Linux driver
+ Copyright(c) 2007-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:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+
+/* e1000_i210
+ * e1000_i211
+ */
+
+#include <linux/types.h>
+#include <linux/if_ether.h>
+
+#include "e1000_hw.h"
+#include "e1000_i210.h"
+
+static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw);
+static void igb_put_hw_semaphore_i210(struct e1000_hw *hw);
+static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
+static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw);
+
+/**
+ * igb_acquire_nvm_i210 - Request for access to EEPROM
+ * @hw: pointer to the HW structure
+ *
+ * Acquire the necessary semaphores for exclusive access to the EEPROM.
+ * 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 igb_acquire_nvm_i210(struct e1000_hw *hw)
+{
+ return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
+}
+
+/**
+ * igb_release_nvm_i210 - Release exclusive access to EEPROM
+ * @hw: pointer to the HW structure
+ *
+ * Stop any current commands to the EEPROM and clear the EEPROM request bit,
+ * then release the semaphores acquired.
+ **/
+void igb_release_nvm_i210(struct e1000_hw *hw)
+{
+ igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
+}
+
+/**
+ * igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
+ * @hw: pointer to the HW structure
+ * @mask: specifies which semaphore to acquire
+ *
+ * Acquire the SW/FW semaphore to access the PHY or NVM. The mask
+ * will also specify which port we're acquiring the lock for.
+ **/
+s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
+{
+ u32 swfw_sync;
+ u32 swmask = mask;
+ u32 fwmask = mask << 16;
+ s32 ret_val = E1000_SUCCESS;
+ s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
+
+ while (i < timeout) {
+ if (igb_get_hw_semaphore_i210(hw)) {
+ ret_val = -E1000_ERR_SWFW_SYNC;
+ goto out;
+ }
+
+ swfw_sync = rd32(E1000_SW_FW_SYNC);
+ if (!(swfw_sync & fwmask))
+ break;
+
+ /*
+ * Firmware currently using resource (fwmask)
+ */
+ igb_put_hw_semaphore_i210(hw);
+ mdelay(5);
+ i++;
+ }
+
+ if (i == timeout) {
+ hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n");
+ ret_val = -E1000_ERR_SWFW_SYNC;
+ goto out;
+ }
+
+ swfw_sync |= swmask;
+ wr32(E1000_SW_FW_SYNC, swfw_sync);
+
+ igb_put_hw_semaphore_i210(hw);
+out:
+ return ret_val;
+}
+
+/**
+ * igb_release_swfw_sync_i210 - Release SW/FW semaphore
+ * @hw: pointer to the HW structure
+ * @mask: specifies which semaphore to acquire
+ *
+ * Release the SW/FW semaphore used to access the PHY or NVM. The mask
+ * will also specify which port we're releasing the lock for.
+ **/
+void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
+{
+ u32 swfw_sync;
+
+ while (igb_get_hw_semaphore_i210(hw) != E1000_SUCCESS)
+ ; /* Empty */
+
+ swfw_sync = rd32(E1000_SW_FW_SYNC);
+ swfw_sync &= ~mask;
+ wr32(E1000_SW_FW_SYNC, swfw_sync);
+
+ igb_put_hw_semaphore_i210(hw);
+}
+
+/**
+ * igb_get_hw_semaphore_i210 - Acquire hardware semaphore
+ * @hw: pointer to the HW structure
+ *
+ * Acquire the HW semaphore to access the PHY or NVM
+ **/
+static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
+{
+ u32 swsm;
+ s32 ret_val = E1000_SUCCESS;
+ s32 timeout = hw->nvm.word_size + 1;
+ s32 i = 0;
+
+ /* Get the FW semaphore. */
+ for (i = 0; i < timeout; i++) {
+ swsm = rd32(E1000_SWSM);
+ wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
+
+ /* Semaphore acquired if bit latched */
+ if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI)
+ break;
+
+ udelay(50);
+ }
+
+ if (i == timeout) {
+ /* Release semaphores */
+ igb_put_hw_semaphore(hw);
+ hw_dbg("Driver can't access the NVM\n");
+ ret_val = -E1000_ERR_NVM;
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * igb_put_hw_semaphore_i210 - Release hardware semaphore
+ * @hw: pointer to the HW structure
+ *
+ * Release hardware semaphore used to access the PHY or NVM
+ **/
+static void igb_put_hw_semaphore_i210(struct e1000_hw *hw)
+{
+ u32 swsm;
+
+ swsm = rd32(E1000_SWSM);
+
+ swsm &= ~E1000_SWSM_SWESMBI;
+
+ wr32(E1000_SWSM, swsm);
+}
+
+/**
+ * igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
+ * @hw: pointer to the HW structure
+ * @offset: offset of word in the Shadow Ram to read
+ * @words: number of words to read
+ * @data: word read from the Shadow Ram
+ *
+ * Reads a 16 bit word from the Shadow Ram using the EERD register.
+ * Uses necessary synchronization semaphores.
+ **/
+s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
+{
+ s32 status = E1000_SUCCESS;
+ u16 i, count;
+
+ /* We cannot hold synchronization semaphores for too long,
+ * because of forceful takeover procedure. However it is more efficient
+ * to read in bursts than synchronizing access for each word. */
+ for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
+ count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
+ E1000_EERD_EEWR_MAX_COUNT : (words - i);
+ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+ status = igb_read_nvm_eerd(hw, offset, count,
+ data + i);
+ hw->nvm.ops.release(hw);
+ } else {
+ status = E1000_ERR_SWFW_SYNC;
+ }
+
+ if (status != E1000_SUCCESS)
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
+ * @hw: pointer to the HW structure
+ * @offset: offset within the Shadow RAM to be written to
+ * @words: number of words to write
+ * @data: 16 bit word(s) to be written to the Shadow RAM
+ *
+ * Writes data to Shadow RAM at offset using EEWR register.
+ *
+ * If e1000_update_nvm_checksum is not called after this function , the
+ * data will not be committed to FLASH and also Shadow RAM will most likely
+ * contain an invalid checksum.
+ *
+ * If error code is returned, data and Shadow RAM may be inconsistent - buffer
+ * partially written.
+ **/
+s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
+{
+ s32 status = E1000_SUCCESS;
+ u16 i, count;
+
+ /* We cannot hold synchronization semaphores for too long,
+ * because of forceful takeover procedure. However it is more efficient
+ * to write in bursts than synchronizing access for each word. */
+ for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
+ count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
+ E1000_EERD_EEWR_MAX_COUNT : (words - i);
+ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+ status = igb_write_nvm_srwr(hw, offset, count,
+ data + i);
+ hw->nvm.ops.release(hw);
+ } else {
+ status = E1000_ERR_SWFW_SYNC;
+ }
+
+ if (status != E1000_SUCCESS)
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * igb_write_nvm_srwr - Write to Shadow Ram using EEWR
+ * @hw: pointer to the HW structure
+ * @offset: offset within the Shadow Ram to be written to
+ * @words: number of words to write
+ * @data: 16 bit word(s) to be written to the Shadow Ram
+ *
+ * Writes data to Shadow Ram at offset using EEWR register.
+ *
+ * If igb_update_nvm_checksum is not called after this function , the
+ * Shadow Ram will most likely contain an invalid checksum.
+ **/
+static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ u32 i, k, eewr = 0;
+ u32 attempts = 100000;
+ s32 ret_val = E1000_SUCCESS;
+
+ /*
+ * 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)) {
+ hw_dbg("nvm parameter(s) out of bounds\n");
+ ret_val = -E1000_ERR_NVM;
+ goto out;
+ }
+
+ for (i = 0; i < words; i++) {
+ eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
+ (data[i] << E1000_NVM_RW_REG_DATA) |
+ E1000_NVM_RW_REG_START;
+
+ wr32(E1000_SRWR, eewr);
+
+ for (k = 0; k < attempts; k++) {
+ if (E1000_NVM_RW_REG_DONE &
+ rd32(E1000_SRWR)) {
+ ret_val = E1000_SUCCESS;
+ break;
+ }
+ udelay(5);
+ }
+
+ if (ret_val != E1000_SUCCESS) {
+ hw_dbg("Shadow RAM write EEWR timed out\n");
+ break;
+ }
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * igb_read_nvm_i211 - Read NVM wrapper function for I211
+ * @hw: pointer to the HW structure
+ * @address: the word address (aka eeprom offset) to read
+ * @data: pointer to the data read
+ *
+ * Wrapper function to return data formerly found in the NVM.
+ **/
+s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
+{
+ s32 ret_val = E1000_SUCCESS;
+
+ /* Only the MAC addr is required to be present in the iNVM */
+ switch (offset) {
+ case NVM_MAC_ADDR:
+ ret_val = igb_read_invm_i211(hw, offset, &data[0]);
+ ret_val |= igb_read_invm_i211(hw, offset+1, &data[1]);
+ ret_val |= igb_read_invm_i211(hw, offset+2, &data[2]);
+ if (ret_val != E1000_SUCCESS)
+ hw_dbg("MAC Addr not found in iNVM\n");
+ break;
+ case NVM_ID_LED_SETTINGS:
+ case NVM_INIT_CTRL_2:
+ case NVM_INIT_CTRL_4:
+ case NVM_LED_1_CFG:
+ case NVM_LED_0_2_CFG:
+ igb_read_invm_i211(hw, offset, data);
+ break;
+ case NVM_COMPAT:
+ *data = ID_LED_DEFAULT_I210;
+ break;
+ case NVM_SUB_DEV_ID:
+ *data = hw->subsystem_device_id;
+ break;
+ case NVM_SUB_VEN_ID:
+ *data = hw->subsystem_vendor_id;
+ break;
+ case NVM_DEV_ID:
+ *data = hw->device_id;
+ break;
+ case NVM_VEN_ID:
+ *data = hw->vendor_id;
+ break;
+ default:
+ hw_dbg("NVM word 0x%02x is not mapped.\n", offset);
+ *data = NVM_RESERVED_WORD;
+ break;
+ }
+ return ret_val;
+}
+
+/**
+ * igb_read_invm_i211 - Reads OTP
+ * @hw: pointer to the HW structure
+ * @address: the word address (aka eeprom offset) to read
+ * @data: pointer to the data read
+ *
+ * Reads 16-bit words from the OTP. Return error when the word is not
+ * stored in OTP.
+ **/
+s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data)
+{
+ s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
+ u32 invm_dword;
+ u16 i;
+ u8 record_type, word_address;
+
+ for (i = 0; i < E1000_INVM_SIZE; i++) {
+ invm_dword = rd32(E1000_INVM_DATA_REG(i));
+ /* Get record type */
+ record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
+ if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
+ break;
+ if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
+ i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
+ if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
+ i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
+ if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
+ word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
+ if (word_address == (u8)address) {
+ *data = INVM_DWORD_TO_WORD_DATA(invm_dword);
+ hw_dbg("Read INVM Word 0x%02x = %x",
+ address, *data);
+ status = E1000_SUCCESS;
+ break;
+ }
+ }
+ }
+ if (status != E1000_SUCCESS)
+ hw_dbg("Requested word 0x%02x not found in OTP\n", address);
+ return status;
+}
+
+/**
+ * igb_validate_nvm_checksum_i210 - 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 igb_validate_nvm_checksum_i210(struct e1000_hw *hw)
+{
+ s32 status = E1000_SUCCESS;
+ s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
+
+ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+
+ /*
+ * Replace the read function with semaphore grabbing with
+ * the one that skips this for a while.
+ * We have semaphore taken already here.
+ */
+ read_op_ptr = hw->nvm.ops.read;
+ hw->nvm.ops.read = igb_read_nvm_eerd;
+
+ status = igb_validate_nvm_checksum(hw);
+
+ /* Revert original read operation. */
+ hw->nvm.ops.read = read_op_ptr;
+
+ hw->nvm.ops.release(hw);
+ } else {
+ status = E1000_ERR_SWFW_SYNC;
+ }
+
+ return status;
+}
+
+
+/**
+ * igb_update_nvm_checksum_i210 - 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. Next commit EEPROM data onto the Flash.
+ **/
+s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 checksum = 0;
+ u16 i, nvm_data;
+
+ /*
+ * Read the first word from the EEPROM. If this times out or fails, do
+ * not continue or we could be in for a very long wait while every
+ * EEPROM read fails
+ */
+ ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data);
+ if (ret_val != E1000_SUCCESS) {
+ hw_dbg("EEPROM read failed\n");
+ goto out;
+ }
+
+ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+ /*
+ * Do not use hw->nvm.ops.write, hw->nvm.ops.read
+ * because we do not want to take the synchronization
+ * semaphores twice here.
+ */
+
+ for (i = 0; i < NVM_CHECKSUM_REG; i++) {
+ ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data);
+ if (ret_val) {
+ hw->nvm.ops.release(hw);
+ hw_dbg("NVM Read Error while updating checksum.\n");
+ goto out;
+ }
+ checksum += nvm_data;
+ }
+ checksum = (u16) NVM_SUM - checksum;
+ ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
+ &checksum);
+ if (ret_val != E1000_SUCCESS) {
+ hw->nvm.ops.release(hw);
+ hw_dbg("NVM Write Error while updating checksum.\n");
+ goto out;
+ }
+
+ hw->nvm.ops.release(hw);
+
+ ret_val = igb_update_flash_i210(hw);
+ } else {
+ ret_val = -E1000_ERR_SWFW_SYNC;
+ }
+out:
+ return ret_val;
+}
+
+/**
+ * igb_update_flash_i210 - Commit EEPROM to the flash
+ * @hw: pointer to the HW structure
+ *
+ **/
+s32 igb_update_flash_i210(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u32 flup;
+
+ ret_val = igb_pool_flash_update_done_i210(hw);
+ if (ret_val == -E1000_ERR_NVM) {
+ hw_dbg("Flash update time out\n");
+ goto out;
+ }
+
+ flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210;
+ wr32(E1000_EECD, flup);
+
+ ret_val = igb_pool_flash_update_done_i210(hw);
+ if (ret_val == E1000_SUCCESS)
+ hw_dbg("Flash update complete\n");
+ else
+ hw_dbg("Flash update time out\n");
+
+out:
+ return ret_val;
+}
+
+/**
+ * igb_pool_flash_update_done_i210 - Pool FLUDONE status.
+ * @hw: pointer to the HW structure
+ *
+ **/
+s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
+{
+ s32 ret_val = -E1000_ERR_NVM;
+ u32 i, reg;
+
+ for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
+ reg = rd32(E1000_EECD);
+ if (reg & E1000_EECD_FLUDONE_I210) {
+ ret_val = E1000_SUCCESS;
+ break;
+ }
+ udelay(5);
+ }
+
+ return ret_val;
+}
+
+/**
+ * igb_valid_led_default_i210 - Verify a valid default LED config
+ * @hw: pointer to the HW structure
+ * @data: pointer to the NVM (EEPROM)
+ *
+ * Read the EEPROM for the current default LED configuration. If the
+ * LED configuration is not valid, set to a valid LED configuration.
+ **/
+s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
+{
+ s32 ret_val;
+
+ ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
+ if (ret_val) {
+ hw_dbg("NVM Read Error\n");
+ goto out;
+ }
+
+ if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
+ switch (hw->phy.media_type) {
+ case e1000_media_type_internal_serdes:
+ *data = ID_LED_DEFAULT_I210_SERDES;
+ break;
+ case e1000_media_type_copper:
+ default:
+ *data = ID_LED_DEFAULT_I210;
+ break;
+ }
+ }
+out:
+ return ret_val;
+}
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.h b/drivers/net/ethernet/intel/igb/e1000_i210.h
new file mode 100644
index 000000000000..5dc2bd3f50bc
--- /dev/null
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.h
@@ -0,0 +1,76 @@
+/*******************************************************************************
+
+ Intel(R) Gigabit Ethernet Linux driver
+ Copyright(c) 2007-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:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#ifndef _E1000_I210_H_
+#define _E1000_I210_H_
+
+extern s32 igb_update_flash_i210(struct e1000_hw *hw);
+extern s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw);
+extern s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw);
+extern s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset,
+ u16 words, u16 *data);
+extern s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset,
+ u16 words, u16 *data);
+extern s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data);
+extern s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
+extern void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
+extern s32 igb_acquire_nvm_i210(struct e1000_hw *hw);
+extern void igb_release_nvm_i210(struct e1000_hw *hw);
+extern s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
+extern s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
+
+#define E1000_STM_OPCODE 0xDB00
+#define E1000_EEPROM_FLASH_SIZE_WORD 0x11
+
+#define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \
+ (u8)((invm_dword) & 0x7)
+#define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \
+ (u8)(((invm_dword) & 0x0000FE00) >> 9)
+#define INVM_DWORD_TO_WORD_DATA(invm_dword) \
+ (u16)(((invm_dword) & 0xFFFF0000) >> 16)
+
+enum E1000_INVM_STRUCTURE_TYPE {
+ E1000_INVM_UNINITIALIZED_STRUCTURE = 0x00,
+ E1000_INVM_WORD_AUTOLOAD_STRUCTURE = 0x01,
+ E1000_INVM_CSR_AUTOLOAD_STRUCTURE = 0x02,
+ E1000_INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE = 0x03,
+ E1000_INVM_RSA_KEY_SHA256_STRUCTURE = 0x04,
+ E1000_INVM_INVALIDATED_STRUCTURE = 0x0F,
+};
+
+#define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8
+#define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1
+
+#define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \
+ (ID_LED_OFF1_OFF2 << 4) | \
+ (ID_LED_DEF1_DEF2))
+#define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \
+ (ID_LED_DEF1_DEF2 << 4) | \
+ (ID_LED_DEF1_DEF2))
+
+#endif
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c
index f57338afd71f..819c145ac762 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.c
@@ -658,6 +658,7 @@ s32 igb_setup_link(struct e1000_hw *hw)
ret_val = igb_set_fc_watermarks(hw);
out:
+
return ret_val;
}
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.c b/drivers/net/ethernet/intel/igb/e1000_nvm.c
index fa2c6ba62139..aa5fcdf3f357 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.c
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.c
@@ -710,4 +710,3 @@ s32 igb_update_nvm_checksum(struct e1000_hw *hw)
out:
return ret_val;
}
-
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c
index 789de5b83aad..7be98b6f1052 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
@@ -35,6 +35,7 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw);
static void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw,
u16 *phy_ctrl);
static s32 igb_wait_autoneg(struct e1000_hw *hw);
+static s32 igb_set_master_slave_mode(struct e1000_hw *hw);
/* Cable length tables */
static const u16 e1000_m88_cable_length_table[] =
@@ -570,6 +571,11 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw)
hw_dbg("Error committing the PHY changes\n");
goto out;
}
+ if (phy->type == e1000_phy_i210) {
+ ret_val = igb_set_master_slave_mode(hw);
+ if (ret_val)
+ return ret_val;
+ }
out:
return ret_val;
@@ -1213,12 +1219,22 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
goto out;
if (!link) {
- if (hw->phy.type != e1000_phy_m88 ||
- hw->phy.id == I347AT4_E_PHY_ID ||
- hw->phy.id == M88E1112_E_PHY_ID) {
+ bool reset_dsp = true;
+
+ switch (hw->phy.id) {
+ case I347AT4_E_PHY_ID:
+ case M88E1112_E_PHY_ID:
+ case I210_I_PHY_ID:
+ reset_dsp = false;
+ break;
+ default:
+ if (hw->phy.type != e1000_phy_m88)
+ reset_dsp = false;
+ break;
+ }
+ if (!reset_dsp)
hw_dbg("Link taking longer than expected.\n");
- } else {
-
+ else {
/*
* We didn't get link.
* Reset the DSP and cross our fingers.
@@ -1243,7 +1259,8 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
if (hw->phy.type != e1000_phy_m88 ||
hw->phy.id == I347AT4_E_PHY_ID ||
- hw->phy.id == M88E1112_E_PHY_ID)
+ hw->phy.id == M88E1112_E_PHY_ID ||
+ hw->phy.id == I210_I_PHY_ID)
goto out;
ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
@@ -1441,6 +1458,7 @@ s32 igb_check_downshift(struct e1000_hw *hw)
u16 phy_data, offset, mask;
switch (phy->type) {
+ case e1000_phy_i210:
case e1000_phy_m88:
case e1000_phy_gg82563:
offset = M88E1000_PHY_SPEC_STATUS;
@@ -1476,7 +1494,7 @@ out:
*
* Polarity is determined based on the PHY specific status register.
**/
-static s32 igb_check_polarity_m88(struct e1000_hw *hw)
+s32 igb_check_polarity_m88(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val;
@@ -1665,6 +1683,7 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
u16 phy_data, phy_data2, index, default_page, is_cm;
switch (hw->phy.id) {
+ case I210_I_PHY_ID:
case I347AT4_E_PHY_ID:
/* Remember the original page select and set it to 7 */
ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
@@ -2129,10 +2148,16 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw)
void igb_power_up_phy_copper(struct e1000_hw *hw)
{
u16 mii_reg = 0;
+ u16 power_reg = 0;
/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg &= ~MII_CR_POWER_DOWN;
+ if (hw->phy.type == e1000_phy_i210) {
+ hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+ power_reg &= ~GS40G_CS_POWER_DOWN;
+ hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+ }
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
}
@@ -2146,10 +2171,18 @@ void igb_power_up_phy_copper(struct e1000_hw *hw)
void igb_power_down_phy_copper(struct e1000_hw *hw)
{
u16 mii_reg = 0;
+ u16 power_reg = 0;
/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
+
+ /* i210 Phy requires an additional bit for power up/down */
+ if (hw->phy.type == e1000_phy_i210) {
+ hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+ power_reg |= GS40G_CS_POWER_DOWN;
+ hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+ }
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
msleep(1);
}
@@ -2345,3 +2378,103 @@ s32 igb_get_cable_length_82580(struct e1000_hw *hw)
out:
return ret_val;
}
+
+/**
+ * igb_write_phy_reg_gs40g - Write GS40G PHY register
+ * @hw: pointer to the HW structure
+ * @offset: lower half is register offset to write to
+ * upper half is page to use.
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore, if necessary, then writes the data to PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 igb_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ s32 ret_val;
+ u16 page = offset >> GS40G_PAGE_SHIFT;
+
+ offset = offset & GS40G_OFFSET_MASK;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = igb_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+ if (ret_val)
+ goto release;
+ ret_val = igb_write_phy_reg_mdic(hw, offset, data);
+
+release:
+ hw->phy.ops.release(hw);
+ return ret_val;
+}
+
+/**
+ * igb_read_phy_reg_gs40g - Read GS40G PHY register
+ * @hw: pointer to the HW structure
+ * @offset: lower half is register offset to read to
+ * upper half is page to use.
+ * @data: data to read at register offset
+ *
+ * Acquires semaphore, if necessary, then reads the data in the PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 igb_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ s32 ret_val;
+ u16 page = offset >> GS40G_PAGE_SHIFT;
+
+ offset = offset & GS40G_OFFSET_MASK;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = igb_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+ if (ret_val)
+ goto release;
+ ret_val = igb_read_phy_reg_mdic(hw, offset, data);
+
+release:
+ hw->phy.ops.release(hw);
+ return ret_val;
+}
+
+/**
+ * igb_set_master_slave_mode - Setup PHY for Master/slave mode
+ * @hw: pointer to the HW structure
+ *
+ * Sets up Master/slave mode
+ **/
+static s32 igb_set_master_slave_mode(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ u16 phy_data;
+
+ /* Resolve Master/Slave mode */
+ ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* load defaults for future use */
+ hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ?
+ ((phy_data & CR_1000T_MS_VALUE) ?
+ e1000_ms_force_master :
+ e1000_ms_force_slave) : e1000_ms_auto;
+
+ switch (hw->phy.ms_type) {
+ case e1000_ms_force_master:
+ phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_force_slave:
+ phy_data |= CR_1000T_MS_ENABLE;
+ phy_data &= ~(CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_auto:
+ phy_data &= ~CR_1000T_MS_ENABLE;
+ /* fall-through */
+ default:
+ break;
+ }
+
+ return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data);
+}
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h
index 4c32ac66ff39..34e40619f16b 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.h
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.h
@@ -73,6 +73,9 @@ s32 igb_copper_link_setup_82580(struct e1000_hw *hw);
s32 igb_get_phy_info_82580(struct e1000_hw *hw);
s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw);
s32 igb_get_cable_length_82580(struct e1000_hw *hw);
+s32 igb_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 igb_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data);
+s32 igb_check_polarity_m88(struct e1000_hw *hw);
/* IGP01E1000 Specific Registers */
#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */
@@ -114,6 +117,13 @@ s32 igb_get_cable_length_82580(struct e1000_hw *hw);
/* I82580 PHY Diagnostics Status */
#define I82580_DSTATUS_CABLE_LENGTH 0x03FC
#define I82580_DSTATUS_CABLE_LENGTH_SHIFT 2
+
+/* 82580 PHY Power Management */
+#define E1000_82580_PHY_POWER_MGMT 0xE14
+#define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */
+#define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */
+#define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */
+
/* Enable flexible speed on link-up */
#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */
#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */
@@ -133,4 +143,16 @@ s32 igb_get_cable_length_82580(struct e1000_hw *hw);
#define E1000_CABLE_LENGTH_UNDEFINED 0xFF
+/* GS40G - I210 PHY defines */
+#define GS40G_PAGE_SELECT 0x16
+#define GS40G_PAGE_SHIFT 16
+#define GS40G_OFFSET_MASK 0xFFFF
+#define GS40G_PAGE_2 0x20000
+#define GS40G_MAC_REG2 0x15
+#define GS40G_MAC_LB 0x4140
+#define GS40G_MAC_SPEED_1G 0X0006
+#define GS40G_COPPER_SPEC 0x0010
+#define GS40G_CS_POWER_DOWN 0x0002
+#define GS40G_LINE_LB 0x4000
+
#endif
diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h
index ccdf36d503fd..35d1e4f2c92c 100644
--- a/drivers/net/ethernet/intel/igb/e1000_regs.h
+++ b/drivers/net/ethernet/intel/igb/e1000_regs.h
@@ -352,4 +352,18 @@
#define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */
#define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */
+#define E1000_SRWR 0x12018 /* Shadow Ram Write Register - RW */
+#define E1000_I210_FLMNGCTL 0x12038
+#define E1000_I210_FLMNGDATA 0x1203C
+#define E1000_I210_FLMNGCNT 0x12040
+
+#define E1000_I210_FLSWCTL 0x12048
+#define E1000_I210_FLSWDATA 0x1204C
+#define E1000_I210_FLSWCNT 0x12050
+
+#define E1000_I210_FLA 0x1201C
+
+#define E1000_INVM_DATA_REG(_n) (0x12120 + 4*(_n))
+#define E1000_INVM_SIZE 64 /* Number of INVM Data Registers */
+
#endif
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 8e33bdd33eea..ae6d3f393a54 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -35,8 +35,8 @@
#include "e1000_82575.h"
#include <linux/clocksource.h>
-#include <linux/timecompare.h>
#include <linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
#include <linux/bitops.h>
#include <linux/if_vlan.h>
@@ -65,10 +65,13 @@ struct igb_adapter;
#define MAX_Q_VECTORS 8
/* Transmit and receive queues */
-#define IGB_MAX_RX_QUEUES (adapter->vfs_allocated_count ? 2 : \
- (hw->mac.type > e1000_82575 ? 8 : 4))
+#define IGB_MAX_RX_QUEUES ((adapter->vfs_allocated_count ? 2 : \
+ (hw->mac.type > e1000_82575 ? 8 : 4)))
+#define IGB_MAX_RX_QUEUES_I210 4
+#define IGB_MAX_RX_QUEUES_I211 2
#define IGB_MAX_TX_QUEUES 16
-
+#define IGB_MAX_TX_QUEUES_I210 4
+#define IGB_MAX_TX_QUEUES_I211 2
#define IGB_MAX_VF_MC_ENTRIES 30
#define IGB_MAX_VF_FUNCTIONS 8
#define IGB_MAX_VFTA_ENTRIES 128
@@ -328,9 +331,6 @@ struct igb_adapter {
/* OS defined structs */
struct pci_dev *pdev;
- struct cyclecounter cycles;
- struct timecounter clock;
- struct timecompare compare;
struct hwtstamp_config hwtstamp_config;
spinlock_t stats64_lock;
@@ -364,6 +364,13 @@ struct igb_adapter {
u32 wvbr;
int node;
u32 *shadow_vfta;
+
+ struct ptp_clock *ptp_clock;
+ struct ptp_clock_info caps;
+ struct delayed_work overflow_work;
+ spinlock_t tmreg_lock;
+ struct cyclecounter cc;
+ struct timecounter tc;
};
#define IGB_FLAG_HAS_MSI (1 << 0)
@@ -378,7 +385,6 @@ struct igb_adapter {
#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coal Flush */
#define IGB_82576_TSYNC_SHIFT 19
-#define IGB_82580_TSYNC_SHIFT 24
#define IGB_TS_HDR_LEN 16
enum e1000_state_t {
__IGB_TESTING,
@@ -414,7 +420,15 @@ extern void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *);
extern bool igb_has_link(struct igb_adapter *adapter);
extern void igb_set_ethtool_ops(struct net_device *);
extern void igb_power_up_link(struct igb_adapter *);
+#ifdef CONFIG_IGB_PTP
+extern void igb_ptp_init(struct igb_adapter *adapter);
+extern void igb_ptp_remove(struct igb_adapter *adapter);
+extern void igb_systim_to_hwtstamp(struct igb_adapter *adapter,
+ struct skb_shared_hwtstamps *hwtstamps,
+ u64 systim);
+
+#endif
static inline s32 igb_reset_phy(struct e1000_hw *hw)
{
if (hw->phy.ops.reset)
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index e10821a0f249..812d4f963bd1 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -335,7 +335,7 @@ static void igb_set_msglevel(struct net_device *netdev, u32 data)
static int igb_get_regs_len(struct net_device *netdev)
{
-#define IGB_REGS_LEN 551
+#define IGB_REGS_LEN 739
return IGB_REGS_LEN * sizeof(u32);
}
@@ -552,10 +552,49 @@ static void igb_get_regs(struct net_device *netdev,
regs_buff[548] = rd32(E1000_TDFT);
regs_buff[549] = rd32(E1000_TDFHS);
regs_buff[550] = rd32(E1000_TDFPC);
- regs_buff[551] = adapter->stats.o2bgptc;
- regs_buff[552] = adapter->stats.b2ospc;
- regs_buff[553] = adapter->stats.o2bspc;
- regs_buff[554] = adapter->stats.b2ogprc;
+
+ if (hw->mac.type > e1000_82580) {
+ regs_buff[551] = adapter->stats.o2bgptc;
+ regs_buff[552] = adapter->stats.b2ospc;
+ regs_buff[553] = adapter->stats.o2bspc;
+ regs_buff[554] = adapter->stats.b2ogprc;
+ }
+
+ if (hw->mac.type != e1000_82576)
+ return;
+ for (i = 0; i < 12; i++)
+ regs_buff[555 + i] = rd32(E1000_SRRCTL(i + 4));
+ for (i = 0; i < 4; i++)
+ regs_buff[567 + i] = rd32(E1000_PSRTYPE(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[571 + i] = rd32(E1000_RDBAL(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[583 + i] = rd32(E1000_RDBAH(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[595 + i] = rd32(E1000_RDLEN(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[607 + i] = rd32(E1000_RDH(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[619 + i] = rd32(E1000_RDT(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[631 + i] = rd32(E1000_RXDCTL(i + 4));
+
+ for (i = 0; i < 12; i++)
+ regs_buff[643 + i] = rd32(E1000_TDBAL(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[655 + i] = rd32(E1000_TDBAH(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[667 + i] = rd32(E1000_TDLEN(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[679 + i] = rd32(E1000_TDH(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[691 + i] = rd32(E1000_TDT(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[703 + i] = rd32(E1000_TXDCTL(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[715 + i] = rd32(E1000_TDWBAL(i + 4));
+ for (i = 0; i < 12; i++)
+ regs_buff[727 + i] = rd32(E1000_TDWBAH(i + 4));
}
static int igb_get_eeprom_len(struct net_device *netdev)
@@ -624,6 +663,9 @@ static int igb_set_eeprom(struct net_device *netdev,
if (eeprom->len == 0)
return -EOPNOTSUPP;
+ if (hw->mac.type == e1000_i211)
+ return -EOPNOTSUPP;
+
if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
return -EFAULT;
@@ -851,6 +893,36 @@ struct igb_reg_test {
#define TABLE64_TEST_LO 5
#define TABLE64_TEST_HI 6
+/* i210 reg test */
+static struct igb_reg_test reg_test_i210[] = {
+ { E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+ { E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
+ { E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
+ { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+ { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+ { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
+ /* RDH is read-only for i210, only test RDT. */
+ { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+ { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 },
+ { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+ { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
+ { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+ { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+ { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
+ { E1000_TDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+ { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
+ { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB },
+ { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF },
+ { E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
+ { E1000_RA, 0, 16, TABLE64_TEST_LO,
+ 0xFFFFFFFF, 0xFFFFFFFF },
+ { E1000_RA, 0, 16, TABLE64_TEST_HI,
+ 0x900FFFFF, 0xFFFFFFFF },
+ { E1000_MTA, 0, 128, TABLE32_TEST,
+ 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0, 0, 0, 0, 0 }
+};
+
/* i350 reg test */
static struct igb_reg_test reg_test_i350[] = {
{ E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
@@ -1073,6 +1145,11 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data)
test = reg_test_i350;
toggle = 0x7FEFF3FF;
break;
+ case e1000_i210:
+ case e1000_i211:
+ test = reg_test_i210;
+ toggle = 0x7FEFF3FF;
+ break;
case e1000_82580:
test = reg_test_82580;
toggle = 0x7FEFF3FF;
@@ -1154,23 +1231,13 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data)
static int igb_eeprom_test(struct igb_adapter *adapter, u64 *data)
{
- u16 temp;
- u16 checksum = 0;
- u16 i;
-
*data = 0;
- /* Read and add up the contents of the EEPROM */
- for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
- if ((adapter->hw.nvm.ops.read(&adapter->hw, i, 1, &temp)) < 0) {
- *data = 1;
- break;
- }
- checksum += temp;
- }
- /* If Checksum is not Correct return error else test passed */
- if ((checksum != (u16) NVM_SUM) && !(*data))
- *data = 2;
+ /* Validate eeprom on all parts but i211 */
+ if (adapter->hw.mac.type != e1000_i211) {
+ if (adapter->hw.nvm.ops.validate(&adapter->hw) < 0)
+ *data = 2;
+ }
return *data;
}
@@ -1236,6 +1303,8 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data)
ics_mask = 0x77DCFED5;
break;
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
ics_mask = 0x77DCFED5;
break;
default:
@@ -1402,23 +1471,35 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 ctrl_reg = 0;
+ u16 phy_reg = 0;
hw->mac.autoneg = false;
- if (hw->phy.type == e1000_phy_m88) {
+ switch (hw->phy.type) {
+ case e1000_phy_m88:
/* Auto-MDI/MDIX Off */
igb_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
/* reset to update Auto-MDI/MDIX */
igb_write_phy_reg(hw, PHY_CONTROL, 0x9140);
/* autoneg off */
igb_write_phy_reg(hw, PHY_CONTROL, 0x8140);
- } else if (hw->phy.type == e1000_phy_82580) {
+ break;
+ case e1000_phy_82580:
/* enable MII loopback */
igb_write_phy_reg(hw, I82580_PHY_LBK_CTRL, 0x8041);
+ break;
+ case e1000_phy_i210:
+ /* set loopback speed in PHY */
+ igb_read_phy_reg(hw, (GS40G_PAGE_SELECT & GS40G_PAGE_2),
+ &phy_reg);
+ phy_reg |= GS40G_MAC_SPEED_1G;
+ igb_write_phy_reg(hw, (GS40G_PAGE_SELECT & GS40G_PAGE_2),
+ phy_reg);
+ ctrl_reg = rd32(E1000_CTRL_EXT);
+ default:
+ break;
}
- ctrl_reg = rd32(E1000_CTRL);
-
/* force 1000, set loopback */
igb_write_phy_reg(hw, PHY_CONTROL, 0x4140);
@@ -1431,7 +1512,7 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
E1000_CTRL_FD | /* Force Duplex to FULL */
E1000_CTRL_SLU); /* Set link up enable bit */
- if (hw->phy.type == e1000_phy_m88)
+ if ((hw->phy.type == e1000_phy_m88) || (hw->phy.type == e1000_phy_i210))
ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
wr32(E1000_CTRL, ctrl_reg);
@@ -1439,7 +1520,7 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
/* Disable the receiver on the PHY so when a cable is plugged in, the
* PHY does not begin to autoneg when a cable is reconnected to the NIC.
*/
- if (hw->phy.type == e1000_phy_m88)
+ if ((hw->phy.type == e1000_phy_m88) || (hw->phy.type == e1000_phy_i210))
igb_phy_disable_receiver(adapter);
udelay(500);
@@ -1704,6 +1785,14 @@ static int igb_loopback_test(struct igb_adapter *adapter, u64 *data)
*data = 0;
goto out;
}
+ if ((adapter->hw.mac.type == e1000_i210)
+ || (adapter->hw.mac.type == e1000_i210)) {
+ dev_err(&adapter->pdev->dev,
+ "Loopback test not supported "
+ "on this part at this time.\n");
+ *data = 0;
+ goto out;
+ }
*data = igb_setup_desc_rings(adapter);
if (*data)
goto out;
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 5ec31598ee47..dd3bfe8cd36c 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -60,8 +60,8 @@
#include "igb.h"
#define MAJ 3
-#define MIN 2
-#define BUILD 10
+#define MIN 4
+#define BUILD 7
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD) "-k"
char igb_driver_name[] = "igb";
@@ -75,6 +75,11 @@ static const struct e1000_info *igb_info_tbl[] = {
};
static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I211_COPPER), board_82575 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER), board_82575 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_FIBER), board_82575 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES), board_82575 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SGMII), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_COPPER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_FIBER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SERDES), board_82575 },
@@ -114,7 +119,6 @@ static void igb_free_all_rx_resources(struct igb_adapter *);
static void igb_setup_mrqc(struct igb_adapter *);
static int igb_probe(struct pci_dev *, const struct pci_device_id *);
static void __devexit igb_remove(struct pci_dev *pdev);
-static void igb_init_hw_timer(struct igb_adapter *adapter);
static int igb_sw_init(struct igb_adapter *);
static int igb_open(struct net_device *);
static int igb_close(struct net_device *);
@@ -565,33 +569,6 @@ exit:
return;
}
-
-/**
- * igb_read_clock - read raw cycle counter (to be used by time counter)
- */
-static cycle_t igb_read_clock(const struct cyclecounter *tc)
-{
- struct igb_adapter *adapter =
- container_of(tc, struct igb_adapter, cycles);
- struct e1000_hw *hw = &adapter->hw;
- u64 stamp = 0;
- int shift = 0;
-
- /*
- * The timestamp latches on lowest register read. For the 82580
- * the lowest register is SYSTIMR instead of SYSTIML. However we never
- * adjusted TIMINCA so SYSTIMR will just read as all 0s so ignore it.
- */
- if (hw->mac.type >= e1000_82580) {
- stamp = rd32(E1000_SYSTIMR) >> 8;
- shift = IGB_82580_TSYNC_SHIFT;
- }
-
- stamp |= (u64)rd32(E1000_SYSTIML) << shift;
- stamp |= (u64)rd32(E1000_SYSTIMH) << (shift + 32);
- return stamp;
-}
-
/**
* igb_get_hw_dev - return device
* used by hardware layer to print debugging information
@@ -669,6 +646,8 @@ static void igb_cache_ring_register(struct igb_adapter *adapter)
case e1000_82575:
case e1000_82580:
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
default:
for (; i < adapter->num_rx_queues; i++)
adapter->rx_ring[i]->reg_idx = rbase_offset + i;
@@ -755,8 +734,11 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
if (adapter->hw.mac.type >= e1000_82576)
set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags);
- /* On i350, loopback VLAN packets have the tag byte-swapped. */
- if (adapter->hw.mac.type == e1000_i350)
+ /*
+ * On i350, i210, and i211, loopback VLAN packets
+ * have the tag byte-swapped.
+ * */
+ if (adapter->hw.mac.type >= e1000_i350)
set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags);
adapter->rx_ring[i] = ring;
@@ -850,6 +832,8 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector)
break;
case e1000_82580:
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
/*
* On 82580 and newer adapters the scheme is similar to 82576
* however instead of ordering column-major we have things
@@ -916,6 +900,8 @@ static void igb_configure_msix(struct igb_adapter *adapter)
case e1000_82576:
case e1000_82580:
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
/* Turn on MSI-X capability first, or our settings
* won't stick. And it will take days to debug. */
wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE |
@@ -1062,6 +1048,11 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter)
if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS))
numvecs += adapter->num_tx_queues;
+ /* i210 and i211 can only have 4 MSIX vectors for rx/tx queues. */
+ if ((adapter->hw.mac.type == e1000_i210)
+ || (adapter->hw.mac.type == e1000_i211))
+ numvecs = 4;
+
/* store the number of vectors reserved for queues */
adapter->num_q_vectors = numvecs;
@@ -1069,6 +1060,7 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter)
numvecs++;
adapter->msix_entries = kcalloc(numvecs, sizeof(struct msix_entry),
GFP_KERNEL);
+
if (!adapter->msix_entries)
goto msi_only;
@@ -1111,9 +1103,12 @@ msi_only:
adapter->flags |= IGB_FLAG_HAS_MSI;
out:
/* Notify the stack of the (possibly) reduced queue counts. */
+ rtnl_lock();
netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
- return netif_set_real_num_rx_queues(adapter->netdev,
- adapter->num_rx_queues);
+ err = netif_set_real_num_rx_queues(adapter->netdev,
+ adapter->num_rx_queues);
+ rtnl_unlock();
+ return err;
}
/**
@@ -1659,6 +1654,8 @@ void igb_reset(struct igb_adapter *adapter)
pba &= E1000_RXPBS_SIZE_MASK_82576;
break;
case e1000_82575:
+ case e1000_i210:
+ case e1000_i211:
default:
pba = E1000_PBA_34K;
break;
@@ -1743,6 +1740,13 @@ void igb_reset(struct igb_adapter *adapter)
if (hw->mac.ops.init_hw(hw))
dev_err(&pdev->dev, "Hardware Error\n");
+ /*
+ * Flow control settings reset on hardware reset, so guarantee flow
+ * control is off when forcing speed.
+ */
+ if (!hw->mac.autoneg)
+ igb_force_mac_fc(hw);
+
igb_init_dmac(adapter, pba);
if (!netif_running(adapter->netdev))
igb_power_down_link(adapter);
@@ -1847,7 +1851,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
*/
if (pdev->is_virtfn) {
WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n",
- pci_name(pdev), pdev->vendor, pdev->device);
+ pci_name(pdev), pdev->vendor, pdev->device);
return -EINVAL;
}
@@ -2001,11 +2005,16 @@ static int __devinit igb_probe(struct pci_dev *pdev,
* known good starting state */
hw->mac.ops.reset_hw(hw);
- /* make sure the NVM is good */
- if (hw->nvm.ops.validate(hw) < 0) {
- dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n");
- err = -EIO;
- goto err_eeprom;
+ /*
+ * make sure the NVM is good , i211 parts have special NVM that
+ * doesn't contain a checksum
+ */
+ if (hw->mac.type != e1000_i211) {
+ if (hw->nvm.ops.validate(hw) < 0) {
+ dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n");
+ err = -EIO;
+ goto err_eeprom;
+ }
}
/* copy the MAC address out of the NVM */
@@ -2110,9 +2119,11 @@ static int __devinit igb_probe(struct pci_dev *pdev,
}
#endif
+#ifdef CONFIG_IGB_PTP
/* do hw tstamp init after resetting */
- igb_init_hw_timer(adapter);
+ igb_ptp_init(adapter);
+#endif
dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
/* print bus type/speed/width info */
dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n",
@@ -2137,6 +2148,8 @@ static int __devinit igb_probe(struct pci_dev *pdev,
adapter->num_rx_queues, adapter->num_tx_queues);
switch (hw->mac.type) {
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
igb_set_eee_i350(hw);
break;
default:
@@ -2184,7 +2197,10 @@ static void __devexit igb_remove(struct pci_dev *pdev)
struct e1000_hw *hw = &adapter->hw;
pm_runtime_get_noresume(&pdev->dev);
+#ifdef CONFIG_IGB_PTP
+ igb_ptp_remove(adapter);
+#endif
/*
* The watchdog timer may be rescheduled, so explicitly
* disable watchdog from being rescheduled.
@@ -2260,9 +2276,14 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
{
#ifdef CONFIG_PCI_IOV
struct pci_dev *pdev = adapter->pdev;
+ struct e1000_hw *hw = &adapter->hw;
int old_vfs = igb_find_enabled_vfs(adapter);
int i;
+ /* Virtualization features not supported on i210 family. */
+ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211))
+ return;
+
if (old_vfs) {
dev_info(&pdev->dev, "%d pre-allocated VFs found - override "
"max_vfs setting of %d\n", old_vfs, max_vfs);
@@ -2274,6 +2295,7 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
sizeof(struct vf_data_storage), GFP_KERNEL);
+
/* if allocation failed then we do not support SR-IOV */
if (!adapter->vf_data) {
adapter->vfs_allocated_count = 0;
@@ -2304,112 +2326,6 @@ out:
}
/**
- * igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp
- * @adapter: board private structure to initialize
- *
- * igb_init_hw_timer initializes the function pointer and values for the hw
- * timer found in hardware.
- **/
-static void igb_init_hw_timer(struct igb_adapter *adapter)
-{
- struct e1000_hw *hw = &adapter->hw;
-
- switch (hw->mac.type) {
- case e1000_i350:
- case e1000_82580:
- memset(&adapter->cycles, 0, sizeof(adapter->cycles));
- adapter->cycles.read = igb_read_clock;
- adapter->cycles.mask = CLOCKSOURCE_MASK(64);
- adapter->cycles.mult = 1;
- /*
- * The 82580 timesync updates the system timer every 8ns by 8ns
- * and the value cannot be shifted. Instead we need to shift
- * the registers to generate a 64bit timer value. As a result
- * SYSTIMR/L/H, TXSTMPL/H, RXSTMPL/H all have to be shifted by
- * 24 in order to generate a larger value for synchronization.
- */
- adapter->cycles.shift = IGB_82580_TSYNC_SHIFT;
- /* disable system timer temporarily by setting bit 31 */
- wr32(E1000_TSAUXC, 0x80000000);
- wrfl();
-
- /* Set registers so that rollover occurs soon to test this. */
- wr32(E1000_SYSTIMR, 0x00000000);
- wr32(E1000_SYSTIML, 0x80000000);
- wr32(E1000_SYSTIMH, 0x000000FF);
- wrfl();
-
- /* enable system timer by clearing bit 31 */
- wr32(E1000_TSAUXC, 0x0);
- wrfl();
-
- timecounter_init(&adapter->clock,
- &adapter->cycles,
- ktime_to_ns(ktime_get_real()));
- /*
- * Synchronize our NIC clock against system wall clock. NIC
- * time stamp reading requires ~3us per sample, each sample
- * was pretty stable even under load => only require 10
- * samples for each offset comparison.
- */
- memset(&adapter->compare, 0, sizeof(adapter->compare));
- adapter->compare.source = &adapter->clock;
- adapter->compare.target = ktime_get_real;
- adapter->compare.num_samples = 10;
- timecompare_update(&adapter->compare, 0);
- break;
- case e1000_82576:
- /*
- * Initialize hardware timer: we keep it running just in case
- * that some program needs it later on.
- */
- memset(&adapter->cycles, 0, sizeof(adapter->cycles));
- adapter->cycles.read = igb_read_clock;
- adapter->cycles.mask = CLOCKSOURCE_MASK(64);
- adapter->cycles.mult = 1;
- /**
- * Scale the NIC clock cycle by a large factor so that
- * relatively small clock corrections can be added or
- * subtracted at each clock tick. The drawbacks of a large
- * factor are a) that the clock register overflows more quickly
- * (not such a big deal) and b) that the increment per tick has
- * to fit into 24 bits. As a result we need to use a shift of
- * 19 so we can fit a value of 16 into the TIMINCA register.
- */
- adapter->cycles.shift = IGB_82576_TSYNC_SHIFT;
- wr32(E1000_TIMINCA,
- (1 << E1000_TIMINCA_16NS_SHIFT) |
- (16 << IGB_82576_TSYNC_SHIFT));
-
- /* Set registers so that rollover occurs soon to test this. */
- wr32(E1000_SYSTIML, 0x00000000);
- wr32(E1000_SYSTIMH, 0xFF800000);
- wrfl();
-
- timecounter_init(&adapter->clock,
- &adapter->cycles,
- ktime_to_ns(ktime_get_real()));
- /*
- * Synchronize our NIC clock against system wall clock. NIC
- * time stamp reading requires ~3us per sample, each sample
- * was pretty stable even under load => only require 10
- * samples for each offset comparison.
- */
- memset(&adapter->compare, 0, sizeof(adapter->compare));
- adapter->compare.source = &adapter->clock;
- adapter->compare.target = ktime_get_real;
- adapter->compare.num_samples = 10;
- timecompare_update(&adapter->compare, 0);
- break;
- case e1000_82575:
- /* 82575 does not support timesync */
- default:
- break;
- }
-
-}
-
-/**
* igb_sw_init - Initialize general software structures (struct igb_adapter)
* @adapter: board private structure to initialize
*
@@ -2454,11 +2370,28 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
} else
adapter->vfs_allocated_count = max_vfs;
break;
+ case e1000_i210:
+ case e1000_i211:
+ adapter->vfs_allocated_count = 0;
+ break;
default:
break;
}
#endif /* CONFIG_PCI_IOV */
- adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus());
+ switch (hw->mac.type) {
+ case e1000_i210:
+ adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES_I210,
+ num_online_cpus());
+ break;
+ case e1000_i211:
+ adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES_I211,
+ num_online_cpus());
+ break;
+ default:
+ adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES,
+ num_online_cpus());
+ break;
+ }
/* i350 cannot do RSS and SR-IOV at the same time */
if (hw->mac.type == e1000_i350 && adapter->vfs_allocated_count)
adapter->rss_queues = 1;
@@ -2488,7 +2421,7 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
/* Explicitly disable IRQ since the NIC can be in any state. */
igb_irq_disable(adapter);
- if (hw->mac.type == e1000_i350)
+ if (hw->mac.type >= e1000_i350)
adapter->flags &= ~IGB_FLAG_DMAC;
set_bit(__IGB_DOWN, &adapter->state);
@@ -2771,8 +2704,6 @@ void igb_configure_tx_ring(struct igb_adapter *adapter,
txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
wr32(E1000_TXDCTL(reg_idx), txdctl);
-
- netdev_tx_reset_queue(txring_txq(ring));
}
/**
@@ -2943,6 +2874,17 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
/* Don't need to set TUOFL or IPOFL, they default to 1 */
wr32(E1000_RXCSUM, rxcsum);
+ /*
+ * Generate RSS hash based on TCP port numbers and/or
+ * IPv4/v6 src and dst addresses since UDP cannot be
+ * hashed reliably due to IP fragmentation
+ */
+
+ mrqc = E1000_MRQC_RSS_FIELD_IPV4 |
+ E1000_MRQC_RSS_FIELD_IPV4_TCP |
+ E1000_MRQC_RSS_FIELD_IPV6 |
+ E1000_MRQC_RSS_FIELD_IPV6_TCP |
+ E1000_MRQC_RSS_FIELD_IPV6_TCP_EX;
/* If VMDq is enabled then we set the appropriate mode for that, else
* we default to RSS so that an RSS hash is calculated per packet even
@@ -2958,25 +2900,15 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
wr32(E1000_VT_CTL, vtctl);
}
if (adapter->rss_queues > 1)
- mrqc = E1000_MRQC_ENABLE_VMDQ_RSS_2Q;
+ mrqc |= E1000_MRQC_ENABLE_VMDQ_RSS_2Q;
else
- mrqc = E1000_MRQC_ENABLE_VMDQ;
+ mrqc |= E1000_MRQC_ENABLE_VMDQ;
} else {
- mrqc = E1000_MRQC_ENABLE_RSS_4Q;
+ if (hw->mac.type != e1000_i211)
+ mrqc |= E1000_MRQC_ENABLE_RSS_4Q;
}
igb_vmm_control(adapter);
- /*
- * Generate RSS hash based on TCP port numbers and/or
- * IPv4/v6 src and dst addresses since UDP cannot be
- * hashed reliably due to IP fragmentation
- */
- 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;
-
wr32(E1000_MRQC, mrqc);
}
@@ -3282,6 +3214,8 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring)
igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
}
+ netdev_tx_reset_queue(txring_txq(tx_ring));
+
size = sizeof(struct igb_tx_buffer) * tx_ring->count;
memset(tx_ring->tx_buffer_info, 0, size);
@@ -3576,7 +3510,7 @@ static void igb_set_rx_mode(struct net_device *netdev)
* we will have issues with VLAN tag stripping not being done for frames
* that are only arriving because we are the default pool
*/
- if (hw->mac.type < e1000_82576)
+ if ((hw->mac.type < e1000_82576) || (hw->mac.type > e1000_i350))
return;
vmolr |= rd32(E1000_VMOLR(vfn)) &
@@ -3673,7 +3607,7 @@ static bool igb_thermal_sensor_event(struct e1000_hw *hw, u32 event)
bool ret = false;
u32 ctrl_ext, thstat;
- /* check for thermal sensor event on i350, copper only */
+ /* check for thermal sensor event on i350 copper only */
if (hw->mac.type == e1000_i350) {
thstat = rd32(E1000_THSTAT);
ctrl_ext = rd32(E1000_CTRL_EXT);
@@ -5718,35 +5652,7 @@ static int igb_poll(struct napi_struct *napi, int budget)
return 0;
}
-/**
- * igb_systim_to_hwtstamp - convert system time value to hw timestamp
- * @adapter: board private structure
- * @shhwtstamps: timestamp structure to update
- * @regval: unsigned 64bit system time value.
- *
- * We need to convert the system time value stored in the RX/TXSTMP registers
- * into a hwtstamp which can be used by the upper level timestamping functions
- */
-static void igb_systim_to_hwtstamp(struct igb_adapter *adapter,
- struct skb_shared_hwtstamps *shhwtstamps,
- u64 regval)
-{
- u64 ns;
-
- /*
- * The 82580 starts with 1ns at bit 0 in RX/TXSTMPL, shift this up to
- * 24 to match clock shift we setup earlier.
- */
- if (adapter->hw.mac.type >= e1000_82580)
- regval <<= IGB_82580_TSYNC_SHIFT;
-
- ns = timecounter_cyc2time(&adapter->clock, regval);
- timecompare_update(&adapter->compare, ns);
- memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
- shhwtstamps->hwtstamp = ns_to_ktime(ns);
- shhwtstamps->syststamp = timecompare_transform(&adapter->compare, ns);
-}
-
+#ifdef CONFIG_IGB_PTP
/**
* igb_tx_hwtstamp - utility function which checks for TX time stamp
* @q_vector: pointer to q_vector containing needed info
@@ -5776,6 +5682,7 @@ static void igb_tx_hwtstamp(struct igb_q_vector *q_vector,
skb_tstamp_tx(buffer_info->skb, &shhwtstamps);
}
+#endif
/**
* igb_clean_tx_irq - Reclaim resources after transmit completes
* @q_vector: pointer to q_vector containing needed info
@@ -5819,9 +5726,11 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
total_bytes += tx_buffer->bytecount;
total_packets += tx_buffer->gso_segs;
+#ifdef CONFIG_IGB_PTP
/* retrieve hardware timestamp */
igb_tx_hwtstamp(q_vector, tx_buffer);
+#endif
/* free the skb */
dev_kfree_skb_any(tx_buffer->skb);
tx_buffer->skb = NULL;
@@ -5993,6 +5902,7 @@ static inline void igb_rx_hash(struct igb_ring *ring,
skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
}
+#ifdef CONFIG_IGB_PTP
static void igb_rx_hwtstamp(struct igb_q_vector *q_vector,
union e1000_adv_rx_desc *rx_desc,
struct sk_buff *skb)
@@ -6032,6 +5942,7 @@ static void igb_rx_hwtstamp(struct igb_q_vector *q_vector,
igb_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
}
+#endif
static void igb_rx_vlan(struct igb_ring *ring,
union e1000_adv_rx_desc *rx_desc,
struct sk_buff *skb)
@@ -6142,7 +6053,9 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
goto next_desc;
}
+#ifdef CONFIG_IGB_PTP
igb_rx_hwtstamp(q_vector, rx_desc, skb);
+#endif
igb_rx_hash(rx_ring, rx_desc, skb);
igb_rx_checksum(rx_ring, rx_desc, skb);
igb_rx_vlan(rx_ring, rx_desc, skb);
@@ -6796,18 +6709,7 @@ static int igb_resume(struct device *dev)
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
- if (!rtnl_is_locked()) {
- /*
- * shut up ASSERT_RTNL() warning in
- * netif_set_real_num_tx/rx_queues.
- */
- rtnl_lock();
- err = igb_init_interrupt_scheme(adapter);
- rtnl_unlock();
- } else {
- err = igb_init_interrupt_scheme(adapter);
- }
- if (err) {
+ if (igb_init_interrupt_scheme(adapter)) {
dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
return -ENOMEM;
}
@@ -7170,6 +7072,8 @@ static void igb_vmm_control(struct igb_adapter *adapter)
switch (hw->mac.type) {
case e1000_82575:
+ case e1000_i210:
+ case e1000_i211:
default:
/* replication is not supported for 82575 */
return;
@@ -7243,6 +7147,9 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba)
/* watchdog timer= +-1000 usec in 32usec intervals */
reg |= (1000 >> 5);
+
+ /* Disable BMC-to-OS Watchdog Enable */
+ reg &= ~E1000_DMACR_DC_BMC2OSW_EN;
wr32(E1000_DMACR, reg);
/*
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
new file mode 100644
index 000000000000..d5ee7fa50723
--- /dev/null
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -0,0 +1,385 @@
+/*
+ * PTP Hardware Clock (PHC) driver for the Intel 82576 and 82580
+ *
+ * Copyright (C) 2011 Richard Cochran <richardcochran@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+
+#include "igb.h"
+
+#define INCVALUE_MASK 0x7fffffff
+#define ISGN 0x80000000
+
+/*
+ * The 82580 timesync updates the system timer every 8ns by 8ns,
+ * and this update value cannot be reprogrammed.
+ *
+ * Neither the 82576 nor the 82580 offer registers wide enough to hold
+ * nanoseconds time values for very long. For the 82580, SYSTIM always
+ * counts nanoseconds, but the upper 24 bits are not availible. The
+ * frequency is adjusted by changing the 32 bit fractional nanoseconds
+ * register, TIMINCA.
+ *
+ * For the 82576, the SYSTIM register time unit is affect by the
+ * choice of the 24 bit TININCA:IV (incvalue) field. Five bits of this
+ * field are needed to provide the nominal 16 nanosecond period,
+ * leaving 19 bits for fractional nanoseconds.
+ *
+ * We scale the NIC clock cycle by a large factor so that relatively
+ * small clock corrections can be added or subtracted at each clock
+ * tick. The drawbacks of a large factor are a) that the clock
+ * register overflows more quickly (not such a big deal) and b) that
+ * the increment per tick has to fit into 24 bits. As a result we
+ * need to use a shift of 19 so we can fit a value of 16 into the
+ * TIMINCA register.
+ *
+ *
+ * SYSTIMH SYSTIML
+ * +--------------+ +---+---+------+
+ * 82576 | 32 | | 8 | 5 | 19 |
+ * +--------------+ +---+---+------+
+ * \________ 45 bits _______/ fract
+ *
+ * +----------+---+ +--------------+
+ * 82580 | 24 | 8 | | 32 |
+ * +----------+---+ +--------------+
+ * reserved \______ 40 bits _____/
+ *
+ *
+ * The 45 bit 82576 SYSTIM overflows every
+ * 2^45 * 10^-9 / 3600 = 9.77 hours.
+ *
+ * The 40 bit 82580 SYSTIM overflows every
+ * 2^40 * 10^-9 / 60 = 18.3 minutes.
+ */
+
+#define IGB_OVERFLOW_PERIOD (HZ * 60 * 9)
+#define INCPERIOD_82576 (1 << E1000_TIMINCA_16NS_SHIFT)
+#define INCVALUE_82576_MASK ((1 << E1000_TIMINCA_16NS_SHIFT) - 1)
+#define INCVALUE_82576 (16 << IGB_82576_TSYNC_SHIFT)
+#define IGB_NBITS_82580 40
+
+/*
+ * SYSTIM read access for the 82576
+ */
+
+static cycle_t igb_82576_systim_read(const struct cyclecounter *cc)
+{
+ u64 val;
+ u32 lo, hi;
+ struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc);
+ struct e1000_hw *hw = &igb->hw;
+
+ lo = rd32(E1000_SYSTIML);
+ hi = rd32(E1000_SYSTIMH);
+
+ val = ((u64) hi) << 32;
+ val |= lo;
+
+ return val;
+}
+
+/*
+ * SYSTIM read access for the 82580
+ */
+
+static cycle_t igb_82580_systim_read(const struct cyclecounter *cc)
+{
+ u64 val;
+ u32 lo, hi, jk;
+ struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc);
+ struct e1000_hw *hw = &igb->hw;
+
+ /*
+ * The timestamp latches on lowest register read. For the 82580
+ * the lowest register is SYSTIMR instead of SYSTIML. However we only
+ * need to provide nanosecond resolution, so we just ignore it.
+ */
+ jk = rd32(E1000_SYSTIMR);
+ lo = rd32(E1000_SYSTIML);
+ hi = rd32(E1000_SYSTIMH);
+
+ val = ((u64) hi) << 32;
+ val |= lo;
+
+ return val;
+}
+
+/*
+ * PTP clock operations
+ */
+
+static int ptp_82576_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+ u64 rate;
+ u32 incvalue;
+ int neg_adj = 0;
+ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, caps);
+ struct e1000_hw *hw = &igb->hw;
+
+ if (ppb < 0) {
+ neg_adj = 1;
+ ppb = -ppb;
+ }
+ rate = ppb;
+ rate <<= 14;
+ rate = div_u64(rate, 1953125);
+
+ incvalue = 16 << IGB_82576_TSYNC_SHIFT;
+
+ if (neg_adj)
+ incvalue -= rate;
+ else
+ incvalue += rate;
+
+ wr32(E1000_TIMINCA, INCPERIOD_82576 | (incvalue & INCVALUE_82576_MASK));
+
+ return 0;
+}
+
+static int ptp_82580_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+ u64 rate;
+ u32 inca;
+ int neg_adj = 0;
+ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, caps);
+ struct e1000_hw *hw = &igb->hw;
+
+ if (ppb < 0) {
+ neg_adj = 1;
+ ppb = -ppb;
+ }
+ rate = ppb;
+ rate <<= 26;
+ rate = div_u64(rate, 1953125);
+
+ inca = rate & INCVALUE_MASK;
+ if (neg_adj)
+ inca |= ISGN;
+
+ wr32(E1000_TIMINCA, inca);
+
+ return 0;
+}
+
+static int igb_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ s64 now;
+ unsigned long flags;
+ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, caps);
+
+ spin_lock_irqsave(&igb->tmreg_lock, flags);
+
+ now = timecounter_read(&igb->tc);
+ now += delta;
+ timecounter_init(&igb->tc, &igb->cc, now);
+
+ spin_unlock_irqrestore(&igb->tmreg_lock, flags);
+
+ return 0;
+}
+
+static int igb_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+ u64 ns;
+ u32 remainder;
+ unsigned long flags;
+ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, caps);
+
+ spin_lock_irqsave(&igb->tmreg_lock, flags);
+
+ ns = timecounter_read(&igb->tc);
+
+ spin_unlock_irqrestore(&igb->tmreg_lock, flags);
+
+ ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+ ts->tv_nsec = remainder;
+
+ return 0;
+}
+
+static int igb_settime(struct ptp_clock_info *ptp, const struct timespec *ts)
+{
+ u64 ns;
+ unsigned long flags;
+ struct igb_adapter *igb = container_of(ptp, struct igb_adapter, caps);
+
+ ns = ts->tv_sec * 1000000000ULL;
+ ns += ts->tv_nsec;
+
+ spin_lock_irqsave(&igb->tmreg_lock, flags);
+
+ timecounter_init(&igb->tc, &igb->cc, ns);
+
+ spin_unlock_irqrestore(&igb->tmreg_lock, flags);
+
+ return 0;
+}
+
+static int ptp_82576_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ return -EOPNOTSUPP;
+}
+
+static int ptp_82580_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ return -EOPNOTSUPP;
+}
+
+static void igb_overflow_check(struct work_struct *work)
+{
+ struct timespec ts;
+ struct igb_adapter *igb =
+ container_of(work, struct igb_adapter, overflow_work.work);
+
+ igb_gettime(&igb->caps, &ts);
+
+ pr_debug("igb overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec);
+
+ schedule_delayed_work(&igb->overflow_work, IGB_OVERFLOW_PERIOD);
+}
+
+void igb_ptp_init(struct igb_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+
+ switch (hw->mac.type) {
+ case e1000_i210:
+ case e1000_i211:
+ case e1000_i350:
+ case e1000_82580:
+ adapter->caps.owner = THIS_MODULE;
+ strcpy(adapter->caps.name, "igb-82580");
+ adapter->caps.max_adj = 62499999;
+ adapter->caps.n_ext_ts = 0;
+ adapter->caps.pps = 0;
+ adapter->caps.adjfreq = ptp_82580_adjfreq;
+ adapter->caps.adjtime = igb_adjtime;
+ adapter->caps.gettime = igb_gettime;
+ adapter->caps.settime = igb_settime;
+ adapter->caps.enable = ptp_82580_enable;
+ adapter->cc.read = igb_82580_systim_read;
+ adapter->cc.mask = CLOCKSOURCE_MASK(IGB_NBITS_82580);
+ adapter->cc.mult = 1;
+ adapter->cc.shift = 0;
+ /* Enable the timer functions by clearing bit 31. */
+ wr32(E1000_TSAUXC, 0x0);
+ break;
+
+ case e1000_82576:
+ adapter->caps.owner = THIS_MODULE;
+ strcpy(adapter->caps.name, "igb-82576");
+ adapter->caps.max_adj = 1000000000;
+ adapter->caps.n_ext_ts = 0;
+ adapter->caps.pps = 0;
+ adapter->caps.adjfreq = ptp_82576_adjfreq;
+ adapter->caps.adjtime = igb_adjtime;
+ adapter->caps.gettime = igb_gettime;
+ adapter->caps.settime = igb_settime;
+ adapter->caps.enable = ptp_82576_enable;
+ adapter->cc.read = igb_82576_systim_read;
+ adapter->cc.mask = CLOCKSOURCE_MASK(64);
+ adapter->cc.mult = 1;
+ adapter->cc.shift = IGB_82576_TSYNC_SHIFT;
+ /* Dial the nominal frequency. */
+ wr32(E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576);
+ break;
+
+ default:
+ adapter->ptp_clock = NULL;
+ return;
+ }
+
+ wrfl();
+
+ timecounter_init(&adapter->tc, &adapter->cc,
+ ktime_to_ns(ktime_get_real()));
+
+ INIT_DELAYED_WORK(&adapter->overflow_work, igb_overflow_check);
+
+ spin_lock_init(&adapter->tmreg_lock);
+
+ schedule_delayed_work(&adapter->overflow_work, IGB_OVERFLOW_PERIOD);
+
+ adapter->ptp_clock = ptp_clock_register(&adapter->caps);
+ if (IS_ERR(adapter->ptp_clock)) {
+ adapter->ptp_clock = NULL;
+ dev_err(&adapter->pdev->dev, "ptp_clock_register failed\n");
+ } else
+ dev_info(&adapter->pdev->dev, "added PHC on %s\n",
+ adapter->netdev->name);
+}
+
+void igb_ptp_remove(struct igb_adapter *adapter)
+{
+ cancel_delayed_work_sync(&adapter->overflow_work);
+
+ if (adapter->ptp_clock) {
+ ptp_clock_unregister(adapter->ptp_clock);
+ dev_info(&adapter->pdev->dev, "removed PHC on %s\n",
+ adapter->netdev->name);
+ }
+}
+
+/**
+ * igb_systim_to_hwtstamp - convert system time value to hw timestamp
+ * @adapter: board private structure
+ * @hwtstamps: timestamp structure to update
+ * @systim: unsigned 64bit system time value.
+ *
+ * We need to convert the system time value stored in the RX/TXSTMP registers
+ * into a hwtstamp which can be used by the upper level timestamping functions.
+ *
+ * The 'tmreg_lock' spinlock is used to protect the consistency of the
+ * system time value. This is needed because reading the 64 bit time
+ * value involves reading two (or three) 32 bit registers. The first
+ * read latches the value. Ditto for writing.
+ *
+ * In addition, here have extended the system time with an overflow
+ * counter in software.
+ **/
+void igb_systim_to_hwtstamp(struct igb_adapter *adapter,
+ struct skb_shared_hwtstamps *hwtstamps,
+ u64 systim)
+{
+ u64 ns;
+ unsigned long flags;
+
+ switch (adapter->hw.mac.type) {
+ case e1000_i210:
+ case e1000_i211:
+ case e1000_i350:
+ case e1000_82580:
+ case e1000_82576:
+ break;
+ default:
+ return;
+ }
+
+ spin_lock_irqsave(&adapter->tmreg_lock, flags);
+
+ ns = timecounter_cyc2time(&adapter->tc, systim);
+
+ spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+
+ memset(hwtstamps, 0, sizeof(*hwtstamps));
+ hwtstamps->hwtstamp = ns_to_ktime(ns);
+}
diff --git a/drivers/net/ethernet/intel/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile
index 8be1d1b2132e..0bdf06bc5c49 100644
--- a/drivers/net/ethernet/intel/ixgbe/Makefile
+++ b/drivers/net/ethernet/intel/ixgbe/Makefile
@@ -34,9 +34,11 @@ obj-$(CONFIG_IXGBE) += ixgbe.o
ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \
ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
- ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o
+ ixgbe_mbx.o ixgbe_x540.o ixgbe_sysfs.o ixgbe_lib.o
ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \
ixgbe_dcb_82599.o ixgbe_dcb_nl.o
+ixgbe-$(CONFIG_IXGBE_PTP) += ixgbe_ptp.o
+
ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 74e192107f9a..3ef3c5284e52 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -36,6 +36,12 @@
#include <linux/aer.h>
#include <linux/if_vlan.h>
+#ifdef CONFIG_IXGBE_PTP
+#include <linux/clocksource.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
+#endif /* CONFIG_IXGBE_PTP */
+
#include "ixgbe_type.h"
#include "ixgbe_common.h"
#include "ixgbe_dcb.h"
@@ -96,6 +102,7 @@
#define IXGBE_TX_FLAGS_FCOE (u32)(1 << 5)
#define IXGBE_TX_FLAGS_FSO (u32)(1 << 6)
#define IXGBE_TX_FLAGS_TXSW (u32)(1 << 7)
+#define IXGBE_TX_FLAGS_TSTAMP (u32)(1 << 8)
#define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000
#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000
#define IXGBE_TX_FLAGS_VLAN_PRIO_SHIFT 29
@@ -331,6 +338,26 @@ struct ixgbe_q_vector {
/* for dynamic allocation of rings associated with this q_vector */
struct ixgbe_ring ring[0] ____cacheline_internodealigned_in_smp;
};
+#ifdef CONFIG_IXGBE_HWMON
+
+#define IXGBE_HWMON_TYPE_LOC 0
+#define IXGBE_HWMON_TYPE_TEMP 1
+#define IXGBE_HWMON_TYPE_CAUTION 2
+#define IXGBE_HWMON_TYPE_MAX 3
+
+struct hwmon_attr {
+ struct device_attribute dev_attr;
+ struct ixgbe_hw *hw;
+ struct ixgbe_thermal_diode_data *sensor;
+ char name[12];
+};
+
+struct hwmon_buff {
+ struct device *device;
+ struct hwmon_attr *hwmon_list;
+ unsigned int n_hwmon;
+};
+#endif /* CONFIG_IXGBE_HWMON */
/*
* microsecond values for various ITR rates shifted by 2 to fit itr register
@@ -438,6 +465,8 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_FDIR_REQUIRES_REINIT (u32)(1 << 7)
#define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP (u32)(1 << 8)
#define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP (u32)(1 << 9)
+#define IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED (u32)(1 << 10)
+#define IXGBE_FLAG2_PTP_PPS_ENABLED (u32)(1 << 11)
/* Tx fast path data */
int num_tx_queues;
@@ -525,6 +554,17 @@ struct ixgbe_adapter {
u32 interrupt_event;
u32 led_reg;
+#ifdef CONFIG_IXGBE_PTP
+ struct ptp_clock *ptp_clock;
+ struct ptp_clock_info ptp_caps;
+ unsigned long last_overflow_check;
+ spinlock_t tmreg_lock;
+ struct cyclecounter cc;
+ struct timecounter tc;
+ u32 base_incval;
+ u32 cycle_speed;
+#endif /* CONFIG_IXGBE_PTP */
+
/* SR-IOV */
DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
unsigned int num_vfs;
@@ -535,6 +575,10 @@ struct ixgbe_adapter {
u32 timer_event_accumulator;
u32 vferr_refcount;
+ struct kobject *info_kobj;
+#ifdef CONFIG_IXGBE_HWMON
+ struct hwmon_buff ixgbe_hwmon_buff;
+#endif /* CONFIG_IXGBE_HWMON */
};
struct ixgbe_fdir_filter {
@@ -574,9 +618,6 @@ extern struct ixgbe_info ixgbe_82599_info;
extern struct ixgbe_info ixgbe_X540_info;
#ifdef CONFIG_IXGBE_DCB
extern const struct dcbnl_rtnl_ops dcbnl_ops;
-extern int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg,
- struct ixgbe_dcb_config *dst_dcb_cfg,
- int tc_max);
#endif
extern char ixgbe_driver_name[];
@@ -600,6 +641,8 @@ extern void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter,
struct ixgbe_ring *);
extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
+extern int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
+ u16 subdevice_id);
extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
extern netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *,
struct ixgbe_adapter *,
@@ -629,10 +672,15 @@ extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
union ixgbe_atr_input *mask);
extern void ixgbe_set_rx_mode(struct net_device *netdev);
#ifdef CONFIG_IXGBE_DCB
+extern void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter);
extern int ixgbe_setup_tc(struct net_device *dev, u8 tc);
#endif
extern void ixgbe_tx_ctxtdesc(struct ixgbe_ring *, u32, u32, u32, u32);
extern void ixgbe_do_reset(struct net_device *netdev);
+#ifdef CONFIG_IXGBE_HWMON
+extern void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter);
+extern int ixgbe_sysfs_init(struct ixgbe_adapter *adapter);
+#endif /* CONFIG_IXGBE_HWMON */
#ifdef IXGBE_FCOE
extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
extern int ixgbe_fso(struct ixgbe_ring *tx_ring,
@@ -663,4 +711,18 @@ static inline struct netdev_queue *txring_txq(const struct ixgbe_ring *ring)
return netdev_get_tx_queue(ring->netdev, ring->queue_index);
}
+#ifdef CONFIG_IXGBE_PTP
+extern void ixgbe_ptp_init(struct ixgbe_adapter *adapter);
+extern void ixgbe_ptp_stop(struct ixgbe_adapter *adapter);
+extern void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter);
+extern void ixgbe_ptp_tx_hwtstamp(struct ixgbe_q_vector *q_vector,
+ struct sk_buff *skb);
+extern void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
+ struct sk_buff *skb);
+extern int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
+ struct ifreq *ifr, int cmd);
+extern void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter);
+extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr);
+#endif /* CONFIG_IXGBE_PTP */
+
#endif /* _IXGBE_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index 85d2e2c4ce4a..42537336110c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -91,29 +91,6 @@ out:
IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr);
}
-/**
- * ixgbe_get_pcie_msix_count_82598 - Gets MSI-X vector count
- * @hw: pointer to hardware structure
- *
- * Read PCIe configuration space, and get the MSI-X vector count from
- * the capabilities table.
- **/
-static u16 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw)
-{
- struct ixgbe_adapter *adapter = hw->back;
- u16 msix_count;
- pci_read_config_word(adapter->pdev, IXGBE_PCIE_MSIX_82598_CAPS,
- &msix_count);
- msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
-
- /* MSI-X count is zero-based in HW, so increment to give proper value */
- msix_count++;
-
- return msix_count;
-}
-
-/**
- */
static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
{
struct ixgbe_mac_info *mac = &hw->mac;
@@ -126,7 +103,7 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES;
mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
- mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw);
+ mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
return 0;
}
@@ -347,24 +324,33 @@ out:
/**
* ixgbe_fc_enable_82598 - Enable flow control
* @hw: pointer to hardware structure
- * @packetbuf_num: packet buffer number (0-7)
*
* Enable flow control according to the current settings.
**/
-static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
+static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
{
s32 ret_val = 0;
u32 fctrl_reg;
u32 rmcs_reg;
u32 reg;
+ u32 fcrtl, fcrth;
u32 link_speed = 0;
+ int i;
bool link_up;
-#ifdef CONFIG_DCB
- if (hw->fc.requested_mode == ixgbe_fc_pfc)
+ /*
+ * Validate the water mark configuration for packet buffer 0. Zero
+ * water marks indicate that the packet buffer was not configured
+ * and the watermarks for packet buffer 0 should always be configured.
+ */
+ if (!hw->fc.low_water ||
+ !hw->fc.high_water[0] ||
+ !hw->fc.pause_time) {
+ hw_dbg(hw, "Invalid water mark configuration\n");
+ ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
goto out;
+ }
-#endif /* CONFIG_DCB */
/*
* On 82598 having Rx FC on causes resets while doing 1G
* so if it's on turn it off once we know link_speed. For
@@ -386,9 +372,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
}
/* Negotiate the fc mode to use */
- ret_val = ixgbe_fc_autoneg(hw);
- if (ret_val == IXGBE_ERR_FLOW_CONTROL)
- goto out;
+ ixgbe_fc_autoneg(hw);
/* Disable any previous flow control settings */
fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
@@ -405,9 +389,6 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
* 2: Tx flow control is enabled (we can send pause frames but
* we do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled.
-#ifdef CONFIG_DCB
- * 4: Priority Flow Control is enabled.
-#endif
* other: Invalid.
*/
switch (hw->fc.current_mode) {
@@ -440,11 +421,6 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
fctrl_reg |= IXGBE_FCTRL_RFCE;
rmcs_reg |= IXGBE_RMCS_TFCE_802_3X;
break;
-#ifdef CONFIG_DCB
- case ixgbe_fc_pfc:
- goto out;
- break;
-#endif /* CONFIG_DCB */
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
ret_val = IXGBE_ERR_CONFIG;
@@ -457,29 +433,29 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg);
IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg);
- /* Set up and enable Rx high/low water mark thresholds, enable XON. */
- if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
- reg = hw->fc.low_water << 6;
- if (hw->fc.send_xon)
- reg |= IXGBE_FCRTL_XONE;
-
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg);
+ fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
- reg = hw->fc.high_water[packetbuf_num] << 6;
- reg |= IXGBE_FCRTH_FCEN;
+ /* Set up and enable Rx high/low water mark thresholds, enable XON. */
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
+ hw->fc.high_water[i]) {
+ fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), fcrth);
+ } else {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0);
+ }
- IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg);
}
/* Configure pause time (2 TCs per register) */
- reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
- if ((packetbuf_num & 1) == 0)
- reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
- else
- reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
- IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
+ reg = hw->fc.pause_time * 0x00010001;
+ for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
+ IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
- IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
+ /* Configure flow control refresh threshold value */
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
out:
return ret_val;
@@ -1300,6 +1276,8 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
.set_fw_drv_ver = NULL,
.acquire_swfw_sync = &ixgbe_acquire_swfw_sync,
.release_swfw_sync = &ixgbe_release_swfw_sync,
+ .get_thermal_sensor_data = NULL,
+ .init_thermal_sensor_thresh = NULL,
};
static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index 9c14685358eb..dee64d2703f0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -2119,6 +2119,8 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing,
.acquire_swfw_sync = &ixgbe_acquire_swfw_sync,
.release_swfw_sync = &ixgbe_release_swfw_sync,
+ .get_thermal_sensor_data = &ixgbe_get_thermal_sensor_data_generic,
+ .init_thermal_sensor_thresh = &ixgbe_init_thermal_sensor_thresh_generic,
};
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 49aa41fe7b84..77ac41feb0fe 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -47,13 +47,6 @@ static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
-static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw);
-static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw);
-static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw);
-static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
-static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
- u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
-static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data);
@@ -64,6 +57,172 @@ static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
/**
+ * ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
+ * control
+ * @hw: pointer to hardware structure
+ *
+ * There are several phys that do not support autoneg flow control. This
+ * function check the device id to see if the associated phy supports
+ * autoneg flow control.
+ **/
+static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+{
+
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_X540T:
+ return 0;
+ case IXGBE_DEV_ID_82599_T3_LOM:
+ return 0;
+ default:
+ return IXGBE_ERR_FC_NOT_SUPPORTED;
+ }
+}
+
+/**
+ * ixgbe_setup_fc - Set up flow control
+ * @hw: pointer to hardware structure
+ *
+ * Called at init time to set up flow control.
+ **/
+static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
+{
+ s32 ret_val = 0;
+ u32 reg = 0, reg_bp = 0;
+ u16 reg_cu = 0;
+
+ /*
+ * Validate the requested mode. Strict IEEE mode does not allow
+ * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
+ */
+ if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
+ hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
+ ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+ goto out;
+ }
+
+ /*
+ * 10gig parts do not have a word in the EEPROM to determine the
+ * default flow control setting, so we explicitly set it to full.
+ */
+ if (hw->fc.requested_mode == ixgbe_fc_default)
+ hw->fc.requested_mode = ixgbe_fc_full;
+
+ /*
+ * Set up the 1G and 10G flow control advertisement registers so the
+ * HW will be able to do fc autoneg once the cable is plugged in. If
+ * we link at 10G, the 1G advertisement is harmless and vice versa.
+ */
+ switch (hw->phy.media_type) {
+ case ixgbe_media_type_fiber:
+ case ixgbe_media_type_backplane:
+ reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+ reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ break;
+ case ixgbe_media_type_copper:
+ hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
+ MDIO_MMD_AN, &reg_cu);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * The possible values of fc.requested_mode are:
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames,
+ * but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but
+ * we do not support receiving pause frames).
+ * 3: Both Rx and Tx flow control (symmetric) are enabled.
+ * other: Invalid.
+ */
+ switch (hw->fc.requested_mode) {
+ case ixgbe_fc_none:
+ /* Flow control completely disabled by software override. */
+ reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ if (hw->phy.media_type == ixgbe_media_type_backplane)
+ reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
+ IXGBE_AUTOC_ASM_PAUSE);
+ else if (hw->phy.media_type == ixgbe_media_type_copper)
+ reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
+ break;
+ case ixgbe_fc_tx_pause:
+ /*
+ * Tx Flow control is enabled, and Rx Flow control is
+ * disabled by software override.
+ */
+ reg |= IXGBE_PCS1GANA_ASM_PAUSE;
+ reg &= ~IXGBE_PCS1GANA_SYM_PAUSE;
+ if (hw->phy.media_type == ixgbe_media_type_backplane) {
+ reg_bp |= IXGBE_AUTOC_ASM_PAUSE;
+ reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE;
+ } else if (hw->phy.media_type == ixgbe_media_type_copper) {
+ reg_cu |= IXGBE_TAF_ASM_PAUSE;
+ reg_cu &= ~IXGBE_TAF_SYM_PAUSE;
+ }
+ break;
+ case ixgbe_fc_rx_pause:
+ /*
+ * Rx Flow control is enabled and Tx Flow control is
+ * disabled by software override. Since there really
+ * isn't a way to advertise that we are capable of RX
+ * Pause ONLY, we will advertise that we support both
+ * symmetric and asymmetric Rx PAUSE, as such we fall
+ * through to the fc_full statement. Later, we will
+ * disable the adapter's ability to send PAUSE frames.
+ */
+ case ixgbe_fc_full:
+ /* Flow control (both Rx and Tx) is enabled by SW override. */
+ reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE;
+ if (hw->phy.media_type == ixgbe_media_type_backplane)
+ reg_bp |= IXGBE_AUTOC_SYM_PAUSE |
+ IXGBE_AUTOC_ASM_PAUSE;
+ else if (hw->phy.media_type == ixgbe_media_type_copper)
+ reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE;
+ break;
+ default:
+ hw_dbg(hw, "Flow control param set incorrectly\n");
+ ret_val = IXGBE_ERR_CONFIG;
+ goto out;
+ break;
+ }
+
+ if (hw->mac.type != ixgbe_mac_X540) {
+ /*
+ * Enable auto-negotiation between the MAC & PHY;
+ * the MAC will advertise clause 37 flow control.
+ */
+ IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
+ reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
+
+ /* Disable AN timeout */
+ if (hw->fc.strict_ieee)
+ reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+
+ IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+ hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+ }
+
+ /*
+ * AUTOC restart handles negotiation of 1G and 10G on backplane
+ * and copper. There is no need to set the PCS1GCTL register.
+ *
+ */
+ if (hw->phy.media_type == ixgbe_media_type_backplane) {
+ reg_bp |= IXGBE_AUTOC_AN_RESTART;
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+ } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
+ (ixgbe_device_supports_autoneg_fc(hw) == 0)) {
+ hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
+ MDIO_MMD_AN, reg_cu);
+ }
+
+ hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
+out:
+ return ret_val;
+}
+
+/**
* ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
* @hw: pointer to hardware structure
*
@@ -95,7 +254,7 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
IXGBE_WRITE_FLUSH(hw);
/* Setup flow control */
- ixgbe_setup_fc(hw, 0);
+ ixgbe_setup_fc(hw);
/* Clear adapter stopped flag */
hw->adapter_stopped = false;
@@ -1923,30 +2082,36 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
/**
* ixgbe_fc_enable_generic - Enable flow control
* @hw: pointer to hardware structure
- * @packetbuf_num: packet buffer number (0-7)
*
* Enable flow control according to the current settings.
**/
-s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
{
s32 ret_val = 0;
u32 mflcn_reg, fccfg_reg;
u32 reg;
u32 fcrtl, fcrth;
+ int i;
-#ifdef CONFIG_DCB
- if (hw->fc.requested_mode == ixgbe_fc_pfc)
+ /*
+ * Validate the water mark configuration for packet buffer 0. Zero
+ * water marks indicate that the packet buffer was not configured
+ * and the watermarks for packet buffer 0 should always be configured.
+ */
+ if (!hw->fc.low_water ||
+ !hw->fc.high_water[0] ||
+ !hw->fc.pause_time) {
+ hw_dbg(hw, "Invalid water mark configuration\n");
+ ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
goto out;
+ }
-#endif /* CONFIG_DCB */
/* Negotiate the fc mode to use */
- ret_val = ixgbe_fc_autoneg(hw);
- if (ret_val == IXGBE_ERR_FLOW_CONTROL)
- goto out;
+ ixgbe_fc_autoneg(hw);
/* Disable any previous flow control settings */
mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
- mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE);
+ mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE);
fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY);
@@ -1959,9 +2124,6 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
* 2: Tx flow control is enabled (we can send pause frames but
* we do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled.
-#ifdef CONFIG_DCB
- * 4: Priority Flow Control is enabled.
-#endif
* other: Invalid.
*/
switch (hw->fc.current_mode) {
@@ -1994,11 +2156,6 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
mflcn_reg |= IXGBE_MFLCN_RFCE;
fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
break;
-#ifdef CONFIG_DCB
- case ixgbe_fc_pfc:
- goto out;
- break;
-#endif /* CONFIG_DCB */
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
ret_val = IXGBE_ERR_CONFIG;
@@ -2011,100 +2168,86 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
- fcrtl = hw->fc.low_water << 10;
+ fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
- if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
- fcrth = hw->fc.high_water[packetbuf_num] << 10;
- fcrth |= IXGBE_FCRTH_FCEN;
- if (hw->fc.send_xon)
- fcrtl |= IXGBE_FCRTL_XONE;
- } else {
- /*
- * If Tx flow control is disabled, set our high water mark
- * to Rx FIFO size minus 32 in order prevent Tx switch
- * loopback from stalling on DMA.
- */
- fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num)) - 32;
- }
+ /* Set up and enable Rx high/low water mark thresholds, enable XON. */
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
+ hw->fc.high_water[i]) {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
+ fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
+ } else {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
+ /*
+ * In order to prevent Tx hangs when the internal Tx
+ * switch is enabled we must set the high water mark
+ * to the maximum FCRTH value. This allows the Tx
+ * switch to function even under heavy Rx workloads.
+ */
+ fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
+ }
- IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), fcrth);
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), fcrtl);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth);
+ }
/* Configure pause time (2 TCs per register) */
- reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
- if ((packetbuf_num & 1) == 0)
- reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
- else
- reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
- IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
+ reg = hw->fc.pause_time * 0x00010001;
+ for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
+ IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
- IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
out:
return ret_val;
}
/**
- * ixgbe_fc_autoneg - Configure flow control
+ * ixgbe_negotiate_fc - Negotiate flow control
* @hw: pointer to hardware structure
+ * @adv_reg: flow control advertised settings
+ * @lp_reg: link partner's flow control settings
+ * @adv_sym: symmetric pause bit in advertisement
+ * @adv_asm: asymmetric pause bit in advertisement
+ * @lp_sym: symmetric pause bit in link partner advertisement
+ * @lp_asm: asymmetric pause bit in link partner advertisement
*
- * Compares our advertised flow control capabilities to those advertised by
- * our link partner, and determines the proper flow control mode to use.
+ * Find the intersection between advertised settings and link partner's
+ * advertised settings
**/
-s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
+static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+ u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
{
- s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
- ixgbe_link_speed speed;
- bool link_up;
-
- if (hw->fc.disable_fc_autoneg)
- goto out;
-
- /*
- * AN should have completed when the cable was plugged in.
- * Look for reasons to bail out. Bail out if:
- * - FC autoneg is disabled, or if
- * - link is not up.
- *
- * Since we're being called from an LSC, link is already known to be up.
- * So use link_up_wait_to_complete=false.
- */
- hw->mac.ops.check_link(hw, &speed, &link_up, false);
- if (!link_up) {
- ret_val = IXGBE_ERR_FLOW_CONTROL;
- goto out;
- }
-
- switch (hw->phy.media_type) {
- /* Autoneg flow control on fiber adapters */
- case ixgbe_media_type_fiber:
- if (speed == IXGBE_LINK_SPEED_1GB_FULL)
- ret_val = ixgbe_fc_autoneg_fiber(hw);
- break;
-
- /* Autoneg flow control on backplane adapters */
- case ixgbe_media_type_backplane:
- ret_val = ixgbe_fc_autoneg_backplane(hw);
- break;
-
- /* Autoneg flow control on copper adapters */
- case ixgbe_media_type_copper:
- if (ixgbe_device_supports_autoneg_fc(hw) == 0)
- ret_val = ixgbe_fc_autoneg_copper(hw);
- break;
-
- default:
- break;
- }
+ if ((!(adv_reg)) || (!(lp_reg)))
+ return IXGBE_ERR_FC_NOT_NEGOTIATED;
-out:
- if (ret_val == 0) {
- hw->fc.fc_was_autonegged = true;
+ if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
+ /*
+ * Now we need to check if the user selected Rx ONLY
+ * of pause frames. In this case, we had to advertise
+ * FULL flow control because we could not advertise RX
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
+ */
+ if (hw->fc.requested_mode == ixgbe_fc_full) {
+ hw->fc.current_mode = ixgbe_fc_full;
+ hw_dbg(hw, "Flow Control = FULL.\n");
+ } else {
+ hw->fc.current_mode = ixgbe_fc_rx_pause;
+ hw_dbg(hw, "Flow Control=RX PAUSE frames only\n");
+ }
+ } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+ (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+ hw->fc.current_mode = ixgbe_fc_tx_pause;
+ hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
+ } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+ !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+ hw->fc.current_mode = ixgbe_fc_rx_pause;
+ hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
} else {
- hw->fc.fc_was_autonegged = false;
- hw->fc.current_mode = hw->fc.requested_mode;
+ hw->fc.current_mode = ixgbe_fc_none;
+ hw_dbg(hw, "Flow Control = NONE.\n");
}
- return ret_val;
+ return 0;
}
/**
@@ -2116,7 +2259,7 @@ out:
static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
{
u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
- s32 ret_val;
+ s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
/*
* On multispeed fiber at 1g, bail out if
@@ -2126,10 +2269,8 @@ static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
- (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
- ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1))
goto out;
- }
pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
@@ -2153,7 +2294,7 @@ out:
static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
{
u32 links2, anlp1_reg, autoc_reg, links;
- s32 ret_val;
+ s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
/*
* On backplane, bail out if
@@ -2161,21 +2302,13 @@ static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
* - we are 82599 and link partner is not AN enabled
*/
links = IXGBE_READ_REG(hw, IXGBE_LINKS);
- if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
- hw->fc.fc_was_autonegged = false;
- hw->fc.current_mode = hw->fc.requested_mode;
- ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ if ((links & IXGBE_LINKS_KX_AN_COMP) == 0)
goto out;
- }
if (hw->mac.type == ixgbe_mac_82599EB) {
links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
- if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
- hw->fc.fc_was_autonegged = false;
- hw->fc.current_mode = hw->fc.requested_mode;
- ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)
goto out;
- }
}
/*
* Read the 10g AN autoc and LP ability registers and resolve
@@ -2217,241 +2350,63 @@ static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw)
}
/**
- * ixgbe_negotiate_fc - Negotiate flow control
- * @hw: pointer to hardware structure
- * @adv_reg: flow control advertised settings
- * @lp_reg: link partner's flow control settings
- * @adv_sym: symmetric pause bit in advertisement
- * @adv_asm: asymmetric pause bit in advertisement
- * @lp_sym: symmetric pause bit in link partner advertisement
- * @lp_asm: asymmetric pause bit in link partner advertisement
- *
- * Find the intersection between advertised settings and link partner's
- * advertised settings
- **/
-static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
- u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
-{
- if ((!(adv_reg)) || (!(lp_reg)))
- return IXGBE_ERR_FC_NOT_NEGOTIATED;
-
- if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
- /*
- * Now we need to check if the user selected Rx ONLY
- * of pause frames. In this case, we had to advertise
- * FULL flow control because we could not advertise RX
- * ONLY. Hence, we must now check to see if we need to
- * turn OFF the TRANSMISSION of PAUSE frames.
- */
- if (hw->fc.requested_mode == ixgbe_fc_full) {
- hw->fc.current_mode = ixgbe_fc_full;
- hw_dbg(hw, "Flow Control = FULL.\n");
- } else {
- hw->fc.current_mode = ixgbe_fc_rx_pause;
- hw_dbg(hw, "Flow Control=RX PAUSE frames only\n");
- }
- } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
- (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
- hw->fc.current_mode = ixgbe_fc_tx_pause;
- hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
- } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
- !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
- hw->fc.current_mode = ixgbe_fc_rx_pause;
- hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
- } else {
- hw->fc.current_mode = ixgbe_fc_none;
- hw_dbg(hw, "Flow Control = NONE.\n");
- }
- return 0;
-}
-
-/**
- * ixgbe_setup_fc - Set up flow control
+ * ixgbe_fc_autoneg - Configure flow control
* @hw: pointer to hardware structure
*
- * Called at init time to set up flow control.
+ * Compares our advertised flow control capabilities to those advertised by
+ * our link partner, and determines the proper flow control mode to use.
**/
-static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
+void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
{
- s32 ret_val = 0;
- u32 reg = 0, reg_bp = 0;
- u16 reg_cu = 0;
-
-#ifdef CONFIG_DCB
- if (hw->fc.requested_mode == ixgbe_fc_pfc) {
- hw->fc.current_mode = hw->fc.requested_mode;
- goto out;
- }
-
-#endif /* CONFIG_DCB */
- /* Validate the packetbuf configuration */
- if (packetbuf_num < 0 || packetbuf_num > 7) {
- hw_dbg(hw, "Invalid packet buffer number [%d], expected range "
- "is 0-7\n", packetbuf_num);
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
- }
+ s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ ixgbe_link_speed speed;
+ bool link_up;
/*
- * Validate the water mark configuration. Zero water marks are invalid
- * because it causes the controller to just blast out fc packets.
+ * AN should have completed when the cable was plugged in.
+ * Look for reasons to bail out. Bail out if:
+ * - FC autoneg is disabled, or if
+ * - link is not up.
+ *
+ * Since we're being called from an LSC, link is already known to be up.
+ * So use link_up_wait_to_complete=false.
*/
- if (!hw->fc.low_water ||
- !hw->fc.high_water[packetbuf_num] ||
- !hw->fc.pause_time) {
- hw_dbg(hw, "Invalid water mark configuration\n");
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+ if (hw->fc.disable_fc_autoneg)
goto out;
- }
- /*
- * Validate the requested mode. Strict IEEE mode does not allow
- * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
- */
- if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
- hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict "
- "IEEE mode\n");
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+ hw->mac.ops.check_link(hw, &speed, &link_up, false);
+ if (!link_up)
goto out;
- }
-
- /*
- * 10gig parts do not have a word in the EEPROM to determine the
- * default flow control setting, so we explicitly set it to full.
- */
- if (hw->fc.requested_mode == ixgbe_fc_default)
- hw->fc.requested_mode = ixgbe_fc_full;
-
- /*
- * Set up the 1G and 10G flow control advertisement registers so the
- * HW will be able to do fc autoneg once the cable is plugged in. If
- * we link at 10G, the 1G advertisement is harmless and vice versa.
- */
switch (hw->phy.media_type) {
+ /* Autoneg flow control on fiber adapters */
case ixgbe_media_type_fiber:
+ if (speed == IXGBE_LINK_SPEED_1GB_FULL)
+ ret_val = ixgbe_fc_autoneg_fiber(hw);
+ break;
+
+ /* Autoneg flow control on backplane adapters */
case ixgbe_media_type_backplane:
- reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
- reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ ret_val = ixgbe_fc_autoneg_backplane(hw);
break;
+ /* Autoneg flow control on copper adapters */
case ixgbe_media_type_copper:
- hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
- MDIO_MMD_AN, &reg_cu);
+ if (ixgbe_device_supports_autoneg_fc(hw) == 0)
+ ret_val = ixgbe_fc_autoneg_copper(hw);
break;
default:
- ;
- }
-
- /*
- * The possible values of fc.requested_mode are:
- * 0: Flow control is completely disabled
- * 1: Rx flow control is enabled (we can receive pause frames,
- * but not send pause frames).
- * 2: Tx flow control is enabled (we can send pause frames but
- * we do not support receiving pause frames).
- * 3: Both Rx and Tx flow control (symmetric) are enabled.
-#ifdef CONFIG_DCB
- * 4: Priority Flow Control is enabled.
-#endif
- * other: Invalid.
- */
- switch (hw->fc.requested_mode) {
- case ixgbe_fc_none:
- /* Flow control completely disabled by software override. */
- reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
- if (hw->phy.media_type == ixgbe_media_type_backplane)
- reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
- IXGBE_AUTOC_ASM_PAUSE);
- else if (hw->phy.media_type == ixgbe_media_type_copper)
- reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
- break;
- case ixgbe_fc_rx_pause:
- /*
- * Rx Flow control is enabled and Tx Flow control is
- * disabled by software override. Since there really
- * isn't a way to advertise that we are capable of RX
- * Pause ONLY, we will advertise that we support both
- * symmetric and asymmetric Rx PAUSE. Later, we will
- * disable the adapter's ability to send PAUSE frames.
- */
- reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
- if (hw->phy.media_type == ixgbe_media_type_backplane)
- reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
- IXGBE_AUTOC_ASM_PAUSE);
- else if (hw->phy.media_type == ixgbe_media_type_copper)
- reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
- break;
- case ixgbe_fc_tx_pause:
- /*
- * Tx Flow control is enabled, and Rx Flow control is
- * disabled by software override.
- */
- reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
- reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
- if (hw->phy.media_type == ixgbe_media_type_backplane) {
- reg_bp |= (IXGBE_AUTOC_ASM_PAUSE);
- reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE);
- } else if (hw->phy.media_type == ixgbe_media_type_copper) {
- reg_cu |= (IXGBE_TAF_ASM_PAUSE);
- reg_cu &= ~(IXGBE_TAF_SYM_PAUSE);
- }
break;
- case ixgbe_fc_full:
- /* Flow control (both Rx and Tx) is enabled by SW override. */
- reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
- if (hw->phy.media_type == ixgbe_media_type_backplane)
- reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
- IXGBE_AUTOC_ASM_PAUSE);
- else if (hw->phy.media_type == ixgbe_media_type_copper)
- reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
- break;
-#ifdef CONFIG_DCB
- case ixgbe_fc_pfc:
- goto out;
- break;
-#endif /* CONFIG_DCB */
- default:
- hw_dbg(hw, "Flow control param set incorrectly\n");
- ret_val = IXGBE_ERR_CONFIG;
- goto out;
- break;
- }
-
- if (hw->mac.type != ixgbe_mac_X540) {
- /*
- * Enable auto-negotiation between the MAC & PHY;
- * the MAC will advertise clause 37 flow control.
- */
- IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
- reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
-
- /* Disable AN timeout */
- if (hw->fc.strict_ieee)
- reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
-
- IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
- hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
- }
-
- /*
- * AUTOC restart handles negotiation of 1G and 10G on backplane
- * and copper. There is no need to set the PCS1GCTL register.
- *
- */
- if (hw->phy.media_type == ixgbe_media_type_backplane) {
- reg_bp |= IXGBE_AUTOC_AN_RESTART;
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
- } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
- (ixgbe_device_supports_autoneg_fc(hw) == 0)) {
- hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
- MDIO_MMD_AN, reg_cu);
}
- hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
out:
- return ret_val;
+ if (ret_val == 0) {
+ hw->fc.fc_was_autonegged = true;
+ } else {
+ hw->fc.fc_was_autonegged = false;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ }
}
/**
@@ -2606,7 +2561,7 @@ s32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw)
break;
else
/* Use interrupt-safe sleep just in case */
- udelay(10);
+ udelay(1000);
}
/* For informational purposes only */
@@ -2783,17 +2738,36 @@ san_mac_addr_out:
* Read PCIe configuration space, and get the MSI-X vector count from
* the capabilities table.
**/
-u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
+u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
{
struct ixgbe_adapter *adapter = hw->back;
- u16 msix_count;
- pci_read_config_word(adapter->pdev, IXGBE_PCIE_MSIX_82599_CAPS,
- &msix_count);
+ u16 msix_count = 1;
+ u16 max_msix_count;
+ u16 pcie_offset;
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS;
+ max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598;
+ break;
+ case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
+ pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS;
+ max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
+ break;
+ default:
+ return msix_count;
+ }
+
+ pci_read_config_word(adapter->pdev, pcie_offset, &msix_count);
msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
- /* MSI-X count is zero-based in HW, so increment to give proper value */
+ /* MSI-X count is zero-based in HW */
msix_count++;
+ if (msix_count > max_msix_count)
+ msix_count = max_msix_count;
+
return msix_count;
}
@@ -3203,28 +3177,6 @@ wwn_prefix_out:
}
/**
- * ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
- * control
- * @hw: pointer to hardware structure
- *
- * There are several phys that do not support autoneg flow control. This
- * function check the device id to see if the associated phy supports
- * autoneg flow control.
- **/
-static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
-{
-
- switch (hw->device_id) {
- case IXGBE_DEV_ID_X540T:
- return 0;
- case IXGBE_DEV_ID_82599_T3_LOM:
- return 0;
- default:
- return IXGBE_ERR_FC_NOT_SUPPORTED;
- }
-}
-
-/**
* ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing
* @hw: pointer to hardware structure
* @enable: enable or disable switch for anti-spoofing
@@ -3585,3 +3537,172 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
}
+
+static const u8 ixgbe_emc_temp_data[4] = {
+ IXGBE_EMC_INTERNAL_DATA,
+ IXGBE_EMC_DIODE1_DATA,
+ IXGBE_EMC_DIODE2_DATA,
+ IXGBE_EMC_DIODE3_DATA
+};
+static const u8 ixgbe_emc_therm_limit[4] = {
+ IXGBE_EMC_INTERNAL_THERM_LIMIT,
+ IXGBE_EMC_DIODE1_THERM_LIMIT,
+ IXGBE_EMC_DIODE2_THERM_LIMIT,
+ IXGBE_EMC_DIODE3_THERM_LIMIT
+};
+
+/**
+ * ixgbe_get_ets_data - Extracts the ETS bit data
+ * @hw: pointer to hardware structure
+ * @ets_cfg: extected ETS data
+ * @ets_offset: offset of ETS data
+ *
+ * Returns error code.
+ **/
+static s32 ixgbe_get_ets_data(struct ixgbe_hw *hw, u16 *ets_cfg,
+ u16 *ets_offset)
+{
+ s32 status = 0;
+
+ status = hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, ets_offset);
+ if (status)
+ goto out;
+
+ if ((*ets_offset == 0x0000) || (*ets_offset == 0xFFFF)) {
+ status = IXGBE_NOT_IMPLEMENTED;
+ goto out;
+ }
+
+ status = hw->eeprom.ops.read(hw, *ets_offset, ets_cfg);
+ if (status)
+ goto out;
+
+ if ((*ets_cfg & IXGBE_ETS_TYPE_MASK) != IXGBE_ETS_TYPE_EMC_SHIFTED) {
+ status = IXGBE_NOT_IMPLEMENTED;
+ goto out;
+ }
+
+out:
+ return status;
+}
+
+/**
+ * ixgbe_get_thermal_sensor_data - Gathers thermal sensor data
+ * @hw: pointer to hardware structure
+ *
+ * Returns the thermal sensor data structure
+ **/
+s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw)
+{
+ s32 status = 0;
+ u16 ets_offset;
+ u16 ets_cfg;
+ u16 ets_sensor;
+ u8 num_sensors;
+ u8 i;
+ struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
+
+ /* Only support thermal sensors attached to physical port 0 */
+ if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
+ status = IXGBE_NOT_IMPLEMENTED;
+ goto out;
+ }
+
+ status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
+ if (status)
+ goto out;
+
+ num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK);
+ if (num_sensors > IXGBE_MAX_SENSORS)
+ num_sensors = IXGBE_MAX_SENSORS;
+
+ for (i = 0; i < num_sensors; i++) {
+ u8 sensor_index;
+ u8 sensor_location;
+
+ status = hw->eeprom.ops.read(hw, (ets_offset + 1 + i),
+ &ets_sensor);
+ if (status)
+ goto out;
+
+ sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >>
+ IXGBE_ETS_DATA_INDEX_SHIFT);
+ sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >>
+ IXGBE_ETS_DATA_LOC_SHIFT);
+
+ if (sensor_location != 0) {
+ status = hw->phy.ops.read_i2c_byte(hw,
+ ixgbe_emc_temp_data[sensor_index],
+ IXGBE_I2C_THERMAL_SENSOR_ADDR,
+ &data->sensor[i].temp);
+ if (status)
+ goto out;
+ }
+ }
+out:
+ return status;
+}
+
+/**
+ * ixgbe_init_thermal_sensor_thresh_generic - Inits thermal sensor thresholds
+ * @hw: pointer to hardware structure
+ *
+ * Inits the thermal sensor thresholds according to the NVM map
+ * and save off the threshold and location values into mac.thermal_sensor_data
+ **/
+s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw)
+{
+ s32 status = 0;
+ u16 ets_offset;
+ u16 ets_cfg;
+ u16 ets_sensor;
+ u8 low_thresh_delta;
+ u8 num_sensors;
+ u8 therm_limit;
+ u8 i;
+ struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
+
+ memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data));
+
+ /* Only support thermal sensors attached to physical port 0 */
+ if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
+ status = IXGBE_NOT_IMPLEMENTED;
+ goto out;
+ }
+
+ status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
+ if (status)
+ goto out;
+
+ low_thresh_delta = ((ets_cfg & IXGBE_ETS_LTHRES_DELTA_MASK) >>
+ IXGBE_ETS_LTHRES_DELTA_SHIFT);
+ num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK);
+ if (num_sensors > IXGBE_MAX_SENSORS)
+ num_sensors = IXGBE_MAX_SENSORS;
+
+ for (i = 0; i < num_sensors; i++) {
+ u8 sensor_index;
+ u8 sensor_location;
+
+ hw->eeprom.ops.read(hw, (ets_offset + 1 + i), &ets_sensor);
+ sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >>
+ IXGBE_ETS_DATA_INDEX_SHIFT);
+ sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >>
+ IXGBE_ETS_DATA_LOC_SHIFT);
+ therm_limit = ets_sensor & IXGBE_ETS_DATA_HTHRESH_MASK;
+
+ hw->phy.ops.write_i2c_byte(hw,
+ ixgbe_emc_therm_limit[sensor_index],
+ IXGBE_I2C_THERMAL_SENSOR_ADDR, therm_limit);
+
+ if (sensor_location == 0)
+ continue;
+
+ data->sensor[i].location = sensor_location;
+ data->sensor[i].caution_thresh = therm_limit;
+ data->sensor[i].max_op_thresh = therm_limit - low_thresh_delta;
+ }
+out:
+ return status;
+}
+
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index 204f06235b45..6222fdb3d3f1 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -31,7 +31,7 @@
#include "ixgbe_type.h"
#include "ixgbe.h"
-u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw);
+u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw);
s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw);
@@ -77,8 +77,8 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw);
s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
-s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num);
-s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw);
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw);
+void ixgbe_fc_autoneg(struct ixgbe_hw *hw);
s32 ixgbe_validate_mac_addr(u8 *mac_addr);
s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
@@ -107,6 +107,19 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
u32 headroom, int strategy);
+#define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8
+#define IXGBE_EMC_INTERNAL_DATA 0x00
+#define IXGBE_EMC_INTERNAL_THERM_LIMIT 0x20
+#define IXGBE_EMC_DIODE1_DATA 0x01
+#define IXGBE_EMC_DIODE1_THERM_LIMIT 0x19
+#define IXGBE_EMC_DIODE2_DATA 0x23
+#define IXGBE_EMC_DIODE2_THERM_LIMIT 0x1A
+#define IXGBE_EMC_DIODE3_DATA 0x2A
+#define IXGBE_EMC_DIODE3_THERM_LIMIT 0x30
+
+s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw);
+s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw);
+
#define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
#ifndef writeq
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
index d3695edfcb8b..87592b458c9c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c
@@ -191,53 +191,46 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
*/
s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en)
{
- u32 reg;
+ u32 fcrtl, reg;
u8 i;
- if (pfc_en) {
- /* Enable Transmit Priority Flow Control */
- reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
- reg &= ~IXGBE_RMCS_TFCE_802_3X;
- /* correct the reporting of our flow control status */
- reg |= IXGBE_RMCS_TFCE_PRIORITY;
- IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
-
- /* Enable Receive Priority Flow Control */
- reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
- reg &= ~IXGBE_FCTRL_RFCE;
- reg |= IXGBE_FCTRL_RPFCE;
- IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
-
- /* Configure pause time */
- for (i = 0; i < (MAX_TRAFFIC_CLASS >> 1); i++)
- IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), 0x68006800);
+ /* Enable Transmit Priority Flow Control */
+ reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
+ reg &= ~IXGBE_RMCS_TFCE_802_3X;
+ reg |= IXGBE_RMCS_TFCE_PRIORITY;
+ IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
- /* Configure flow control refresh threshold value */
- IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400);
- }
+ /* Enable Receive Priority Flow Control */
+ reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
+ reg &= ~(IXGBE_FCTRL_RPFCE | IXGBE_FCTRL_RFCE);
- /*
- * Configure flow control thresholds and enable priority flow control
- * for each traffic class.
- */
- for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
- int enabled = pfc_en & (1 << i);
+ if (pfc_en)
+ reg |= IXGBE_FCTRL_RPFCE;
- reg = hw->fc.low_water << 10;
+ IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
- if (enabled == pfc_enabled_tx ||
- enabled == pfc_enabled_full)
- reg |= IXGBE_FCRTL_XONE;
+ fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
+ /* Configure PFC Tx thresholds per TC */
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ if (!(pfc_en & (1 << i))) {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0);
+ continue;
+ }
+
+ reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg);
+ }
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), reg);
+ /* Configure pause time */
+ reg = hw->fc.pause_time * 0x00010001;
+ for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
+ IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
- reg = hw->fc.high_water[i] << 10;
- if (enabled == pfc_enabled_tx ||
- enabled == pfc_enabled_full)
- reg |= IXGBE_FCRTH_FCEN;
+ /* Configure flow control refresh threshold value */
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
- IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg);
- }
return 0;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
index 888a419dc3d9..4eac80d01857 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c
@@ -211,24 +211,42 @@ s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
*/
s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
{
- u32 i, j, reg;
+ u32 i, j, fcrtl, reg;
u8 max_tc = 0;
- for (i = 0; i < MAX_USER_PRIORITY; i++)
+ /* Enable Transmit Priority Flow Control */
+ IXGBE_WRITE_REG(hw, IXGBE_FCCFG, IXGBE_FCCFG_TFCE_PRIORITY);
+
+ /* Enable Receive Priority Flow Control */
+ reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
+ reg |= IXGBE_MFLCN_DPF;
+
+ /*
+ * X540 supports per TC Rx priority flow control. So
+ * clear all TCs and only enable those that should be
+ * enabled.
+ */
+ reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE);
+
+ if (hw->mac.type == ixgbe_mac_X540)
+ reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT;
+
+ if (pfc_en)
+ reg |= IXGBE_MFLCN_RPFCE;
+
+ IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
+
+ for (i = 0; i < MAX_USER_PRIORITY; i++) {
if (prio_tc[i] > max_tc)
max_tc = prio_tc[i];
+ }
+
+ fcrtl = (hw->fc.low_water << 10) | IXGBE_FCRTL_XONE;
/* Configure PFC Tx thresholds per TC */
- for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ for (i = 0; i <= max_tc; i++) {
int enabled = 0;
- if (i > max_tc) {
- reg = 0;
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg);
- IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg);
- continue;
- }
-
for (j = 0; j < MAX_USER_PRIORITY; j++) {
if ((prio_tc[j] == i) && (pfc_en & (1 << j))) {
enabled = 1;
@@ -236,61 +254,29 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
}
}
- reg = hw->fc.low_water << 10;
-
- if (enabled)
- reg |= IXGBE_FCRTL_XONE;
- IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg);
+ if (enabled) {
+ reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
+ } else {
+ reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
+ }
- reg = hw->fc.high_water[i] << 10;
- if (enabled)
- reg |= IXGBE_FCRTH_FCEN;
IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg);
}
- if (pfc_en) {
- /* Configure pause time (2 TCs per register) */
- reg = hw->fc.pause_time | (hw->fc.pause_time << 16);
- for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
- IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
-
- /* Configure flow control refresh threshold value */
- IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
-
-
- reg = IXGBE_FCCFG_TFCE_PRIORITY;
- IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg);
- /*
- * Enable Receive PFC
- * 82599 will always honor XOFF frames we receive when
- * we are in PFC mode however X540 only honors enabled
- * traffic classes.
- */
- reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
- reg &= ~IXGBE_MFLCN_RFCE;
- reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF;
-
- if (hw->mac.type == ixgbe_mac_X540) {
- reg &= ~IXGBE_MFLCN_RPFCE_MASK;
- reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT;
- }
+ for (; i < MAX_TRAFFIC_CLASS; i++) {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), 0);
+ }
- IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
-
- } else {
- /* X540 devices have a RX bit that should be cleared
- * if PFC is disabled on all TCs but PFC features is
- * enabled.
- */
- if (hw->mac.type == ixgbe_mac_X540) {
- reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
- reg &= ~IXGBE_MFLCN_RPFCE_MASK;
- IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
- }
+ /* Configure pause time (2 TCs per register) */
+ reg = hw->fc.pause_time * 0x00010001;
+ for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
+ IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
- for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
- hw->mac.ops.fc_enable(hw, i);
- }
+ /* Configure flow control refresh threshold value */
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
return 0;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
index 652e4b09546d..5164a21b13ca 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
@@ -44,18 +44,26 @@
#define DCB_NO_HW_CHG 1 /* DCB configuration did not change */
#define DCB_HW_CHG 2 /* DCB configuration changed, no reset */
-int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *scfg,
- struct ixgbe_dcb_config *dcfg, int tc_max)
+static int ixgbe_copy_dcb_cfg(struct ixgbe_adapter *adapter, int tc_max)
{
+ struct ixgbe_dcb_config *scfg = &adapter->temp_dcb_cfg;
+ struct ixgbe_dcb_config *dcfg = &adapter->dcb_cfg;
struct tc_configuration *src = NULL;
struct tc_configuration *dst = NULL;
int i, j;
int tx = DCB_TX_CONFIG;
int rx = DCB_RX_CONFIG;
int changes = 0;
+#ifdef IXGBE_FCOE
+ struct dcb_app app = {
+ .selector = DCB_APP_IDTYPE_ETHTYPE,
+ .protocol = ETH_P_FCOE,
+ };
+ u8 up = dcb_getapp(adapter->netdev, &app);
- if (!scfg || !dcfg)
- return changes;
+ if (up && !(up & (1 << adapter->fcoe.up)))
+ changes |= BIT_APP_UPCHG;
+#endif
for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) {
src = &scfg->tc_config[i - DCB_PG_ATTR_TC_0];
@@ -330,60 +338,20 @@ static void ixgbe_dcbnl_devreset(struct net_device *dev)
static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_dcb_config *dcb_cfg = &adapter->dcb_cfg;
+ struct ixgbe_hw *hw = &adapter->hw;
int ret = DCB_NO_HW_CHG;
int i;
-#ifdef IXGBE_FCOE
- struct dcb_app app = {
- .selector = DCB_APP_IDTYPE_ETHTYPE,
- .protocol = ETH_P_FCOE,
- };
- u8 up;
-
- /* In IEEE mode, use the IEEE Ethertype selector value */
- if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) {
- app.selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE;
- up = dcb_ieee_getapp_mask(netdev, &app);
- } else {
- up = dcb_getapp(netdev, &app);
- }
-#endif
/* Fail command if not in CEE mode */
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
return ret;
- adapter->dcb_set_bitmap |= ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg,
- &adapter->dcb_cfg,
+ adapter->dcb_set_bitmap |= ixgbe_copy_dcb_cfg(adapter,
MAX_TRAFFIC_CLASS);
if (!adapter->dcb_set_bitmap)
return ret;
- if (adapter->dcb_cfg.pfc_mode_enable) {
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
- if (adapter->hw.fc.current_mode != ixgbe_fc_pfc)
- adapter->last_lfc_mode =
- adapter->hw.fc.current_mode;
- break;
- default:
- break;
- }
- adapter->hw.fc.requested_mode = ixgbe_fc_pfc;
- } else {
- switch (adapter->hw.mac.type) {
- case ixgbe_mac_82598EB:
- adapter->hw.fc.requested_mode = ixgbe_fc_none;
- break;
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540:
- adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
- break;
- default:
- break;
- }
- }
-
if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) {
u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS];
u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS];
@@ -396,23 +364,19 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
#endif
- ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg,
- max_frame, DCB_TX_CONFIG);
- ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg,
- max_frame, DCB_RX_CONFIG);
+ ixgbe_dcb_calculate_tc_credits(hw, dcb_cfg, max_frame,
+ DCB_TX_CONFIG);
+ ixgbe_dcb_calculate_tc_credits(hw, dcb_cfg, max_frame,
+ DCB_RX_CONFIG);
- ixgbe_dcb_unpack_refill(&adapter->dcb_cfg,
- DCB_TX_CONFIG, refill);
- ixgbe_dcb_unpack_max(&adapter->dcb_cfg, max);
- ixgbe_dcb_unpack_bwgid(&adapter->dcb_cfg,
- DCB_TX_CONFIG, bwg_id);
- ixgbe_dcb_unpack_prio(&adapter->dcb_cfg,
- DCB_TX_CONFIG, prio_type);
- ixgbe_dcb_unpack_map(&adapter->dcb_cfg,
- DCB_TX_CONFIG, prio_tc);
+ ixgbe_dcb_unpack_refill(dcb_cfg, DCB_TX_CONFIG, refill);
+ ixgbe_dcb_unpack_max(dcb_cfg, max);
+ ixgbe_dcb_unpack_bwgid(dcb_cfg, DCB_TX_CONFIG, bwg_id);
+ ixgbe_dcb_unpack_prio(dcb_cfg, DCB_TX_CONFIG, prio_type);
+ ixgbe_dcb_unpack_map(dcb_cfg, DCB_TX_CONFIG, prio_tc);
- ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max,
- bwg_id, prio_type, prio_tc);
+ ixgbe_dcb_hw_ets_config(hw, refill, max, bwg_id,
+ prio_type, prio_tc);
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
netdev_set_prio_tc_map(netdev, i, prio_tc[i]);
@@ -421,27 +385,34 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
}
if (adapter->dcb_set_bitmap & BIT_PFC) {
- u8 pfc_en;
- u8 prio_tc[MAX_USER_PRIORITY];
+ if (dcb_cfg->pfc_mode_enable) {
+ u8 pfc_en;
+ u8 prio_tc[MAX_USER_PRIORITY];
+
+ ixgbe_dcb_unpack_map(dcb_cfg, DCB_TX_CONFIG, prio_tc);
+ ixgbe_dcb_unpack_pfc(dcb_cfg, &pfc_en);
+ ixgbe_dcb_hw_pfc_config(hw, pfc_en, prio_tc);
+ } else {
+ hw->mac.ops.fc_enable(hw);
+ }
- ixgbe_dcb_unpack_map(&adapter->dcb_cfg,
- DCB_TX_CONFIG, prio_tc);
- ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en);
- ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en, prio_tc);
- if (ret != DCB_HW_CHG_RST)
- ret = DCB_HW_CHG;
- }
+ ixgbe_set_rx_drop_en(adapter);
- if (adapter->dcb_cfg.pfc_mode_enable)
- adapter->hw.fc.current_mode = ixgbe_fc_pfc;
+ ret = DCB_HW_CHG;
+ }
#ifdef IXGBE_FCOE
/* Reprogam FCoE hardware offloads when the traffic class
* FCoE is using changes. This happens if the APP info
* changes or the up2tc mapping is updated.
*/
- if ((up && !(up & (1 << adapter->fcoe.up))) ||
- (adapter->dcb_set_bitmap & BIT_APP_UPCHG)) {
+ if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
+ struct dcb_app app = {
+ .selector = DCB_APP_IDTYPE_ETHTYPE,
+ .protocol = ETH_P_FCOE,
+ };
+ u8 up = dcb_getapp(netdev, &app);
+
adapter->fcoe.up = ffs(up) - 1;
ixgbe_dcbnl_devreset(netdev);
ret = DCB_HW_CHG_RST;
@@ -650,7 +621,9 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
struct ieee_pfc *pfc)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
+ struct ixgbe_hw *hw = &adapter->hw;
u8 *prio_tc;
+ int err;
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
return -EINVAL;
@@ -664,7 +637,16 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
prio_tc = adapter->ixgbe_ieee_ets->prio_tc;
memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc));
- return ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en, prio_tc);
+
+ /* Enable link flow control parameters if PFC is disabled */
+ if (pfc->pfc_en)
+ err = ixgbe_dcb_hw_pfc_config(hw, pfc->pfc_en, prio_tc);
+ else
+ err = hw->mac.ops.fc_enable(hw);
+
+ ixgbe_set_rx_drop_en(adapter);
+
+ return err;
}
static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 31a2bf76a346..3178f1ec3711 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -391,11 +391,6 @@ static void ixgbe_get_pauseparam(struct net_device *netdev,
} else if (hw->fc.current_mode == ixgbe_fc_full) {
pause->rx_pause = 1;
pause->tx_pause = 1;
-#ifdef CONFIG_DCB
- } else if (hw->fc.current_mode == ixgbe_fc_pfc) {
- pause->rx_pause = 0;
- pause->tx_pause = 0;
-#endif
}
}
@@ -404,21 +399,14 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
- struct ixgbe_fc_info fc;
+ struct ixgbe_fc_info fc = hw->fc;
-#ifdef CONFIG_DCB
- if (adapter->dcb_cfg.pfc_mode_enable ||
- ((hw->mac.type == ixgbe_mac_82598EB) &&
- (adapter->flags & IXGBE_FLAG_DCB_ENABLED)))
+ /* 82598 does no support link flow control with DCB enabled */
+ if ((hw->mac.type == ixgbe_mac_82598EB) &&
+ (adapter->flags & IXGBE_FLAG_DCB_ENABLED))
return -EINVAL;
-#endif
- fc = hw->fc;
-
- if (pause->autoneg != AUTONEG_ENABLE)
- fc.disable_fc_autoneg = true;
- else
- fc.disable_fc_autoneg = false;
+ fc.disable_fc_autoneg = (pause->autoneg != AUTONEG_ENABLE);
if ((pause->rx_pause && pause->tx_pause) || pause->autoneg)
fc.requested_mode = ixgbe_fc_full;
@@ -426,14 +414,8 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
fc.requested_mode = ixgbe_fc_rx_pause;
else if (!pause->rx_pause && pause->tx_pause)
fc.requested_mode = ixgbe_fc_tx_pause;
- else if (!pause->rx_pause && !pause->tx_pause)
- fc.requested_mode = ixgbe_fc_none;
else
- return -EINVAL;
-
-#ifdef CONFIG_DCB
- adapter->last_lfc_mode = fc.requested_mode;
-#endif
+ fc.requested_mode = ixgbe_fc_none;
/* if the thing changed then we'll update and use new autoneg */
if (memcmp(&fc, &hw->fc, sizeof(struct ixgbe_fc_info))) {
@@ -1780,6 +1762,8 @@ static u16 ixgbe_clean_test_rings(struct ixgbe_ring *rx_ring,
rx_desc = IXGBE_RX_DESC(rx_ring, rx_ntc);
}
+ netdev_tx_reset_queue(txring_txq(tx_ring));
+
/* re-map buffers to ring, store next to clean values */
ixgbe_alloc_rx_buffers(rx_ring, count);
rx_ring->next_to_clean = rx_ntc;
@@ -1969,53 +1953,12 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter,
struct ethtool_wolinfo *wol)
{
struct ixgbe_hw *hw = &adapter->hw;
- int retval = 1;
- u16 wol_cap = adapter->eeprom_cap & IXGBE_DEVICE_CAPS_WOL_MASK;
-
- /* WOL not supported except for the following */
- switch(hw->device_id) {
- case IXGBE_DEV_ID_82599_SFP:
- /* Only these subdevices could supports WOL */
- switch (hw->subsystem_device_id) {
- case IXGBE_SUBDEV_ID_82599_560FLR:
- /* only support first port */
- if (hw->bus.func != 0) {
- wol->supported = 0;
- break;
- }
- case IXGBE_SUBDEV_ID_82599_SFP:
- retval = 0;
- break;
- default:
- wol->supported = 0;
- break;
- }
- break;
- case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
- /* All except this subdevice support WOL */
- if (hw->subsystem_device_id ==
- IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ) {
- wol->supported = 0;
- break;
- }
- retval = 0;
- break;
- case IXGBE_DEV_ID_82599_KX4:
- retval = 0;
- break;
- case IXGBE_DEV_ID_X540T:
- /* check eeprom to see if enabled wol */
- if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
- ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) &&
- (hw->bus.func == 0))) {
- retval = 0;
- break;
- }
+ int retval = 0;
- /* All others not supported */
- wol->supported = 0;
- break;
- default:
+ /* WOL not supported for all devices */
+ if (!ixgbe_wol_supported(adapter, hw->device_id,
+ hw->subsystem_device_id)) {
+ retval = 1;
wol->supported = 0;
}
@@ -2753,6 +2696,46 @@ static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
return ret;
}
+static int ixgbe_get_ts_info(struct net_device *dev,
+ struct ethtool_ts_info *info)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+ switch (adapter->hw.mac.type) {
+#ifdef CONFIG_IXGBE_PTP
+ case ixgbe_mac_X540:
+ case ixgbe_mac_82599EB:
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ if (adapter->ptp_clock)
+ info->phc_index = ptp_clock_index(adapter->ptp_clock);
+ else
+ info->phc_index = -1;
+
+ info->tx_types =
+ (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+
+ info->rx_filters =
+ (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+ (1 << HWTSTAMP_FILTER_SOME);
+ break;
+#endif /* CONFIG_IXGBE_PTP */
+ default:
+ return ethtool_op_get_ts_info(dev, info);
+ break;
+ }
+ return 0;
+}
+
static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_settings = ixgbe_get_settings,
.set_settings = ixgbe_set_settings,
@@ -2781,6 +2764,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
.set_coalesce = ixgbe_set_coalesce,
.get_rxnfc = ixgbe_get_rxnfc,
.set_rxnfc = ixgbe_set_rxnfc,
+ .get_ts_info = ixgbe_get_ts_info,
};
void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index ed1b47dc0834..af1a5314b494 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -523,11 +523,17 @@ static void ixgbe_add_ring(struct ixgbe_ring *ring,
/**
* ixgbe_alloc_q_vector - Allocate memory for a single interrupt vector
* @adapter: board private structure to initialize
+ * @v_count: q_vectors allocated on adapter, used for ring interleaving
* @v_idx: index of vector in adapter struct
+ * @txr_count: total number of Tx rings to allocate
+ * @txr_idx: index of first Tx ring to allocate
+ * @rxr_count: total number of Rx rings to allocate
+ * @rxr_idx: index of first Rx ring to allocate
*
* We allocate one q_vector. If allocation fails we return -ENOMEM.
**/
-static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, int v_idx,
+static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
+ int v_count, int v_idx,
int txr_count, int txr_idx,
int rxr_count, int rxr_idx)
{
@@ -598,7 +604,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, int v_idx,
/* update count and index */
txr_count--;
- txr_idx++;
+ txr_idx += v_count;
/* push pointer to next ring */
ring++;
@@ -641,7 +647,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, int v_idx,
/* update count and index */
rxr_count--;
- rxr_idx++;
+ rxr_idx += v_count;
/* push pointer to next ring */
ring++;
@@ -700,24 +706,23 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
q_vectors = 1;
if (q_vectors >= (rxr_remaining + txr_remaining)) {
- for (; rxr_remaining; v_idx++, q_vectors--) {
- int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors);
- err = ixgbe_alloc_q_vector(adapter, v_idx,
- 0, 0, rqpv, rxr_idx);
+ for (; rxr_remaining; v_idx++) {
+ err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx,
+ 0, 0, 1, rxr_idx);
if (err)
goto err_out;
/* update counts and index */
- rxr_remaining -= rqpv;
- rxr_idx += rqpv;
+ rxr_remaining--;
+ rxr_idx++;
}
}
- for (; q_vectors; v_idx++, q_vectors--) {
- int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors);
- int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors);
- err = ixgbe_alloc_q_vector(adapter, v_idx,
+ for (; v_idx < q_vectors; v_idx++) {
+ int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx);
+ int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx);
+ err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx,
tqpv, txr_idx,
rqpv, rxr_idx);
@@ -726,9 +731,9 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
/* update counts and index */
rxr_remaining -= rqpv;
- rxr_idx += rqpv;
txr_remaining -= tqpv;
- txr_idx += tqpv;
+ rxr_idx++;
+ txr_idx++;
}
return 0;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 88f6b2e9b72d..bf20457ea23a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -63,8 +63,8 @@ static char ixgbe_default_device_descr[] =
"Intel(R) 10 Gigabit Network Connection";
#endif
#define MAJ 3
-#define MIN 8
-#define BUILD 21
+#define MIN 9
+#define BUILD 15
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD) "-k"
const char ixgbe_driver_version[] = DRV_VERSION;
@@ -133,7 +133,7 @@ static struct notifier_block dca_notifier = {
static unsigned int max_vfs;
module_param(max_vfs, uint, 0);
MODULE_PARM_DESC(max_vfs,
- "Maximum number of virtual functions to allocate per physical function");
+ "Maximum number of virtual functions to allocate per physical function - default is zero and maximum value is 63");
#endif /* CONFIG_PCI_IOV */
static unsigned int allow_unsupported_sfp;
@@ -610,35 +610,50 @@ void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *ring,
/* tx_buffer must be completely set up in the transmit path */
}
-static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
+static void ixgbe_update_xoff_rx_lfc(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_hw_stats *hwstats = &adapter->stats;
- u32 data = 0;
- u32 xoff[8] = {0};
int i;
+ u32 data;
- if ((hw->fc.current_mode == ixgbe_fc_full) ||
- (hw->fc.current_mode == ixgbe_fc_rx_pause)) {
- switch (hw->mac.type) {
- case ixgbe_mac_82598EB:
- data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
- break;
- default:
- data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
- }
- hwstats->lxoffrxc += data;
+ if ((hw->fc.current_mode != ixgbe_fc_full) &&
+ (hw->fc.current_mode != ixgbe_fc_rx_pause))
+ return;
- /* refill credits (no tx hang) if we received xoff */
- if (!data)
- return;
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB:
+ data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+ break;
+ default:
+ data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+ }
+ hwstats->lxoffrxc += data;
- for (i = 0; i < adapter->num_tx_queues; i++)
- clear_bit(__IXGBE_HANG_CHECK_ARMED,
- &adapter->tx_ring[i]->state);
+ /* refill credits (no tx hang) if we received xoff */
+ if (!data)
return;
- } else if (!(adapter->dcb_cfg.pfc_mode_enable))
+
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ clear_bit(__IXGBE_HANG_CHECK_ARMED,
+ &adapter->tx_ring[i]->state);
+}
+
+static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbe_hw_stats *hwstats = &adapter->stats;
+ u32 xoff[8] = {0};
+ int i;
+ bool pfc_en = adapter->dcb_cfg.pfc_mode_enable;
+
+ if (adapter->ixgbe_ieee_pfc)
+ pfc_en |= !!(adapter->ixgbe_ieee_pfc->pfc_en);
+
+ if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED) || !pfc_en) {
+ ixgbe_update_xoff_rx_lfc(adapter);
return;
+ }
/* update stats for each tc, only valid with PFC enabled */
for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) {
@@ -774,6 +789,13 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
total_bytes += tx_buffer->bytecount;
total_packets += tx_buffer->gso_segs;
+#ifdef CONFIG_IXGBE_PTP
+ if (unlikely(tx_buffer->tx_flags &
+ IXGBE_TX_FLAGS_TSTAMP))
+ ixgbe_ptp_tx_hwtstamp(q_vector,
+ tx_buffer->skb);
+
+#endif
/* free the skb */
dev_kfree_skb_any(tx_buffer->skb);
@@ -1144,7 +1166,7 @@ static bool ixgbe_alloc_mapped_page(struct ixgbe_ring *rx_ring,
* there isn't much point in holding memory we can't use
*/
if (dma_mapping_error(rx_ring->dev, dma)) {
- put_page(page);
+ __free_pages(page, ixgbe_rx_pg_order(rx_ring));
bi->page = NULL;
rx_ring->rx_stats.alloc_rx_page_failed++;
@@ -1374,6 +1396,11 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
ixgbe_rx_checksum(rx_ring, rx_desc, skb);
+#ifdef CONFIG_IXGBE_PTP
+ if (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS))
+ ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb);
+#endif
+
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);
@@ -2295,6 +2322,9 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data)
}
ixgbe_check_fan_failure(adapter, eicr);
+#ifdef CONFIG_IXGBE_PTP
+ ixgbe_ptp_check_pps_event(adapter, eicr);
+#endif
/* re-enable the original interrupt state, no lsc, no queues */
if (!test_bit(__IXGBE_DOWN, &adapter->state))
@@ -2487,6 +2517,9 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
}
ixgbe_check_fan_failure(adapter, eicr);
+#ifdef CONFIG_IXGBE_PTP
+ ixgbe_ptp_check_pps_event(adapter, eicr);
+#endif
/* would disable interrupts here but EIAM disabled it */
napi_schedule(&q_vector->napi);
@@ -2671,8 +2704,6 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
/* enable queue */
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), txdctl);
- netdev_tx_reset_queue(txring_txq(ring));
-
/* TXDCTL.EN will return 0 on 82598 if link is down, so skip it */
if (hw->mac.type == ixgbe_mac_82598EB &&
!(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
@@ -2758,6 +2789,61 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
ixgbe_configure_tx_ring(adapter, adapter->tx_ring[i]);
}
+static void ixgbe_enable_rx_drop(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *ring)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u8 reg_idx = ring->reg_idx;
+ u32 srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(reg_idx));
+
+ srrctl |= IXGBE_SRRCTL_DROP_EN;
+
+ IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(reg_idx), srrctl);
+}
+
+static void ixgbe_disable_rx_drop(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *ring)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u8 reg_idx = ring->reg_idx;
+ u32 srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(reg_idx));
+
+ srrctl &= ~IXGBE_SRRCTL_DROP_EN;
+
+ IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(reg_idx), srrctl);
+}
+
+#ifdef CONFIG_IXGBE_DCB
+void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter)
+#else
+static void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter)
+#endif
+{
+ int i;
+ bool pfc_en = adapter->dcb_cfg.pfc_mode_enable;
+
+ if (adapter->ixgbe_ieee_pfc)
+ pfc_en |= !!(adapter->ixgbe_ieee_pfc->pfc_en);
+
+ /*
+ * We should set the drop enable bit if:
+ * SR-IOV is enabled
+ * or
+ * Number of Rx queues > 1 and flow control is disabled
+ *
+ * This allows us to avoid head of line blocking for security
+ * and performance reasons.
+ */
+ if (adapter->num_vfs || (adapter->num_rx_queues > 1 &&
+ !(adapter->hw.fc.current_mode & ixgbe_fc_tx_pause) && !pfc_en)) {
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ ixgbe_enable_rx_drop(adapter, adapter->rx_ring[i]);
+ } else {
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ ixgbe_disable_rx_drop(adapter, adapter->rx_ring[i]);
+ }
+}
+
#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter,
@@ -2904,33 +2990,6 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl);
}
-/**
- * ixgbe_set_uta - Set unicast filter table address
- * @adapter: board private structure
- *
- * The unicast table address is a register array of 32-bit registers.
- * The table is meant to be used in a way similar to how the MTA is used
- * however due to certain limitations in the hardware it is necessary to
- * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous
- * enable bit to allow vlan tag stripping when promiscuous mode is enabled
- **/
-static void ixgbe_set_uta(struct ixgbe_adapter *adapter)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- int i;
-
- /* The UTA table only exists on 82599 hardware and newer */
- if (hw->mac.type < ixgbe_mac_82599EB)
- return;
-
- /* we only need to do this if VMDq is enabled */
- if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
- return;
-
- for (i = 0; i < 128; i++)
- IXGBE_WRITE_REG(hw, IXGBE_UTA(i), ~0);
-}
-
#define IXGBE_MAX_RX_DESC_POLL 10
static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
struct ixgbe_ring *ring)
@@ -3216,8 +3275,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
/* Program registers for the distribution of queues */
ixgbe_setup_mrqc(adapter);
- ixgbe_set_uta(adapter);
-
/* set_rx_buffer_len must be called before ring initialization */
ixgbe_set_rx_buffer_len(adapter);
@@ -3454,16 +3511,17 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
}
ixgbe_vlan_filter_enable(adapter);
hw->addr_ctrl.user_set_promisc = false;
- /*
- * Write addresses to available RAR registers, if there is not
- * sufficient space to store all the addresses then enable
- * unicast promiscuous mode
- */
- count = ixgbe_write_uc_addr_list(netdev);
- if (count < 0) {
- fctrl |= IXGBE_FCTRL_UPE;
- vmolr |= IXGBE_VMOLR_ROPE;
- }
+ }
+
+ /*
+ * Write addresses to available RAR registers, if there is not
+ * sufficient space to store all the addresses then enable
+ * unicast promiscuous mode
+ */
+ count = ixgbe_write_uc_addr_list(netdev);
+ if (count < 0) {
+ fctrl |= IXGBE_FCTRL_UPE;
+ vmolr |= IXGBE_VMOLR_ROPE;
}
if (adapter->num_vfs) {
@@ -4130,7 +4188,8 @@ static void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring)
DMA_FROM_DEVICE);
rx_buffer->dma = 0;
if (rx_buffer->page)
- put_page(rx_buffer->page);
+ __free_pages(rx_buffer->page,
+ ixgbe_rx_pg_order(rx_ring));
rx_buffer->page = NULL;
}
@@ -4167,6 +4226,8 @@ static void ixgbe_clean_tx_ring(struct ixgbe_ring *tx_ring)
ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
}
+ netdev_tx_reset_queue(txring_txq(tx_ring));
+
size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count;
memset(tx_ring->tx_buffer_info, 0, size);
@@ -4418,17 +4479,14 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->dcb_cfg.pfc_mode_enable = false;
adapter->dcb_set_bitmap = 0x00;
adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE;
- ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg,
- MAX_TRAFFIC_CLASS);
+ memcpy(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
+ sizeof(adapter->temp_dcb_cfg));
#endif
/* default flow control settings */
hw->fc.requested_mode = ixgbe_fc_full;
hw->fc.current_mode = ixgbe_fc_full; /* init for ethtool output */
-#ifdef CONFIG_DCB
- adapter->last_lfc_mode = hw->fc.current_mode;
-#endif
ixgbe_pbthresh_setup(adapter);
hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
hw->fc.send_xon = true;
@@ -4866,10 +4924,12 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
netif_device_detach(netdev);
if (netif_running(netdev)) {
+ rtnl_lock();
ixgbe_down(adapter);
ixgbe_free_irq(adapter);
ixgbe_free_all_tx_resources(adapter);
ixgbe_free_all_rx_resources(adapter);
+ rtnl_unlock();
}
ixgbe_clear_interrupt_scheme(adapter);
@@ -4991,9 +5051,6 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
u64 rsc_count = 0;
u64 rsc_flush = 0;
- for (i = 0; i < 16; i++)
- adapter->hw_rx_no_dma_resources +=
- IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
for (i = 0; i < adapter->num_rx_queues; i++) {
rsc_count += adapter->rx_ring[i]->rx_stats.rsc_count;
rsc_flush += adapter->rx_ring[i]->rx_stats.rsc_flush;
@@ -5096,6 +5153,9 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
hwstats->b2ospc += IXGBE_READ_REG(hw, IXGBE_B2OSPC);
hwstats->b2ogprc += IXGBE_READ_REG(hw, IXGBE_B2OGPRC);
case ixgbe_mac_82599EB:
+ for (i = 0; i < 16; i++)
+ adapter->hw_rx_no_dma_resources +=
+ IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL);
IXGBE_READ_REG(hw, IXGBE_GORCH); /* to clear */
hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL);
@@ -5273,7 +5333,7 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
u32 link_speed = adapter->link_speed;
bool link_up = adapter->link_up;
- int i;
+ bool pfc_en = adapter->dcb_cfg.pfc_mode_enable;
if (!(adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE))
return;
@@ -5285,13 +5345,13 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter)
link_speed = IXGBE_LINK_SPEED_10GB_FULL;
link_up = true;
}
- if (link_up) {
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
- hw->mac.ops.fc_enable(hw, i);
- } else {
- hw->mac.ops.fc_enable(hw, 0);
- }
+
+ if (adapter->ixgbe_ieee_pfc)
+ pfc_en |= !!(adapter->ixgbe_ieee_pfc->pfc_en);
+
+ if (link_up && !((adapter->flags & IXGBE_FLAG_DCB_ENABLED) && pfc_en)) {
+ hw->mac.ops.fc_enable(hw);
+ ixgbe_set_rx_drop_en(adapter);
}
if (link_up ||
@@ -5345,6 +5405,11 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
flow_rx = false;
break;
}
+
+#ifdef CONFIG_IXGBE_PTP
+ ixgbe_ptp_start_cyclecounter(adapter);
+#endif
+
e_info(drv, "NIC Link is Up %s, Flow Control: %s\n",
(link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
"10 Gbps" :
@@ -5382,6 +5447,10 @@ static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *adapter)
if (ixgbe_is_sfp(hw) && hw->mac.type == ixgbe_mac_82598EB)
adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP;
+#ifdef CONFIG_IXGBE_PTP
+ ixgbe_ptp_start_cyclecounter(adapter);
+#endif
+
e_info(drv, "NIC Link is Down\n");
netif_carrier_off(netdev);
}
@@ -5681,6 +5750,9 @@ static void ixgbe_service_task(struct work_struct *work)
ixgbe_watchdog_subtask(adapter);
ixgbe_fdir_reinit_subtask(adapter);
ixgbe_check_hang_subtask(adapter);
+#ifdef CONFIG_IXGBE_PTP
+ ixgbe_ptp_overflow_check(adapter);
+#endif
ixgbe_service_event_complete(adapter);
}
@@ -5831,6 +5903,11 @@ static __le32 ixgbe_tx_cmd_type(u32 tx_flags)
if (tx_flags & IXGBE_TX_FLAGS_HW_VLAN)
cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_VLE);
+#ifdef CONFIG_IXGBE_PTP
+ if (tx_flags & IXGBE_TX_FLAGS_TSTAMP)
+ cmd_type |= cpu_to_le32(IXGBE_ADVTXD_MAC_TSTAMP);
+#endif
+
/* set segmentation enable bits for TSO/FSO */
#ifdef IXGBE_FCOE
if (tx_flags & (IXGBE_TX_FLAGS_TSO | IXGBE_TX_FLAGS_FSO))
@@ -6221,6 +6298,15 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
tx_flags |= IXGBE_TX_FLAGS_SW_VLAN;
}
+ skb_tx_timestamp(skb);
+
+#ifdef CONFIG_IXGBE_PTP
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ tx_flags |= IXGBE_TX_FLAGS_TSTAMP;
+ }
+#endif
+
#ifdef CONFIG_PCI_IOV
/*
* Use the l2switch_enable flag - would be false if the DMA
@@ -6373,7 +6459,14 @@ static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- return mdio_mii_ioctl(&adapter->hw.phy.mdio, if_mii(req), cmd);
+ switch (cmd) {
+#ifdef CONFIG_IXGBE_PTP
+ case SIOCSHWTSTAMP:
+ return ixgbe_ptp_hwtstamp_ioctl(adapter, req, cmd);
+#endif
+ default:
+ return mdio_mii_ioctl(&adapter->hw.phy.mdio, if_mii(req), cmd);
+ }
}
/**
@@ -6565,15 +6658,17 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
if (tc) {
netdev_set_num_tc(dev, tc);
- adapter->last_lfc_mode = adapter->hw.fc.current_mode;
adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
- if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+ adapter->last_lfc_mode = adapter->hw.fc.requested_mode;
adapter->hw.fc.requested_mode = ixgbe_fc_none;
+ }
} else {
netdev_reset_tc(dev);
- adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
@@ -6622,7 +6717,7 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev,
/* Turn off LRO if not RSC capable */
if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE))
features &= ~NETIF_F_LRO;
-
+
return features;
}
@@ -6681,6 +6776,74 @@ static int ixgbe_set_features(struct net_device *netdev,
return 0;
}
+static int ixgbe_ndo_fdb_add(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr,
+ u16 flags)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int err = -EOPNOTSUPP;
+
+ if (ndm->ndm_state & NUD_PERMANENT) {
+ pr_info("%s: FDB only supports static addresses\n",
+ ixgbe_driver_name);
+ return -EINVAL;
+ }
+
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+ if (is_unicast_ether_addr(addr))
+ err = dev_uc_add_excl(dev, addr);
+ else if (is_multicast_ether_addr(addr))
+ err = dev_mc_add_excl(dev, addr);
+ else
+ err = -EINVAL;
+ }
+
+ /* Only return duplicate errors if NLM_F_EXCL is set */
+ if (err == -EEXIST && !(flags & NLM_F_EXCL))
+ err = 0;
+
+ return err;
+}
+
+static int ixgbe_ndo_fdb_del(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int err = -EOPNOTSUPP;
+
+ if (ndm->ndm_state & NUD_PERMANENT) {
+ pr_info("%s: FDB only supports static addresses\n",
+ ixgbe_driver_name);
+ return -EINVAL;
+ }
+
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+ if (is_unicast_ether_addr(addr))
+ err = dev_uc_del(dev, addr);
+ else if (is_multicast_ether_addr(addr))
+ err = dev_mc_del(dev, addr);
+ else
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static int ixgbe_ndo_fdb_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+ idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
+
+ return idx;
+}
+
static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbe_open,
.ndo_stop = ixgbe_close,
@@ -6717,6 +6880,9 @@ static const struct net_device_ops ixgbe_netdev_ops = {
#endif /* IXGBE_FCOE */
.ndo_set_features = ixgbe_set_features,
.ndo_fix_features = ixgbe_fix_features,
+ .ndo_fdb_add = ixgbe_ndo_fdb_add,
+ .ndo_fdb_del = ixgbe_ndo_fdb_del,
+ .ndo_fdb_dump = ixgbe_ndo_fdb_dump,
};
static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
@@ -6731,14 +6897,66 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
/* The 82599 supports up to 64 VFs per physical function
* but this implementation limits allocation to 63 so that
* basic networking resources are still available to the
- * physical function
+ * physical function. If the user requests greater thn
+ * 63 VFs then it is an error - reset to default of zero.
*/
- adapter->num_vfs = (max_vfs > 63) ? 63 : max_vfs;
+ adapter->num_vfs = (max_vfs > 63) ? 0 : max_vfs;
ixgbe_enable_sriov(adapter, ii);
#endif /* CONFIG_PCI_IOV */
}
/**
+ * ixgbe_wol_supported - Check whether device supports WoL
+ * @hw: hw specific details
+ * @device_id: the device ID
+ * @subdev_id: the subsystem device ID
+ *
+ * This function is used by probe and ethtool to determine
+ * which devices have WoL support
+ *
+ **/
+int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
+ u16 subdevice_id)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u16 wol_cap = adapter->eeprom_cap & IXGBE_DEVICE_CAPS_WOL_MASK;
+ int is_wol_supported = 0;
+
+ switch (device_id) {
+ case IXGBE_DEV_ID_82599_SFP:
+ /* Only these subdevices could supports WOL */
+ switch (subdevice_id) {
+ case IXGBE_SUBDEV_ID_82599_560FLR:
+ /* only support first port */
+ if (hw->bus.func != 0)
+ break;
+ case IXGBE_SUBDEV_ID_82599_SFP:
+ is_wol_supported = 1;
+ break;
+ }
+ break;
+ case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
+ /* All except this subdevice support WOL */
+ if (subdevice_id != IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ)
+ is_wol_supported = 1;
+ break;
+ case IXGBE_DEV_ID_82599_KX4:
+ is_wol_supported = 1;
+ break;
+ case IXGBE_DEV_ID_X540T:
+ /* check eeprom to see if enabled wol */
+ if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
+ ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) &&
+ (hw->bus.func == 0))) {
+ is_wol_supported = 1;
+ }
+ break;
+ }
+
+ return is_wol_supported;
+}
+
+/**
* ixgbe_probe - Device Initialization Routine
* @pdev: PCI device information struct
* @ent: entry in ixgbe_pci_tbl
@@ -6764,7 +6982,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
u16 device_caps;
#endif
u32 eec;
- u16 wol_cap;
/* Catch broken hardware that put the wrong VF device ID in
* the PCIe SR-IOV capability.
@@ -7028,42 +7245,18 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
netdev->features &= ~NETIF_F_RXHASH;
}
- /* WOL not supported for all but the following */
+ /* WOL not supported for all devices */
adapter->wol = 0;
- switch (pdev->device) {
- case IXGBE_DEV_ID_82599_SFP:
- /* Only these subdevice supports WOL */
- switch (pdev->subsystem_device) {
- case IXGBE_SUBDEV_ID_82599_560FLR:
- /* only support first port */
- if (hw->bus.func != 0)
- break;
- case IXGBE_SUBDEV_ID_82599_SFP:
- adapter->wol = IXGBE_WUFC_MAG;
- break;
- }
- break;
- case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
- /* All except this subdevice support WOL */
- if (pdev->subsystem_device != IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ)
- adapter->wol = IXGBE_WUFC_MAG;
- break;
- case IXGBE_DEV_ID_82599_KX4:
+ hw->eeprom.ops.read(hw, 0x2c, &adapter->eeprom_cap);
+ if (ixgbe_wol_supported(adapter, pdev->device, pdev->subsystem_device))
adapter->wol = IXGBE_WUFC_MAG;
- break;
- case IXGBE_DEV_ID_X540T:
- /* Check eeprom to see if it is enabled */
- hw->eeprom.ops.read(hw, 0x2c, &adapter->eeprom_cap);
- wol_cap = adapter->eeprom_cap & IXGBE_DEVICE_CAPS_WOL_MASK;
- if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
- ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) &&
- (hw->bus.func == 0)))
- adapter->wol = IXGBE_WUFC_MAG;
- break;
- }
device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+#ifdef CONFIG_IXGBE_PTP
+ ixgbe_ptp_init(adapter);
+#endif /* CONFIG_IXGBE_PTP*/
+
/* save off EEPROM version number */
hw->eeprom.ops.read(hw, 0x2e, &adapter->eeprom_verh);
hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl);
@@ -7150,6 +7343,12 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
e_dev_info("%s\n", ixgbe_default_device_descr);
cards_found++;
+
+#ifdef CONFIG_IXGBE_HWMON
+ if (ixgbe_sysfs_init(adapter))
+ e_err(probe, "failed to allocate sysfs resources\n");
+#endif /* CONFIG_IXGBE_HWMON */
+
return 0;
err_register:
@@ -7188,6 +7387,10 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
set_bit(__IXGBE_DOWN, &adapter->state);
cancel_work_sync(&adapter->service_task);
+#ifdef CONFIG_IXGBE_PTP
+ ixgbe_ptp_stop(adapter);
+#endif
+
#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
@@ -7196,6 +7399,10 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
}
#endif
+#ifdef CONFIG_IXGBE_HWMON
+ ixgbe_sysfs_exit(adapter);
+#endif /* CONFIG_IXGBE_HWMON */
+
#ifdef IXGBE_FCOE
if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
ixgbe_cleanup_fcoe(adapter);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index bf9f82f4b1ae..24117709d6a2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -1582,13 +1582,21 @@ static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data)
**/
static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
{
- *i2cctl |= IXGBE_I2C_CLK_OUT;
-
- IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl);
- IXGBE_WRITE_FLUSH(hw);
+ u32 i = 0;
+ u32 timeout = IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT;
+ u32 i2cctl_r = 0;
- /* SCL rise time (1000ns) */
- udelay(IXGBE_I2C_T_RISE);
+ for (i = 0; i < timeout; i++) {
+ *i2cctl |= IXGBE_I2C_CLK_OUT;
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl);
+ IXGBE_WRITE_FLUSH(hw);
+ /* SCL rise time (1000ns) */
+ udelay(IXGBE_I2C_T_RISE);
+
+ i2cctl_r = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+ if (i2cctl_r & IXGBE_I2C_CLK_IN)
+ break;
+ }
}
/**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
new file mode 100644
index 000000000000..ddc6a4d19302
--- /dev/null
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -0,0 +1,900 @@
+/*******************************************************************************
+
+ Intel 10 Gigabit PCI Express 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:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+#include "ixgbe.h"
+#include <linux/export.h>
+
+/*
+ * The 82599 and the X540 do not have true 64bit nanosecond scale
+ * counter registers. Instead, SYSTIME is defined by a fixed point
+ * system which allows the user to define the scale counter increment
+ * value at every level change of the oscillator driving the SYSTIME
+ * value. For both devices the TIMINCA:IV field defines this
+ * increment. On the X540 device, 31 bits are provided. However on the
+ * 82599 only provides 24 bits. The time unit is determined by the
+ * clock frequency of the oscillator in combination with the TIMINCA
+ * register. When these devices link at 10Gb the oscillator has a
+ * period of 6.4ns. In order to convert the scale counter into
+ * nanoseconds the cyclecounter and timecounter structures are
+ * used. The SYSTIME registers need to be converted to ns values by use
+ * of only a right shift (division by power of 2). The following math
+ * determines the largest incvalue that will fit into the available
+ * bits in the TIMINCA register.
+ *
+ * PeriodWidth: Number of bits to store the clock period
+ * MaxWidth: The maximum width value of the TIMINCA register
+ * Period: The clock period for the oscillator
+ * round(): discard the fractional portion of the calculation
+ *
+ * Period * [ 2 ^ ( MaxWidth - PeriodWidth ) ]
+ *
+ * For the X540, MaxWidth is 31 bits, and the base period is 6.4 ns
+ * For the 82599, MaxWidth is 24 bits, and the base period is 6.4 ns
+ *
+ * The period also changes based on the link speed:
+ * At 10Gb link or no link, the period remains the same.
+ * At 1Gb link, the period is multiplied by 10. (64ns)
+ * At 100Mb link, the period is multiplied by 100. (640ns)
+ *
+ * The calculated value allows us to right shift the SYSTIME register
+ * value in order to quickly convert it into a nanosecond clock,
+ * while allowing for the maximum possible adjustment value.
+ *
+ * These diagrams are only for the 10Gb link period
+ *
+ * SYSTIMEH SYSTIMEL
+ * +--------------+ +--------------+
+ * X540 | 32 | | 1 | 3 | 28 |
+ * *--------------+ +--------------+
+ * \________ 36 bits ______/ fract
+ *
+ * +--------------+ +--------------+
+ * 82599 | 32 | | 8 | 3 | 21 |
+ * *--------------+ +--------------+
+ * \________ 43 bits ______/ fract
+ *
+ * The 36 bit X540 SYSTIME overflows every
+ * 2^36 * 10^-9 / 60 = 1.14 minutes or 69 seconds
+ *
+ * The 43 bit 82599 SYSTIME overflows every
+ * 2^43 * 10^-9 / 3600 = 2.4 hours
+ */
+#define IXGBE_INCVAL_10GB 0x66666666
+#define IXGBE_INCVAL_1GB 0x40000000
+#define IXGBE_INCVAL_100 0x50000000
+
+#define IXGBE_INCVAL_SHIFT_10GB 28
+#define IXGBE_INCVAL_SHIFT_1GB 24
+#define IXGBE_INCVAL_SHIFT_100 21
+
+#define IXGBE_INCVAL_SHIFT_82599 7
+#define IXGBE_INCPER_SHIFT_82599 24
+#define IXGBE_MAX_TIMEADJ_VALUE 0x7FFFFFFFFFFFFFFFULL
+
+#define IXGBE_OVERFLOW_PERIOD (HZ * 30)
+
+#ifndef NSECS_PER_SEC
+#define NSECS_PER_SEC 1000000000ULL
+#endif
+
+/**
+ * ixgbe_ptp_read - read raw cycle counter (to be used by time counter)
+ * @cc - the cyclecounter structure
+ *
+ * this function reads the cyclecounter registers and is called by the
+ * cyclecounter structure used to construct a ns counter from the
+ * arbitrary fixed point registers
+ */
+static cycle_t ixgbe_ptp_read(const struct cyclecounter *cc)
+{
+ struct ixgbe_adapter *adapter =
+ container_of(cc, struct ixgbe_adapter, cc);
+ struct ixgbe_hw *hw = &adapter->hw;
+ u64 stamp = 0;
+
+ stamp |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIML);
+ stamp |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32;
+
+ return stamp;
+}
+
+/**
+ * ixgbe_ptp_adjfreq
+ * @ptp - the ptp clock structure
+ * @ppb - parts per billion adjustment from base
+ *
+ * adjust the frequency of the ptp cycle counter by the
+ * indicated ppb from the base frequency.
+ */
+static int ixgbe_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+ struct ixgbe_adapter *adapter =
+ container_of(ptp, struct ixgbe_adapter, ptp_caps);
+ struct ixgbe_hw *hw = &adapter->hw;
+ u64 freq;
+ u32 diff, incval;
+ int neg_adj = 0;
+
+ if (ppb < 0) {
+ neg_adj = 1;
+ ppb = -ppb;
+ }
+
+ smp_mb();
+ incval = ACCESS_ONCE(adapter->base_incval);
+
+ freq = incval;
+ freq *= ppb;
+ diff = div_u64(freq, 1000000000ULL);
+
+ incval = neg_adj ? (incval - diff) : (incval + diff);
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_X540:
+ IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, incval);
+ break;
+ case ixgbe_mac_82599EB:
+ IXGBE_WRITE_REG(hw, IXGBE_TIMINCA,
+ (1 << IXGBE_INCPER_SHIFT_82599) |
+ incval);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_ptp_adjtime
+ * @ptp - the ptp clock structure
+ * @delta - offset to adjust the cycle counter by
+ *
+ * adjust the timer by resetting the timecounter structure.
+ */
+static int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ struct ixgbe_adapter *adapter =
+ container_of(ptp, struct ixgbe_adapter, ptp_caps);
+ unsigned long flags;
+ u64 now;
+
+ spin_lock_irqsave(&adapter->tmreg_lock, flags);
+
+ now = timecounter_read(&adapter->tc);
+ now += delta;
+
+ /* reset the timecounter */
+ timecounter_init(&adapter->tc,
+ &adapter->cc,
+ now);
+
+ spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+ return 0;
+}
+
+/**
+ * ixgbe_ptp_gettime
+ * @ptp - the ptp clock structure
+ * @ts - timespec structure to hold the current time value
+ *
+ * read the timecounter and return the correct value on ns,
+ * after converting it into a struct timespec.
+ */
+static int ixgbe_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+ struct ixgbe_adapter *adapter =
+ container_of(ptp, struct ixgbe_adapter, ptp_caps);
+ u64 ns;
+ u32 remainder;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->tmreg_lock, flags);
+ ns = timecounter_read(&adapter->tc);
+ spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+
+ ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder);
+ ts->tv_nsec = remainder;
+
+ return 0;
+}
+
+/**
+ * ixgbe_ptp_settime
+ * @ptp - the ptp clock structure
+ * @ts - the timespec containing the new time for the cycle counter
+ *
+ * reset the timecounter to use a new base value instead of the kernel
+ * wall timer value.
+ */
+static int ixgbe_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec *ts)
+{
+ struct ixgbe_adapter *adapter =
+ container_of(ptp, struct ixgbe_adapter, ptp_caps);
+ u64 ns;
+ unsigned long flags;
+
+ ns = ts->tv_sec * 1000000000ULL;
+ ns += ts->tv_nsec;
+
+ /* reset the timecounter */
+ spin_lock_irqsave(&adapter->tmreg_lock, flags);
+ timecounter_init(&adapter->tc, &adapter->cc, ns);
+ spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+
+ return 0;
+}
+
+/**
+ * ixgbe_ptp_enable
+ * @ptp - the ptp clock structure
+ * @rq - the requested feature to change
+ * @on - whether to enable or disable the feature
+ *
+ * enable (or disable) ancillary features of the phc subsystem.
+ * our driver only supports the PPS feature on the X540
+ */
+static int ixgbe_ptp_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ struct ixgbe_adapter *adapter =
+ container_of(ptp, struct ixgbe_adapter, ptp_caps);
+
+ /**
+ * When PPS is enabled, unmask the interrupt for the ClockOut
+ * feature, so that the interrupt handler can send the PPS
+ * event when the clock SDP triggers. Clear mask when PPS is
+ * disabled
+ */
+ if (rq->type == PTP_CLK_REQ_PPS) {
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_X540:
+ if (on)
+ adapter->flags2 |= IXGBE_FLAG2_PTP_PPS_ENABLED;
+ else
+ adapter->flags2 &=
+ ~IXGBE_FLAG2_PTP_PPS_ENABLED;
+ return 0;
+ default:
+ break;
+ }
+ }
+
+ return -ENOTSUPP;
+}
+
+/**
+ * ixgbe_ptp_check_pps_event
+ * @adapter - the private adapter structure
+ * @eicr - the interrupt cause register value
+ *
+ * This function is called by the interrupt routine when checking for
+ * interrupts. It will check and handle a pps event.
+ */
+void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct ptp_clock_event event;
+
+ event.type = PTP_CLOCK_PPS;
+
+ /* Make sure ptp clock is valid, and PPS event enabled */
+ if (!adapter->ptp_clock ||
+ !(adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED))
+ return;
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_X540:
+ if (eicr & IXGBE_EICR_TIMESYNC)
+ ptp_clock_event(adapter->ptp_clock, &event);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * ixgbe_ptp_enable_sdp
+ * @hw - the hardware private structure
+ * @shift - the clock shift for calculating nanoseconds
+ *
+ * this function enables the clock out feature on the sdp0 for the
+ * X540 device. It will create a 1second periodic output that can be
+ * used as the PPS (via an interrupt).
+ *
+ * It calculates when the systime will be on an exact second, and then
+ * aligns the start of the PPS signal to that value. The shift is
+ * necessary because it can change based on the link speed.
+ */
+static void ixgbe_ptp_enable_sdp(struct ixgbe_hw *hw, int shift)
+{
+ u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh;
+ u64 clock_edge = 0;
+ u32 rem;
+
+ switch (hw->mac.type) {
+ case ixgbe_mac_X540:
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+
+ /*
+ * enable the SDP0 pin as output, and connected to the native
+ * function for Timesync (ClockOut)
+ */
+ esdp |= (IXGBE_ESDP_SDP0_DIR |
+ IXGBE_ESDP_SDP0_NATIVE);
+
+ /*
+ * enable the Clock Out feature on SDP0, and allow interrupts
+ * to occur when the pin changes
+ */
+ tsauxc = (IXGBE_TSAUXC_EN_CLK |
+ IXGBE_TSAUXC_SYNCLK |
+ IXGBE_TSAUXC_SDP0_INT);
+
+ /* clock period (or pulse length) */
+ clktiml = (u32)(NSECS_PER_SEC << shift);
+ clktimh = (u32)((NSECS_PER_SEC << shift) >> 32);
+
+ clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIML);
+ clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32;
+
+ /*
+ * account for the fact that we can't do u64 division
+ * with remainder, by converting the clock values into
+ * nanoseconds first
+ */
+ clock_edge >>= shift;
+ div_u64_rem(clock_edge, NSECS_PER_SEC, &rem);
+ clock_edge += (NSECS_PER_SEC - rem);
+ clock_edge <<= shift;
+
+ /* specify the initial clock start time */
+ trgttiml = (u32)clock_edge;
+ trgttimh = (u32)(clock_edge >> 32);
+
+ IXGBE_WRITE_REG(hw, IXGBE_CLKTIML, clktiml);
+ IXGBE_WRITE_REG(hw, IXGBE_CLKTIMH, clktimh);
+ IXGBE_WRITE_REG(hw, IXGBE_TRGTTIML0, trgttiml);
+ IXGBE_WRITE_REG(hw, IXGBE_TRGTTIMH0, trgttimh);
+
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+ IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc);
+
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_TIMESYNC);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * ixgbe_ptp_disable_sdp
+ * @hw - the private hardware structure
+ *
+ * this function disables the auxiliary SDP clock out feature
+ */
+static void ixgbe_ptp_disable_sdp(struct ixgbe_hw *hw)
+{
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_TIMESYNC);
+ IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0);
+}
+
+/**
+ * ixgbe_ptp_overflow_check - delayed work to detect SYSTIME overflow
+ * @work: structure containing information about this work task
+ *
+ * this work function is scheduled to continue reading the timecounter
+ * in order to prevent missing when the system time registers wrap
+ * around. This needs to be run approximately twice a minute when no
+ * PTP activity is occurring.
+ */
+void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter)
+{
+ unsigned long elapsed_jiffies = adapter->last_overflow_check - jiffies;
+ struct timespec ts;
+
+ if ((adapter->flags2 & IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED) &&
+ (elapsed_jiffies >= IXGBE_OVERFLOW_PERIOD)) {
+ ixgbe_ptp_gettime(&adapter->ptp_caps, &ts);
+ adapter->last_overflow_check = jiffies;
+ }
+}
+
+/**
+ * ixgbe_ptp_tx_hwtstamp - utility function which checks for TX time stamp
+ * @q_vector: structure containing interrupt and ring information
+ * @skb: particular skb to send timestamp with
+ *
+ * if the timestamp is valid, we convert it into the timecounter ns
+ * value, then store that result into the shhwtstamps structure which
+ * is passed up the network stack
+ */
+void ixgbe_ptp_tx_hwtstamp(struct ixgbe_q_vector *q_vector,
+ struct sk_buff *skb)
+{
+ struct ixgbe_adapter *adapter;
+ struct ixgbe_hw *hw;
+ struct skb_shared_hwtstamps shhwtstamps;
+ u64 regval = 0, ns;
+ u32 tsynctxctl;
+ unsigned long flags;
+
+ /* we cannot process timestamps on a ring without a q_vector */
+ if (!q_vector || !q_vector->adapter)
+ return;
+
+ adapter = q_vector->adapter;
+ hw = &adapter->hw;
+
+ tsynctxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL);
+ regval |= (u64)IXGBE_READ_REG(hw, IXGBE_TXSTMPL);
+ regval |= (u64)IXGBE_READ_REG(hw, IXGBE_TXSTMPH) << 32;
+
+ /*
+ * if TX timestamp is not valid, exit after clearing the
+ * timestamp registers
+ */
+ if (!(tsynctxctl & IXGBE_TSYNCTXCTL_VALID))
+ return;
+
+ spin_lock_irqsave(&adapter->tmreg_lock, flags);
+ ns = timecounter_cyc2time(&adapter->tc, regval);
+ spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ shhwtstamps.hwtstamp = ns_to_ktime(ns);
+ skb_tstamp_tx(skb, &shhwtstamps);
+}
+
+/**
+ * ixgbe_ptp_rx_hwtstamp - utility function which checks for RX time stamp
+ * @q_vector: structure containing interrupt and ring information
+ * @skb: particular skb to send timestamp with
+ *
+ * if the timestamp is valid, we convert it into the timecounter ns
+ * value, then store that result into the shhwtstamps structure which
+ * is passed up the network stack
+ */
+void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
+ struct sk_buff *skb)
+{
+ struct ixgbe_adapter *adapter;
+ struct ixgbe_hw *hw;
+ struct skb_shared_hwtstamps *shhwtstamps;
+ u64 regval = 0, ns;
+ u32 tsyncrxctl;
+ unsigned long flags;
+
+ /* we cannot process timestamps on a ring without a q_vector */
+ if (!q_vector || !q_vector->adapter)
+ return;
+
+ adapter = q_vector->adapter;
+ hw = &adapter->hw;
+
+ tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL);
+ regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPL);
+ regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPH) << 32;
+
+ /*
+ * If this bit is set, then the RX registers contain the time stamp. No
+ * other packet will be time stamped until we read these registers, so
+ * read the registers to make them available again. Because only one
+ * packet can be time stamped at a time, we know that the register
+ * values must belong to this one here and therefore we don't need to
+ * compare any of the additional attributes stored for it.
+ *
+ * If nothing went wrong, then it should have a skb_shared_tx that we
+ * can turn into a skb_shared_hwtstamps.
+ */
+ if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID))
+ return;
+
+ spin_lock_irqsave(&adapter->tmreg_lock, flags);
+ ns = timecounter_cyc2time(&adapter->tc, regval);
+ spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+
+ shhwtstamps = skb_hwtstamps(skb);
+ shhwtstamps->hwtstamp = ns_to_ktime(ns);
+}
+
+/**
+ * ixgbe_ptp_hwtstamp_ioctl - control hardware time stamping
+ * @adapter: pointer to adapter struct
+ * @ifreq: ioctl data
+ * @cmd: particular ioctl requested
+ *
+ * Outgoing time stamping can be enabled and disabled. Play nice and
+ * disable it when requested, although it shouldn't case any overhead
+ * when no packet needs it. At most one packet in the queue may be
+ * marked for time stamping, otherwise it would be impossible to tell
+ * for sure to which packet the hardware time stamp belongs.
+ *
+ * Incoming time stamping has to be configured via the hardware
+ * filters. Not all combinations are supported, in particular event
+ * type has to be specified. Matching the kind of event packet is
+ * not supported, with the exception of "all V2 events regardless of
+ * level 2 or 4".
+ */
+int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
+ struct ifreq *ifr, int cmd)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct hwtstamp_config config;
+ u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED;
+ u32 tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED;
+ u32 tsync_rx_mtrl = 0;
+ bool is_l4 = false;
+ bool is_l2 = false;
+ u32 regval;
+
+ if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (config.flags)
+ return -EINVAL;
+
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ tsync_tx_ctl = 0;
+ case HWTSTAMP_TX_ON:
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ switch (config.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ tsync_rx_ctl = 0;
+ break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
+ tsync_rx_mtrl = IXGBE_RXMTRL_V1_SYNC_MSG;
+ is_l4 = true;
+ break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
+ tsync_rx_mtrl = IXGBE_RXMTRL_V1_DELAY_REQ_MSG;
+ is_l4 = true;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L2_L4_V2;
+ tsync_rx_mtrl = IXGBE_RXMTRL_V2_SYNC_MSG;
+ is_l2 = true;
+ is_l4 = true;
+ config.rx_filter = HWTSTAMP_FILTER_SOME;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L2_L4_V2;
+ tsync_rx_mtrl = IXGBE_RXMTRL_V2_DELAY_REQ_MSG;
+ is_l2 = true;
+ is_l4 = true;
+ config.rx_filter = HWTSTAMP_FILTER_SOME;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2;
+ config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ is_l2 = true;
+ is_l4 = true;
+ break;
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_ALL:
+ default:
+ /*
+ * register RXMTRL must be set, therefore it is not
+ * possible to time stamp both V1 Sync and Delay_Req messages
+ * and hardware does not support timestamping all packets
+ * => return error
+ */
+ return -ERANGE;
+ }
+
+ if (hw->mac.type == ixgbe_mac_82598EB) {
+ if (tsync_rx_ctl | tsync_tx_ctl)
+ return -ERANGE;
+ return 0;
+ }
+
+ /* define ethertype filter for timestamped packets */
+ if (is_l2)
+ IXGBE_WRITE_REG(hw, IXGBE_ETQF(3),
+ (IXGBE_ETQF_FILTER_EN | /* enable filter */
+ IXGBE_ETQF_1588 | /* enable timestamping */
+ ETH_P_1588)); /* 1588 eth protocol type */
+ else
+ IXGBE_WRITE_REG(hw, IXGBE_ETQF(3), 0);
+
+#define PTP_PORT 319
+ /* L4 Queue Filter[3]: filter by destination port and protocol */
+ if (is_l4) {
+ u32 ftqf = (IXGBE_FTQF_PROTOCOL_UDP /* UDP */
+ | IXGBE_FTQF_POOL_MASK_EN /* Pool not compared */
+ | IXGBE_FTQF_QUEUE_ENABLE);
+
+ ftqf |= ((IXGBE_FTQF_PROTOCOL_COMP_MASK /* protocol check */
+ & IXGBE_FTQF_DEST_PORT_MASK /* dest check */
+ & IXGBE_FTQF_SOURCE_PORT_MASK) /* source check */
+ << IXGBE_FTQF_5TUPLE_MASK_SHIFT);
+
+ IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(3),
+ (3 << IXGBE_IMIR_RX_QUEUE_SHIFT_82599 |
+ IXGBE_IMIR_SIZE_BP_82599));
+
+ /* enable port check */
+ IXGBE_WRITE_REG(hw, IXGBE_SDPQF(3),
+ (htons(PTP_PORT) |
+ htons(PTP_PORT) << 16));
+
+ IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), ftqf);
+
+ tsync_rx_mtrl |= PTP_PORT << 16;
+ } else {
+ IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), 0);
+ }
+
+ /* enable/disable TX */
+ regval = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL);
+ regval &= ~IXGBE_TSYNCTXCTL_ENABLED;
+ regval |= tsync_tx_ctl;
+ IXGBE_WRITE_REG(hw, IXGBE_TSYNCTXCTL, regval);
+
+ /* enable/disable RX */
+ regval = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL);
+ regval &= ~(IXGBE_TSYNCRXCTL_ENABLED | IXGBE_TSYNCRXCTL_TYPE_MASK);
+ regval |= tsync_rx_ctl;
+ IXGBE_WRITE_REG(hw, IXGBE_TSYNCRXCTL, regval);
+
+ /* define which PTP packets are time stamped */
+ IXGBE_WRITE_REG(hw, IXGBE_RXMTRL, tsync_rx_mtrl);
+
+ IXGBE_WRITE_FLUSH(hw);
+
+ /* clear TX/RX time stamp registers, just to be sure */
+ regval = IXGBE_READ_REG(hw, IXGBE_TXSTMPH);
+ regval = IXGBE_READ_REG(hw, IXGBE_RXSTMPH);
+
+ return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+ -EFAULT : 0;
+}
+
+/**
+ * ixgbe_ptp_start_cyclecounter - create the cycle counter from hw
+ * @adapter - pointer to the adapter structure
+ *
+ * this function initializes the timecounter and cyclecounter
+ * structures for use in generated a ns counter from the arbitrary
+ * fixed point cycles registers in the hardware.
+ *
+ * A change in link speed impacts the frequency of the DMA clock on
+ * the device, which is used to generate the cycle counter
+ * registers. Therefor this function is called whenever the link speed
+ * changes.
+ *
+ * This function also turns on the SDP pin for clock out feature (X540
+ * only), because this is where the shift is first calculated.
+ */
+void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 incval = 0;
+ u32 shift = 0;
+ u32 cycle_speed;
+ unsigned long flags;
+
+ /**
+ * Determine what speed we need to set the cyclecounter
+ * for. It should be different for 100Mb, 1Gb, and 10Gb. Treat
+ * unknown speeds as 10Gb. (Hence why we can't just copy the
+ * link_speed.
+ */
+ switch (adapter->link_speed) {
+ case IXGBE_LINK_SPEED_100_FULL:
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ cycle_speed = adapter->link_speed;
+ break;
+ default:
+ /* cycle speed should be 10Gb when there is no link */
+ cycle_speed = IXGBE_LINK_SPEED_10GB_FULL;
+ break;
+ }
+
+ /* Bail if the cycle speed didn't change */
+ if (adapter->cycle_speed == cycle_speed)
+ return;
+
+ /* disable the SDP clock out */
+ ixgbe_ptp_disable_sdp(hw);
+
+ /**
+ * Scale the NIC cycle counter by a large factor so that
+ * relatively small corrections to the frequency can be added
+ * or subtracted. The drawbacks of a large factor include
+ * (a) the clock register overflows more quickly, (b) the cycle
+ * counter structure must be able to convert the systime value
+ * to nanoseconds using only a multiplier and a right-shift,
+ * and (c) the value must fit within the timinca register space
+ * => math based on internal DMA clock rate and available bits
+ */
+ switch (cycle_speed) {
+ case IXGBE_LINK_SPEED_100_FULL:
+ incval = IXGBE_INCVAL_100;
+ shift = IXGBE_INCVAL_SHIFT_100;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ incval = IXGBE_INCVAL_1GB;
+ shift = IXGBE_INCVAL_SHIFT_1GB;
+ break;
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ incval = IXGBE_INCVAL_10GB;
+ shift = IXGBE_INCVAL_SHIFT_10GB;
+ break;
+ }
+
+ /**
+ * Modify the calculated values to fit within the correct
+ * number of bits specified by the hardware. The 82599 doesn't
+ * have the same space as the X540, so bitshift the calculated
+ * values to fit.
+ */
+ switch (hw->mac.type) {
+ case ixgbe_mac_X540:
+ IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, incval);
+ break;
+ case ixgbe_mac_82599EB:
+ incval >>= IXGBE_INCVAL_SHIFT_82599;
+ shift -= IXGBE_INCVAL_SHIFT_82599;
+ IXGBE_WRITE_REG(hw, IXGBE_TIMINCA,
+ (1 << IXGBE_INCPER_SHIFT_82599) |
+ incval);
+ break;
+ default:
+ /* other devices aren't supported */
+ return;
+ }
+
+ /* reset the system time registers */
+ IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
+ IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
+ IXGBE_WRITE_FLUSH(hw);
+
+ /* now that the shift has been calculated and the systime
+ * registers reset, (re-)enable the Clock out feature*/
+ ixgbe_ptp_enable_sdp(hw, shift);
+
+ /* store the new cycle speed */
+ adapter->cycle_speed = cycle_speed;
+
+ ACCESS_ONCE(adapter->base_incval) = incval;
+ smp_mb();
+
+ /* grab the ptp lock */
+ spin_lock_irqsave(&adapter->tmreg_lock, flags);
+
+ memset(&adapter->cc, 0, sizeof(adapter->cc));
+ adapter->cc.read = ixgbe_ptp_read;
+ adapter->cc.mask = CLOCKSOURCE_MASK(64);
+ adapter->cc.shift = shift;
+ adapter->cc.mult = 1;
+
+ /* reset the ns time counter */
+ timecounter_init(&adapter->tc, &adapter->cc,
+ ktime_to_ns(ktime_get_real()));
+
+ spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+}
+
+/**
+ * ixgbe_ptp_init
+ * @adapter - the ixgbe private adapter structure
+ *
+ * This function performs the required steps for enabling ptp
+ * support. If ptp support has already been loaded it simply calls the
+ * cyclecounter init routine and exits.
+ */
+void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ switch (adapter->hw.mac.type) {
+ case ixgbe_mac_X540:
+ snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
+ adapter->ptp_caps.owner = THIS_MODULE;
+ adapter->ptp_caps.max_adj = 250000000;
+ adapter->ptp_caps.n_alarm = 0;
+ adapter->ptp_caps.n_ext_ts = 0;
+ adapter->ptp_caps.n_per_out = 0;
+ adapter->ptp_caps.pps = 1;
+ adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq;
+ adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime;
+ adapter->ptp_caps.gettime = ixgbe_ptp_gettime;
+ adapter->ptp_caps.settime = ixgbe_ptp_settime;
+ adapter->ptp_caps.enable = ixgbe_ptp_enable;
+ break;
+ case ixgbe_mac_82599EB:
+ snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
+ adapter->ptp_caps.owner = THIS_MODULE;
+ adapter->ptp_caps.max_adj = 250000000;
+ adapter->ptp_caps.n_alarm = 0;
+ adapter->ptp_caps.n_ext_ts = 0;
+ adapter->ptp_caps.n_per_out = 0;
+ adapter->ptp_caps.pps = 0;
+ adapter->ptp_caps.adjfreq = ixgbe_ptp_adjfreq;
+ adapter->ptp_caps.adjtime = ixgbe_ptp_adjtime;
+ adapter->ptp_caps.gettime = ixgbe_ptp_gettime;
+ adapter->ptp_caps.settime = ixgbe_ptp_settime;
+ adapter->ptp_caps.enable = ixgbe_ptp_enable;
+ break;
+ default:
+ adapter->ptp_clock = NULL;
+ return;
+ }
+
+ spin_lock_init(&adapter->tmreg_lock);
+
+ ixgbe_ptp_start_cyclecounter(adapter);
+
+ /* (Re)start the overflow check */
+ adapter->flags2 |= IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED;
+
+ adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps);
+ if (IS_ERR(adapter->ptp_clock)) {
+ adapter->ptp_clock = NULL;
+ e_dev_err("ptp_clock_register failed\n");
+ } else
+ e_dev_info("registered PHC device on %s\n", netdev->name);
+
+ return;
+}
+
+/**
+ * ixgbe_ptp_stop - disable ptp device and stop the overflow check
+ * @adapter: pointer to adapter struct
+ *
+ * this function stops the ptp support, and cancels the delayed work.
+ */
+void ixgbe_ptp_stop(struct ixgbe_adapter *adapter)
+{
+ ixgbe_ptp_disable_sdp(&adapter->hw);
+
+ /* stop the overflow check task */
+ adapter->flags2 &= ~IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED;
+
+ if (adapter->ptp_clock) {
+ ptp_clock_unregister(adapter->ptp_clock);
+ adapter->ptp_clock = NULL;
+ e_dev_info("removed PHC on %s\n",
+ adapter->netdev->name);
+ }
+}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index 88a58cb08569..2d971d18696e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -544,13 +544,18 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf);
- if (retval)
+ if (retval) {
pr_err("Error receiving message from VF\n");
+ return retval;
+ }
/* this is a message we already processed, do nothing */
if (msgbuf[0] & (IXGBE_VT_MSGTYPE_ACK | IXGBE_VT_MSGTYPE_NACK))
return retval;
+ /* flush the ack before we write any messages back */
+ IXGBE_WRITE_FLUSH(hw);
+
/*
* until the vf completes a virtual function reset it should not be
* allowed to start any configuration.
@@ -637,6 +642,12 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
case IXGBE_VF_SET_MACVLAN:
index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >>
IXGBE_VT_MSGINFO_SHIFT;
+ if (adapter->vfinfo[vf].pf_set_mac && index > 0) {
+ e_warn(drv, "VF %d requested MACVLAN filter but is "
+ "administratively denied\n", vf);
+ retval = -1;
+ break;
+ }
/*
* If the VF is allowed to set MAC filters then turn off
* anti-spoofing to avoid false positives. An index
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c
new file mode 100644
index 000000000000..1d80b1cefa6a
--- /dev/null
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c
@@ -0,0 +1,245 @@
+/*******************************************************************************
+
+ Intel 10 Gigabit PCI Express 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:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include "ixgbe.h"
+#include "ixgbe_common.h"
+#include "ixgbe_type.h"
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/device.h>
+#include <linux/netdevice.h>
+#include <linux/hwmon.h>
+
+#ifdef CONFIG_IXGBE_HWMON
+/* hwmon callback functions */
+static ssize_t ixgbe_hwmon_show_location(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
+ dev_attr);
+ return sprintf(buf, "loc%u\n",
+ ixgbe_attr->sensor->location);
+}
+
+static ssize_t ixgbe_hwmon_show_temp(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
+ dev_attr);
+ unsigned int value;
+
+ /* reset the temp field */
+ ixgbe_attr->hw->mac.ops.get_thermal_sensor_data(ixgbe_attr->hw);
+
+ value = ixgbe_attr->sensor->temp;
+
+ /* display millidegree */
+ value *= 1000;
+
+ return sprintf(buf, "%u\n", value);
+}
+
+static ssize_t ixgbe_hwmon_show_cautionthresh(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
+ dev_attr);
+ unsigned int value = ixgbe_attr->sensor->caution_thresh;
+
+ /* display millidegree */
+ value *= 1000;
+
+ return sprintf(buf, "%u\n", value);
+}
+
+static ssize_t ixgbe_hwmon_show_maxopthresh(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
+ dev_attr);
+ unsigned int value = ixgbe_attr->sensor->max_op_thresh;
+
+ /* display millidegree */
+ value *= 1000;
+
+ return sprintf(buf, "%u\n", value);
+}
+
+/*
+ * ixgbe_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file.
+ * @ adapter: pointer to the adapter structure
+ * @ offset: offset in the eeprom sensor data table
+ * @ type: type of sensor data to display
+ *
+ * For each file we want in hwmon's sysfs interface we need a device_attribute
+ * This is included in our hwmon_attr struct that contains the references to
+ * the data structures we need to get the data to display.
+ */
+static int ixgbe_add_hwmon_attr(struct ixgbe_adapter *adapter,
+ unsigned int offset, int type) {
+ int rc;
+ unsigned int n_attr;
+ struct hwmon_attr *ixgbe_attr;
+
+ n_attr = adapter->ixgbe_hwmon_buff.n_hwmon;
+ ixgbe_attr = &adapter->ixgbe_hwmon_buff.hwmon_list[n_attr];
+
+ switch (type) {
+ case IXGBE_HWMON_TYPE_LOC:
+ ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_location;
+ snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
+ "temp%u_label", offset);
+ break;
+ case IXGBE_HWMON_TYPE_TEMP:
+ ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_temp;
+ snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
+ "temp%u_input", offset);
+ break;
+ case IXGBE_HWMON_TYPE_CAUTION:
+ ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_cautionthresh;
+ snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
+ "temp%u_max", offset);
+ break;
+ case IXGBE_HWMON_TYPE_MAX:
+ ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_maxopthresh;
+ snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
+ "temp%u_crit", offset);
+ break;
+ default:
+ rc = -EPERM;
+ return rc;
+ }
+
+ /* These always the same regardless of type */
+ ixgbe_attr->sensor =
+ &adapter->hw.mac.thermal_sensor_data.sensor[offset];
+ ixgbe_attr->hw = &adapter->hw;
+ ixgbe_attr->dev_attr.store = NULL;
+ ixgbe_attr->dev_attr.attr.mode = S_IRUGO;
+ ixgbe_attr->dev_attr.attr.name = ixgbe_attr->name;
+
+ rc = device_create_file(&adapter->pdev->dev,
+ &ixgbe_attr->dev_attr);
+
+ if (rc == 0)
+ ++adapter->ixgbe_hwmon_buff.n_hwmon;
+
+ return rc;
+}
+
+static void ixgbe_sysfs_del_adapter(struct ixgbe_adapter *adapter)
+{
+ int i;
+
+ if (adapter == NULL)
+ return;
+
+ for (i = 0; i < adapter->ixgbe_hwmon_buff.n_hwmon; i++) {
+ device_remove_file(&adapter->pdev->dev,
+ &adapter->ixgbe_hwmon_buff.hwmon_list[i].dev_attr);
+ }
+
+ kfree(adapter->ixgbe_hwmon_buff.hwmon_list);
+
+ if (adapter->ixgbe_hwmon_buff.device)
+ hwmon_device_unregister(adapter->ixgbe_hwmon_buff.device);
+}
+
+/* called from ixgbe_main.c */
+void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter)
+{
+ ixgbe_sysfs_del_adapter(adapter);
+}
+
+/* called from ixgbe_main.c */
+int ixgbe_sysfs_init(struct ixgbe_adapter *adapter)
+{
+ struct hwmon_buff *ixgbe_hwmon = &adapter->ixgbe_hwmon_buff;
+ unsigned int i;
+ int n_attrs;
+ int rc = 0;
+
+ /* If this method isn't defined we don't support thermals */
+ if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) {
+ goto exit;
+ }
+
+ /* Don't create thermal hwmon interface if no sensors present */
+ if (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw))
+ goto exit;
+
+ /*
+ * Allocation space for max attributs
+ * max num sensors * values (loc, temp, max, caution)
+ */
+ n_attrs = IXGBE_MAX_SENSORS * 4;
+ ixgbe_hwmon->hwmon_list = kcalloc(n_attrs, sizeof(struct hwmon_attr),
+ GFP_KERNEL);
+ if (!ixgbe_hwmon->hwmon_list) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ ixgbe_hwmon->device = hwmon_device_register(&adapter->pdev->dev);
+ if (IS_ERR(ixgbe_hwmon->device)) {
+ rc = PTR_ERR(ixgbe_hwmon->device);
+ goto err;
+ }
+
+ for (i = 0; i < IXGBE_MAX_SENSORS; i++) {
+ /*
+ * Only create hwmon sysfs entries for sensors that have
+ * meaningful data for.
+ */
+ if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0)
+ continue;
+
+ /* Bail if any hwmon attr struct fails to initialize */
+ rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_CAUTION);
+ rc |= ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_LOC);
+ rc |= ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_TEMP);
+ rc |= ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_MAX);
+ if (rc)
+ goto err;
+ }
+
+ goto exit;
+
+err:
+ ixgbe_sysfs_del_adapter(adapter);
+exit:
+ return rc;
+}
+#endif /* CONFIG_IXGBE_HWMON */
+
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 8636e8344fc9..204848d2448c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -110,6 +110,28 @@
#define IXGBE_I2C_CLK_OUT 0x00000002
#define IXGBE_I2C_DATA_IN 0x00000004
#define IXGBE_I2C_DATA_OUT 0x00000008
+#define IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT 500
+
+#define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8
+#define IXGBE_EMC_INTERNAL_DATA 0x00
+#define IXGBE_EMC_INTERNAL_THERM_LIMIT 0x20
+#define IXGBE_EMC_DIODE1_DATA 0x01
+#define IXGBE_EMC_DIODE1_THERM_LIMIT 0x19
+#define IXGBE_EMC_DIODE2_DATA 0x23
+#define IXGBE_EMC_DIODE2_THERM_LIMIT 0x1A
+
+#define IXGBE_MAX_SENSORS 3
+
+struct ixgbe_thermal_diode_data {
+ u8 location;
+ u8 temp;
+ u8 caution_thresh;
+ u8 max_op_thresh;
+};
+
+struct ixgbe_thermal_sensor_data {
+ struct ixgbe_thermal_diode_data sensor[IXGBE_MAX_SENSORS];
+};
/* Interrupt Registers */
#define IXGBE_EICR 0x00800
@@ -802,6 +824,8 @@
#define IXGBE_TRGTTIMH0 0x08C28 /* Target Time Register 0 High - RW */
#define IXGBE_TRGTTIML1 0x08C2C /* Target Time Register 1 Low - RW */
#define IXGBE_TRGTTIMH1 0x08C30 /* Target Time Register 1 High - RW */
+#define IXGBE_CLKTIML 0x08C34 /* Clock Out Time Register Low - RW */
+#define IXGBE_CLKTIMH 0x08C38 /* Clock Out Time Register High - RW */
#define IXGBE_FREQOUT0 0x08C34 /* Frequency Out 0 Control register - RW */
#define IXGBE_FREQOUT1 0x08C38 /* Frequency Out 1 Control register - RW */
#define IXGBE_AUXSTMPL0 0x08C3C /* Auxiliary Time Stamp 0 register Low - RO */
@@ -1287,6 +1311,7 @@ enum {
#define IXGBE_EICR_LINKSEC 0x00200000 /* PN Threshold */
#define IXGBE_EICR_MNG 0x00400000 /* Manageability Event Interrupt */
#define IXGBE_EICR_TS 0x00800000 /* Thermal Sensor Event */
+#define IXGBE_EICR_TIMESYNC 0x01000000 /* Timesync Event */
#define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */
#define IXGBE_EICR_GPI_SDP1 0x02000000 /* Gen Purpose Interrupt on SDP1 */
#define IXGBE_EICR_GPI_SDP2 0x04000000 /* Gen Purpose Interrupt on SDP2 */
@@ -1304,6 +1329,7 @@ enum {
#define IXGBE_EICS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */
#define IXGBE_EICS_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EICS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
+#define IXGBE_EICS_TIMESYNC IXGBE_EICR_TIMESYNC /* Timesync Event */
#define IXGBE_EICS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */
#define IXGBE_EICS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */
#define IXGBE_EICS_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */
@@ -1322,6 +1348,7 @@ enum {
#define IXGBE_EIMS_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EIMS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
#define IXGBE_EIMS_TS IXGBE_EICR_TS /* Thermel Sensor Event */
+#define IXGBE_EIMS_TIMESYNC IXGBE_EICR_TIMESYNC /* Timesync Event */
#define IXGBE_EIMS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */
#define IXGBE_EIMS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */
#define IXGBE_EIMS_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */
@@ -1339,6 +1366,7 @@ enum {
#define IXGBE_EIMC_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */
#define IXGBE_EIMC_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EIMC_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
+#define IXGBE_EIMC_TIMESYNC IXGBE_EICR_TIMESYNC /* Timesync Event */
#define IXGBE_EIMC_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */
#define IXGBE_EIMC_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */
#define IXGBE_EIMC_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */
@@ -1479,8 +1507,10 @@ enum {
#define IXGBE_ESDP_SDP4 0x00000010 /* SDP4 Data Value */
#define IXGBE_ESDP_SDP5 0x00000020 /* SDP5 Data Value */
#define IXGBE_ESDP_SDP6 0x00000040 /* SDP6 Data Value */
+#define IXGBE_ESDP_SDP0_DIR 0x00000100 /* SDP0 IO direction */
#define IXGBE_ESDP_SDP4_DIR 0x00000004 /* SDP4 IO direction */
#define IXGBE_ESDP_SDP5_DIR 0x00002000 /* SDP5 IO direction */
+#define IXGBE_ESDP_SDP0_NATIVE 0x00010000 /* SDP0 Native Function */
/* LEDCTL Bit Masks */
#define IXGBE_LED_IVRT_BASE 0x00000040
@@ -1677,11 +1707,29 @@ enum {
#define IXGBE_PBANUM0_PTR 0x15
#define IXGBE_PBANUM1_PTR 0x16
#define IXGBE_FREE_SPACE_PTR 0X3E
+
+/* External Thermal Sensor Config */
+#define IXGBE_ETS_CFG 0x26
+#define IXGBE_ETS_LTHRES_DELTA_MASK 0x07C0
+#define IXGBE_ETS_LTHRES_DELTA_SHIFT 6
+#define IXGBE_ETS_TYPE_MASK 0x0038
+#define IXGBE_ETS_TYPE_SHIFT 3
+#define IXGBE_ETS_TYPE_EMC 0x000
+#define IXGBE_ETS_TYPE_EMC_SHIFTED 0x000
+#define IXGBE_ETS_NUM_SENSORS_MASK 0x0007
+#define IXGBE_ETS_DATA_LOC_MASK 0x3C00
+#define IXGBE_ETS_DATA_LOC_SHIFT 10
+#define IXGBE_ETS_DATA_INDEX_MASK 0x0300
+#define IXGBE_ETS_DATA_INDEX_SHIFT 8
+#define IXGBE_ETS_DATA_HTHRESH_MASK 0x00FF
+
#define IXGBE_SAN_MAC_ADDR_PTR 0x28
#define IXGBE_DEVICE_CAPS 0x2C
#define IXGBE_SERIAL_NUMBER_MAC_ADDR 0x11
#define IXGBE_PCIE_MSIX_82599_CAPS 0x72
+#define IXGBE_MAX_MSIX_VECTORS_82599 0x40
#define IXGBE_PCIE_MSIX_82598_CAPS 0x62
+#define IXGBE_MAX_MSIX_VECTORS_82598 0x13
/* MSI-X capability fields masks */
#define IXGBE_PCIE_MSIX_TBL_SZ_MASK 0x7FF
@@ -1839,6 +1887,40 @@ enum {
#define IXGBE_RXDCTL_RLPML_EN 0x00008000
#define IXGBE_RXDCTL_VME 0x40000000 /* VLAN mode enable */
+#define IXGBE_TSAUXC_EN_CLK 0x00000004
+#define IXGBE_TSAUXC_SYNCLK 0x00000008
+#define IXGBE_TSAUXC_SDP0_INT 0x00000040
+
+#define IXGBE_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */
+#define IXGBE_TSYNCTXCTL_ENABLED 0x00000010 /* Tx timestamping enabled */
+
+#define IXGBE_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */
+#define IXGBE_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */
+#define IXGBE_TSYNCRXCTL_TYPE_L2_V2 0x00
+#define IXGBE_TSYNCRXCTL_TYPE_L4_V1 0x02
+#define IXGBE_TSYNCRXCTL_TYPE_L2_L4_V2 0x04
+#define IXGBE_TSYNCRXCTL_TYPE_EVENT_V2 0x0A
+#define IXGBE_TSYNCRXCTL_ENABLED 0x00000010 /* Rx Timestamping enabled */
+
+#define IXGBE_RXMTRL_V1_CTRLT_MASK 0x000000FF
+#define IXGBE_RXMTRL_V1_SYNC_MSG 0x00
+#define IXGBE_RXMTRL_V1_DELAY_REQ_MSG 0x01
+#define IXGBE_RXMTRL_V1_FOLLOWUP_MSG 0x02
+#define IXGBE_RXMTRL_V1_DELAY_RESP_MSG 0x03
+#define IXGBE_RXMTRL_V1_MGMT_MSG 0x04
+
+#define IXGBE_RXMTRL_V2_MSGID_MASK 0x0000FF00
+#define IXGBE_RXMTRL_V2_SYNC_MSG 0x0000
+#define IXGBE_RXMTRL_V2_DELAY_REQ_MSG 0x0100
+#define IXGBE_RXMTRL_V2_PDELAY_REQ_MSG 0x0200
+#define IXGBE_RXMTRL_V2_PDELAY_RESP_MSG 0x0300
+#define IXGBE_RXMTRL_V2_FOLLOWUP_MSG 0x0800
+#define IXGBE_RXMTRL_V2_DELAY_RESP_MSG 0x0900
+#define IXGBE_RXMTRL_V2_PDELAY_FOLLOWUP_MSG 0x0A00
+#define IXGBE_RXMTRL_V2_ANNOUNCE_MSG 0x0B00
+#define IXGBE_RXMTRL_V2_SIGNALING_MSG 0x0C00
+#define IXGBE_RXMTRL_V2_MGMT_MSG 0x0D00
+
#define IXGBE_FCTRL_SBP 0x00000002 /* Store Bad Packet */
#define IXGBE_FCTRL_MPE 0x00000100 /* Multicast Promiscuous Ena*/
#define IXGBE_FCTRL_UPE 0x00000200 /* Unicast Promiscuous Ena */
@@ -1852,7 +1934,7 @@ enum {
#define IXGBE_MFLCN_DPF 0x00000002 /* Discard Pause Frame */
#define IXGBE_MFLCN_RPFCE 0x00000004 /* Receive Priority FC Enable */
#define IXGBE_MFLCN_RFCE 0x00000008 /* Receive FC Enable */
-#define IXGBE_MFLCN_RPFCE_MASK 0x00000FF0 /* Receive FC Mask */
+#define IXGBE_MFLCN_RPFCE_MASK 0x00000FF4 /* Receive FC Mask */
#define IXGBE_MFLCN_RPFCE_SHIFT 4
@@ -1968,6 +2050,7 @@ enum {
#define IXGBE_RXDADV_STAT_FCSTAT_NODDP 0x00000010 /* 01: Ctxt w/o DDP */
#define IXGBE_RXDADV_STAT_FCSTAT_FCPRSP 0x00000020 /* 10: Recv. FCP_RSP */
#define IXGBE_RXDADV_STAT_FCSTAT_DDP 0x00000030 /* 11: Ctxt w/ DDP */
+#define IXGBE_RXDADV_STAT_TS 0x00010000 /* IEEE 1588 Time Stamp */
/* PSRTYPE bit definitions */
#define IXGBE_PSRTYPE_TCPHDR 0x00000010
@@ -2245,6 +2328,7 @@ struct ixgbe_adv_tx_context_desc {
/* Adv Transmit Descriptor Config Masks */
#define IXGBE_ADVTXD_DTALEN_MASK 0x0000FFFF /* Data buf length(bytes) */
#define IXGBE_ADVTXD_MAC_LINKSEC 0x00040000 /* Insert LinkSec */
+#define IXGBE_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE 1588 Time Stamp */
#define IXGBE_ADVTXD_IPSEC_SA_INDEX_MASK 0x000003FF /* IPSec SA index */
#define IXGBE_ADVTXD_IPSEC_ESP_LEN_MASK 0x000001FF /* IPSec ESP length */
#define IXGBE_ADVTXD_DTYP_MASK 0x00F00000 /* DTYP mask */
@@ -2533,9 +2617,6 @@ enum ixgbe_fc_mode {
ixgbe_fc_rx_pause,
ixgbe_fc_tx_pause,
ixgbe_fc_full,
-#ifdef CONFIG_DCB
- ixgbe_fc_pfc,
-#endif
ixgbe_fc_default
};
@@ -2768,10 +2849,12 @@ struct ixgbe_mac_operations {
void (*set_vlan_anti_spoofing)(struct ixgbe_hw *, bool, int);
/* Flow Control */
- s32 (*fc_enable)(struct ixgbe_hw *, s32);
+ s32 (*fc_enable)(struct ixgbe_hw *);
/* Manageability interface */
s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8);
+ s32 (*get_thermal_sensor_data)(struct ixgbe_hw *);
+ s32 (*init_thermal_sensor_thresh)(struct ixgbe_hw *hw);
};
struct ixgbe_phy_operations {
@@ -2813,6 +2896,7 @@ struct ixgbe_mac_info {
u16 wwnn_prefix;
/* prefix for World Wide Port Name (WWPN) */
u16 wwpn_prefix;
+ u16 max_msix_vectors;
#define IXGBE_MAX_MTA 128
u32 mta_shadow[IXGBE_MAX_MTA];
s32 mc_filter_type;
@@ -2823,12 +2907,12 @@ struct ixgbe_mac_info {
u32 rx_pb_size;
u32 max_tx_queues;
u32 max_rx_queues;
- u32 max_msix_vectors;
u32 orig_autoc;
u32 orig_autoc2;
bool orig_link_settings_stored;
bool autotry_restart;
u8 flags;
+ struct ixgbe_thermal_sensor_data thermal_sensor_data;
};
struct ixgbe_phy_info {
@@ -2938,7 +3022,6 @@ struct ixgbe_info {
#define IXGBE_ERR_OVERTEMP -26
#define IXGBE_ERR_FC_NOT_NEGOTIATED -27
#define IXGBE_ERR_FC_NOT_SUPPORTED -28
-#define IXGBE_ERR_FLOW_CONTROL -29
#define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE -30
#define IXGBE_ERR_PBA_SECTION -31
#define IXGBE_ERR_INVALID_ARGUMENT -32
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index 97a991403bbd..f90ec078ece2 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -849,6 +849,8 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
.release_swfw_sync = &ixgbe_release_swfw_sync_X540,
.disable_rx_buff = &ixgbe_disable_rx_buff_generic,
.enable_rx_buff = &ixgbe_enable_rx_buff_generic,
+ .get_thermal_sensor_data = NULL,
+ .init_thermal_sensor_thresh = NULL,
};
static struct ixgbe_eeprom_operations eeprom_ops_X540 = {
diff --git a/drivers/net/ethernet/intel/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h
index 947b5c830735..e09a6cc633bb 100644
--- a/drivers/net/ethernet/intel/ixgbevf/defines.h
+++ b/drivers/net/ethernet/intel/ixgbevf/defines.h
@@ -40,6 +40,7 @@
typedef u32 ixgbe_link_speed;
#define IXGBE_LINK_SPEED_1GB_FULL 0x0020
#define IXGBE_LINK_SPEED_10GB_FULL 0x0080
+#define IXGBE_LINK_SPEED_100_FULL 0x0008
#define IXGBE_CTRL_RST 0x04000000 /* Reset (SW) */
#define IXGBE_RXDCTL_ENABLE 0x02000000 /* Enable specific Rx Queue */
@@ -48,6 +49,7 @@ typedef u32 ixgbe_link_speed;
#define IXGBE_LINKS_SPEED_82599 0x30000000
#define IXGBE_LINKS_SPEED_10G_82599 0x30000000
#define IXGBE_LINKS_SPEED_1G_82599 0x20000000
+#define IXGBE_LINKS_SPEED_100_82599 0x10000000
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
#define IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE 8
diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
index 2bfe0d1d7958..e8dddf572d38 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
@@ -107,10 +107,20 @@ static int ixgbevf_get_settings(struct net_device *netdev,
hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
if (link_up) {
- ethtool_cmd_speed_set(
- ecmd,
- (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ?
- SPEED_10000 : SPEED_1000);
+ __u32 speed = SPEED_10000;
+ switch (link_speed) {
+ case IXGBE_LINK_SPEED_10GB_FULL:
+ speed = SPEED_10000;
+ break;
+ case IXGBE_LINK_SPEED_1GB_FULL:
+ speed = SPEED_1000;
+ break;
+ case IXGBE_LINK_SPEED_100_FULL:
+ speed = SPEED_100;
+ break;
+ }
+
+ ethtool_cmd_speed_set(ecmd, speed);
ecmd->duplex = DUPLEX_FULL;
} else {
ethtool_cmd_speed_set(ecmd, -1);
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index dfed420a1bf6..0a1b99240d43 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -287,7 +287,7 @@ extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops;
extern const char ixgbevf_driver_name[];
extern const char ixgbevf_driver_version[];
-extern int ixgbevf_up(struct ixgbevf_adapter *adapter);
+extern void ixgbevf_up(struct ixgbevf_adapter *adapter);
extern void ixgbevf_down(struct ixgbevf_adapter *adapter);
extern void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter);
extern void ixgbevf_reset(struct ixgbevf_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 307611ae831d..f69ec4288b10 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -57,7 +57,7 @@ const char ixgbevf_driver_name[] = "ixgbevf";
static const char ixgbevf_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
-#define DRV_VERSION "2.2.0-k"
+#define DRV_VERSION "2.6.0-k"
const char ixgbevf_driver_version[] = DRV_VERSION;
static char ixgbevf_copyright[] =
"Copyright (c) 2009 - 2012 Intel Corporation.";
@@ -1608,13 +1608,14 @@ static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter)
adapter->stats.base_vfmprc = adapter->stats.last_vfmprc;
}
-static int ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
+static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct ixgbe_hw *hw = &adapter->hw;
int i, j = 0;
int num_rx_rings = adapter->num_rx_queues;
u32 txdctl, rxdctl;
+ u32 msg[2];
for (i = 0; i < adapter->num_tx_queues; i++) {
j = adapter->tx_ring[i].reg_idx;
@@ -1653,6 +1654,10 @@ static int ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0);
}
+ msg[0] = IXGBE_VF_SET_LPE;
+ msg[1] = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
+ hw->mbx.ops.write_posted(hw, msg, 2);
+
clear_bit(__IXGBEVF_DOWN, &adapter->state);
ixgbevf_napi_enable_all(adapter);
@@ -1667,24 +1672,20 @@ static int ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
adapter->link_check_timeout = jiffies;
mod_timer(&adapter->watchdog_timer, jiffies);
- return 0;
}
-int ixgbevf_up(struct ixgbevf_adapter *adapter)
+void ixgbevf_up(struct ixgbevf_adapter *adapter)
{
- int err;
struct ixgbe_hw *hw = &adapter->hw;
ixgbevf_configure(adapter);
- err = ixgbevf_up_complete(adapter);
+ ixgbevf_up_complete(adapter);
/* clear any pending interrupts, may auto mask */
IXGBE_READ_REG(hw, IXGBE_VTEICR);
ixgbevf_irq_enable(adapter, true, true);
-
- return err;
}
/**
@@ -2673,9 +2674,7 @@ static int ixgbevf_open(struct net_device *netdev)
*/
ixgbevf_map_rings_to_vectors(adapter);
- err = ixgbevf_up_complete(adapter);
- if (err)
- goto err_up;
+ ixgbevf_up_complete(adapter);
/* clear any pending interrupts, may auto mask */
IXGBE_READ_REG(hw, IXGBE_VTEICR);
@@ -2689,7 +2688,6 @@ static int ixgbevf_open(struct net_device *netdev)
err_req_irq:
ixgbevf_down(adapter);
-err_up:
ixgbevf_free_irq(adapter);
err_setup_rx:
ixgbevf_free_all_rx_resources(adapter);
@@ -3196,9 +3194,11 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
/* must set new MTU before calling down or up */
netdev->mtu = new_mtu;
- msg[0] = IXGBE_VF_SET_LPE;
- msg[1] = max_frame;
- hw->mbx.ops.write_posted(hw, msg, 2);
+ if (!netif_running(netdev)) {
+ msg[0] = IXGBE_VF_SET_LPE;
+ msg[1] = max_frame;
+ hw->mbx.ops.write_posted(hw, msg, 2);
+ }
if (netif_running(netdev))
ixgbevf_reinit_locked(adapter);
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index 74be7411242a..ec89b86f7ca4 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -404,11 +404,17 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw,
else
*link_up = false;
- if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
- IXGBE_LINKS_SPEED_10G_82599)
+ switch (links_reg & IXGBE_LINKS_SPEED_82599) {
+ case IXGBE_LINKS_SPEED_10G_82599:
*speed = IXGBE_LINK_SPEED_10GB_FULL;
- else
+ break;
+ case IXGBE_LINKS_SPEED_1G_82599:
*speed = IXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ case IXGBE_LINKS_SPEED_100_82599:
+ *speed = IXGBE_LINK_SPEED_100_FULL;
+ break;
+ }
return 0;
}
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 99cd233266ac..04d901d0ff63 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -1672,6 +1672,7 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops = {
.get_strings = mv643xx_eth_get_strings,
.get_ethtool_stats = mv643xx_eth_get_ethtool_stats,
.get_sset_count = mv643xx_eth_get_sset_count,
+ .get_ts_info = ethtool_op_get_ts_info,
};
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index efec6b60b327..1db023b075a1 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1456,6 +1456,7 @@ static const struct ethtool_ops pxa168_ethtool_ops = {
.set_settings = pxa168_set_settings,
.get_drvinfo = pxa168_get_drvinfo,
.get_link = ethtool_op_get_link,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static const struct net_device_ops pxa168_eth_netdev_ops = {
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 487a6c8bd4ec..cace36f2ab92 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -4825,14 +4825,14 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw)
init_waitqueue_head(&hw->msi_wait);
- sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW);
-
err = request_irq(pdev->irq, sky2_test_intr, 0, DRV_NAME, hw);
if (err) {
dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
return err;
}
+ sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW);
+
sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
sky2_read8(hw, B0_CTST);
diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig
index 1bb93531f1ba..5f027f95cc84 100644
--- a/drivers/net/ethernet/mellanox/mlx4/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig
@@ -11,6 +11,18 @@ config MLX4_EN
This driver supports Mellanox Technologies ConnectX Ethernet
devices.
+config MLX4_EN_DCB
+ bool "Data Center Bridging (DCB) Support"
+ default y
+ depends on MLX4_EN && DCB
+ ---help---
+ Say Y here if you want to use Data Center Bridging (DCB) in the
+ driver.
+ If set to N, will not be able to configure QoS and ratelimit attributes.
+ This flag is depended on the kernel's DCB support.
+
+ If unsure, set to Y
+
config MLX4_CORE
tristate
depends on PCI
diff --git a/drivers/net/ethernet/mellanox/mlx4/Makefile b/drivers/net/ethernet/mellanox/mlx4/Makefile
index 4a40ab967eeb..293127d28b33 100644
--- a/drivers/net/ethernet/mellanox/mlx4/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx4/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_MLX4_EN) += mlx4_en.o
mlx4_en-y := en_main.o en_tx.o en_rx.o en_ethtool.o en_port.o en_cq.o \
en_resources.o en_netdev.o en_selftest.o
+mlx4_en-$(CONFIG_MLX4_EN_DCB) += en_dcb_nl.o
diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c
index 8be20e7ea3d1..06fef5b44f77 100644
--- a/drivers/net/ethernet/mellanox/mlx4/alloc.c
+++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c
@@ -124,9 +124,6 @@ void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
spin_lock(&bitmap->lock);
bitmap_clear(bitmap->table, obj, cnt);
- bitmap->last = min(bitmap->last, obj);
- bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
- & bitmap->mask;
bitmap->avail += cnt;
spin_unlock(&bitmap->lock);
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 773c70ea3f62..1bcead1fa2f6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1254,7 +1254,6 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
u32 reply;
- u32 slave_status = 0;
u8 is_going_down = 0;
int i;
@@ -1274,10 +1273,8 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
}
/*check if we are in the middle of FLR process,
if so return "retry" status to the slave*/
- if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) {
- slave_status = MLX4_DELAY_RESET_SLAVE;
+ if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd)
goto inform_slave_state;
- }
/* write the version in the event field */
reply |= mlx4_comm_get_version();
@@ -1557,7 +1554,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
return 0;
err_resource:
- mlx4_free_resource_tracker(dev);
+ mlx4_free_resource_tracker(dev, RES_TR_FREE_ALL);
err_thread:
flush_workqueue(priv->mfunc.master.comm_wq);
destroy_workqueue(priv->mfunc.master.comm_wq);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
index 00b81272e314..908a460d8db6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
@@ -124,11 +124,7 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
cq->mcq.comp = cq->is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq;
cq->mcq.event = mlx4_en_cq_event;
- if (cq->is_tx) {
- init_timer(&cq->timer);
- cq->timer.function = mlx4_en_poll_tx_cq;
- cq->timer.data = (unsigned long) cq;
- } else {
+ if (!cq->is_tx) {
netif_napi_add(cq->dev, &cq->napi, mlx4_en_poll_rx_cq, 64);
napi_enable(&cq->napi);
}
@@ -151,16 +147,12 @@ void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
{
- struct mlx4_en_dev *mdev = priv->mdev;
-
- if (cq->is_tx)
- del_timer(&cq->timer);
- else {
+ if (!cq->is_tx) {
napi_disable(&cq->napi);
netif_napi_del(&cq->napi);
}
- mlx4_cq_free(mdev->dev, &cq->mcq);
+ mlx4_cq_free(priv->mdev->dev, &cq->mcq);
}
/* Set rx cq moderation parameters */
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
new file mode 100644
index 000000000000..5d36795877cb
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2011 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/dcbnl.h>
+#include <linux/math64.h>
+
+#include "mlx4_en.h"
+
+static int mlx4_en_dcbnl_ieee_getets(struct net_device *dev,
+ struct ieee_ets *ets)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct ieee_ets *my_ets = &priv->ets;
+
+ /* No IEEE PFC settings available */
+ if (!my_ets)
+ return -EINVAL;
+
+ ets->ets_cap = IEEE_8021QAZ_MAX_TCS;
+ ets->cbs = my_ets->cbs;
+ memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
+ memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
+ memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
+
+ return 0;
+}
+
+static int mlx4_en_ets_validate(struct mlx4_en_priv *priv, struct ieee_ets *ets)
+{
+ int i;
+ int total_ets_bw = 0;
+ int has_ets_tc = 0;
+
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+ if (ets->prio_tc[i] > MLX4_EN_NUM_UP) {
+ en_err(priv, "Bad priority in UP <=> TC mapping. TC: %d, UP: %d\n",
+ i, ets->prio_tc[i]);
+ return -EINVAL;
+ }
+
+ switch (ets->tc_tsa[i]) {
+ case IEEE_8021QAZ_TSA_STRICT:
+ break;
+ case IEEE_8021QAZ_TSA_ETS:
+ has_ets_tc = 1;
+ total_ets_bw += ets->tc_tx_bw[i];
+ break;
+ default:
+ en_err(priv, "TC[%d]: Not supported TSA: %d\n",
+ i, ets->tc_tsa[i]);
+ return -ENOTSUPP;
+ }
+ }
+
+ if (has_ets_tc && total_ets_bw != MLX4_EN_BW_MAX) {
+ en_err(priv, "Bad ETS BW sum: %d. Should be exactly 100%%\n",
+ total_ets_bw);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mlx4_en_config_port_scheduler(struct mlx4_en_priv *priv,
+ struct ieee_ets *ets, u16 *ratelimit)
+{
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int num_strict = 0;
+ int i;
+ __u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS] = { 0 };
+ __u8 pg[IEEE_8021QAZ_MAX_TCS] = { 0 };
+
+ ets = ets ?: &priv->ets;
+ ratelimit = ratelimit ?: priv->maxrate;
+
+ /* higher TC means higher priority => lower pg */
+ for (i = IEEE_8021QAZ_MAX_TCS - 1; i >= 0; i--) {
+ switch (ets->tc_tsa[i]) {
+ case IEEE_8021QAZ_TSA_STRICT:
+ pg[i] = num_strict++;
+ tc_tx_bw[i] = MLX4_EN_BW_MAX;
+ break;
+ case IEEE_8021QAZ_TSA_ETS:
+ pg[i] = MLX4_EN_TC_ETS;
+ tc_tx_bw[i] = ets->tc_tx_bw[i] ?: MLX4_EN_BW_MIN;
+ break;
+ }
+ }
+
+ return mlx4_SET_PORT_SCHEDULER(mdev->dev, priv->port, tc_tx_bw, pg,
+ ratelimit);
+}
+
+static int
+mlx4_en_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
+
+ err = mlx4_en_ets_validate(priv, ets);
+ if (err)
+ return err;
+
+ err = mlx4_SET_PORT_PRIO2TC(mdev->dev, priv->port, ets->prio_tc);
+ if (err)
+ return err;
+
+ err = mlx4_en_config_port_scheduler(priv, ets, NULL);
+ if (err)
+ return err;
+
+ memcpy(&priv->ets, ets, sizeof(priv->ets));
+
+ return 0;
+}
+
+static int mlx4_en_dcbnl_ieee_getpfc(struct net_device *dev,
+ struct ieee_pfc *pfc)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ pfc->pfc_cap = IEEE_8021QAZ_MAX_TCS;
+ pfc->pfc_en = priv->prof->tx_ppp;
+
+ return 0;
+}
+
+static int mlx4_en_dcbnl_ieee_setpfc(struct net_device *dev,
+ struct ieee_pfc *pfc)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
+
+ en_dbg(DRV, priv, "cap: 0x%x en: 0x%x mbc: 0x%x delay: %d\n",
+ pfc->pfc_cap,
+ pfc->pfc_en,
+ pfc->mbc,
+ pfc->delay);
+
+ priv->prof->rx_pause = priv->prof->tx_pause = !!pfc->pfc_en;
+ priv->prof->rx_ppp = priv->prof->tx_ppp = pfc->pfc_en;
+
+ err = mlx4_SET_PORT_general(mdev->dev, priv->port,
+ priv->rx_skb_size + ETH_FCS_LEN,
+ priv->prof->tx_pause,
+ priv->prof->tx_ppp,
+ priv->prof->rx_pause,
+ priv->prof->rx_ppp);
+ if (err)
+ en_err(priv, "Failed setting pause params\n");
+
+ return err;
+}
+
+static u8 mlx4_en_dcbnl_getdcbx(struct net_device *dev)
+{
+ return DCB_CAP_DCBX_VER_IEEE;
+}
+
+static u8 mlx4_en_dcbnl_setdcbx(struct net_device *dev, u8 mode)
+{
+ if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
+ (mode & DCB_CAP_DCBX_VER_CEE) ||
+ !(mode & DCB_CAP_DCBX_VER_IEEE) ||
+ !(mode & DCB_CAP_DCBX_HOST))
+ return 1;
+
+ return 0;
+}
+
+#define MLX4_RATELIMIT_UNITS_IN_KB 100000 /* rate-limit HW unit in Kbps */
+static int mlx4_en_dcbnl_ieee_getmaxrate(struct net_device *dev,
+ struct ieee_maxrate *maxrate)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int i;
+
+ if (!priv->maxrate)
+ return -EINVAL;
+
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
+ maxrate->tc_maxrate[i] =
+ priv->maxrate[i] * MLX4_RATELIMIT_UNITS_IN_KB;
+
+ return 0;
+}
+
+static int mlx4_en_dcbnl_ieee_setmaxrate(struct net_device *dev,
+ struct ieee_maxrate *maxrate)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ u16 tmp[IEEE_8021QAZ_MAX_TCS];
+ int i, err;
+
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+ /* Convert from Kbps into HW units, rounding result up.
+ * Setting to 0, means unlimited BW.
+ */
+ tmp[i] = div_u64(maxrate->tc_maxrate[i] +
+ MLX4_RATELIMIT_UNITS_IN_KB - 1,
+ MLX4_RATELIMIT_UNITS_IN_KB);
+ }
+
+ err = mlx4_en_config_port_scheduler(priv, NULL, tmp);
+ if (err)
+ return err;
+
+ memcpy(priv->maxrate, tmp, sizeof(*priv->maxrate));
+
+ return 0;
+}
+
+const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops = {
+ .ieee_getets = mlx4_en_dcbnl_ieee_getets,
+ .ieee_setets = mlx4_en_dcbnl_ieee_setets,
+ .ieee_getmaxrate = mlx4_en_dcbnl_ieee_getmaxrate,
+ .ieee_setmaxrate = mlx4_en_dcbnl_ieee_setmaxrate,
+ .ieee_getpfc = mlx4_en_dcbnl_ieee_getpfc,
+ .ieee_setpfc = mlx4_en_dcbnl_ieee_setpfc,
+
+ .getdcbx = mlx4_en_dcbnl_getdcbx,
+ .setdcbx = mlx4_en_dcbnl_setdcbx,
+};
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 70346fd7f9c4..72901ce2b088 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -83,7 +83,7 @@ static const char main_strings[][ETH_GSTRING_LEN] = {
#define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS)
static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
- "Interupt Test",
+ "Interrupt Test",
"Link Test",
"Speed Test",
"Register Test",
@@ -359,8 +359,8 @@ static int mlx4_en_get_coalesce(struct net_device *dev,
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- coal->tx_coalesce_usecs = 0;
- coal->tx_max_coalesced_frames = 0;
+ coal->tx_coalesce_usecs = priv->tx_usecs;
+ coal->tx_max_coalesced_frames = priv->tx_frames;
coal->rx_coalesce_usecs = priv->rx_usecs;
coal->rx_max_coalesced_frames = priv->rx_frames;
@@ -388,6 +388,21 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
MLX4_EN_RX_COAL_TIME :
coal->rx_coalesce_usecs;
+ /* Setting TX coalescing parameters */
+ if (coal->tx_coalesce_usecs != priv->tx_usecs ||
+ coal->tx_max_coalesced_frames != priv->tx_frames) {
+ priv->tx_usecs = coal->tx_coalesce_usecs;
+ priv->tx_frames = coal->tx_max_coalesced_frames;
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ priv->tx_cq[i].moder_cnt = priv->tx_frames;
+ priv->tx_cq[i].moder_time = priv->tx_usecs;
+ if (mlx4_en_set_cq_moder(priv, &priv->tx_cq[i])) {
+ en_warn(priv, "Failed changing moderation "
+ "for TX cq %d\n", i);
+ }
+ }
+ }
+
/* Set adaptive coalescing params */
priv->pkt_rate_low = coal->pkt_rate_low;
priv->rx_usecs_low = coal->rx_coalesce_usecs_low;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index 2097a7d3c5b8..988b2424e1c6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -101,6 +101,8 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
int i;
params->udp_rss = udp_rss;
+ params->num_tx_rings_p_up = min_t(int, num_online_cpus(),
+ MLX4_EN_MAX_TX_RING_P_UP);
if (params->udp_rss && !(mdev->dev->caps.flags
& MLX4_DEV_CAP_FLAG_UDP_RSS)) {
mlx4_warn(mdev, "UDP RSS is not supported on this device.\n");
@@ -113,8 +115,8 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
params->prof[i].tx_ppp = pfctx;
params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
- params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS +
- (!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
+ params->prof[i].tx_ring_num = params->num_tx_rings_p_up *
+ MLX4_EN_NUM_UP;
params->prof[i].rss_rings = 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 31b455a49273..926d8aac941c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -45,6 +45,27 @@
#include "mlx4_en.h"
#include "en_port.h"
+static int mlx4_en_setup_tc(struct net_device *dev, u8 up)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int i;
+ unsigned int q, offset = 0;
+
+ if (up && up != MLX4_EN_NUM_UP)
+ return -EINVAL;
+
+ netdev_set_num_tc(dev, up);
+
+ /* Partition Tx queues evenly amongst UP's */
+ q = priv->tx_ring_num / up;
+ for (i = 0; i < up; i++) {
+ netdev_set_tc_queue(dev, i, q, offset);
+ offset += q;
+ }
+
+ return 0;
+}
+
static int mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -421,6 +442,8 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
*/
priv->rx_frames = MLX4_EN_RX_COAL_TARGET;
priv->rx_usecs = MLX4_EN_RX_COAL_TIME;
+ priv->tx_frames = MLX4_EN_TX_COAL_PKTS;
+ priv->tx_usecs = MLX4_EN_TX_COAL_TIME;
en_dbg(INTR, priv, "Default coalesing params for mtu:%d - "
"rx_frames:%d rx_usecs:%d\n",
priv->dev->mtu, priv->rx_frames, priv->rx_usecs);
@@ -437,8 +460,8 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
for (i = 0; i < priv->tx_ring_num; i++) {
cq = &priv->tx_cq[i];
- cq->moder_cnt = MLX4_EN_TX_COAL_PKTS;
- cq->moder_time = MLX4_EN_TX_COAL_TIME;
+ cq->moder_cnt = priv->tx_frames;
+ cq->moder_time = priv->tx_usecs;
}
/* Reset auto-moderation params */
@@ -650,12 +673,18 @@ int mlx4_en_start_port(struct net_device *dev)
/* Configure ring */
tx_ring = &priv->tx_ring[i];
- err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn);
+ err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
+ i / priv->mdev->profile.num_tx_rings_p_up);
if (err) {
en_err(priv, "Failed allocating Tx ring\n");
mlx4_en_deactivate_cq(priv, cq);
goto tx_err;
}
+ tx_ring->tx_queue = netdev_get_tx_queue(dev, i);
+
+ /* Arm CQ for TX completions */
+ mlx4_en_arm_cq(priv, cq);
+
/* Set initial ownership of all Tx TXBBs to SW (1) */
for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
*((u32 *) (tx_ring->buf + j)) = 0xffffffff;
@@ -797,12 +826,15 @@ static void mlx4_en_restart(struct work_struct *work)
watchdog_task);
struct mlx4_en_dev *mdev = priv->mdev;
struct net_device *dev = priv->dev;
+ int i;
en_dbg(DRV, priv, "Watchdog task called for port %d\n", priv->port);
mutex_lock(&mdev->state_lock);
if (priv->port_up) {
mlx4_en_stop_port(dev);
+ for (i = 0; i < priv->tx_ring_num; i++)
+ netdev_tx_reset_queue(priv->tx_ring[i].tx_queue);
if (mlx4_en_start_port(dev))
en_err(priv, "Failed restarting port %d\n", priv->port);
}
@@ -966,6 +998,10 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
mutex_unlock(&mdev->state_lock);
mlx4_en_free_resources(priv);
+
+ kfree(priv->tx_ring);
+ kfree(priv->tx_cq);
+
free_netdev(dev);
}
@@ -1036,6 +1072,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
.ndo_poll_controller = mlx4_en_netpoll,
#endif
.ndo_set_features = mlx4_en_set_features,
+ .ndo_setup_tc = mlx4_en_setup_tc,
};
int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
@@ -1070,6 +1107,18 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
MLX4_WQE_CTRL_SOLICITED);
priv->tx_ring_num = prof->tx_ring_num;
+ priv->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring) *
+ priv->tx_ring_num, GFP_KERNEL);
+ if (!priv->tx_ring) {
+ err = -ENOMEM;
+ goto out;
+ }
+ priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq) * priv->tx_ring_num,
+ GFP_KERNEL);
+ if (!priv->tx_cq) {
+ err = -ENOMEM;
+ goto out;
+ }
priv->rx_ring_num = prof->rx_ring_num;
priv->mac_index = -1;
priv->msg_enable = MLX4_EN_MSG_LEVEL;
@@ -1079,6 +1128,10 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
+#ifdef CONFIG_MLX4_EN_DCB
+ if (!mlx4_is_slave(priv->mdev->dev))
+ dev->dcbnl_ops = &mlx4_en_dcbnl_ops;
+#endif
/* Query for default mac and max mtu */
priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_port.h b/drivers/net/ethernet/mellanox/mlx4/en_port.h
index 6934fd7e66ed..745090b49d9e 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_port.h
+++ b/drivers/net/ethernet/mellanox/mlx4/en_port.h
@@ -39,6 +39,8 @@
#define SET_PORT_PROMISC_SHIFT 31
#define SET_PORT_MC_PROMISC_SHIFT 30
+#define MLX4_EN_NUM_TC 8
+
#define VLAN_FLTR_SIZE 128
struct mlx4_set_vlan_fltr_mbox {
__be32 entry[VLAN_FLTR_SIZE];
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
index bcbc54c16947..10c24c784b70 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
@@ -39,7 +39,7 @@
void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
int is_tx, int rss, int qpn, int cqn,
- struct mlx4_qp_context *context)
+ int user_prio, struct mlx4_qp_context *context)
{
struct mlx4_en_dev *mdev = priv->mdev;
@@ -57,6 +57,10 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
context->local_qpn = cpu_to_be32(qpn);
context->pri_path.ackto = 1 & 0x07;
context->pri_path.sched_queue = 0x83 | (priv->port - 1) << 6;
+ if (user_prio >= 0) {
+ context->pri_path.sched_queue |= user_prio << 3;
+ context->pri_path.feup = 1 << 6;
+ }
context->pri_path.counter_index = 0xff;
context->cqn_send = cpu_to_be32(cqn);
context->cqn_recv = cpu_to_be32(cqn);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 9adbd53da525..d49a7ac3187d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -823,7 +823,7 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
memset(context, 0, sizeof *context);
mlx4_en_fill_qp_context(priv, ring->actual_size, ring->stride, 0, 0,
- qpn, ring->cqn, context);
+ qpn, ring->cqn, -1, context);
context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma);
/* Cancel FCS removal if FW allows */
@@ -890,7 +890,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
}
rss_map->indir_qp.event = mlx4_en_sqp_event;
mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
- priv->rx_ring[0].cqn, &context);
+ priv->rx_ring[0].cqn, -1, &context);
if (!priv->prof->rss_rings || priv->prof->rss_rings > priv->rx_ring_num)
rss_rings = priv->rx_ring_num;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 17968244c399..019d856b1334 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -67,8 +67,6 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
inline_thold = min(inline_thold, MAX_INLINE);
- spin_lock_init(&ring->comp_lock);
-
tmp = size * sizeof(struct mlx4_en_tx_info);
ring->tx_info = vmalloc(tmp);
if (!ring->tx_info)
@@ -156,7 +154,7 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring,
- int cq)
+ int cq, int user_prio)
{
struct mlx4_en_dev *mdev = priv->mdev;
int err;
@@ -174,7 +172,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
ring->doorbell_qpn = ring->qp.qpn << 8;
mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
- ring->cqn, &ring->context);
+ ring->cqn, user_prio, &ring->context);
if (ring->bf_enabled)
ring->context.usr_page = cpu_to_be32(ring->bf.uar->index);
@@ -317,6 +315,8 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
int size = cq->size;
u32 size_mask = ring->size_mask;
struct mlx4_cqe *buf = cq->buf;
+ u32 packets = 0;
+ u32 bytes = 0;
if (!priv->port_up)
return;
@@ -345,6 +345,8 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
priv, ring, ring_index,
!!((ring->cons + txbbs_skipped) &
ring->size));
+ packets++;
+ bytes += ring->tx_info[ring_index].nr_bytes;
} while (ring_index != new_index);
++cons_index;
@@ -361,13 +363,14 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
mlx4_cq_set_ci(mcq);
wmb();
ring->cons += txbbs_skipped;
+ netdev_tx_completed_queue(ring->tx_queue, packets, bytes);
/* Wakeup Tx queue if this ring stopped it */
if (unlikely(ring->blocked)) {
if ((u32) (ring->prod - ring->cons) <=
ring->size - HEADROOM - MAX_DESC_TXBBS) {
ring->blocked = 0;
- netif_tx_wake_queue(netdev_get_tx_queue(dev, cq->ring));
+ netif_tx_wake_queue(ring->tx_queue);
priv->port_stats.wake_queue++;
}
}
@@ -377,41 +380,12 @@ void mlx4_en_tx_irq(struct mlx4_cq *mcq)
{
struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq);
struct mlx4_en_priv *priv = netdev_priv(cq->dev);
- struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring];
- if (!spin_trylock(&ring->comp_lock))
- return;
mlx4_en_process_tx_cq(cq->dev, cq);
- mod_timer(&cq->timer, jiffies + 1);
- spin_unlock(&ring->comp_lock);
+ mlx4_en_arm_cq(priv, cq);
}
-void mlx4_en_poll_tx_cq(unsigned long data)
-{
- struct mlx4_en_cq *cq = (struct mlx4_en_cq *) data;
- struct mlx4_en_priv *priv = netdev_priv(cq->dev);
- struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring];
- u32 inflight;
-
- INC_PERF_COUNTER(priv->pstats.tx_poll);
-
- if (!spin_trylock_irq(&ring->comp_lock)) {
- mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT);
- return;
- }
- mlx4_en_process_tx_cq(cq->dev, cq);
- inflight = (u32) (ring->prod - ring->cons - ring->last_nr_txbb);
-
- /* If there are still packets in flight and the timer has not already
- * been scheduled by the Tx routine then schedule it here to guarantee
- * completion processing of these packets */
- if (inflight && priv->port_up)
- mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT);
-
- spin_unlock_irq(&ring->comp_lock);
-}
-
static struct mlx4_en_tx_desc *mlx4_en_bounce_to_desc(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring,
u32 index,
@@ -440,25 +414,6 @@ static struct mlx4_en_tx_desc *mlx4_en_bounce_to_desc(struct mlx4_en_priv *priv,
return ring->buf + index * TXBB_SIZE;
}
-static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
-{
- struct mlx4_en_cq *cq = &priv->tx_cq[tx_ind];
- struct mlx4_en_tx_ring *ring = &priv->tx_ring[tx_ind];
- unsigned long flags;
-
- /* If we don't have a pending timer, set one up to catch our recent
- post in case the interface becomes idle */
- if (!timer_pending(&cq->timer))
- mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT);
-
- /* Poll the CQ every mlx4_en_TX_MODER_POLL packets */
- if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0)
- if (spin_trylock_irqsave(&ring->comp_lock, flags)) {
- mlx4_en_process_tx_cq(priv->dev, cq);
- spin_unlock_irqrestore(&ring->comp_lock, flags);
- }
-}
-
static int is_inline(struct sk_buff *skb, void **pfrag)
{
void *ptr;
@@ -571,17 +526,16 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- u16 vlan_tag = 0;
+ u16 rings_p_up = priv->mdev->profile.num_tx_rings_p_up;
+ u8 up = 0;
- /* If we support per priority flow control and the packet contains
- * a vlan tag, send the packet to the TX ring assigned to that priority
- */
- if (priv->prof->rx_ppp && vlan_tx_tag_present(skb)) {
- vlan_tag = vlan_tx_tag_get(skb);
- return MLX4_EN_NUM_TX_RINGS + (vlan_tag >> 13);
- }
+ if (dev->num_tc)
+ return skb_tx_hash(dev, skb);
- return skb_tx_hash(dev, skb);
+ if (vlan_tx_tag_present(skb))
+ up = vlan_tx_tag_get(skb) >> VLAN_PRIO_SHIFT;
+
+ return __skb_tx_hash(dev, skb, rings_p_up) + up * rings_p_up;
}
static void mlx4_bf_copy(void __iomem *dst, unsigned long *src, unsigned bytecnt)
@@ -594,7 +548,6 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_en_tx_ring *ring;
- struct mlx4_en_cq *cq;
struct mlx4_en_tx_desc *tx_desc;
struct mlx4_wqe_data_seg *data;
struct skb_frag_struct *frag;
@@ -638,13 +591,10 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(((int)(ring->prod - ring->cons)) >
ring->size - HEADROOM - MAX_DESC_TXBBS)) {
/* every full Tx ring stops queue */
- netif_tx_stop_queue(netdev_get_tx_queue(dev, tx_ind));
+ netif_tx_stop_queue(ring->tx_queue);
ring->blocked = 1;
priv->port_stats.queue_stopped++;
- /* Use interrupts to find out when queue opened */
- cq = &priv->tx_cq[tx_ind];
- mlx4_en_arm_cq(priv, cq);
return NETDEV_TX_BUSY;
}
@@ -707,7 +657,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
priv->port_stats.tso_packets++;
i = ((skb->len - lso_header_size) / skb_shinfo(skb)->gso_size) +
!!((skb->len - lso_header_size) % skb_shinfo(skb)->gso_size);
- ring->bytes += skb->len + (i - 1) * lso_header_size;
+ tx_info->nr_bytes = skb->len + (i - 1) * lso_header_size;
ring->packets += i;
} else {
/* Normal (Non LSO) packet */
@@ -715,10 +665,12 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
((ring->prod & ring->size) ?
cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0);
data = &tx_desc->data;
- ring->bytes += max(skb->len, (unsigned int) ETH_ZLEN);
+ tx_info->nr_bytes = max_t(unsigned int, skb->len, ETH_ZLEN);
ring->packets++;
}
+ ring->bytes += tx_info->nr_bytes;
+ netdev_tx_sent_queue(ring->tx_queue, tx_info->nr_bytes);
AVG_PERF_COUNTER(priv->pstats.tx_pktsz_avg, skb->len);
@@ -792,9 +744,6 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
iowrite32be(ring->doorbell_qpn, ring->bf.uar->map + MLX4_SEND_DOORBELL);
}
- /* Poll CQ here */
- mlx4_en_xmit_poll(priv, tx_ind);
-
return NETDEV_TX_OK;
tx_drop:
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 2a02ba522e60..68f5cd6cb3c7 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -118,6 +118,20 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags)
mlx4_dbg(dev, " %s\n", fname[i]);
}
+static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
+{
+ static const char * const fname[] = {
+ [0] = "RSS support",
+ [1] = "RSS Toeplitz Hash Function support",
+ [2] = "RSS XOR Hash Function support"
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(fname); ++i)
+ if (fname[i] && (flags & (1LL << i)))
+ mlx4_dbg(dev, " %s\n", fname[i]);
+}
+
int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg)
{
struct mlx4_cmd_mailbox *mailbox;
@@ -346,6 +360,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET 0x29
#define QUERY_DEV_CAP_MAX_RES_QP_OFFSET 0x2b
#define QUERY_DEV_CAP_MAX_GSO_OFFSET 0x2d
+#define QUERY_DEV_CAP_RSS_OFFSET 0x2e
#define QUERY_DEV_CAP_MAX_RDMA_OFFSET 0x2f
#define QUERY_DEV_CAP_RSZ_SRQ_OFFSET 0x33
#define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35
@@ -390,6 +405,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98
#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0
+ dev_cap->flags2 = 0;
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
@@ -439,6 +455,17 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
else
dev_cap->max_gso_sz = 1 << field;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_RSS_OFFSET);
+ if (field & 0x20)
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_XOR;
+ if (field & 0x10)
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS_TOP;
+ field &= 0xf;
+ if (field) {
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RSS;
+ dev_cap->max_rss_tbl_sz = 1 << field;
+ } else
+ dev_cap->max_rss_tbl_sz = 0;
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET);
dev_cap->max_rdma_global = 1 << (field & 0x3f);
MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET);
@@ -632,8 +659,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg);
mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz);
mlx4_dbg(dev, "Max counters: %d\n", dev_cap->max_counters);
+ mlx4_dbg(dev, "Max RSS Table size: %d\n", dev_cap->max_rss_tbl_sz);
dump_dev_cap_flags(dev, dev_cap->flags);
+ dump_dev_cap_flags2(dev, dev_cap->flags2);
out:
mlx4_free_cmd_mailbox(dev, mailbox);
@@ -1164,9 +1193,8 @@ int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
if (err)
return err;
- priv->mfunc.master.slave_state[slave].init_port_mask |=
- (1 << port);
}
+ priv->mfunc.master.slave_state[slave].init_port_mask |= (1 << port);
++priv->mfunc.master.init_port_ref[port];
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h
index e1a5fa56bcbc..64c0399e4b78 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.h
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.h
@@ -79,6 +79,7 @@ struct mlx4_dev_cap {
u64 trans_code[MLX4_MAX_PORTS + 1];
u16 stat_rate_support;
u64 flags;
+ u64 flags2;
int reserved_uars;
int uar_size;
int min_page_sz;
@@ -110,6 +111,7 @@ struct mlx4_dev_cap {
u32 reserved_lkey;
u64 max_icm_sz;
int max_gso_sz;
+ int max_rss_tbl_sz;
u8 supported_port_types[MLX4_MAX_PORTS + 1];
u8 suggested_type[MLX4_MAX_PORTS + 1];
u8 default_sense[MLX4_MAX_PORTS + 1];
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 8bb05b46db86..2e024a68fa81 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -272,10 +272,12 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.max_msg_sz = dev_cap->max_msg_sz;
dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1);
dev->caps.flags = dev_cap->flags;
+ dev->caps.flags2 = dev_cap->flags2;
dev->caps.bmme_flags = dev_cap->bmme_flags;
dev->caps.reserved_lkey = dev_cap->reserved_lkey;
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
+ dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz;
/* Sense port always allowed on supported devices for ConnectX1 and 2 */
if (dev->pdev->device != 0x1003)
@@ -1306,7 +1308,7 @@ static void mlx4_cleanup_counters_table(struct mlx4_dev *dev)
mlx4_bitmap_cleanup(&mlx4_priv(dev)->counters_bitmap);
}
-int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
+int __mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -1319,13 +1321,44 @@ int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
return 0;
}
+
+int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
+{
+ u64 out_param;
+ int err;
+
+ if (mlx4_is_mfunc(dev)) {
+ err = mlx4_cmd_imm(dev, 0, &out_param, RES_COUNTER,
+ RES_OP_RESERVE, MLX4_CMD_ALLOC_RES,
+ MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+ if (!err)
+ *idx = get_param_l(&out_param);
+
+ return err;
+ }
+ return __mlx4_counter_alloc(dev, idx);
+}
EXPORT_SYMBOL_GPL(mlx4_counter_alloc);
-void mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
+void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
{
mlx4_bitmap_free(&mlx4_priv(dev)->counters_bitmap, idx);
return;
}
+
+void mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
+{
+ u64 in_param;
+
+ if (mlx4_is_mfunc(dev)) {
+ set_param_l(&in_param, idx);
+ mlx4_cmd(dev, in_param, RES_COUNTER, RES_OP_RESERVE,
+ MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A,
+ MLX4_CMD_WRAPPED);
+ return;
+ }
+ __mlx4_counter_free(dev, idx);
+}
EXPORT_SYMBOL_GPL(mlx4_counter_free);
static int mlx4_setup_hca(struct mlx4_dev *dev)
@@ -1865,7 +1898,6 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
mlx4_err(dev, "Failed to enable sriov,"
"continuing without sriov enabled"
" (err = %d).\n", err);
- num_vfs = 0;
err = 0;
} else {
mlx4_warn(dev, "Running in master mode\n");
@@ -2022,7 +2054,7 @@ err_cmd:
mlx4_cmd_cleanup(dev);
err_sriov:
- if (num_vfs && (dev->flags & MLX4_FLAG_SRIOV))
+ if (dev->flags & MLX4_FLAG_SRIOV)
pci_disable_sriov(pdev);
err_rel_own:
@@ -2070,6 +2102,10 @@ static void mlx4_remove_one(struct pci_dev *pdev)
mlx4_CLOSE_PORT(dev, p);
}
+ if (mlx4_is_master(dev))
+ mlx4_free_resource_tracker(dev,
+ RES_TR_FREE_SLAVES_ONLY);
+
mlx4_cleanup_counters_table(dev);
mlx4_cleanup_mcg_table(dev);
mlx4_cleanup_qp_table(dev);
@@ -2082,7 +2118,8 @@ static void mlx4_remove_one(struct pci_dev *pdev)
mlx4_cleanup_pd_table(dev);
if (mlx4_is_master(dev))
- mlx4_free_resource_tracker(dev);
+ mlx4_free_resource_tracker(dev,
+ RES_TR_FREE_STRUCTS_ONLY);
iounmap(priv->kar);
mlx4_uar_free(dev, &priv->driver_uar);
@@ -2099,7 +2136,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
if (dev->flags & MLX4_FLAG_MSI_X)
pci_disable_msix(pdev);
- if (num_vfs && (dev->flags & MLX4_FLAG_SRIOV)) {
+ if (dev->flags & MLX4_FLAG_SRIOV) {
mlx4_warn(dev, "Disabling sriov\n");
pci_disable_sriov(pdev);
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c
index 4799e824052f..f4a8f98e402a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mcg.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c
@@ -357,7 +357,6 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
u32 prot;
int i;
bool found;
- int last_index;
int err;
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -419,7 +418,6 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
if (err)
goto out_mailbox;
}
- last_index = entry->index;
}
/* add the new qpn to list of promisc qps */
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 2a0ff2cc7182..86b6e5a2fabf 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -53,6 +53,26 @@
#define DRV_VERSION "1.1"
#define DRV_RELDATE "Dec, 2011"
+#define MLX4_NUM_UP 8
+#define MLX4_NUM_TC 8
+#define MLX4_RATELIMIT_UNITS 3 /* 100 Mbps */
+#define MLX4_RATELIMIT_DEFAULT 0xffff
+
+struct mlx4_set_port_prio2tc_context {
+ u8 prio2tc[4];
+};
+
+struct mlx4_port_scheduler_tc_cfg_be {
+ __be16 pg;
+ __be16 bw_precentage;
+ __be16 max_bw_units; /* 3-100Mbps, 4-1Gbps, other values - reserved */
+ __be16 max_bw_value;
+};
+
+struct mlx4_set_port_scheduler_context {
+ struct mlx4_port_scheduler_tc_cfg_be tc[MLX4_NUM_TC];
+};
+
enum {
MLX4_HCR_BASE = 0x80680,
MLX4_HCR_SIZE = 0x0001c,
@@ -126,6 +146,11 @@ enum mlx4_alloc_mode {
RES_OP_MAP_ICM,
};
+enum mlx4_res_tracker_free_type {
+ RES_TR_FREE_ALL,
+ RES_TR_FREE_SLAVES_ONLY,
+ RES_TR_FREE_STRUCTS_ONLY,
+};
/*
*Virtual HCR structures.
@@ -851,6 +876,10 @@ void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac);
int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac);
int __mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
int start_index, int npages, u64 *page_list);
+int __mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx);
+void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx);
+int __mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn);
+void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn);
void mlx4_start_catas_poll(struct mlx4_dev *dev);
void mlx4_stop_catas_poll(struct mlx4_dev *dev);
@@ -1007,7 +1036,8 @@ int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev,
void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave_id);
int mlx4_init_resource_tracker(struct mlx4_dev *dev);
-void mlx4_free_resource_tracker(struct mlx4_dev *dev);
+void mlx4_free_resource_tracker(struct mlx4_dev *dev,
+ enum mlx4_res_tracker_free_type type);
int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index d69fee41f24a..6ae350921b1a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -40,6 +40,9 @@
#include <linux/mutex.h>
#include <linux/netdevice.h>
#include <linux/if_vlan.h>
+#ifdef CONFIG_MLX4_EN_DCB
+#include <linux/dcbnl.h>
+#endif
#include <linux/mlx4/device.h>
#include <linux/mlx4/qp.h>
@@ -108,9 +111,8 @@ enum {
#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE)
#define MLX4_EN_SMALL_PKT_SIZE 64
-#define MLX4_EN_NUM_TX_RINGS 8
-#define MLX4_EN_NUM_PPP_RINGS 8
-#define MAX_TX_RINGS (MLX4_EN_NUM_TX_RINGS + MLX4_EN_NUM_PPP_RINGS)
+#define MLX4_EN_MAX_TX_RING_P_UP 32
+#define MLX4_EN_NUM_UP 8
#define MLX4_EN_DEF_TX_RING_SIZE 512
#define MLX4_EN_DEF_RX_RING_SIZE 1024
@@ -118,7 +120,7 @@ enum {
#define MLX4_EN_RX_COAL_TARGET 44
#define MLX4_EN_RX_COAL_TIME 0x10
-#define MLX4_EN_TX_COAL_PKTS 5
+#define MLX4_EN_TX_COAL_PKTS 16
#define MLX4_EN_TX_COAL_TIME 0x80
#define MLX4_EN_RX_RATE_LOW 400000
@@ -196,6 +198,7 @@ enum cq_type {
struct mlx4_en_tx_info {
struct sk_buff *skb;
u32 nr_txbb;
+ u32 nr_bytes;
u8 linear;
u8 data_offset;
u8 inl;
@@ -251,9 +254,9 @@ struct mlx4_en_tx_ring {
unsigned long bytes;
unsigned long packets;
unsigned long tx_csum;
- spinlock_t comp_lock;
struct mlx4_bf bf;
bool bf_enabled;
+ struct netdev_queue *tx_queue;
};
struct mlx4_en_rx_desc {
@@ -304,8 +307,6 @@ struct mlx4_en_cq {
spinlock_t lock;
struct net_device *dev;
struct napi_struct napi;
- /* Per-core Tx cq processing support */
- struct timer_list timer;
int size;
int buf_size;
unsigned vector;
@@ -336,6 +337,7 @@ struct mlx4_en_profile {
u32 active_ports;
u32 small_pkt_int;
u8 no_reset;
+ u8 num_tx_rings_p_up;
struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1];
};
@@ -411,6 +413,15 @@ struct mlx4_en_frag_info {
};
+#ifdef CONFIG_MLX4_EN_DCB
+/* Minimal TC BW - setting to 0 will block traffic */
+#define MLX4_EN_BW_MIN 1
+#define MLX4_EN_BW_MAX 100 /* Utilize 100% of the line */
+
+#define MLX4_EN_TC_ETS 7
+
+#endif
+
struct mlx4_en_priv {
struct mlx4_en_dev *mdev;
struct mlx4_en_port_profile *prof;
@@ -465,9 +476,9 @@ struct mlx4_en_priv {
u16 num_frags;
u16 log_rx_info;
- struct mlx4_en_tx_ring tx_ring[MAX_TX_RINGS];
+ struct mlx4_en_tx_ring *tx_ring;
struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS];
- struct mlx4_en_cq tx_cq[MAX_TX_RINGS];
+ struct mlx4_en_cq *tx_cq;
struct mlx4_en_cq rx_cq[MAX_RX_RINGS];
struct work_struct mcast_task;
struct work_struct mac_task;
@@ -484,6 +495,11 @@ struct mlx4_en_priv {
int vids[128];
bool wol;
struct device *ddev;
+
+#ifdef CONFIG_MLX4_EN_DCB
+ struct ieee_ets ets;
+ u16 maxrate[IEEE_8021QAZ_MAX_TCS];
+#endif
};
enum mlx4_en_wol {
@@ -512,7 +528,6 @@ void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
-void mlx4_en_poll_tx_cq(unsigned long data);
void mlx4_en_tx_irq(struct mlx4_cq *mcq);
u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb);
netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -522,7 +537,7 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ri
void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring);
int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring,
- int cq);
+ int cq, int user_prio);
void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring);
@@ -540,8 +555,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev,
int budget);
int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget);
void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
- int is_tx, int rss, int qpn, int cqn,
- struct mlx4_qp_context *context);
+ int is_tx, int rss, int qpn, int cqn, int user_prio,
+ struct mlx4_qp_context *context);
void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event);
int mlx4_en_map_buffer(struct mlx4_buf *buf);
void mlx4_en_unmap_buffer(struct mlx4_buf *buf);
@@ -558,6 +573,10 @@ int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv);
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
+#ifdef CONFIG_MLX4_EN_DCB
+extern const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops;
+#endif
+
#define MLX4_EN_NUM_SELF_TEST 5
void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf);
u64 mlx4_en_mac_to_u64(u8 *addr);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c
index fe2ac8449c19..af55b7ce5341 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mr.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mr.c
@@ -788,7 +788,6 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages,
int max_maps, u8 page_shift, struct mlx4_fmr *fmr)
{
struct mlx4_priv *priv = mlx4_priv(dev);
- u64 mtt_offset;
int err = -ENOMEM;
if (max_maps > dev->caps.max_fmr_maps)
@@ -811,8 +810,6 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages,
if (err)
return err;
- mtt_offset = fmr->mr.mtt.offset * dev->caps.mtt_entry_sz;
-
fmr->mtts = mlx4_table_find(&priv->mr_table.mtt_table,
fmr->mr.mtt.offset,
&fmr->dma_handle);
@@ -895,6 +892,6 @@ EXPORT_SYMBOL_GPL(mlx4_fmr_free);
int mlx4_SYNC_TPT(struct mlx4_dev *dev)
{
return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_SYNC_TPT, 1000,
- MLX4_CMD_WRAPPED);
+ MLX4_CMD_NATIVE);
}
EXPORT_SYMBOL_GPL(mlx4_SYNC_TPT);
diff --git a/drivers/net/ethernet/mellanox/mlx4/pd.c b/drivers/net/ethernet/mellanox/mlx4/pd.c
index db4746d0dca7..1ac88637ad9d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/pd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/pd.c
@@ -63,7 +63,7 @@ void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn)
}
EXPORT_SYMBOL_GPL(mlx4_pd_free);
-int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
+int __mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -73,12 +73,47 @@ int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
return 0;
}
+
+int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
+{
+ u64 out_param;
+ int err;
+
+ if (mlx4_is_mfunc(dev)) {
+ err = mlx4_cmd_imm(dev, 0, &out_param,
+ RES_XRCD, RES_OP_RESERVE,
+ MLX4_CMD_ALLOC_RES,
+ MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+ if (err)
+ return err;
+
+ *xrcdn = get_param_l(&out_param);
+ return 0;
+ }
+ return __mlx4_xrcd_alloc(dev, xrcdn);
+}
EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc);
-void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
+void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
{
mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn);
}
+
+void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
+{
+ u64 in_param;
+ int err;
+
+ if (mlx4_is_mfunc(dev)) {
+ set_param_l(&in_param, xrcdn);
+ err = mlx4_cmd(dev, in_param, RES_XRCD,
+ RES_OP_RESERVE, MLX4_CMD_FREE_RES,
+ MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+ if (err)
+ mlx4_warn(dev, "Failed to release xrcdn %d\n", xrcdn);
+ } else
+ __mlx4_xrcd_free(dev, xrcdn);
+}
EXPORT_SYMBOL_GPL(mlx4_xrcd_free);
int mlx4_init_pd_table(struct mlx4_dev *dev)
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index 77535ff18f1b..1fe2c7a8b40c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -338,13 +338,12 @@ EXPORT_SYMBOL_GPL(__mlx4_unregister_mac);
void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
{
u64 out_param;
- int err;
if (mlx4_is_mfunc(dev)) {
set_param_l(&out_param, port);
- err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
- RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+ (void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
+ RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
+ MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
return;
}
__mlx4_unregister_mac(dev, port, mac);
@@ -834,6 +833,68 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
}
EXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc);
+int mlx4_SET_PORT_PRIO2TC(struct mlx4_dev *dev, u8 port, u8 *prio2tc)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_set_port_prio2tc_context *context;
+ int err;
+ u32 in_mod;
+ int i;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ context = mailbox->buf;
+ memset(context, 0, sizeof *context);
+
+ for (i = 0; i < MLX4_NUM_UP; i += 2)
+ context->prio2tc[i >> 1] = prio2tc[i] << 4 | prio2tc[i + 1];
+
+ in_mod = MLX4_SET_PORT_PRIO2TC << 8 | port;
+ err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+EXPORT_SYMBOL(mlx4_SET_PORT_PRIO2TC);
+
+int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw,
+ u8 *pg, u16 *ratelimit)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_set_port_scheduler_context *context;
+ int err;
+ u32 in_mod;
+ int i;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ context = mailbox->buf;
+ memset(context, 0, sizeof *context);
+
+ for (i = 0; i < MLX4_NUM_TC; i++) {
+ struct mlx4_port_scheduler_tc_cfg_be *tc = &context->tc[i];
+ u16 r = ratelimit && ratelimit[i] ? ratelimit[i] :
+ MLX4_RATELIMIT_DEFAULT;
+
+ tc->pg = htons(pg[i]);
+ tc->bw_precentage = htons(tc_tx_bw[i]);
+
+ tc->max_bw_units = htons(MLX4_RATELIMIT_UNITS);
+ tc->max_bw_value = htons(r);
+ }
+
+ in_mod = MLX4_SET_PORT_SCHEDULER << 8 | port;
+ err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
+ MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+EXPORT_SYMBOL(mlx4_SET_PORT_SCHEDULER);
+
int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 8752e6e08169..b45d0e7f6ab0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -89,17 +89,6 @@ enum res_qp_states {
RES_QP_HW
};
-static inline const char *qp_states_str(enum res_qp_states state)
-{
- switch (state) {
- case RES_QP_BUSY: return "RES_QP_BUSY";
- case RES_QP_RESERVED: return "RES_QP_RESERVED";
- case RES_QP_MAPPED: return "RES_QP_MAPPED";
- case RES_QP_HW: return "RES_QP_HW";
- default: return "Unknown";
- }
-}
-
struct res_qp {
struct res_common com;
struct res_mtt *mtt;
@@ -173,16 +162,6 @@ enum res_srq_states {
RES_SRQ_HW,
};
-static inline const char *srq_states_str(enum res_srq_states state)
-{
- switch (state) {
- case RES_SRQ_BUSY: return "RES_SRQ_BUSY";
- case RES_SRQ_ALLOCATED: return "RES_SRQ_ALLOCATED";
- case RES_SRQ_HW: return "RES_SRQ_HW";
- default: return "Unknown";
- }
-}
-
struct res_srq {
struct res_common com;
struct res_mtt *mtt;
@@ -195,20 +174,21 @@ enum res_counter_states {
RES_COUNTER_ALLOCATED,
};
-static inline const char *counter_states_str(enum res_counter_states state)
-{
- switch (state) {
- case RES_COUNTER_BUSY: return "RES_COUNTER_BUSY";
- case RES_COUNTER_ALLOCATED: return "RES_COUNTER_ALLOCATED";
- default: return "Unknown";
- }
-}
-
struct res_counter {
struct res_common com;
int port;
};
+enum res_xrcdn_states {
+ RES_XRCD_BUSY = RES_ANY_BUSY,
+ RES_XRCD_ALLOCATED,
+};
+
+struct res_xrcdn {
+ struct res_common com;
+ int port;
+};
+
/* For Debug uses */
static const char *ResourceType(enum mlx4_resource rt)
{
@@ -221,6 +201,7 @@ static const char *ResourceType(enum mlx4_resource rt)
case RES_MAC: return "RES_MAC";
case RES_EQ: return "RES_EQ";
case RES_COUNTER: return "RES_COUNTER";
+ case RES_XRCD: return "RES_XRCD";
default: return "Unknown resource type !!!";
};
}
@@ -254,16 +235,23 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev)
return 0 ;
}
-void mlx4_free_resource_tracker(struct mlx4_dev *dev)
+void mlx4_free_resource_tracker(struct mlx4_dev *dev,
+ enum mlx4_res_tracker_free_type type)
{
struct mlx4_priv *priv = mlx4_priv(dev);
int i;
if (priv->mfunc.master.res_tracker.slave_list) {
- for (i = 0 ; i < dev->num_slaves; i++)
- mlx4_delete_all_resources_for_slave(dev, i);
-
- kfree(priv->mfunc.master.res_tracker.slave_list);
+ if (type != RES_TR_FREE_STRUCTS_ONLY)
+ for (i = 0 ; i < dev->num_slaves; i++)
+ if (type == RES_TR_FREE_ALL ||
+ dev->caps.function != i)
+ mlx4_delete_all_resources_for_slave(dev, i);
+
+ if (type != RES_TR_FREE_SLAVES_ONLY) {
+ kfree(priv->mfunc.master.res_tracker.slave_list);
+ priv->mfunc.master.res_tracker.slave_list = NULL;
+ }
}
}
@@ -471,6 +459,20 @@ static struct res_common *alloc_counter_tr(int id)
return &ret->com;
}
+static struct res_common *alloc_xrcdn_tr(int id)
+{
+ struct res_xrcdn *ret;
+
+ ret = kzalloc(sizeof *ret, GFP_KERNEL);
+ if (!ret)
+ return NULL;
+
+ ret->com.res_id = id;
+ ret->com.state = RES_XRCD_ALLOCATED;
+
+ return &ret->com;
+}
+
static struct res_common *alloc_tr(int id, enum mlx4_resource type, int slave,
int extra)
{
@@ -501,7 +503,9 @@ static struct res_common *alloc_tr(int id, enum mlx4_resource type, int slave,
case RES_COUNTER:
ret = alloc_counter_tr(id);
break;
-
+ case RES_XRCD:
+ ret = alloc_xrcdn_tr(id);
+ break;
default:
return NULL;
}
@@ -624,6 +628,16 @@ static int remove_counter_ok(struct res_counter *res)
return 0;
}
+static int remove_xrcdn_ok(struct res_xrcdn *res)
+{
+ if (res->com.state == RES_XRCD_BUSY)
+ return -EBUSY;
+ else if (res->com.state != RES_XRCD_ALLOCATED)
+ return -EPERM;
+
+ return 0;
+}
+
static int remove_cq_ok(struct res_cq *res)
{
if (res->com.state == RES_CQ_BUSY)
@@ -663,6 +677,8 @@ static int remove_ok(struct res_common *res, enum mlx4_resource type, int extra)
return remove_eq_ok((struct res_eq *)res);
case RES_COUNTER:
return remove_counter_ok((struct res_counter *)res);
+ case RES_XRCD:
+ return remove_xrcdn_ok((struct res_xrcdn *)res);
default:
return -EINVAL;
}
@@ -1269,6 +1285,50 @@ static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
return 0;
}
+static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
+ u64 in_param, u64 *out_param)
+{
+ u32 index;
+ int err;
+
+ if (op != RES_OP_RESERVE)
+ return -EINVAL;
+
+ err = __mlx4_counter_alloc(dev, &index);
+ if (err)
+ return err;
+
+ err = add_res_range(dev, slave, index, 1, RES_COUNTER, 0);
+ if (err)
+ __mlx4_counter_free(dev, index);
+ else
+ set_param_l(out_param, index);
+
+ return err;
+}
+
+static int xrcdn_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
+ u64 in_param, u64 *out_param)
+{
+ u32 xrcdn;
+ int err;
+
+ if (op != RES_OP_RESERVE)
+ return -EINVAL;
+
+ err = __mlx4_xrcd_alloc(dev, &xrcdn);
+ if (err)
+ return err;
+
+ err = add_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);
+ if (err)
+ __mlx4_xrcd_free(dev, xrcdn);
+ else
+ set_param_l(out_param, xrcdn);
+
+ return err;
+}
+
int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
@@ -1314,6 +1374,16 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
vhcr->in_param, &vhcr->out_param);
break;
+ case RES_COUNTER:
+ err = counter_alloc_res(dev, slave, vhcr->op_modifier, alop,
+ vhcr->in_param, &vhcr->out_param);
+ break;
+
+ case RES_XRCD:
+ err = xrcdn_alloc_res(dev, slave, vhcr->op_modifier, alop,
+ vhcr->in_param, &vhcr->out_param);
+ break;
+
default:
err = -EINVAL;
break;
@@ -1496,6 +1566,44 @@ static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
return 0;
}
+static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
+ u64 in_param, u64 *out_param)
+{
+ int index;
+ int err;
+
+ if (op != RES_OP_RESERVE)
+ return -EINVAL;
+
+ index = get_param_l(&in_param);
+ err = rem_res_range(dev, slave, index, 1, RES_COUNTER, 0);
+ if (err)
+ return err;
+
+ __mlx4_counter_free(dev, index);
+
+ return err;
+}
+
+static int xrcdn_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
+ u64 in_param, u64 *out_param)
+{
+ int xrcdn;
+ int err;
+
+ if (op != RES_OP_RESERVE)
+ return -EINVAL;
+
+ xrcdn = get_param_l(&in_param);
+ err = rem_res_range(dev, slave, xrcdn, 1, RES_XRCD, 0);
+ if (err)
+ return err;
+
+ __mlx4_xrcd_free(dev, xrcdn);
+
+ return err;
+}
+
int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
@@ -1541,6 +1649,15 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
vhcr->in_param, &vhcr->out_param);
break;
+ case RES_COUNTER:
+ err = counter_free_res(dev, slave, vhcr->op_modifier, alop,
+ vhcr->in_param, &vhcr->out_param);
+ break;
+
+ case RES_XRCD:
+ err = xrcdn_free_res(dev, slave, vhcr->op_modifier, alop,
+ vhcr->in_param, &vhcr->out_param);
+
default:
break;
}
@@ -2536,7 +2653,7 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_qp qp; /* dummy for calling attach/detach */
u8 *gid = inbox->buf;
enum mlx4_protocol prot = (vhcr->in_modifier >> 28) & 0x7;
- int err, err1;
+ int err;
int qpn;
struct res_qp *rqp;
int attach = vhcr->op_modifier;
@@ -2571,7 +2688,7 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
ex_rem:
/* ignore error return below, already in error */
- err1 = rem_mcg_res(dev, slave, rqp, gid, prot, type);
+ (void) rem_mcg_res(dev, slave, rqp, gid, prot, type);
ex_put:
put_res(dev, slave, qpn, RES_QP);
@@ -2604,13 +2721,12 @@ static void detach_qp(struct mlx4_dev *dev, int slave, struct res_qp *rqp)
{
struct res_gid *rgid;
struct res_gid *tmp;
- int err;
struct mlx4_qp qp; /* dummy for calling attach/detach */
list_for_each_entry_safe(rgid, tmp, &rqp->mcg_list, list) {
qp.qpn = rqp->local_qpn;
- err = mlx4_qp_detach_common(dev, &qp, rgid->gid, rgid->prot,
- rgid->steer);
+ (void) mlx4_qp_detach_common(dev, &qp, rgid->gid, rgid->prot,
+ rgid->steer);
list_del(&rgid->list);
kfree(rgid);
}
@@ -3036,14 +3152,13 @@ static void rem_slave_eqs(struct mlx4_dev *dev, int slave)
MLX4_CMD_HW2SW_EQ,
MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_NATIVE);
- mlx4_dbg(dev, "rem_slave_eqs: failed"
- " to move slave %d eqs %d to"
- " SW ownership\n", slave, eqn);
+ if (err)
+ mlx4_dbg(dev, "rem_slave_eqs: failed"
+ " to move slave %d eqs %d to"
+ " SW ownership\n", slave, eqn);
mlx4_free_cmd_mailbox(dev, mailbox);
- if (!err) {
- atomic_dec(&eq->mtt->ref_count);
- state = RES_EQ_RESERVED;
- }
+ atomic_dec(&eq->mtt->ref_count);
+ state = RES_EQ_RESERVED;
break;
default:
@@ -3056,6 +3171,64 @@ static void rem_slave_eqs(struct mlx4_dev *dev, int slave)
spin_unlock_irq(mlx4_tlock(dev));
}
+static void rem_slave_counters(struct mlx4_dev *dev, int slave)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
+ struct list_head *counter_list =
+ &tracker->slave_list[slave].res_list[RES_COUNTER];
+ struct res_counter *counter;
+ struct res_counter *tmp;
+ int err;
+ int index;
+
+ err = move_all_busy(dev, slave, RES_COUNTER);
+ if (err)
+ mlx4_warn(dev, "rem_slave_counters: Could not move all counters to "
+ "busy for slave %d\n", slave);
+
+ spin_lock_irq(mlx4_tlock(dev));
+ list_for_each_entry_safe(counter, tmp, counter_list, com.list) {
+ if (counter->com.owner == slave) {
+ index = counter->com.res_id;
+ radix_tree_delete(&tracker->res_tree[RES_COUNTER], index);
+ list_del(&counter->com.list);
+ kfree(counter);
+ __mlx4_counter_free(dev, index);
+ }
+ }
+ spin_unlock_irq(mlx4_tlock(dev));
+}
+
+static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
+ struct list_head *xrcdn_list =
+ &tracker->slave_list[slave].res_list[RES_XRCD];
+ struct res_xrcdn *xrcd;
+ struct res_xrcdn *tmp;
+ int err;
+ int xrcdn;
+
+ err = move_all_busy(dev, slave, RES_XRCD);
+ if (err)
+ mlx4_warn(dev, "rem_slave_xrcdns: Could not move all xrcdns to "
+ "busy for slave %d\n", slave);
+
+ spin_lock_irq(mlx4_tlock(dev));
+ list_for_each_entry_safe(xrcd, tmp, xrcdn_list, com.list) {
+ if (xrcd->com.owner == slave) {
+ xrcdn = xrcd->com.res_id;
+ radix_tree_delete(&tracker->res_tree[RES_XRCD], xrcdn);
+ list_del(&xrcd->com.list);
+ kfree(xrcd);
+ __mlx4_xrcd_free(dev, xrcdn);
+ }
+ }
+ spin_unlock_irq(mlx4_tlock(dev));
+}
+
void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -3069,5 +3242,7 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
rem_slave_mrs(dev, slave);
rem_slave_eqs(dev, slave);
rem_slave_mtts(dev, slave);
+ rem_slave_counters(dev, slave);
+ rem_slave_xrcdns(dev, slave);
mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
}
diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
index f84dd2dc82b6..24fb049ac2f2 100644
--- a/drivers/net/ethernet/micrel/ks8842.c
+++ b/drivers/net/ethernet/micrel/ks8842.c
@@ -1262,7 +1262,7 @@ static struct platform_driver ks8842_platform_driver = {
.owner = THIS_MODULE,
},
.probe = ks8842_probe,
- .remove = ks8842_remove,
+ .remove = __devexit_p(ks8842_remove),
};
module_platform_driver(ks8842_platform_driver);
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index f8dda009d3c0..5e313e9a252f 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -618,10 +618,8 @@ static void ks8851_irq_work(struct work_struct *work)
netif_dbg(ks, intr, ks->netdev,
"%s: status 0x%04x\n", __func__, status);
- if (status & IRQ_LCI) {
- /* should do something about checking link status */
+ if (status & IRQ_LCI)
handled |= IRQ_LCI;
- }
if (status & IRQ_LDI) {
u16 pmecr = ks8851_rdreg16(ks, KS_PMECR);
@@ -684,6 +682,9 @@ static void ks8851_irq_work(struct work_struct *work)
mutex_unlock(&ks->lock);
+ if (status & IRQ_LCI)
+ mii_check_link(&ks->mii);
+
if (status & IRQ_TXI)
netif_wake_queue(ks->netdev);
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 27273ae1a6e6..90153fc983cb 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -4033,7 +4033,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->netdev_ops = &myri10ge_netdev_ops;
netdev->mtu = myri10ge_initial_mtu;
- netdev->base_addr = mgp->iomem_base;
netdev->hw_features = mgp->features | NETIF_F_LRO | NETIF_F_RXCSUM;
netdev->features = netdev->hw_features;
@@ -4047,12 +4046,10 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->vlan_features &= ~NETIF_F_TSO;
/* make sure we can get an irq, and that MSI can be
- * setup (if available). Also ensure netdev->irq
- * is set to correct value if MSI is enabled */
+ * setup (if available). */
status = myri10ge_request_irq(mgp);
if (status != 0)
goto abort_with_firmware;
- netdev->irq = pdev->irq;
myri10ge_free_irq(mgp);
/* Save configuration space to be restored if the
@@ -4077,7 +4074,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
else
dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
mgp->msi_enabled ? "MSI" : "xPIC",
- netdev->irq, mgp->tx_boundary, mgp->fw_name,
+ pdev->irq, mgp->tx_boundary, mgp->fw_name,
(mgp->wc_enabled ? "Enabled" : "Disabled"));
board_number++;
diff --git a/drivers/net/ethernet/natsemi/Kconfig b/drivers/net/ethernet/natsemi/Kconfig
index eb836f770f50..f157334579fd 100644
--- a/drivers/net/ethernet/natsemi/Kconfig
+++ b/drivers/net/ethernet/natsemi/Kconfig
@@ -6,9 +6,8 @@ config NET_VENDOR_NATSEMI
bool "National Semi-conductor devices"
default y
depends on AMIGA_PCMCIA || ARM || EISA || EXPERIMENTAL || H8300 || \
- ISA || M32R || MAC || MACH_JAZZ || MACH_TX49XX || MCA || \
- MCA_LEGACY || MIPS || PCI || PCMCIA || SUPERH || \
- XTENSA_PLATFORM_XT2000 || ZORRO
+ ISA || M32R || MAC || MACH_JAZZ || MACH_TX49XX || MIPS || \
+ PCI || PCMCIA || SUPERH || XTENSA_PLATFORM_XT2000 || ZORRO
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -21,21 +20,6 @@ config NET_VENDOR_NATSEMI
if NET_VENDOR_NATSEMI
-config IBMLANA
- tristate "IBM LAN Adapter/A support"
- depends on MCA
- ---help---
- This is a Micro Channel Ethernet adapter. You need to set
- CONFIG_MCA to use this driver. It is both available as an in-kernel
- driver and as a module.
-
- To compile this driver as a module, choose M here. The only
- currently supported card is the IBM LAN Adapter/A for Ethernet. It
- will both support 16K and 32K memory windows, however a 32K window
- gives a better security against packet losses. Usage of multiple
- boards with this driver should be possible, but has not been tested
- up to now due to lack of hardware.
-
config MACSONIC
tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
depends on MAC
diff --git a/drivers/net/ethernet/natsemi/Makefile b/drivers/net/ethernet/natsemi/Makefile
index 9aa5dea52b3e..764c532a96d1 100644
--- a/drivers/net/ethernet/natsemi/Makefile
+++ b/drivers/net/ethernet/natsemi/Makefile
@@ -2,7 +2,6 @@
# Makefile for the National Semi-conductor Sonic devices.
#
-obj-$(CONFIG_IBMLANA) += ibmlana.o
obj-$(CONFIG_MACSONIC) += macsonic.o
obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
obj-$(CONFIG_NATSEMI) += natsemi.o
diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
index d38e48d4f430..5b61d12f8b91 100644
--- a/drivers/net/ethernet/natsemi/natsemi.c
+++ b/drivers/net/ethernet/natsemi/natsemi.c
@@ -547,6 +547,7 @@ struct netdev_private {
struct sk_buff *tx_skbuff[TX_RING_SIZE];
dma_addr_t tx_dma[TX_RING_SIZE];
struct net_device *dev;
+ void __iomem *ioaddr;
struct napi_struct napi;
/* Media monitoring timer */
struct timer_list timer;
@@ -699,7 +700,9 @@ static ssize_t natsemi_set_dspcfg_workaround(struct device *dev,
static inline void __iomem *ns_ioaddr(struct net_device *dev)
{
- return (void __iomem *) dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+
+ return np->ioaddr;
}
static inline void natsemi_irq_enable(struct net_device *dev)
@@ -863,10 +866,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
/* Store MAC Address in perm_addr */
memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
- dev->base_addr = (unsigned long __force) ioaddr;
- dev->irq = irq;
-
np = netdev_priv(dev);
+ np->ioaddr = ioaddr;
+
netif_napi_add(dev, &np->napi, natsemi_poll, 64);
np->dev = dev;
@@ -914,9 +916,6 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
}
option = find_cnt < MAX_UNITS ? options[find_cnt] : 0;
- if (dev->mem_start)
- option = dev->mem_start;
-
/* The lower four bits are the media type. */
if (option) {
if (option & 0x200)
@@ -1532,20 +1531,21 @@ static int netdev_open(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem * ioaddr = ns_ioaddr(dev);
+ const int irq = np->pci_dev->irq;
int i;
/* Reset the chip, just in case. */
natsemi_reset(dev);
- i = request_irq(dev->irq, intr_handler, IRQF_SHARED, dev->name, dev);
+ i = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev);
if (i) return i;
if (netif_msg_ifup(np))
printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
- dev->name, dev->irq);
+ dev->name, irq);
i = alloc_ring(dev);
if (i < 0) {
- free_irq(dev->irq, dev);
+ free_irq(irq, dev);
return i;
}
napi_enable(&np->napi);
@@ -1794,6 +1794,7 @@ static void netdev_timer(unsigned long data)
struct netdev_private *np = netdev_priv(dev);
void __iomem * ioaddr = ns_ioaddr(dev);
int next_tick = NATSEMI_TIMER_FREQ;
+ const int irq = np->pci_dev->irq;
if (netif_msg_timer(np)) {
/* DO NOT read the IntrStatus register,
@@ -1817,14 +1818,14 @@ static void netdev_timer(unsigned long data)
if (netif_msg_drv(np))
printk(KERN_NOTICE "%s: possible phy reset: "
"re-initializing\n", dev->name);
- disable_irq(dev->irq);
+ disable_irq(irq);
spin_lock_irq(&np->lock);
natsemi_stop_rxtx(dev);
dump_ring(dev);
reinit_ring(dev);
init_registers(dev);
spin_unlock_irq(&np->lock);
- enable_irq(dev->irq);
+ enable_irq(irq);
} else {
/* hurry back */
next_tick = HZ;
@@ -1841,10 +1842,10 @@ static void netdev_timer(unsigned long data)
spin_unlock_irq(&np->lock);
}
if (np->oom) {
- disable_irq(dev->irq);
+ disable_irq(irq);
np->oom = 0;
refill_rx(dev);
- enable_irq(dev->irq);
+ enable_irq(irq);
if (!np->oom) {
writel(RxOn, ioaddr + ChipCmd);
} else {
@@ -1885,8 +1886,9 @@ static void ns_tx_timeout(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
void __iomem * ioaddr = ns_ioaddr(dev);
+ const int irq = np->pci_dev->irq;
- disable_irq(dev->irq);
+ disable_irq(irq);
spin_lock_irq(&np->lock);
if (!np->hands_off) {
if (netif_msg_tx_err(np))
@@ -1905,7 +1907,7 @@ static void ns_tx_timeout(struct net_device *dev)
dev->name);
}
spin_unlock_irq(&np->lock);
- enable_irq(dev->irq);
+ enable_irq(irq);
dev->trans_start = jiffies; /* prevent tx timeout */
dev->stats.tx_errors++;
@@ -2470,9 +2472,12 @@ static struct net_device_stats *get_stats(struct net_device *dev)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void natsemi_poll_controller(struct net_device *dev)
{
- disable_irq(dev->irq);
- intr_handler(dev->irq, dev);
- enable_irq(dev->irq);
+ struct netdev_private *np = netdev_priv(dev);
+ const int irq = np->pci_dev->irq;
+
+ disable_irq(irq);
+ intr_handler(irq, dev);
+ enable_irq(irq);
}
#endif
@@ -2523,8 +2528,9 @@ static int natsemi_change_mtu(struct net_device *dev, int new_mtu)
if (netif_running(dev)) {
struct netdev_private *np = netdev_priv(dev);
void __iomem * ioaddr = ns_ioaddr(dev);
+ const int irq = np->pci_dev->irq;
- disable_irq(dev->irq);
+ disable_irq(irq);
spin_lock(&np->lock);
/* stop engines */
natsemi_stop_rxtx(dev);
@@ -2537,7 +2543,7 @@ static int natsemi_change_mtu(struct net_device *dev, int new_mtu)
/* restart engines */
writel(RxOn | TxOn, ioaddr + ChipCmd);
spin_unlock(&np->lock);
- enable_irq(dev->irq);
+ enable_irq(irq);
}
return 0;
}
@@ -3135,6 +3141,7 @@ static int netdev_close(struct net_device *dev)
{
void __iomem * ioaddr = ns_ioaddr(dev);
struct netdev_private *np = netdev_priv(dev);
+ const int irq = np->pci_dev->irq;
if (netif_msg_ifdown(np))
printk(KERN_DEBUG
@@ -3156,14 +3163,14 @@ static int netdev_close(struct net_device *dev)
*/
del_timer_sync(&np->timer);
- disable_irq(dev->irq);
+ disable_irq(irq);
spin_lock_irq(&np->lock);
natsemi_irq_disable(dev);
np->hands_off = 1;
spin_unlock_irq(&np->lock);
- enable_irq(dev->irq);
+ enable_irq(irq);
- free_irq(dev->irq, dev);
+ free_irq(irq, dev);
/* Interrupt disabled, interrupt handler released,
* queue stopped, timer deleted, rtnl_lock held
@@ -3256,9 +3263,11 @@ static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state)
rtnl_lock();
if (netif_running (dev)) {
+ const int irq = np->pci_dev->irq;
+
del_timer_sync(&np->timer);
- disable_irq(dev->irq);
+ disable_irq(irq);
spin_lock_irq(&np->lock);
natsemi_irq_disable(dev);
@@ -3267,7 +3276,7 @@ static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state)
netif_stop_queue(dev);
spin_unlock_irq(&np->lock);
- enable_irq(dev->irq);
+ enable_irq(irq);
napi_disable(&np->napi);
@@ -3307,6 +3316,8 @@ static int natsemi_resume (struct pci_dev *pdev)
if (netif_device_present(dev))
goto out;
if (netif_running(dev)) {
+ const int irq = np->pci_dev->irq;
+
BUG_ON(!np->hands_off);
ret = pci_enable_device(pdev);
if (ret < 0) {
@@ -3320,13 +3331,13 @@ static int natsemi_resume (struct pci_dev *pdev)
natsemi_reset(dev);
init_ring(dev);
- disable_irq(dev->irq);
+ disable_irq(irq);
spin_lock_irq(&np->lock);
np->hands_off = 0;
init_registers(dev);
netif_device_attach(dev);
spin_unlock_irq(&np->lock);
- enable_irq(dev->irq);
+ enable_irq(irq);
mod_timer(&np->timer, round_jiffies(jiffies + 1*HZ));
}
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index 6338ef8606ae..bb367582c1e8 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -2846,6 +2846,7 @@ static int s2io_poll_inta(struct napi_struct *napi, int budget)
static void s2io_netpoll(struct net_device *dev)
{
struct s2io_nic *nic = netdev_priv(dev);
+ const int irq = nic->pdev->irq;
struct XENA_dev_config __iomem *bar0 = nic->bar0;
u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
int i;
@@ -2855,7 +2856,7 @@ static void s2io_netpoll(struct net_device *dev)
if (pci_channel_offline(nic->pdev))
return;
- disable_irq(dev->irq);
+ disable_irq(irq);
writeq(val64, &bar0->rx_traffic_int);
writeq(val64, &bar0->tx_traffic_int);
@@ -2884,7 +2885,7 @@ static void s2io_netpoll(struct net_device *dev)
break;
}
}
- enable_irq(dev->irq);
+ enable_irq(irq);
}
#endif
@@ -3897,9 +3898,7 @@ static void remove_msix_isr(struct s2io_nic *sp)
static void remove_inta_isr(struct s2io_nic *sp)
{
- struct net_device *dev = sp->dev;
-
- free_irq(sp->pdev->irq, dev);
+ free_irq(sp->pdev->irq, sp->dev);
}
/* ********************************************************* *
@@ -7046,7 +7045,7 @@ static int s2io_add_isr(struct s2io_nic *sp)
}
}
if (sp->config.intr_type == INTA) {
- err = request_irq((int)sp->pdev->irq, s2io_isr, IRQF_SHARED,
+ err = request_irq(sp->pdev->irq, s2io_isr, IRQF_SHARED,
sp->name, dev);
if (err) {
DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
@@ -7908,9 +7907,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
goto bar1_remap_failed;
}
- dev->irq = pdev->irq;
- dev->base_addr = (unsigned long)sp->bar0;
-
/* Initializing the BAR1 address as the start of the FIFO pointer. */
for (j = 0; j < MAX_TX_FIFOS; j++) {
mac_control->tx_FIFO_start[j] = sp->bar1 + (j * 0x00020000);
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index ef76725454d2..51387c31914b 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -1882,25 +1882,24 @@ static int vxge_poll_inta(struct napi_struct *napi, int budget)
*/
static void vxge_netpoll(struct net_device *dev)
{
- struct __vxge_hw_device *hldev;
- struct vxgedev *vdev;
-
- vdev = netdev_priv(dev);
- hldev = pci_get_drvdata(vdev->pdev);
+ struct vxgedev *vdev = netdev_priv(dev);
+ struct pci_dev *pdev = vdev->pdev;
+ struct __vxge_hw_device *hldev = pci_get_drvdata(pdev);
+ const int irq = pdev->irq;
vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__);
- if (pci_channel_offline(vdev->pdev))
+ if (pci_channel_offline(pdev))
return;
- disable_irq(dev->irq);
+ disable_irq(irq);
vxge_hw_device_clear_tx_rx(hldev);
vxge_hw_device_clear_tx_rx(hldev);
VXGE_COMPLETE_ALL_RX(vdev);
VXGE_COMPLETE_ALL_TX(vdev);
- enable_irq(dev->irq);
+ enable_irq(irq);
vxge_debug_entryexit(VXGE_TRACE,
"%s:%d Exiting...", __func__, __LINE__);
@@ -2860,12 +2859,12 @@ static int vxge_open(struct net_device *dev)
vdev->config.rx_pause_enable);
if (vdev->vp_reset_timer.function == NULL)
- vxge_os_timer(vdev->vp_reset_timer,
- vxge_poll_vp_reset, vdev, (HZ/2));
+ vxge_os_timer(&vdev->vp_reset_timer, vxge_poll_vp_reset, vdev,
+ HZ / 2);
/* There is no need to check for RxD leak and RxD lookup on Titan1A */
if (vdev->titan1 && vdev->vp_lockup_timer.function == NULL)
- vxge_os_timer(vdev->vp_lockup_timer, vxge_poll_vp_lockup, vdev,
+ vxge_os_timer(&vdev->vp_lockup_timer, vxge_poll_vp_lockup, vdev,
HZ / 2);
set_bit(__VXGE_STATE_CARD_UP, &vdev->state);
@@ -3424,9 +3423,6 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
ndev->features |= ndev->hw_features |
NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
- /* Driver entry points */
- ndev->irq = vdev->pdev->irq;
- ndev->base_addr = (unsigned long) hldev->bar0;
ndev->netdev_ops = &vxge_netdev_ops;
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.h b/drivers/net/ethernet/neterion/vxge/vxge-main.h
index f52a42d1dbb7..35f3e7552ec2 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.h
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.h
@@ -416,12 +416,15 @@ struct vxge_tx_priv {
static int p = val; \
module_param(p, int, 0)
-#define vxge_os_timer(timer, handle, arg, exp) do { \
- init_timer(&timer); \
- timer.function = handle; \
- timer.data = (unsigned long) arg; \
- mod_timer(&timer, (jiffies + exp)); \
- } while (0);
+static inline
+void vxge_os_timer(struct timer_list *timer, void (*func)(unsigned long data),
+ struct vxgedev *vdev, unsigned long timeout)
+{
+ init_timer(timer);
+ timer->function = func;
+ timer->data = (unsigned long)vdev;
+ mod_timer(timer, jiffies + timeout);
+}
void vxge_initialize_ethtool_ops(struct net_device *ndev);
enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev);
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index aca13046e432..928913c4f3ff 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -2279,6 +2279,8 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_sent_queue(np->dev, skb->len);
+ skb_tx_timestamp(skb);
+
np->put_tx.orig = put_tx;
spin_unlock_irqrestore(&np->lock, flags);
@@ -2426,6 +2428,8 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
netdev_sent_queue(np->dev, skb->len);
+ skb_tx_timestamp(skb);
+
np->put_tx.ex = put_tx;
spin_unlock_irqrestore(&np->lock, flags);
@@ -3942,13 +3946,11 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
ret = pci_enable_msi(np->pci_dev);
if (ret == 0) {
np->msi_flags |= NV_MSI_ENABLED;
- dev->irq = np->pci_dev->irq;
if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0) {
netdev_info(dev, "request_irq failed %d\n",
ret);
pci_disable_msi(np->pci_dev);
np->msi_flags &= ~NV_MSI_ENABLED;
- dev->irq = np->pci_dev->irq;
goto out_err;
}
@@ -5649,9 +5651,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->base = ioremap(addr, np->register_size);
if (!np->base)
goto out_relreg;
- dev->base_addr = (unsigned long)np->base;
-
- dev->irq = pci_dev->irq;
np->rx_ring_size = RX_RING_DEFAULT;
np->tx_ring_size = TX_RING_DEFAULT;
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index 6dfc26d85e47..8d2666fcffd7 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -40,6 +40,7 @@
#include <linux/skbuff.h>
#include <linux/phy.h>
#include <linux/dma-mapping.h>
+#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/types.h>
@@ -340,13 +341,17 @@
*/
#define LPC_POWERDOWN_MACAHB (1 << 31)
-/* Upon the upcoming introduction of device tree usage in LPC32xx,
- * lpc_phy_interface_mode() and use_iram_for_net() will be extended with a
- * device parameter for access to device tree information at runtime, instead
- * of defining the values at compile time
- */
-static inline phy_interface_t lpc_phy_interface_mode(void)
+static phy_interface_t lpc_phy_interface_mode(struct device *dev)
{
+ if (dev && dev->of_node) {
+ const char *mode = of_get_property(dev->of_node,
+ "phy-mode", NULL);
+ if (mode && !strcmp(mode, "mii"))
+ return PHY_INTERFACE_MODE_MII;
+ return PHY_INTERFACE_MODE_RMII;
+ }
+
+ /* non-DT */
#ifdef CONFIG_ARCH_LPC32XX_MII_SUPPORT
return PHY_INTERFACE_MODE_MII;
#else
@@ -354,12 +359,16 @@ static inline phy_interface_t lpc_phy_interface_mode(void)
#endif
}
-static inline int use_iram_for_net(void)
+static bool use_iram_for_net(struct device *dev)
{
+ if (dev && dev->of_node)
+ return of_property_read_bool(dev->of_node, "use-iram");
+
+ /* non-DT */
#ifdef CONFIG_ARCH_LPC32XX_IRAM_FOR_NET
- return 1;
+ return true;
#else
- return 0;
+ return false;
#endif
}
@@ -664,7 +673,7 @@ static void __lpc_eth_init(struct netdata_local *pldat)
LPC_ENET_CLRT(pldat->net_base));
writel(LPC_IPGR_LOAD_PART2(0x12), LPC_ENET_IPGR(pldat->net_base));
- if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII)
+ if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII)
writel(LPC_COMMAND_PASSRUNTFRAME,
LPC_ENET_COMMAND(pldat->net_base));
else {
@@ -804,12 +813,13 @@ static int lpc_mii_probe(struct net_device *ndev)
}
/* Attach to the PHY */
- if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII)
+ if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII)
netdev_info(ndev, "using MII interface\n");
else
netdev_info(ndev, "using RMII interface\n");
phydev = phy_connect(ndev, dev_name(&phydev->dev),
- &lpc_handle_link_change, 0, lpc_phy_interface_mode());
+ &lpc_handle_link_change, 0,
+ lpc_phy_interface_mode(&pldat->pdev->dev));
if (IS_ERR(phydev)) {
netdev_err(ndev, "Could not attach to PHY\n");
@@ -843,7 +853,7 @@ static int lpc_mii_init(struct netdata_local *pldat)
}
/* Setup MII mode */
- if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII)
+ if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII)
writel(LPC_COMMAND_PASSRUNTFRAME,
LPC_ENET_COMMAND(pldat->net_base));
else {
@@ -990,10 +1000,10 @@ static int __lpc_handle_recv(struct net_device *ndev, int budget)
ndev->stats.rx_errors++;
} else {
/* Packet is good */
- skb = dev_alloc_skb(len + 8);
- if (!skb)
+ skb = dev_alloc_skb(len);
+ if (!skb) {
ndev->stats.rx_dropped++;
- else {
+ } else {
prdbuf = skb_put(skb, len);
/* Copy packet from buffer */
@@ -1315,18 +1325,26 @@ static const struct net_device_ops lpc_netdev_ops = {
static int lpc_eth_drv_probe(struct platform_device *pdev)
{
struct resource *res;
- struct resource *dma_res;
struct net_device *ndev;
struct netdata_local *pldat;
struct phy_device *phydev;
dma_addr_t dma_handle;
int irq, ret;
+ u32 tmp;
+
+ /* Setup network interface for RMII or MII mode */
+ tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL);
+ tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK;
+ if (lpc_phy_interface_mode(&pdev->dev) == PHY_INTERFACE_MODE_MII)
+ tmp |= LPC32XX_CLKPWR_MACCTRL_USE_MII_PINS;
+ else
+ tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS;
+ __raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL);
/* Get platform resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
irq = platform_get_irq(pdev, 0);
- if ((!res) || (!dma_res) || (irq < 0) || (irq >= NR_IRQS)) {
+ if ((!res) || (irq < 0) || (irq >= NR_IRQS)) {
dev_err(&pdev->dev, "error getting resources.\n");
ret = -ENXIO;
goto err_exit;
@@ -1389,17 +1407,19 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
sizeof(struct txrx_desc_t) + sizeof(struct rx_status_t));
pldat->dma_buff_base_v = 0;
- if (use_iram_for_net()) {
- dma_handle = dma_res->start;
+ if (use_iram_for_net(&pldat->pdev->dev)) {
+ dma_handle = LPC32XX_IRAM_BASE;
if (pldat->dma_buff_size <= lpc32xx_return_iram_size())
pldat->dma_buff_base_v =
- io_p2v(dma_res->start);
+ io_p2v(LPC32XX_IRAM_BASE);
else
netdev_err(ndev,
"IRAM not big enough for net buffers, using SDRAM instead.\n");
}
if (pldat->dma_buff_base_v == 0) {
+ pldat->pdev->dev.coherent_dma_mask = 0xFFFFFFFF;
+ pldat->pdev->dev.dma_mask = &pldat->pdev->dev.coherent_dma_mask;
pldat->dma_buff_size = PAGE_ALIGN(pldat->dma_buff_size);
/* Allocate a chunk of memory for the DMA ethernet buffers
@@ -1488,7 +1508,7 @@ err_out_unregister_netdev:
platform_set_drvdata(pdev, NULL);
unregister_netdev(ndev);
err_out_dma_unmap:
- if (!use_iram_for_net() ||
+ if (!use_iram_for_net(&pldat->pdev->dev) ||
pldat->dma_buff_size > lpc32xx_return_iram_size())
dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size,
pldat->dma_buff_base_v,
@@ -1515,7 +1535,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
unregister_netdev(ndev);
platform_set_drvdata(pdev, NULL);
- if (!use_iram_for_net() ||
+ if (!use_iram_for_net(&pldat->pdev->dev) ||
pldat->dma_buff_size > lpc32xx_return_iram_size())
dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size,
pldat->dma_buff_base_v,
@@ -1584,6 +1604,14 @@ static int lpc_eth_drv_resume(struct platform_device *pdev)
}
#endif
+#ifdef CONFIG_OF
+static const struct of_device_id lpc_eth_match[] = {
+ { .compatible = "nxp,lpc-eth" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lpc_eth_match);
+#endif
+
static struct platform_driver lpc_eth_driver = {
.probe = lpc_eth_drv_probe,
.remove = __devexit_p(lpc_eth_drv_remove),
@@ -1593,6 +1621,7 @@ static struct platform_driver lpc_eth_driver = {
#endif
.driver = {
.name = MODNAME,
+ .of_match_table = of_match_ptr(lpc_eth_match),
},
};
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
index dd14915f54bb..b07311eaa693 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
@@ -584,7 +584,6 @@ struct pch_gbe_hw_stats {
/**
* struct pch_gbe_adapter - board specific private data structure
* @stats_lock: Spinlock structure for status
- * @tx_queue_lock: Spinlock structure for transmit
* @ethtool_lock: Spinlock structure for ethtool
* @irq_sem: Semaphore for interrupt
* @netdev: Pointer of network device structure
@@ -609,7 +608,6 @@ struct pch_gbe_hw_stats {
struct pch_gbe_adapter {
spinlock_t stats_lock;
- spinlock_t tx_queue_lock;
spinlock_t ethtool_lock;
atomic_t irq_sem;
struct net_device *netdev;
@@ -660,6 +658,7 @@ extern u32 pch_src_uuid_lo_read(struct pci_dev *pdev);
extern u32 pch_src_uuid_hi_read(struct pci_dev *pdev);
extern u64 pch_rx_snap_read(struct pci_dev *pdev);
extern u64 pch_tx_snap_read(struct pci_dev *pdev);
+extern int pch_set_station_address(u8 *addr, struct pci_dev *pdev);
#endif
/* pch_gbe_param.c */
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 8035e5ff6e06..3787c64ee71c 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
@@ -79,7 +79,6 @@ const char pch_driver_version[] = DRV_VERSION;
#define PCH_GBE_PAUSE_PKT4_VALUE 0x01000888
#define PCH_GBE_PAUSE_PKT5_VALUE 0x0000FFFF
-#define PCH_GBE_ETH_ALEN 6
/* This defines the bits that are set in the Interrupt Mask
* Set/Read Register. Each bit is documented below:
@@ -101,18 +100,19 @@ const char pch_driver_version[] = DRV_VERSION;
#ifdef CONFIG_PCH_PTP
/* Macros for ieee1588 */
-#define TICKS_NS_SHIFT 5
-
/* 0x40 Time Synchronization Channel Control Register Bits */
#define MASTER_MODE (1<<0)
-#define SLAVE_MODE (0<<0)
+#define SLAVE_MODE (0)
#define V2_MODE (1<<31)
-#define CAP_MODE0 (0<<16)
+#define CAP_MODE0 (0)
#define CAP_MODE2 (1<<17)
/* 0x44 Time Synchronization Channel Event Register Bits */
#define TX_SNAPSHOT_LOCKED (1<<0)
#define RX_SNAPSHOT_LOCKED (1<<1)
+
+#define PTP_L4_MULTICAST_SA "01:00:5e:00:01:81"
+#define PTP_L2_MULTICAST_SA "01:1b:19:00:00:00"
#endif
static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT;
@@ -120,6 +120,7 @@ static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT;
static int pch_gbe_mdio_read(struct net_device *netdev, int addr, int reg);
static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg,
int data);
+static void pch_gbe_set_multi(struct net_device *netdev);
#ifdef CONFIG_PCH_PTP
static struct sock_filter ptp_filter[] = {
@@ -133,10 +134,8 @@ static int pch_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
u16 *hi, *id;
u32 lo;
- if ((sk_run_filter(skb, ptp_filter) != PTP_CLASS_V2_IPV4) &&
- (sk_run_filter(skb, ptp_filter) != PTP_CLASS_V1_IPV4)) {
+ if (sk_run_filter(skb, ptp_filter) == PTP_CLASS_NONE)
return 0;
- }
offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
@@ -153,8 +152,8 @@ static int pch_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid)
seqid == *id);
}
-static void pch_rx_timestamp(
- struct pch_gbe_adapter *adapter, struct sk_buff *skb)
+static void
+pch_rx_timestamp(struct pch_gbe_adapter *adapter, struct sk_buff *skb)
{
struct skb_shared_hwtstamps *shhwtstamps;
struct pci_dev *pdev;
@@ -183,7 +182,6 @@ static void pch_rx_timestamp(
goto out;
ns = pch_rx_snap_read(pdev);
- ns <<= TICKS_NS_SHIFT;
shhwtstamps = skb_hwtstamps(skb);
memset(shhwtstamps, 0, sizeof(*shhwtstamps));
@@ -192,8 +190,8 @@ out:
pch_ch_event_write(pdev, RX_SNAPSHOT_LOCKED);
}
-static void pch_tx_timestamp(
- struct pch_gbe_adapter *adapter, struct sk_buff *skb)
+static void
+pch_tx_timestamp(struct pch_gbe_adapter *adapter, struct sk_buff *skb)
{
struct skb_shared_hwtstamps shhwtstamps;
struct pci_dev *pdev;
@@ -202,17 +200,16 @@ static void pch_tx_timestamp(
u32 cnt, val;
shtx = skb_shinfo(skb);
- if (unlikely(shtx->tx_flags & SKBTX_HW_TSTAMP && adapter->hwts_tx_en))
- shtx->tx_flags |= SKBTX_IN_PROGRESS;
- else
+ if (likely(!(shtx->tx_flags & SKBTX_HW_TSTAMP && adapter->hwts_tx_en)))
return;
+ shtx->tx_flags |= SKBTX_IN_PROGRESS;
+
/* Get ieee1588's dev information */
pdev = adapter->ptp_pdev;
/*
* This really stinks, but we have to poll for the Tx time stamp.
- * Usually, the time stamp is ready after 4 to 6 microseconds.
*/
for (cnt = 0; cnt < 100; cnt++) {
val = pch_ch_event_read(pdev);
@@ -226,7 +223,6 @@ static void pch_tx_timestamp(
}
ns = pch_tx_snap_read(pdev);
- ns <<= TICKS_NS_SHIFT;
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
shhwtstamps.hwtstamp = ns_to_ktime(ns);
@@ -240,6 +236,7 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
struct hwtstamp_config cfg;
struct pch_gbe_adapter *adapter = netdev_priv(netdev);
struct pci_dev *pdev;
+ u8 station[20];
if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
return -EFAULT;
@@ -267,15 +264,23 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
adapter->hwts_rx_en = 0;
- pch_ch_control_write(pdev, (SLAVE_MODE | CAP_MODE0));
+ pch_ch_control_write(pdev, SLAVE_MODE | CAP_MODE0);
break;
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
adapter->hwts_rx_en = 1;
- pch_ch_control_write(pdev, (MASTER_MODE | CAP_MODE0));
+ pch_ch_control_write(pdev, MASTER_MODE | CAP_MODE0);
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ adapter->hwts_rx_en = 1;
+ pch_ch_control_write(pdev, V2_MODE | CAP_MODE2);
+ strcpy(station, PTP_L4_MULTICAST_SA);
+ pch_set_station_address(station, pdev);
break;
- case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
adapter->hwts_rx_en = 1;
- pch_ch_control_write(pdev, (V2_MODE | CAP_MODE2));
+ pch_ch_control_write(pdev, V2_MODE | CAP_MODE2);
+ strcpy(station, PTP_L2_MULTICAST_SA);
+ pch_set_station_address(station, pdev);
break;
default:
return -ERANGE;
@@ -399,18 +404,18 @@ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw)
iowrite32(PCH_GBE_MODE_GMII_ETHER, &hw->reg->MODE);
#endif
pch_gbe_wait_clr_bit(&hw->reg->RESET, PCH_GBE_ALL_RST);
- /* Setup the receive address */
+ /* Setup the receive addresses */
pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
return;
}
static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw)
{
- /* Read the MAC address. and store to the private data */
+ /* Read the MAC addresses. and store to the private data */
pch_gbe_mac_read_mac_addr(hw);
iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET);
pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST);
- /* Setup the MAC address */
+ /* Setup the MAC addresses */
pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
return;
}
@@ -460,7 +465,7 @@ static void pch_gbe_mac_mc_addr_list_update(struct pch_gbe_hw *hw,
if (mc_addr_count) {
pch_gbe_mac_mar_set(hw, mc_addr_list, i);
mc_addr_count--;
- mc_addr_list += PCH_GBE_ETH_ALEN;
+ mc_addr_list += ETH_ALEN;
} else {
/* Clear MAC address mask */
adrmask = ioread32(&hw->reg->ADDR_MASK);
@@ -640,14 +645,11 @@ static void pch_gbe_mac_set_pause_packet(struct pch_gbe_hw *hw)
*/
static int pch_gbe_alloc_queues(struct pch_gbe_adapter *adapter)
{
- int size;
-
- size = (int)sizeof(struct pch_gbe_tx_ring);
- adapter->tx_ring = kzalloc(size, GFP_KERNEL);
+ adapter->tx_ring = kzalloc(sizeof(*adapter->tx_ring), GFP_KERNEL);
if (!adapter->tx_ring)
return -ENOMEM;
- size = (int)sizeof(struct pch_gbe_rx_ring);
- adapter->rx_ring = kzalloc(size, GFP_KERNEL);
+
+ adapter->rx_ring = kzalloc(sizeof(*adapter->rx_ring), GFP_KERNEL);
if (!adapter->rx_ring) {
kfree(adapter->tx_ring);
return -ENOMEM;
@@ -778,6 +780,8 @@ void pch_gbe_reinit_locked(struct pch_gbe_adapter *adapter)
void pch_gbe_reset(struct pch_gbe_adapter *adapter)
{
pch_gbe_mac_reset_hw(&adapter->hw);
+ /* reprogram multicast address register after reset */
+ pch_gbe_set_multi(adapter->netdev);
/* Setup the receive address. */
pch_gbe_mac_init_rx_addrs(&adapter->hw, PCH_GBE_MAR_ENTRIES);
if (pch_gbe_hal_init_hw(&adapter->hw))
@@ -1162,7 +1166,6 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
struct sk_buff *tmp_skb;
unsigned int frame_ctrl;
unsigned int ring_num;
- unsigned long flags;
/*-- Set frame control --*/
frame_ctrl = 0;
@@ -1182,8 +1185,6 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
if (skb->protocol == htons(ETH_P_IP)) {
struct iphdr *iph = ip_hdr(skb);
unsigned int offset;
- iph->check = 0;
- iph->check = ip_fast_csum((u8 *) iph, iph->ihl);
offset = skb_transport_offset(skb);
if (iph->protocol == IPPROTO_TCP) {
skb->csum = 0;
@@ -1211,14 +1212,14 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
}
}
}
- spin_lock_irqsave(&tx_ring->tx_lock, flags);
+
ring_num = tx_ring->next_to_use;
if (unlikely((ring_num + 1) == tx_ring->count))
tx_ring->next_to_use = 0;
else
tx_ring->next_to_use = ring_num + 1;
- spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+
buffer_info = &tx_ring->buffer_info[ring_num];
tmp_skb = buffer_info->skb;
@@ -1342,6 +1343,8 @@ static void pch_gbe_stop_receive(struct pch_gbe_adapter *adapter)
/* Stop Receive */
pch_gbe_mac_reset_rx(hw);
}
+ /* reprogram multicast address register after reset */
+ pch_gbe_set_multi(adapter->netdev);
}
static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
@@ -1518,7 +1521,7 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter,
&rx_ring->rx_buff_pool_logic,
GFP_KERNEL);
if (!rx_ring->rx_buff_pool) {
- pr_err("Unable to allocate memory for the receive poll buffer\n");
+ pr_err("Unable to allocate memory for the receive pool buffer\n");
return -ENOMEM;
}
memset(rx_ring->rx_buff_pool, 0, size);
@@ -1637,15 +1640,17 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter,
pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n",
cleaned_count);
/* Recover from running out of Tx resources in xmit_frame */
+ spin_lock(&tx_ring->tx_lock);
if (unlikely(cleaned && (netif_queue_stopped(adapter->netdev)))) {
netif_wake_queue(adapter->netdev);
adapter->stats.tx_restart_count++;
pr_debug("Tx wake queue\n");
}
- spin_lock(&adapter->tx_queue_lock);
+
tx_ring->next_to_clean = i;
- spin_unlock(&adapter->tx_queue_lock);
+
pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean);
+ spin_unlock(&tx_ring->tx_lock);
return cleaned;
}
@@ -1924,7 +1929,6 @@ static int pch_gbe_request_irq(struct pch_gbe_adapter *adapter)
}
-static void pch_gbe_set_multi(struct net_device *netdev);
/**
* pch_gbe_up - Up GbE network device
* @adapter: Board private structure
@@ -2037,7 +2041,6 @@ static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter)
return -ENOMEM;
}
spin_lock_init(&adapter->hw.miim_lock);
- spin_lock_init(&adapter->tx_queue_lock);
spin_lock_init(&adapter->stats_lock);
spin_lock_init(&adapter->ethtool_lock);
atomic_set(&adapter->irq_sem, 0);
@@ -2142,10 +2145,10 @@ static int pch_gbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tx_ring->next_to_use, tx_ring->next_to_clean);
return NETDEV_TX_BUSY;
}
- spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
/* CRC,ITAG no support */
pch_gbe_tx_queue(adapter, tx_ring, skb);
+ spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c
index 0d29f5f4b8e4..c2367158350e 100644
--- a/drivers/net/ethernet/packetengines/hamachi.c
+++ b/drivers/net/ethernet/packetengines/hamachi.c
@@ -683,8 +683,6 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
}
hmp->base = ioaddr;
- dev->base_addr = (unsigned long)ioaddr;
- dev->irq = irq;
pci_set_drvdata(pdev, dev);
hmp->chip_id = chip_id;
@@ -859,14 +857,11 @@ static int hamachi_open(struct net_device *dev)
u32 rx_int_var, tx_int_var;
u16 fifo_info;
- i = request_irq(dev->irq, hamachi_interrupt, IRQF_SHARED, dev->name, dev);
+ i = request_irq(hmp->pci_dev->irq, hamachi_interrupt, IRQF_SHARED,
+ dev->name, dev);
if (i)
return i;
- if (hamachi_debug > 1)
- printk(KERN_DEBUG "%s: hamachi_open() irq %d.\n",
- dev->name, dev->irq);
-
hamachi_init_ring(dev);
#if ADDRLEN == 64
@@ -1705,7 +1700,7 @@ static int hamachi_close(struct net_device *dev)
}
#endif /* __i386__ debugging only */
- free_irq(dev->irq, dev);
+ free_irq(hmp->pci_dev->irq, dev);
del_timer_sync(&hmp->timer);
diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c
index 7757b80ef924..04e622fd468d 100644
--- a/drivers/net/ethernet/packetengines/yellowfin.c
+++ b/drivers/net/ethernet/packetengines/yellowfin.c
@@ -427,9 +427,6 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
/* Reset the chip. */
iowrite32(0x80000000, ioaddr + DMACtrl);
- dev->base_addr = (unsigned long)ioaddr;
- dev->irq = irq;
-
pci_set_drvdata(pdev, dev);
spin_lock_init(&np->lock);
@@ -569,25 +566,20 @@ static void mdio_write(void __iomem *ioaddr, int phy_id, int location, int value
static int yellowfin_open(struct net_device *dev)
{
struct yellowfin_private *yp = netdev_priv(dev);
+ const int irq = yp->pci_dev->irq;
void __iomem *ioaddr = yp->base;
- int i, ret;
+ int i, rc;
/* Reset the chip. */
iowrite32(0x80000000, ioaddr + DMACtrl);
- ret = request_irq(dev->irq, yellowfin_interrupt, IRQF_SHARED, dev->name, dev);
- if (ret)
- return ret;
-
- if (yellowfin_debug > 1)
- netdev_printk(KERN_DEBUG, dev, "%s() irq %d\n",
- __func__, dev->irq);
+ rc = request_irq(irq, yellowfin_interrupt, IRQF_SHARED, dev->name, dev);
+ if (rc)
+ return rc;
- ret = yellowfin_init_ring(dev);
- if (ret) {
- free_irq(dev->irq, dev);
- return ret;
- }
+ rc = yellowfin_init_ring(dev);
+ if (rc < 0)
+ goto err_free_irq;
iowrite32(yp->rx_ring_dma, ioaddr + RxPtr);
iowrite32(yp->tx_ring_dma, ioaddr + TxPtr);
@@ -647,8 +639,12 @@ static int yellowfin_open(struct net_device *dev)
yp->timer.data = (unsigned long)dev;
yp->timer.function = yellowfin_timer; /* timer handler */
add_timer(&yp->timer);
+out:
+ return rc;
- return 0;
+err_free_irq:
+ free_irq(irq, dev);
+ goto out;
}
static void yellowfin_timer(unsigned long data)
@@ -1251,7 +1247,7 @@ static int yellowfin_close(struct net_device *dev)
}
#endif /* __i386__ debugging only */
- free_irq(dev->irq, dev);
+ free_irq(yp->pci_dev->irq, dev);
/* Free all the skbuffs in the Rx queue. */
for (i = 0; i < RX_RING_SIZE; i++) {
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index ddc95b0ac78d..e559dfa06d6a 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -623,7 +623,7 @@ static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
mac->rx = NULL;
}
-static void pasemi_mac_replenish_rx_ring(const struct net_device *dev,
+static void pasemi_mac_replenish_rx_ring(struct net_device *dev,
const int limit)
{
const struct pasemi_mac *mac = netdev_priv(dev);
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
index b5de8a7b90f1..37ccbe54e62d 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 78
-#define NETXEN_NIC_LINUX_VERSIONID "4.0.78"
+#define _NETXEN_NIC_LINUX_SUBVERSION 79
+#define NETXEN_NIC_LINUX_VERSIONID "4.0.79"
#define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c))
#define _major(v) (((v) >> 24) & 0xff)
@@ -419,6 +419,8 @@ struct rcv_desc {
(((sts_data) >> 52) & 0x1)
#define netxen_get_lro_sts_seq_number(sts_data) \
((sts_data) & 0x0FFFFFFFF)
+#define netxen_get_lro_sts_mss(sts_data1) \
+ ((sts_data1 >> 32) & 0x0FFFF)
struct status_desc {
@@ -794,6 +796,7 @@ struct netxen_cmd_args {
#define NX_CAP0_JUMBO_CONTIGUOUS NX_CAP_BIT(0, 7)
#define NX_CAP0_LRO_CONTIGUOUS NX_CAP_BIT(0, 8)
#define NX_CAP0_HW_LRO NX_CAP_BIT(0, 10)
+#define NX_CAP0_HW_LRO_MSS NX_CAP_BIT(0, 21)
/*
* Context state
@@ -1073,6 +1076,8 @@ typedef struct {
#define NX_FW_CAPABILITY_FVLANTX (1 << 9)
#define NX_FW_CAPABILITY_HW_LRO (1 << 10)
#define NX_FW_CAPABILITY_GBE_LINK_CFG (1 << 11)
+#define NX_FW_CAPABILITY_MORE_CAPS (1 << 31)
+#define NX_FW_CAPABILITY_2_LRO_MAX_TCP_SEG (1 << 2)
/* module types */
#define LINKEVENT_MODULE_NOT_PRESENT 1
@@ -1155,6 +1160,7 @@ typedef struct {
#define NETXEN_NIC_BRIDGE_ENABLED 0X10
#define NETXEN_NIC_DIAG_ENABLED 0x20
#define NETXEN_FW_RESET_OWNER 0x40
+#define NETXEN_FW_MSS_CAP 0x80
#define NETXEN_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED))
@@ -1201,6 +1207,9 @@ typedef struct {
#define NX_FORCE_FW_RESET 0xdeaddead
+/* Fw dump levels */
+static const u32 FW_DUMP_LEVELS[] = { 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff };
+
/* Flash read/write address */
#define NX_FW_DUMP_REG1 0x00130060
#define NX_FW_DUMP_REG2 0x001e0000
@@ -1814,6 +1823,13 @@ struct netxen_brdinfo {
char short_name[NETXEN_MAX_SHORT_NAME];
};
+struct netxen_dimm_cfg {
+ u8 presence;
+ u8 mem_type;
+ u8 dimm_type;
+ u32 size;
+};
+
static const struct netxen_brdinfo netxen_boards[] = {
{NETXEN_BRDTYPE_P2_SB31_10G_CX4, 1, "XGb CX4"},
{NETXEN_BRDTYPE_P2_SB31_10G_HMEZ, 1, "XGb HMEZ"},
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
index f3c0057a802b..7f556a84925d 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
@@ -229,7 +229,7 @@ netxen_setup_minidump(struct netxen_adapter *adapter)
adapter->mdump.md_template;
adapter->mdump.md_capture_buff = NULL;
adapter->mdump.fw_supports_md = 1;
- adapter->mdump.md_enabled = 1;
+ adapter->mdump.md_enabled = 0;
return err;
@@ -328,6 +328,9 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS);
+ if (adapter->flags & NETXEN_FW_MSS_CAP)
+ cap |= NX_CAP0_HW_LRO_MSS;
+
prq->capabilities[0] = cpu_to_le32(cap);
prq->host_int_crb_mode =
cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED);
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
index 8c39299331a2..39730403782f 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
@@ -834,7 +834,7 @@ netxen_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
static int
netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val)
{
- int ret = 0;
+ int i;
struct netxen_adapter *adapter = netdev_priv(netdev);
struct netxen_minidump *mdump = &adapter->mdump;
@@ -844,7 +844,7 @@ netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val)
mdump->md_enabled = 1;
if (adapter->fw_mdump_rdy) {
netdev_info(netdev, "Previous dump not cleared, not forcing dump\n");
- return ret;
+ return 0;
}
netdev_info(netdev, "Forcing a fw dump\n");
nx_dev_request_reset(adapter);
@@ -867,19 +867,21 @@ netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val)
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",
+ for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) {
+ if (val->flag == FW_DUMP_LEVELS[i]) {
+ mdump->md_capture_mask = val->flag;
+ netdev_info(netdev,
+ "Driver mask changed to: 0x%x\n",
mdump->md_capture_mask);
- break;
+ return 0;
+ }
}
netdev_info(netdev,
"Invalid dump level: 0x%x\n", val->flag);
return -EINVAL;
}
- return ret;
+ return 0;
}
static int
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h
index b1a897cd9a8d..28e076960bcb 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h
@@ -776,6 +776,7 @@ enum {
#define CRB_SW_INT_MASK_3 (NETXEN_NIC_REG(0x1e8))
#define CRB_FW_CAPABILITIES_1 (NETXEN_CAM_RAM(0x128))
+#define CRB_FW_CAPABILITIES_2 (NETXEN_CAM_RAM(0x12c))
#define CRB_MAC_BLOCK_START (NETXEN_CAM_RAM(0x1c0))
/*
@@ -955,6 +956,31 @@ enum {
#define NX_CRB_DEV_REF_COUNT (NETXEN_CAM_RAM(0x138))
#define NX_CRB_DEV_STATE (NETXEN_CAM_RAM(0x140))
+/* MiniDIMM related macros */
+#define NETXEN_DIMM_CAPABILITY (NETXEN_CAM_RAM(0x258))
+#define NETXEN_DIMM_PRESENT 0x1
+#define NETXEN_DIMM_MEMTYPE_DDR2_SDRAM 0x2
+#define NETXEN_DIMM_SIZE 0x4
+#define NETXEN_DIMM_MEMTYPE(VAL) ((VAL >> 3) & 0xf)
+#define NETXEN_DIMM_NUMROWS(VAL) ((VAL >> 7) & 0xf)
+#define NETXEN_DIMM_NUMCOLS(VAL) ((VAL >> 11) & 0xf)
+#define NETXEN_DIMM_NUMRANKS(VAL) ((VAL >> 15) & 0x3)
+#define NETXEN_DIMM_DATAWIDTH(VAL) ((VAL >> 18) & 0x3)
+#define NETXEN_DIMM_NUMBANKS(VAL) ((VAL >> 21) & 0xf)
+#define NETXEN_DIMM_TYPE(VAL) ((VAL >> 25) & 0x3f)
+#define NETXEN_DIMM_VALID_FLAG 0x80000000
+
+#define NETXEN_DIMM_MEM_DDR2_SDRAM 0x8
+
+#define NETXEN_DIMM_STD_MEM_SIZE 512
+
+#define NETXEN_DIMM_TYPE_RDIMM 0x1
+#define NETXEN_DIMM_TYPE_UDIMM 0x2
+#define NETXEN_DIMM_TYPE_SO_DIMM 0x4
+#define NETXEN_DIMM_TYPE_Micro_DIMM 0x8
+#define NETXEN_DIMM_TYPE_Mini_RDIMM 0x10
+#define NETXEN_DIMM_TYPE_Mini_UDIMM 0x20
+
/* Device State */
#define NX_DEV_COLD 1
#define NX_DEV_INITALIZING 2
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
index 718b27440351..8694124ef77d 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
@@ -1131,7 +1131,6 @@ netxen_validate_firmware(struct netxen_adapter *adapter)
_build(file_fw_ver));
return -EINVAL;
}
-
val = nx_get_bios_version(adapter);
netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
if ((__force u32)val != bios) {
@@ -1261,8 +1260,7 @@ next:
void
netxen_release_firmware(struct netxen_adapter *adapter)
{
- if (adapter->fw)
- release_firmware(adapter->fw);
+ release_firmware(adapter->fw);
adapter->fw = NULL;
}
@@ -1661,6 +1659,9 @@ netxen_process_lro(struct netxen_adapter *adapter,
length = skb->len;
+ if (adapter->flags & NETXEN_FW_MSS_CAP)
+ skb_shinfo(skb)->gso_size = netxen_get_lro_sts_mss(sts_data1);
+
netif_receive_skb(skb);
adapter->stats.lro_pkts++;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 65a718f9ccd3..342b3a79bd0f 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1184,6 +1184,7 @@ netxen_nic_attach(struct netxen_adapter *adapter)
int err, ring;
struct nx_host_rds_ring *rds_ring;
struct nx_host_tx_ring *tx_ring;
+ u32 capab2;
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
return 0;
@@ -1192,6 +1193,13 @@ netxen_nic_attach(struct netxen_adapter *adapter)
if (err)
return err;
+ adapter->flags &= ~NETXEN_FW_MSS_CAP;
+ if (adapter->capabilities & NX_FW_CAPABILITY_MORE_CAPS) {
+ capab2 = NXRD32(adapter, CRB_FW_CAPABILITIES_2);
+ if (capab2 & NX_FW_CAPABILITY_2_LRO_MAX_TCP_SEG)
+ adapter->flags |= NETXEN_FW_MSS_CAP;
+ }
+
err = netxen_napi_add(adapter, netdev);
if (err)
return err;
@@ -1810,7 +1818,6 @@ netxen_tso_check(struct net_device *netdev,
flags = FLAGS_VLAN_TAGGED;
} else if (vlan_tx_tag_present(skb)) {
-
flags = FLAGS_VLAN_OOB;
vid = vlan_tx_tag_get(skb);
netxen_set_tx_vlan_tci(first_desc, vid);
@@ -2926,6 +2933,134 @@ static struct bin_attribute bin_attr_mem = {
.write = netxen_sysfs_write_mem,
};
+static ssize_t
+netxen_sysfs_read_dimm(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct netxen_adapter *adapter = dev_get_drvdata(dev);
+ struct net_device *netdev = adapter->netdev;
+ struct netxen_dimm_cfg dimm;
+ u8 dw, rows, cols, banks, ranks;
+ u32 val;
+
+ if (size != sizeof(struct netxen_dimm_cfg)) {
+ netdev_err(netdev, "Invalid size\n");
+ return -1;
+ }
+
+ memset(&dimm, 0, sizeof(struct netxen_dimm_cfg));
+ val = NXRD32(adapter, NETXEN_DIMM_CAPABILITY);
+
+ /* Checks if DIMM info is valid. */
+ if (val & NETXEN_DIMM_VALID_FLAG) {
+ netdev_err(netdev, "Invalid DIMM flag\n");
+ dimm.presence = 0xff;
+ goto out;
+ }
+
+ rows = NETXEN_DIMM_NUMROWS(val);
+ cols = NETXEN_DIMM_NUMCOLS(val);
+ ranks = NETXEN_DIMM_NUMRANKS(val);
+ banks = NETXEN_DIMM_NUMBANKS(val);
+ dw = NETXEN_DIMM_DATAWIDTH(val);
+
+ dimm.presence = (val & NETXEN_DIMM_PRESENT);
+
+ /* Checks if DIMM info is present. */
+ if (!dimm.presence) {
+ netdev_err(netdev, "DIMM not present\n");
+ goto out;
+ }
+
+ dimm.dimm_type = NETXEN_DIMM_TYPE(val);
+
+ switch (dimm.dimm_type) {
+ case NETXEN_DIMM_TYPE_RDIMM:
+ case NETXEN_DIMM_TYPE_UDIMM:
+ case NETXEN_DIMM_TYPE_SO_DIMM:
+ case NETXEN_DIMM_TYPE_Micro_DIMM:
+ case NETXEN_DIMM_TYPE_Mini_RDIMM:
+ case NETXEN_DIMM_TYPE_Mini_UDIMM:
+ break;
+ default:
+ netdev_err(netdev, "Invalid DIMM type %x\n", dimm.dimm_type);
+ goto out;
+ }
+
+ if (val & NETXEN_DIMM_MEMTYPE_DDR2_SDRAM)
+ dimm.mem_type = NETXEN_DIMM_MEM_DDR2_SDRAM;
+ else
+ dimm.mem_type = NETXEN_DIMM_MEMTYPE(val);
+
+ if (val & NETXEN_DIMM_SIZE) {
+ dimm.size = NETXEN_DIMM_STD_MEM_SIZE;
+ goto out;
+ }
+
+ if (!rows) {
+ netdev_err(netdev, "Invalid no of rows %x\n", rows);
+ goto out;
+ }
+
+ if (!cols) {
+ netdev_err(netdev, "Invalid no of columns %x\n", cols);
+ goto out;
+ }
+
+ if (!banks) {
+ netdev_err(netdev, "Invalid no of banks %x\n", banks);
+ goto out;
+ }
+
+ ranks += 1;
+
+ switch (dw) {
+ case 0x0:
+ dw = 32;
+ break;
+ case 0x1:
+ dw = 33;
+ break;
+ case 0x2:
+ dw = 36;
+ break;
+ case 0x3:
+ dw = 64;
+ break;
+ case 0x4:
+ dw = 72;
+ break;
+ case 0x5:
+ dw = 80;
+ break;
+ case 0x6:
+ dw = 128;
+ break;
+ case 0x7:
+ dw = 144;
+ break;
+ default:
+ netdev_err(netdev, "Invalid data-width %x\n", dw);
+ goto out;
+ }
+
+ dimm.size = ((1 << rows) * (1 << cols) * dw * banks * ranks) / 8;
+ /* Size returned in MB. */
+ dimm.size = (dimm.size) / 0x100000;
+out:
+ memcpy(buf, &dimm, sizeof(struct netxen_dimm_cfg));
+ return sizeof(struct netxen_dimm_cfg);
+
+}
+
+static struct bin_attribute bin_attr_dimm = {
+ .attr = { .name = "dimm", .mode = (S_IRUGO | S_IWUSR) },
+ .size = 0,
+ .read = netxen_sysfs_read_dimm,
+};
+
static void
netxen_create_sysfs_entries(struct netxen_adapter *adapter)
@@ -2963,6 +3098,8 @@ netxen_create_diag_entries(struct netxen_adapter *adapter)
dev_info(dev, "failed to create crb sysfs entry\n");
if (device_create_bin_file(dev, &bin_attr_mem))
dev_info(dev, "failed to create mem sysfs entry\n");
+ if (device_create_bin_file(dev, &bin_attr_dimm))
+ dev_info(dev, "failed to create dimm sysfs entry\n");
}
@@ -2975,6 +3112,7 @@ netxen_remove_diag_entries(struct netxen_adapter *adapter)
device_remove_file(dev, &dev_attr_diag_mode);
device_remove_bin_file(dev, &bin_attr_crb);
device_remove_bin_file(dev, &bin_attr_mem);
+ device_remove_bin_file(dev, &bin_attr_dimm);
}
#ifdef CONFIG_INET
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 385a4d5c7c25..8680a5dae4a2 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -36,8 +36,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 27
-#define QLCNIC_LINUX_VERSIONID "5.0.27"
+#define _QLCNIC_LINUX_SUBVERSION 28
+#define QLCNIC_LINUX_VERSIONID "5.0.28"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -607,6 +607,7 @@ struct qlcnic_recv_context {
#define QLCNIC_CDRP_CMD_CONFIG_PORT 0x0000002E
#define QLCNIC_CDRP_CMD_TEMP_SIZE 0x0000002f
#define QLCNIC_CDRP_CMD_GET_TEMP_HDR 0x00000030
+#define QLCNIC_CDRP_CMD_GET_MAC_STATS 0x00000037
#define QLCNIC_RCODE_SUCCESS 0
#define QLCNIC_RCODE_NOT_SUPPORTED 9
@@ -1180,18 +1181,62 @@ struct qlcnic_esw_func_cfg {
#define QLCNIC_STATS_ESWITCH 2
#define QLCNIC_QUERY_RX_COUNTER 0
#define QLCNIC_QUERY_TX_COUNTER 1
-#define QLCNIC_ESW_STATS_NOT_AVAIL 0xffffffffffffffffULL
+#define QLCNIC_STATS_NOT_AVAIL 0xffffffffffffffffULL
+#define QLCNIC_FILL_STATS(VAL1) \
+ (((VAL1) == QLCNIC_STATS_NOT_AVAIL) ? 0 : VAL1)
+#define QLCNIC_MAC_STATS 1
+#define QLCNIC_ESW_STATS 2
#define QLCNIC_ADD_ESW_STATS(VAL1, VAL2)\
do { \
- if (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) && \
- ((VAL2) != QLCNIC_ESW_STATS_NOT_AVAIL)) \
+ if (((VAL1) == QLCNIC_STATS_NOT_AVAIL) && \
+ ((VAL2) != QLCNIC_STATS_NOT_AVAIL)) \
(VAL1) = (VAL2); \
- else if (((VAL1) != QLCNIC_ESW_STATS_NOT_AVAIL) && \
- ((VAL2) != QLCNIC_ESW_STATS_NOT_AVAIL)) \
+ else if (((VAL1) != QLCNIC_STATS_NOT_AVAIL) && \
+ ((VAL2) != QLCNIC_STATS_NOT_AVAIL)) \
(VAL1) += (VAL2); \
} while (0)
+struct qlcnic_mac_statistics{
+ __le64 mac_tx_frames;
+ __le64 mac_tx_bytes;
+ __le64 mac_tx_mcast_pkts;
+ __le64 mac_tx_bcast_pkts;
+ __le64 mac_tx_pause_cnt;
+ __le64 mac_tx_ctrl_pkt;
+ __le64 mac_tx_lt_64b_pkts;
+ __le64 mac_tx_lt_127b_pkts;
+ __le64 mac_tx_lt_255b_pkts;
+ __le64 mac_tx_lt_511b_pkts;
+ __le64 mac_tx_lt_1023b_pkts;
+ __le64 mac_tx_lt_1518b_pkts;
+ __le64 mac_tx_gt_1518b_pkts;
+ __le64 rsvd1[3];
+
+ __le64 mac_rx_frames;
+ __le64 mac_rx_bytes;
+ __le64 mac_rx_mcast_pkts;
+ __le64 mac_rx_bcast_pkts;
+ __le64 mac_rx_pause_cnt;
+ __le64 mac_rx_ctrl_pkt;
+ __le64 mac_rx_lt_64b_pkts;
+ __le64 mac_rx_lt_127b_pkts;
+ __le64 mac_rx_lt_255b_pkts;
+ __le64 mac_rx_lt_511b_pkts;
+ __le64 mac_rx_lt_1023b_pkts;
+ __le64 mac_rx_lt_1518b_pkts;
+ __le64 mac_rx_gt_1518b_pkts;
+ __le64 rsvd2[3];
+
+ __le64 mac_rx_length_error;
+ __le64 mac_rx_length_small;
+ __le64 mac_rx_length_large;
+ __le64 mac_rx_jabber;
+ __le64 mac_rx_dropped;
+ __le64 mac_rx_crc_error;
+ __le64 mac_align_error;
+} __packed;
+
struct __qlcnic_esw_statistics {
__le16 context_id;
__le16 version;
@@ -1352,6 +1397,8 @@ enum op_codes {
#define QLCNIC_ENABLE_FW_DUMP 0xaddfeed
#define QLCNIC_DISABLE_FW_DUMP 0xbadfeed
#define QLCNIC_FORCE_FW_RESET 0xdeaddead
+#define QLCNIC_SET_QUIESCENT 0xadd00010
+#define QLCNIC_RESET_QUIESCENT 0xadd00020
struct qlcnic_dump_operations {
enum op_codes opcode;
@@ -1510,6 +1557,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8,
int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8,
struct __qlcnic_esw_statistics *);
int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
+int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *);
extern int qlcnic_config_tso;
/*
@@ -1559,6 +1607,7 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
}
extern const struct ethtool_ops qlcnic_ethtool_ops;
+extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
struct qlcnic_nic_template {
int (*config_bridged_mode) (struct qlcnic_adapter *, u32);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index 569a837d2ac4..8db85244e8ad 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -905,6 +905,65 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
return err;
}
+/* This routine will retrieve the MAC statistics from firmware */
+int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
+ struct qlcnic_mac_statistics *mac_stats)
+{
+ struct qlcnic_mac_statistics *stats;
+ struct qlcnic_cmd_args cmd;
+ size_t stats_size = sizeof(struct qlcnic_mac_statistics);
+ dma_addr_t stats_dma_t;
+ void *stats_addr;
+ int err;
+
+ stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
+ &stats_dma_t, GFP_KERNEL);
+ if (!stats_addr) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Unable to allocate memory.\n", __func__);
+ return -ENOMEM;
+ }
+ memset(stats_addr, 0, stats_size);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.req.cmd = QLCNIC_CDRP_CMD_GET_MAC_STATS;
+ cmd.req.arg1 = stats_size << 16;
+ cmd.req.arg2 = MSD(stats_dma_t);
+ cmd.req.arg3 = LSD(stats_dma_t);
+
+ qlcnic_issue_cmd(adapter, &cmd);
+ err = cmd.rsp.cmd;
+
+ if (!err) {
+ stats = stats_addr;
+ mac_stats->mac_tx_frames = le64_to_cpu(stats->mac_tx_frames);
+ mac_stats->mac_tx_bytes = le64_to_cpu(stats->mac_tx_bytes);
+ mac_stats->mac_tx_mcast_pkts =
+ le64_to_cpu(stats->mac_tx_mcast_pkts);
+ mac_stats->mac_tx_bcast_pkts =
+ le64_to_cpu(stats->mac_tx_bcast_pkts);
+ mac_stats->mac_rx_frames = le64_to_cpu(stats->mac_rx_frames);
+ mac_stats->mac_rx_bytes = le64_to_cpu(stats->mac_rx_bytes);
+ mac_stats->mac_rx_mcast_pkts =
+ le64_to_cpu(stats->mac_rx_mcast_pkts);
+ mac_stats->mac_rx_length_error =
+ le64_to_cpu(stats->mac_rx_length_error);
+ mac_stats->mac_rx_length_small =
+ le64_to_cpu(stats->mac_rx_length_small);
+ mac_stats->mac_rx_length_large =
+ le64_to_cpu(stats->mac_rx_length_large);
+ mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber);
+ mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped);
+ mac_stats->mac_rx_crc_error = le64_to_cpu(stats->mac_rx_crc_error);
+ } else {
+ dev_info(&adapter->pdev->dev,
+ "%s: Get mac stats failed =%d.\n", __func__, err);
+ }
+
+ dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
+ stats_dma_t);
+ return err;
+}
+
int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
@@ -920,13 +979,13 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
return -EIO;
memset(esw_stats, 0, sizeof(u64));
- esw_stats->unicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
- esw_stats->multicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
- esw_stats->broadcast_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
- esw_stats->dropped_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
- esw_stats->errors = QLCNIC_ESW_STATS_NOT_AVAIL;
- esw_stats->local_frames = QLCNIC_ESW_STATS_NOT_AVAIL;
- esw_stats->numbytes = QLCNIC_ESW_STATS_NOT_AVAIL;
+ esw_stats->unicast_frames = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->multicast_frames = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->broadcast_frames = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->dropped_frames = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->errors = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->local_frames = QLCNIC_STATS_NOT_AVAIL;
+ esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL;
esw_stats->context_id = eswitch;
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 89ddf7f7d7df..9e9e78a5c4d7 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -78,8 +78,46 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx numbytes",
};
-#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
+static const char qlcnic_mac_stats_strings [][ETH_GSTRING_LEN] = {
+ "mac_tx_frames",
+ "mac_tx_bytes",
+ "mac_tx_mcast_pkts",
+ "mac_tx_bcast_pkts",
+ "mac_tx_pause_cnt",
+ "mac_tx_ctrl_pkt",
+ "mac_tx_lt_64b_pkts",
+ "mac_tx_lt_127b_pkts",
+ "mac_tx_lt_255b_pkts",
+ "mac_tx_lt_511b_pkts",
+ "mac_tx_lt_1023b_pkts",
+ "mac_tx_lt_1518b_pkts",
+ "mac_tx_gt_1518b_pkts",
+ "mac_rx_frames",
+ "mac_rx_bytes",
+ "mac_rx_mcast_pkts",
+ "mac_rx_bcast_pkts",
+ "mac_rx_pause_cnt",
+ "mac_rx_ctrl_pkt",
+ "mac_rx_lt_64b_pkts",
+ "mac_rx_lt_127b_pkts",
+ "mac_rx_lt_255b_pkts",
+ "mac_rx_lt_511b_pkts",
+ "mac_rx_lt_1023b_pkts",
+ "mac_rx_lt_1518b_pkts",
+ "mac_rx_gt_1518b_pkts",
+ "mac_rx_length_error",
+ "mac_rx_length_small",
+ "mac_rx_length_large",
+ "mac_rx_jabber",
+ "mac_rx_dropped",
+ "mac_rx_crc_error",
+ "mac_align_error",
+};
+
+#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
+#define QLCNIC_MAC_STATS_LEN ARRAY_SIZE(qlcnic_mac_stats_strings)
#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
+#define QLCNIC_TOTAL_STATS_LEN QLCNIC_STATS_LEN + QLCNIC_MAC_STATS_LEN
static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
"Register_Test_on_offline",
@@ -644,8 +682,8 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset)
return QLCNIC_TEST_LEN;
case ETH_SS_STATS:
if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
- return QLCNIC_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
- return QLCNIC_STATS_LEN;
+ return QLCNIC_TOTAL_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
+ return QLCNIC_TOTAL_STATS_LEN;
default:
return -EOPNOTSUPP;
}
@@ -851,7 +889,7 @@ static void
qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
- int index, i;
+ int index, i, j;
switch (stringset) {
case ETH_SS_TEST:
@@ -864,6 +902,11 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
qlcnic_gstrings_stats[index].stat_string,
ETH_GSTRING_LEN);
}
+ for (j = 0; j < QLCNIC_MAC_STATS_LEN; index++, j++) {
+ memcpy(data + index * ETH_GSTRING_LEN,
+ qlcnic_mac_stats_strings[j],
+ ETH_GSTRING_LEN);
+ }
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
return;
for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
@@ -874,22 +917,64 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
}
}
-#define QLCNIC_FILL_ESWITCH_STATS(VAL1) \
- (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) ? 0 : VAL1)
-
static void
-qlcnic_fill_device_stats(int *index, u64 *data,
- struct __qlcnic_esw_statistics *stats)
+qlcnic_fill_stats(int *index, u64 *data, void *stats, int type)
{
int ind = *index;
- data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->unicast_frames);
- data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->multicast_frames);
- data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->broadcast_frames);
- data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->dropped_frames);
- data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->errors);
- data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->local_frames);
- data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->numbytes);
+ if (type == QLCNIC_MAC_STATS) {
+ struct qlcnic_mac_statistics *mac_stats =
+ (struct qlcnic_mac_statistics *)stats;
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts);
+ data[ind++] =
+ QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts);
+ data[ind++] =
+ QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts);
+ data[ind++] =
+ QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts);
+ data[ind++] =
+ QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts);
+ data[ind++] =
+ QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts);
+ data[ind++] =
+ QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error);
+ data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_align_error);
+ } else if (type == QLCNIC_ESW_STATS) {
+ struct __qlcnic_esw_statistics *esw_stats =
+ (struct __qlcnic_esw_statistics *)stats;
+ data[ind++] = QLCNIC_FILL_STATS(esw_stats->unicast_frames);
+ data[ind++] = QLCNIC_FILL_STATS(esw_stats->multicast_frames);
+ data[ind++] = QLCNIC_FILL_STATS(esw_stats->broadcast_frames);
+ data[ind++] = QLCNIC_FILL_STATS(esw_stats->dropped_frames);
+ data[ind++] = QLCNIC_FILL_STATS(esw_stats->errors);
+ data[ind++] = QLCNIC_FILL_STATS(esw_stats->local_frames);
+ data[ind++] = QLCNIC_FILL_STATS(esw_stats->numbytes);
+ }
*index = ind;
}
@@ -900,6 +985,7 @@ qlcnic_get_ethtool_stats(struct net_device *dev,
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
struct qlcnic_esw_statistics port_stats;
+ struct qlcnic_mac_statistics mac_stats;
int index, ret;
for (index = 0; index < QLCNIC_STATS_LEN; index++) {
@@ -911,6 +997,11 @@ qlcnic_get_ethtool_stats(struct net_device *dev,
sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
}
+ /* Retrieve MAC statistics from firmware */
+ memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
+ qlcnic_get_mac_stats(adapter, &mac_stats);
+ qlcnic_fill_stats(&index, data, &mac_stats, QLCNIC_MAC_STATS);
+
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
return;
@@ -920,14 +1011,14 @@ qlcnic_get_ethtool_stats(struct net_device *dev,
if (ret)
return;
- qlcnic_fill_device_stats(&index, data, &port_stats.rx);
+ qlcnic_fill_stats(&index, data, &port_stats.rx, QLCNIC_ESW_STATS);
ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
if (ret)
return;
- qlcnic_fill_device_stats(&index, data, &port_stats.tx);
+ qlcnic_fill_stats(&index, data, &port_stats.tx, QLCNIC_ESW_STATS);
}
static int qlcnic_set_led(struct net_device *dev,
@@ -1132,11 +1223,21 @@ qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+ if (!fw_dump->tmpl_hdr) {
+ netdev_err(adapter->netdev, "FW Dump not supported\n");
+ return -ENOTSUPP;
+ }
+
if (fw_dump->clr)
dump->len = fw_dump->tmpl_hdr->size + fw_dump->size;
else
dump->len = 0;
- dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
+
+ if (!fw_dump->enable)
+ dump->flag = ETH_FW_DUMP_DISABLE;
+ else
+ dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
+
dump->version = adapter->fw_version;
return 0;
}
@@ -1150,6 +1251,11 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+ if (!fw_dump->tmpl_hdr) {
+ netdev_err(netdev, "FW Dump not supported\n");
+ return -ENOTSUPP;
+ }
+
if (!fw_dump->clr) {
netdev_info(netdev, "Dump not available\n");
return -EINVAL;
@@ -1177,55 +1283,74 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
static int
qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
{
- int ret = 0;
+ int i;
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+ u32 state;
switch (val->flag) {
case QLCNIC_FORCE_FW_DUMP_KEY:
+ if (!fw_dump->tmpl_hdr) {
+ netdev_err(netdev, "FW dump not supported\n");
+ return -ENOTSUPP;
+ }
if (!fw_dump->enable) {
netdev_info(netdev, "FW dump not enabled\n");
- return ret;
+ return 0;
}
if (fw_dump->clr) {
netdev_info(netdev,
"Previous dump not cleared, not forcing dump\n");
- return ret;
+ return 0;
}
netdev_info(netdev, "Forcing a FW dump\n");
qlcnic_dev_request_reset(adapter);
break;
case QLCNIC_DISABLE_FW_DUMP:
- if (fw_dump->enable) {
+ if (fw_dump->enable && fw_dump->tmpl_hdr) {
netdev_info(netdev, "Disabling FW dump\n");
fw_dump->enable = 0;
}
- break;
+ return 0;
case QLCNIC_ENABLE_FW_DUMP:
- if (!fw_dump->enable && fw_dump->tmpl_hdr) {
+ if (!fw_dump->tmpl_hdr) {
+ netdev_err(netdev, "FW dump not supported\n");
+ return -ENOTSUPP;
+ }
+ if (!fw_dump->enable) {
netdev_info(netdev, "Enabling FW dump\n");
fw_dump->enable = 1;
}
- break;
+ return 0;
case QLCNIC_FORCE_FW_RESET:
netdev_info(netdev, "Forcing a FW reset\n");
qlcnic_dev_request_reset(adapter);
adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
- break;
+ return 0;
+ case QLCNIC_SET_QUIESCENT:
+ case QLCNIC_RESET_QUIESCENT:
+ state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
+ netdev_info(netdev, "Device in FAILED state\n");
+ return 0;
default:
- if (val->flag > QLCNIC_DUMP_MASK_MAX ||
- val->flag < QLCNIC_DUMP_MASK_MIN) {
- netdev_info(netdev,
- "Invalid dump level: 0x%x\n", val->flag);
- ret = -EINVAL;
- goto out;
+ if (!fw_dump->tmpl_hdr) {
+ netdev_err(netdev, "FW dump not supported\n");
+ return -ENOTSUPP;
+ }
+ for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) {
+ if (val->flag == FW_DUMP_LEVELS[i]) {
+ fw_dump->tmpl_hdr->drv_cap_mask =
+ val->flag;
+ netdev_info(netdev, "Driver mask changed to: 0x%x\n",
+ fw_dump->tmpl_hdr->drv_cap_mask);
+ return 0;
+ }
}
- fw_dump->tmpl_hdr->drv_cap_mask = val->flag & 0xff;
- netdev_info(netdev, "Driver mask changed to: 0x%x\n",
- fw_dump->tmpl_hdr->drv_cap_mask);
+ netdev_info(netdev, "Invalid dump level: 0x%x\n", val->flag);
+ return -EINVAL;
}
-out:
- return ret;
+ return 0;
}
const struct ethtool_ops qlcnic_ethtool_ops = {
@@ -1258,3 +1383,10 @@ const struct ethtool_ops qlcnic_ethtool_ops = {
.get_dump_data = qlcnic_get_dump_data,
.set_dump = qlcnic_set_dump,
};
+
+const struct ethtool_ops qlcnic_ethtool_failed_ops = {
+ .get_settings = qlcnic_get_settings,
+ .get_drvinfo = qlcnic_get_drvinfo,
+ .set_msglevel = qlcnic_set_msglevel,
+ .get_msglevel = qlcnic_get_msglevel,
+};
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index a52819303d1b..6ced3195aad3 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -704,6 +704,8 @@ enum {
#define QLCNIC_DEV_FAILED 0x6
#define QLCNIC_DEV_QUISCENT 0x7
+#define QLCNIC_DEV_BADBAD 0xbad0bad0
+
#define QLCNIC_DEV_NPAR_NON_OPER 0 /* NON Operational */
#define QLCNIC_DEV_NPAR_OPER 1 /* NPAR Operational */
#define QLCNIC_DEV_NPAR_OPER_TIMEO 30 /* Operational time out */
@@ -776,6 +778,10 @@ struct qlcnic_legacy_intr_set {
#define FLASH_ROM_WINDOW 0x42110030
#define FLASH_ROM_DATA 0x42150000
+
+static const u32 FW_DUMP_LEVELS[] = {
+ 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff };
+
static const u32 MIU_TEST_READ_DATA[] = {
0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC, };
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
index d32cf0ddf1b9..799fd40ed03a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -1321,8 +1321,7 @@ next:
void
qlcnic_release_firmware(struct qlcnic_adapter *adapter)
{
- if (adapter->fw)
- release_firmware(adapter->fw);
+ release_firmware(adapter->fw);
adapter->fw = NULL;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 75c32e875fef..46e77a2c5121 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -338,6 +338,10 @@ static const struct net_device_ops qlcnic_netdev_ops = {
#endif
};
+static const struct net_device_ops qlcnic_netdev_failed_ops = {
+ .ndo_open = qlcnic_open,
+};
+
static struct qlcnic_nic_template qlcnic_ops = {
.config_bridged_mode = qlcnic_config_bridged_mode,
.config_led = qlcnic_config_led,
@@ -1623,8 +1627,9 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = adapter->nic_ops->start_firmware(adapter);
if (err) {
- dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n");
- goto err_out_decr_ref;
+ dev_err(&pdev->dev, "Loading fw failed. Please Reboot\n"
+ "\t\tIf reboot doesn't help, try flashing the card\n");
+ goto err_out_maintenance_mode;
}
if (qlcnic_read_mac_addr(adapter))
@@ -1695,6 +1700,18 @@ err_out_disable_pdev:
pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
return err;
+
+err_out_maintenance_mode:
+ netdev->netdev_ops = &qlcnic_netdev_failed_ops;
+ SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops);
+ err = register_netdev(netdev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register net device\n");
+ goto err_out_decr_ref;
+ }
+ pci_set_drvdata(pdev, adapter);
+ qlcnic_create_diag_entries(adapter);
+ return 0;
}
static void __devexit qlcnic_remove(struct pci_dev *pdev)
@@ -1831,8 +1848,14 @@ done:
static int qlcnic_open(struct net_device *netdev)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
+ u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
int err;
+ if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) {
+ netdev_err(netdev, "Device in FAILED state\n");
+ return -EIO;
+ }
+
netif_carrier_off(netdev);
err = qlcnic_attach(adapter);
@@ -1942,7 +1965,7 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter,
__le16 vlan_id = 0;
u8 hindex;
- if (!compare_ether_addr(phdr->h_source, adapter->mac_addr))
+ if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
return;
if (adapter->fhash.fnum >= adapter->fhash.fmax)
@@ -2212,8 +2235,7 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (adapter->flags & QLCNIC_MACSPOOF) {
phdr = (struct ethhdr *)skb->data;
- if (compare_ether_addr(phdr->h_source,
- adapter->mac_addr))
+ if (!ether_addr_equal(phdr->h_source, adapter->mac_addr))
goto drop_packet;
}
@@ -3018,6 +3040,12 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
return;
state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+ if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) {
+ netdev_err(adapter->netdev,
+ "Device is in FAILED state, Please Reboot\n");
+ qlcnic_api_unlock(adapter);
+ return;
+ }
if (state == QLCNIC_DEV_READY) {
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET);
@@ -3061,6 +3089,9 @@ qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter)
while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
msleep(10);
+ if (!adapter->fw_work.work.func)
+ return;
+
cancel_delayed_work_sync(&adapter->fw_work);
}
@@ -4280,6 +4311,7 @@ static void
qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
+ u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
if (device_create_bin_file(dev, &bin_attr_port_stats))
dev_info(dev, "failed to create port stats sysfs entry");
@@ -4288,14 +4320,19 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
return;
if (device_create_file(dev, &dev_attr_diag_mode))
dev_info(dev, "failed to create diag_mode sysfs entry\n");
- if (device_create_file(dev, &dev_attr_beacon))
- dev_info(dev, "failed to create beacon sysfs entry");
if (device_create_bin_file(dev, &bin_attr_crb))
dev_info(dev, "failed to create crb sysfs entry\n");
if (device_create_bin_file(dev, &bin_attr_mem))
dev_info(dev, "failed to create mem sysfs entry\n");
+
+ if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
+ return;
+
if (device_create_bin_file(dev, &bin_attr_pci_config))
dev_info(dev, "failed to create pci config sysfs entry");
+ if (device_create_file(dev, &dev_attr_beacon))
+ dev_info(dev, "failed to create beacon sysfs entry");
+
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
return;
if (device_create_bin_file(dev, &bin_attr_esw_config))
@@ -4314,16 +4351,19 @@ static void
qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
+ u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
device_remove_bin_file(dev, &bin_attr_port_stats);
if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
return;
device_remove_file(dev, &dev_attr_diag_mode);
- device_remove_file(dev, &dev_attr_beacon);
device_remove_bin_file(dev, &bin_attr_crb);
device_remove_bin_file(dev, &bin_attr_mem);
+ if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
+ return;
device_remove_bin_file(dev, &bin_attr_pci_config);
+ device_remove_file(dev, &dev_attr_beacon);
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
return;
device_remove_bin_file(dev, &bin_attr_esw_config);
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index 49343ec21c82..09d8d33171df 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -3845,7 +3845,7 @@ static int ql_wol(struct ql_adapter *qdev)
if (qdev->wol & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_PHY | WAKE_UCAST |
WAKE_MCAST | WAKE_BCAST)) {
netif_err(qdev, ifdown, qdev->ndev,
- "Unsupported WOL paramter. qdev->wol = 0x%x.\n",
+ "Unsupported WOL parameter. qdev->wol = 0x%x.\n",
qdev->wol);
return -EINVAL;
}
diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c
index b96e1920e045..4de73643fec6 100644
--- a/drivers/net/ethernet/rdc/r6040.c
+++ b/drivers/net/ethernet/rdc/r6040.c
@@ -4,7 +4,7 @@
* Copyright (C) 2004 Sten Wang <sten.wang@rdc.com.tw>
* Copyright (C) 2007
* Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
- * Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2007-2012 Florian Fainelli <florian@openwrt.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -74,9 +74,13 @@
#define MT_ICR 0x0C /* TX interrupt control */
#define MR_ICR 0x10 /* RX interrupt control */
#define MTPR 0x14 /* TX poll command register */
+#define TM2TX 0x0001 /* Trigger MAC to transmit */
#define MR_BSR 0x18 /* RX buffer size */
#define MR_DCR 0x1A /* RX descriptor control */
#define MLSR 0x1C /* Last status */
+#define TX_FIFO_UNDR 0x0200 /* TX FIFO under-run */
+#define TX_EXCEEDC 0x2000 /* Transmit exceed collision */
+#define TX_LATEC 0x4000 /* Transmit late collision */
#define MMDIO 0x20 /* MDIO control register */
#define MDIO_WRITE 0x4000 /* MDIO write */
#define MDIO_READ 0x2000 /* MDIO read */
@@ -124,6 +128,9 @@
#define MID_3M 0x82 /* MID3 Medium */
#define MID_3H 0x84 /* MID3 High */
#define PHY_CC 0x88 /* PHY status change configuration register */
+#define SCEN 0x8000 /* PHY status change enable */
+#define PHYAD_SHIFT 8 /* PHY address shift */
+#define TMRDIV_SHIFT 0 /* Timer divider shift */
#define PHY_ST 0x8A /* PHY status register */
#define MAC_SM 0xAC /* MAC status machine */
#define MAC_SM_RST 0x0002 /* MAC status machine reset */
@@ -137,6 +144,8 @@
#define MBCR_DEFAULT 0x012A /* MAC Bus Control Register */
#define MCAST_MAX 3 /* Max number multicast addresses to filter */
+#define MAC_DEF_TIMEOUT 2048 /* Default MAC read/write operation timeout */
+
/* Descriptor status */
#define DSC_OWNER_MAC 0x8000 /* MAC is the owner of this descriptor */
#define DSC_RX_OK 0x4000 /* RX was successful */
@@ -187,7 +196,7 @@ struct r6040_private {
dma_addr_t rx_ring_dma;
dma_addr_t tx_ring_dma;
u16 tx_free_desc;
- u16 mcr0, mcr1;
+ u16 mcr0;
struct net_device *dev;
struct mii_bus *mii_bus;
struct napi_struct napi;
@@ -204,7 +213,7 @@ static char version[] __devinitdata = DRV_NAME
/* Read a word data from PHY Chip */
static int r6040_phy_read(void __iomem *ioaddr, int phy_addr, int reg)
{
- int limit = 2048;
+ int limit = MAC_DEF_TIMEOUT;
u16 cmd;
iowrite16(MDIO_READ + reg + (phy_addr << 8), ioaddr + MMDIO);
@@ -222,7 +231,7 @@ static int r6040_phy_read(void __iomem *ioaddr, int phy_addr, int reg)
static void r6040_phy_write(void __iomem *ioaddr,
int phy_addr, int reg, u16 val)
{
- int limit = 2048;
+ int limit = MAC_DEF_TIMEOUT;
u16 cmd;
iowrite16(val, ioaddr + MMWD);
@@ -358,27 +367,35 @@ err_exit:
return rc;
}
-static void r6040_init_mac_regs(struct net_device *dev)
+static void r6040_reset_mac(struct r6040_private *lp)
{
- struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
- int limit = 2048;
+ int limit = MAC_DEF_TIMEOUT;
u16 cmd;
- /* Mask Off Interrupt */
- iowrite16(MSK_INT, ioaddr + MIER);
-
- /* Reset RDC MAC */
iowrite16(MAC_RST, ioaddr + MCR1);
while (limit--) {
cmd = ioread16(ioaddr + MCR1);
if (cmd & MAC_RST)
break;
}
+
/* Reset internal state machine */
iowrite16(MAC_SM_RST, ioaddr + MAC_SM);
iowrite16(0, ioaddr + MAC_SM);
mdelay(5);
+}
+
+static void r6040_init_mac_regs(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
+
+ /* Mask Off Interrupt */
+ iowrite16(MSK_INT, ioaddr + MIER);
+
+ /* Reset RDC MAC */
+ r6040_reset_mac(lp);
/* MAC Bus Control Register */
iowrite16(MBCR_DEFAULT, ioaddr + MBCR);
@@ -407,7 +424,7 @@ static void r6040_init_mac_regs(struct net_device *dev)
/* Let TX poll the descriptors
* we may got called by r6040_tx_timeout which has left
* some unsent tx buffers */
- iowrite16(0x01, ioaddr + MTPR);
+ iowrite16(TM2TX, ioaddr + MTPR);
}
static void r6040_tx_timeout(struct net_device *dev)
@@ -445,18 +462,13 @@ static void r6040_down(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
- int limit = 2048;
u16 *adrp;
- u16 cmd;
/* Stop MAC */
iowrite16(MSK_INT, ioaddr + MIER); /* Mask Off Interrupt */
- iowrite16(MAC_RST, ioaddr + MCR1); /* Reset RDC MAC */
- while (limit--) {
- cmd = ioread16(ioaddr + MCR1);
- if (cmd & MAC_RST)
- break;
- }
+
+ /* Reset RDC MAC */
+ r6040_reset_mac(lp);
/* Restore MAC Address to MIDx */
adrp = (u16 *) dev->dev_addr;
@@ -599,9 +611,9 @@ static void r6040_tx(struct net_device *dev)
/* Check for errors */
err = ioread16(ioaddr + MLSR);
- if (err & 0x0200)
- dev->stats.rx_fifo_errors++;
- if (err & (0x2000 | 0x4000))
+ if (err & TX_FIFO_UNDR)
+ dev->stats.tx_fifo_errors++;
+ if (err & (TX_EXCEEDC | TX_LATEC))
dev->stats.tx_carrier_errors++;
if (descptr->status & DSC_OWNER_MAC)
@@ -736,11 +748,7 @@ static void r6040_mac_address(struct net_device *dev)
u16 *adrp;
/* Reset MAC */
- iowrite16(MAC_RST, ioaddr + MCR1);
- /* Reset internal state machine */
- iowrite16(MAC_SM_RST, ioaddr + MAC_SM);
- iowrite16(0, ioaddr + MAC_SM);
- mdelay(5);
+ r6040_reset_mac(lp);
/* Restore MAC Address */
adrp = (u16 *) dev->dev_addr;
@@ -840,7 +848,7 @@ static netdev_tx_t r6040_start_xmit(struct sk_buff *skb,
skb_tx_timestamp(skb);
/* Trigger the MAC to check the TX descriptor */
- iowrite16(0x01, ioaddr + MTPR);
+ iowrite16(TM2TX, ioaddr + MTPR);
lp->tx_insert_ptr = descptr->vndescp;
/* If no tx resource, stop */
@@ -973,6 +981,7 @@ static const struct ethtool_ops netdev_ethtool_ops = {
.get_settings = netdev_get_settings,
.set_settings = netdev_set_settings,
.get_link = ethtool_op_get_link,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static const struct net_device_ops r6040_netdev_ops = {
@@ -1126,10 +1135,15 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
err = -EIO;
goto err_out_free_res;
}
+
/* If PHY status change register is still set to zero it means the
- * bootloader didn't initialize it */
+ * bootloader didn't initialize it, so we set it to:
+ * - enable phy status change
+ * - enable all phy addresses
+ * - set to lowest timer divider */
if (ioread16(ioaddr + PHY_CC) == 0)
- iowrite16(0x9f07, ioaddr + PHY_CC);
+ iowrite16(SCEN | PHY_MAX_ADDR << PHYAD_SHIFT |
+ 7 << TMRDIV_SHIFT, ioaddr + PHY_CC);
/* Init system & device */
lp->base = ioaddr;
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index b3287c0fe279..5eef290997f9 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -635,9 +635,12 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
*/
static void cp_poll_controller(struct net_device *dev)
{
- disable_irq(dev->irq);
- cp_interrupt(dev->irq, dev);
- enable_irq(dev->irq);
+ struct cp_private *cp = netdev_priv(dev);
+ const int irq = cp->pdev->irq;
+
+ disable_irq(irq);
+ cp_interrupt(irq, dev);
+ enable_irq(irq);
}
#endif
@@ -1117,6 +1120,7 @@ static void cp_free_rings (struct cp_private *cp)
static int cp_open (struct net_device *dev)
{
struct cp_private *cp = netdev_priv(dev);
+ const int irq = cp->pdev->irq;
int rc;
netif_dbg(cp, ifup, dev, "enabling interface\n");
@@ -1129,7 +1133,7 @@ static int cp_open (struct net_device *dev)
cp_init_hw(cp);
- rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev);
+ rc = request_irq(irq, cp_interrupt, IRQF_SHARED, dev->name, dev);
if (rc)
goto err_out_hw;
@@ -1166,7 +1170,7 @@ static int cp_close (struct net_device *dev)
spin_unlock_irqrestore(&cp->lock, flags);
- free_irq(dev->irq, dev);
+ free_irq(cp->pdev->irq, dev);
cp_free_rings(cp);
return 0;
@@ -1914,7 +1918,6 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
(unsigned long long)pciaddr);
goto err_out_res;
}
- dev->base_addr = (unsigned long) regs;
cp->regs = regs;
cp_stop_hw(cp);
@@ -1942,14 +1945,12 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
NETIF_F_HIGHDMA;
- dev->irq = pdev->irq;
-
rc = register_netdev(dev);
if (rc)
goto err_out_iomap;
- netdev_info(dev, "RTL-8139C+ at 0x%lx, %pM, IRQ %d\n",
- dev->base_addr, dev->dev_addr, dev->irq);
+ netdev_info(dev, "RTL-8139C+ at 0x%p, %pM, IRQ %d\n",
+ regs, dev->dev_addr, pdev->irq);
pci_set_drvdata(pdev, dev);
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index df7fd8d083dc..03df076ed596 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -148,9 +148,9 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
/* Whether to use MMIO or PIO. Default to MMIO. */
#ifdef CONFIG_8139TOO_PIO
-static int use_io = 1;
+static bool use_io = true;
#else
-static int use_io = 0;
+static bool use_io = false;
#endif
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
@@ -620,7 +620,7 @@ MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-module_param(use_io, int, 0);
+module_param(use_io, bool, 0);
MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO");
module_param(multicast_filter_limit, int, 0);
module_param_array(media, int, NULL, 0);
@@ -750,15 +750,22 @@ static void rtl8139_chip_reset (void __iomem *ioaddr)
static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev)
{
+ struct device *d = &pdev->dev;
void __iomem *ioaddr;
struct net_device *dev;
struct rtl8139_private *tp;
u8 tmp8;
int rc, disable_dev_on_err = 0;
- unsigned int i;
- unsigned long pio_start, pio_end, pio_flags, pio_len;
- unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
+ unsigned int i, bar;
+ unsigned long io_len;
u32 version;
+ static const struct {
+ unsigned long mask;
+ char *type;
+ } res[] = {
+ { IORESOURCE_IO, "PIO" },
+ { IORESOURCE_MEM, "MMIO" }
+ };
assert (pdev != NULL);
@@ -777,78 +784,45 @@ static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev)
if (rc)
goto err_out;
- pio_start = pci_resource_start (pdev, 0);
- pio_end = pci_resource_end (pdev, 0);
- pio_flags = pci_resource_flags (pdev, 0);
- pio_len = pci_resource_len (pdev, 0);
-
- mmio_start = pci_resource_start (pdev, 1);
- mmio_end = pci_resource_end (pdev, 1);
- mmio_flags = pci_resource_flags (pdev, 1);
- mmio_len = pci_resource_len (pdev, 1);
-
- /* set this immediately, we need to know before
- * we talk to the chip directly */
- pr_debug("PIO region size == 0x%02lX\n", pio_len);
- pr_debug("MMIO region size == 0x%02lX\n", mmio_len);
-
-retry:
- if (use_io) {
- /* make sure PCI base addr 0 is PIO */
- if (!(pio_flags & IORESOURCE_IO)) {
- dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
- /* check for weird/broken PCI region reporting */
- if (pio_len < RTL_MIN_IO_SIZE) {
- dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
- } else {
- /* make sure PCI base addr 1 is MMIO */
- if (!(mmio_flags & IORESOURCE_MEM)) {
- dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
- if (mmio_len < RTL_MIN_IO_SIZE) {
- dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
- }
-
rc = pci_request_regions (pdev, DRV_NAME);
if (rc)
goto err_out;
disable_dev_on_err = 1;
- /* enable PCI bus-mastering */
pci_set_master (pdev);
- if (use_io) {
- ioaddr = pci_iomap(pdev, 0, 0);
- if (!ioaddr) {
- dev_err(&pdev->dev, "cannot map PIO, aborting\n");
- rc = -EIO;
- goto err_out;
- }
- dev->base_addr = pio_start;
- tp->regs_len = pio_len;
- } else {
- /* ioremap MMIO region */
- ioaddr = pci_iomap(pdev, 1, 0);
- if (ioaddr == NULL) {
- dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n");
- pci_release_regions(pdev);
- use_io = 1;
+retry:
+ /* PIO bar register comes first. */
+ bar = !use_io;
+
+ io_len = pci_resource_len(pdev, bar);
+
+ dev_dbg(d, "%s region size = 0x%02lX\n", res[bar].type, io_len);
+
+ if (!(pci_resource_flags(pdev, bar) & res[bar].mask)) {
+ dev_err(d, "region #%d not a %s resource, aborting\n", bar,
+ res[bar].type);
+ rc = -ENODEV;
+ goto err_out;
+ }
+ if (io_len < RTL_MIN_IO_SIZE) {
+ dev_err(d, "Invalid PCI %s region size(s), aborting\n",
+ res[bar].type);
+ rc = -ENODEV;
+ goto err_out;
+ }
+
+ ioaddr = pci_iomap(pdev, bar, 0);
+ if (!ioaddr) {
+ dev_err(d, "cannot map %s\n", res[bar].type);
+ if (!use_io) {
+ use_io = true;
goto retry;
}
- dev->base_addr = (long) ioaddr;
- tp->regs_len = mmio_len;
+ rc = -ENODEV;
+ goto err_out;
}
+ tp->regs_len = io_len;
tp->mmio_addr = ioaddr;
/* Bring old chips out of low-power mode. */
@@ -1035,8 +1009,6 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
dev->hw_features |= NETIF_F_RXALL;
dev->hw_features |= NETIF_F_RXFCS;
- dev->irq = pdev->irq;
-
/* tp zeroed and aligned in alloc_etherdev */
tp = netdev_priv(dev);
@@ -1062,9 +1034,9 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
pci_set_drvdata (pdev, dev);
- netdev_info(dev, "%s at 0x%lx, %pM, IRQ %d\n",
+ netdev_info(dev, "%s at 0x%p, %pM, IRQ %d\n",
board_info[ent->driver_data].name,
- dev->base_addr, dev->dev_addr, dev->irq);
+ ioaddr, dev->dev_addr, pdev->irq);
netdev_dbg(dev, "Identified 8139 chip type '%s'\n",
rtl_chip_info[tp->chipset].name);
@@ -1339,10 +1311,11 @@ static void mdio_write (struct net_device *dev, int phy_id, int location,
static int rtl8139_open (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
- int retval;
void __iomem *ioaddr = tp->mmio_addr;
+ const int irq = tp->pci_dev->irq;
+ int retval;
- retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev);
+ retval = request_irq(irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev);
if (retval)
return retval;
@@ -1351,7 +1324,7 @@ static int rtl8139_open (struct net_device *dev)
tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN,
&tp->rx_ring_dma, GFP_KERNEL);
if (tp->tx_bufs == NULL || tp->rx_ring == NULL) {
- free_irq(dev->irq, dev);
+ free_irq(irq, dev);
if (tp->tx_bufs)
dma_free_coherent(&tp->pci_dev->dev, TX_BUF_TOT_LEN,
@@ -1377,7 +1350,7 @@ static int rtl8139_open (struct net_device *dev)
"%s() ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n",
__func__,
(unsigned long long)pci_resource_start (tp->pci_dev, 1),
- dev->irq, RTL_R8 (MediaStatus),
+ irq, RTL_R8 (MediaStatus),
tp->mii.full_duplex ? "full" : "half");
rtl8139_start_thread(tp);
@@ -2240,9 +2213,12 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
*/
static void rtl8139_poll_controller(struct net_device *dev)
{
- disable_irq(dev->irq);
- rtl8139_interrupt(dev->irq, dev);
- enable_irq(dev->irq);
+ struct rtl8139_private *tp = netdev_priv(dev);
+ const int irq = tp->pci_dev->irq;
+
+ disable_irq(irq);
+ rtl8139_interrupt(irq, dev);
+ enable_irq(irq);
}
#endif
@@ -2295,7 +2271,7 @@ static int rtl8139_close (struct net_device *dev)
spin_unlock_irqrestore (&tp->lock, flags);
- free_irq (dev->irq, dev);
+ free_irq(tp->pci_dev->irq, dev);
rtl8139_tx_clear (tp);
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index f54509377efa..00b4f56a671c 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -44,6 +44,8 @@
#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw"
#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw"
#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw"
+#define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw"
+#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw"
#ifdef RTL8169_DEBUG
#define assert(expr) \
@@ -61,8 +63,12 @@
#define R8169_MSG_DEFAULT \
(NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
-#define TX_BUFFS_AVAIL(tp) \
- (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1)
+#define TX_SLOTS_AVAIL(tp) \
+ (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx)
+
+/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
+#define TX_FRAGS_READY_FOR(tp,nr_frags) \
+ (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1))
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
The RTL chips use a 64 element hash table based on the Ethernet CRC. */
@@ -133,6 +139,8 @@ enum mac_version {
RTL_GIGA_MAC_VER_34,
RTL_GIGA_MAC_VER_35,
RTL_GIGA_MAC_VER_36,
+ RTL_GIGA_MAC_VER_37,
+ RTL_GIGA_MAC_VER_38,
RTL_GIGA_MAC_NONE = 0xff,
};
@@ -245,6 +253,12 @@ static const struct {
[RTL_GIGA_MAC_VER_36] =
_R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2,
JUMBO_9K, false),
+ [RTL_GIGA_MAC_VER_37] =
+ _R("RTL8402", RTL_TD_1, FIRMWARE_8402_1,
+ JUMBO_1K, true),
+ [RTL_GIGA_MAC_VER_38] =
+ _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1,
+ JUMBO_9K, false),
};
#undef _R
@@ -315,6 +329,8 @@ enum rtl_registers {
Config0 = 0x51,
Config1 = 0x52,
Config2 = 0x53,
+#define PME_SIGNAL (1 << 5) /* 8168c and later */
+
Config3 = 0x54,
Config4 = 0x55,
Config5 = 0x56,
@@ -355,6 +371,9 @@ enum rtl8168_8101_registers {
#define CSIAR_BYTE_ENABLE 0x0f
#define CSIAR_BYTE_ENABLE_SHIFT 12
#define CSIAR_ADDR_MASK 0x0fff
+#define CSIAR_FUNC_CARD 0x00000000
+#define CSIAR_FUNC_SDIO 0x00010000
+#define CSIAR_FUNC_NIC 0x00020000
PMCH = 0x6f,
EPHYAR = 0x80,
#define EPHYAR_FLAG 0x80000000
@@ -716,6 +735,11 @@ struct rtl8169_private {
void (*disable)(struct rtl8169_private *);
} jumbo_ops;
+ struct csi_ops {
+ void (*write)(void __iomem *, int, int);
+ u32 (*read)(void __iomem *, int);
+ } csi_ops;
+
int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
int (*get_settings)(struct net_device *, struct ethtool_cmd *);
void (*phy_reset_enable)(struct rtl8169_private *tp);
@@ -768,6 +792,8 @@ MODULE_FIRMWARE(FIRMWARE_8168E_3);
MODULE_FIRMWARE(FIRMWARE_8105E_1);
MODULE_FIRMWARE(FIRMWARE_8168F_1);
MODULE_FIRMWARE(FIRMWARE_8168F_2);
+MODULE_FIRMWARE(FIRMWARE_8402_1);
+MODULE_FIRMWARE(FIRMWARE_8411_1);
static void rtl_lock_work(struct rtl8169_private *tp)
{
@@ -1078,40 +1104,6 @@ static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr)
return value;
}
-static void rtl_csi_write(void __iomem *ioaddr, int addr, int value)
-{
- unsigned int i;
-
- RTL_W32(CSIDR, value);
- RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
- CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
-
- for (i = 0; i < 100; i++) {
- if (!(RTL_R32(CSIAR) & CSIAR_FLAG))
- break;
- udelay(10);
- }
-}
-
-static u32 rtl_csi_read(void __iomem *ioaddr, int addr)
-{
- u32 value = ~0x00;
- unsigned int i;
-
- RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
- CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
-
- for (i = 0; i < 100; i++) {
- if (RTL_R32(CSIAR) & CSIAR_FLAG) {
- value = RTL_R32(CSIDR);
- break;
- }
- udelay(10);
- }
-
- return value;
-}
-
static
void rtl_eri_write(void __iomem *ioaddr, int addr, u32 mask, u32 val, int type)
{
@@ -1281,7 +1273,8 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp)
if (!netif_running(dev))
return;
- if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
+ if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_38) {
if (RTL_R8(PHYstatus) & _1000bpsF) {
rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111,
0x00000011, ERIAR_EXGMAC);
@@ -1316,6 +1309,16 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp)
rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111,
0x0000003f, ERIAR_EXGMAC);
}
+ } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
+ if (RTL_R8(PHYstatus) & _10bps) {
+ rtl_eri_write(ioaddr, 0x1d0, ERIAR_MASK_0011,
+ 0x4d02, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_0011,
+ 0x0060, ERIAR_EXGMAC);
+ } else {
+ rtl_eri_write(ioaddr, 0x1d0, ERIAR_MASK_0011,
+ 0x0000, ERIAR_EXGMAC);
+ }
}
}
@@ -1396,7 +1399,6 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
u16 reg;
u8 mask;
} cfg[] = {
- { WAKE_ANY, Config1, PMEnable },
{ WAKE_PHY, Config3, LinkUp },
{ WAKE_MAGIC, Config3, MagicPacket },
{ WAKE_UCAST, Config5, UWF },
@@ -1404,16 +1406,32 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
{ WAKE_MCAST, Config5, MWF },
{ WAKE_ANY, Config5, LanWake }
};
+ u8 options;
RTL_W8(Cfg9346, Cfg9346_Unlock);
for (i = 0; i < ARRAY_SIZE(cfg); i++) {
- u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
+ options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
if (wolopts & cfg[i].opt)
options |= cfg[i].mask;
RTL_W8(cfg[i].reg, options);
}
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17:
+ options = RTL_R8(Config1) & ~PMEnable;
+ if (wolopts)
+ options |= PMEnable;
+ RTL_W8(Config1, options);
+ break;
+ default:
+ options = RTL_R8(Config2) & ~PME_SIGNAL;
+ if (wolopts)
+ options |= PME_SIGNAL;
+ RTL_W8(Config2, options);
+ break;
+ }
+
RTL_W8(Cfg9346, Cfg9346_Lock);
}
@@ -1853,6 +1871,7 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_strings = rtl8169_get_strings,
.get_sset_count = rtl8169_get_sset_count,
.get_ethtool_stats = rtl8169_get_ethtool_stats,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static void rtl8169_get_mac_version(struct rtl8169_private *tp,
@@ -1876,6 +1895,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
int mac_version;
} mac_info[] = {
/* 8168F family. */
+ { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 },
{ 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
{ 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
@@ -1913,6 +1933,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
{ 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
/* 8101 family. */
+ { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 },
{ 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 },
{ 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 },
{ 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 },
@@ -3013,6 +3034,28 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x1f, 0x0000);
}
+static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
+{
+ /* For 4-corner performance improve */
+ rtl_writephy(tp, 0x1f, 0x0005);
+ rtl_writephy(tp, 0x05, 0x8b80);
+ rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* PHY auto speed down */
+ rtl_writephy(tp, 0x1f, 0x0007);
+ rtl_writephy(tp, 0x1e, 0x002d);
+ rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+ rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
+
+ /* Improve 10M EEE waveform */
+ rtl_writephy(tp, 0x1f, 0x0005);
+ rtl_writephy(tp, 0x05, 0x8b86);
+ rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+}
+
static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
{
static const struct phy_reg phy_reg_init[] = {
@@ -3054,24 +3097,7 @@ static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
- /* For 4-corner performance improve */
- rtl_writephy(tp, 0x1f, 0x0005);
- rtl_writephy(tp, 0x05, 0x8b80);
- rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0000);
-
- /* PHY auto speed down */
- rtl_writephy(tp, 0x1f, 0x0007);
- rtl_writephy(tp, 0x1e, 0x002d);
- rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0000);
- rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
-
- /* Improve 10M EEE waveform */
- rtl_writephy(tp, 0x1f, 0x0005);
- rtl_writephy(tp, 0x05, 0x8b86);
- rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
- rtl_writephy(tp, 0x1f, 0x0000);
+ rtl8168f_hw_phy_config(tp);
/* Improve 2-pair detection performance */
rtl_writephy(tp, 0x1f, 0x0005);
@@ -3084,23 +3110,104 @@ static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
{
rtl_apply_firmware(tp);
- /* For 4-corner performance improve */
+ rtl8168f_hw_phy_config(tp);
+}
+
+static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ static const struct phy_reg phy_reg_init[] = {
+ /* Channel estimation fine tune */
+ { 0x1f, 0x0003 },
+ { 0x09, 0xa20f },
+ { 0x1f, 0x0000 },
+
+ /* Modify green table for giga & fnet */
+ { 0x1f, 0x0005 },
+ { 0x05, 0x8b55 },
+ { 0x06, 0x0000 },
+ { 0x05, 0x8b5e },
+ { 0x06, 0x0000 },
+ { 0x05, 0x8b67 },
+ { 0x06, 0x0000 },
+ { 0x05, 0x8b70 },
+ { 0x06, 0x0000 },
+ { 0x1f, 0x0000 },
+ { 0x1f, 0x0007 },
+ { 0x1e, 0x0078 },
+ { 0x17, 0x0000 },
+ { 0x19, 0x00aa },
+ { 0x1f, 0x0000 },
+
+ /* Modify green table for 10M */
+ { 0x1f, 0x0005 },
+ { 0x05, 0x8b79 },
+ { 0x06, 0xaa00 },
+ { 0x1f, 0x0000 },
+
+ /* Disable hiimpedance detection (RTCT) */
+ { 0x1f, 0x0003 },
+ { 0x01, 0x328a },
+ { 0x1f, 0x0000 }
+ };
+
+
+ rtl_apply_firmware(tp);
+
+ rtl8168f_hw_phy_config(tp);
+
+ /* Improve 2-pair detection performance */
rtl_writephy(tp, 0x1f, 0x0005);
- rtl_writephy(tp, 0x05, 0x8b80);
- rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
+ rtl_writephy(tp, 0x05, 0x8b85);
+ rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
rtl_writephy(tp, 0x1f, 0x0000);
- /* PHY auto speed down */
- rtl_writephy(tp, 0x1f, 0x0007);
- rtl_writephy(tp, 0x1e, 0x002d);
- rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
+ rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+ /* Modify green table for giga */
+ rtl_writephy(tp, 0x1f, 0x0005);
+ rtl_writephy(tp, 0x05, 0x8b54);
+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
+ rtl_writephy(tp, 0x05, 0x8b5d);
+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
+ rtl_writephy(tp, 0x05, 0x8a7c);
+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
+ rtl_writephy(tp, 0x05, 0x8a7f);
+ rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000);
+ rtl_writephy(tp, 0x05, 0x8a82);
+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
+ rtl_writephy(tp, 0x05, 0x8a85);
+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
+ rtl_writephy(tp, 0x05, 0x8a88);
+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
rtl_writephy(tp, 0x1f, 0x0000);
- rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
- /* Improve 10M EEE waveform */
+ /* uc same-seed solution */
rtl_writephy(tp, 0x1f, 0x0005);
- rtl_writephy(tp, 0x05, 0x8b86);
- rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
+ rtl_writephy(tp, 0x05, 0x8b85);
+ rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000);
+ rtl_writephy(tp, 0x1f, 0x0000);
+
+ /* eee setting */
+ rtl_w1w0_eri(ioaddr, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC);
+ rtl_writephy(tp, 0x1f, 0x0005);
+ rtl_writephy(tp, 0x05, 0x8b85);
+ rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
+ rtl_writephy(tp, 0x1f, 0x0004);
+ rtl_writephy(tp, 0x1f, 0x0007);
+ rtl_writephy(tp, 0x1e, 0x0020);
+ rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
+ rtl_writephy(tp, 0x1f, 0x0000);
+ rtl_writephy(tp, 0x0d, 0x0007);
+ rtl_writephy(tp, 0x0e, 0x003c);
+ rtl_writephy(tp, 0x0d, 0x4007);
+ rtl_writephy(tp, 0x0e, 0x0000);
+ rtl_writephy(tp, 0x0d, 0x0000);
+
+ /* Green feature */
+ rtl_writephy(tp, 0x1f, 0x0003);
+ rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
+ rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
rtl_writephy(tp, 0x1f, 0x0000);
}
@@ -3147,6 +3254,25 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
}
+static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ /* Disable ALDPS before setting firmware */
+ rtl_writephy(tp, 0x1f, 0x0000);
+ rtl_writephy(tp, 0x18, 0x0310);
+ msleep(20);
+
+ rtl_apply_firmware(tp);
+
+ /* EEE setting */
+ rtl_eri_write(ioaddr, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+ rtl_writephy(tp, 0x1f, 0x0004);
+ rtl_writephy(tp, 0x10, 0x401f);
+ rtl_writephy(tp, 0x19, 0x7030);
+ rtl_writephy(tp, 0x1f, 0x0000);
+}
+
static void rtl_hw_phy_config(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -3235,6 +3361,14 @@ static void rtl_hw_phy_config(struct net_device *dev)
rtl8168f_2_hw_phy_config(tp);
break;
+ case RTL_GIGA_MAC_VER_37:
+ rtl8402_hw_phy_config(tp);
+ break;
+
+ case RTL_GIGA_MAC_VER_38:
+ rtl8411_hw_phy_config(tp);
+ break;
+
default:
break;
}
@@ -3472,6 +3606,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_32:
case RTL_GIGA_MAC_VER_33:
case RTL_GIGA_MAC_VER_34:
+ case RTL_GIGA_MAC_VER_37:
+ case RTL_GIGA_MAC_VER_38:
RTL_W32(RxConfig, RTL_R32(RxConfig) |
AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
break;
@@ -3507,15 +3643,45 @@ static void r810x_phy_power_up(struct rtl8169_private *tp)
static void r810x_pll_power_down(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
+
if (rtl_wol_pll_power_down(tp))
return;
r810x_phy_power_down(tp);
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_07:
+ case RTL_GIGA_MAC_VER_08:
+ case RTL_GIGA_MAC_VER_09:
+ case RTL_GIGA_MAC_VER_10:
+ case RTL_GIGA_MAC_VER_13:
+ case RTL_GIGA_MAC_VER_16:
+ break;
+ default:
+ RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
+ break;
+ }
}
static void r810x_pll_power_up(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
+
r810x_phy_power_up(tp);
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_07:
+ case RTL_GIGA_MAC_VER_08:
+ case RTL_GIGA_MAC_VER_09:
+ case RTL_GIGA_MAC_VER_10:
+ case RTL_GIGA_MAC_VER_13:
+ case RTL_GIGA_MAC_VER_16:
+ break;
+ default:
+ RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
+ break;
+ }
}
static void r8168_phy_power_up(struct rtl8169_private *tp)
@@ -3619,13 +3785,6 @@ static void r8168_pll_power_up(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
- tp->mac_version == RTL_GIGA_MAC_VER_28 ||
- tp->mac_version == RTL_GIGA_MAC_VER_31) &&
- r8168dp_check_dash(tp)) {
- return;
- }
-
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_25:
case RTL_GIGA_MAC_VER_26:
@@ -3670,6 +3829,7 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_16:
case RTL_GIGA_MAC_VER_29:
case RTL_GIGA_MAC_VER_30:
+ case RTL_GIGA_MAC_VER_37:
ops->down = r810x_pll_power_down;
ops->up = r810x_pll_power_up;
break;
@@ -3694,6 +3854,7 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_34:
case RTL_GIGA_MAC_VER_35:
case RTL_GIGA_MAC_VER_36:
+ case RTL_GIGA_MAC_VER_38:
ops->down = r8168_pll_power_down;
ops->up = r8168_pll_power_up;
break;
@@ -3979,7 +4140,9 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
udelay(20);
} else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
tp->mac_version == RTL_GIGA_MAC_VER_35 ||
- tp->mac_version == RTL_GIGA_MAC_VER_36) {
+ tp->mac_version == RTL_GIGA_MAC_VER_36 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_37 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_38) {
RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
while (!(RTL_R32(TxConfig) & TXCFG_EMPTY))
udelay(100);
@@ -4185,22 +4348,141 @@ static void rtl_hw_start_8169(struct net_device *dev)
RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
}
-static void rtl_csi_access_enable(void __iomem *ioaddr, u32 bits)
+static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
+{
+ if (tp->csi_ops.write)
+ tp->csi_ops.write(tp->mmio_addr, addr, value);
+}
+
+static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
+{
+ if (tp->csi_ops.read)
+ return tp->csi_ops.read(tp->mmio_addr, addr);
+ else
+ return ~0;
+}
+
+static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits)
{
u32 csi;
- csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff;
- rtl_csi_write(ioaddr, 0x070c, csi | bits);
+ csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
+ rtl_csi_write(tp, 0x070c, csi | bits);
+}
+
+static void rtl_csi_access_enable_1(struct rtl8169_private *tp)
+{
+ rtl_csi_access_enable(tp, 0x17000000);
+}
+
+static void rtl_csi_access_enable_2(struct rtl8169_private *tp)
+{
+ rtl_csi_access_enable(tp, 0x27000000);
+}
+
+static void r8169_csi_write(void __iomem *ioaddr, int addr, int value)
+{
+ unsigned int i;
+
+ RTL_W32(CSIDR, value);
+ RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
+
+ for (i = 0; i < 100; i++) {
+ if (!(RTL_R32(CSIAR) & CSIAR_FLAG))
+ break;
+ udelay(10);
+ }
+}
+
+static u32 r8169_csi_read(void __iomem *ioaddr, int addr)
+{
+ u32 value = ~0x00;
+ unsigned int i;
+
+ RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
+
+ for (i = 0; i < 100; i++) {
+ if (RTL_R32(CSIAR) & CSIAR_FLAG) {
+ value = RTL_R32(CSIDR);
+ break;
+ }
+ udelay(10);
+ }
+
+ return value;
+}
+
+static void r8402_csi_write(void __iomem *ioaddr, int addr, int value)
+{
+ unsigned int i;
+
+ RTL_W32(CSIDR, value);
+ RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT |
+ CSIAR_FUNC_NIC);
+
+ for (i = 0; i < 100; i++) {
+ if (!(RTL_R32(CSIAR) & CSIAR_FLAG))
+ break;
+ udelay(10);
+ }
}
-static void rtl_csi_access_enable_1(void __iomem *ioaddr)
+static u32 r8402_csi_read(void __iomem *ioaddr, int addr)
{
- rtl_csi_access_enable(ioaddr, 0x17000000);
+ u32 value = ~0x00;
+ unsigned int i;
+
+ RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC |
+ CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
+
+ for (i = 0; i < 100; i++) {
+ if (RTL_R32(CSIAR) & CSIAR_FLAG) {
+ value = RTL_R32(CSIDR);
+ break;
+ }
+ udelay(10);
+ }
+
+ return value;
}
-static void rtl_csi_access_enable_2(void __iomem *ioaddr)
+static void __devinit rtl_init_csi_ops(struct rtl8169_private *tp)
{
- rtl_csi_access_enable(ioaddr, 0x27000000);
+ struct csi_ops *ops = &tp->csi_ops;
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_01:
+ case RTL_GIGA_MAC_VER_02:
+ case RTL_GIGA_MAC_VER_03:
+ case RTL_GIGA_MAC_VER_04:
+ case RTL_GIGA_MAC_VER_05:
+ case RTL_GIGA_MAC_VER_06:
+ case RTL_GIGA_MAC_VER_10:
+ case RTL_GIGA_MAC_VER_11:
+ case RTL_GIGA_MAC_VER_12:
+ case RTL_GIGA_MAC_VER_13:
+ case RTL_GIGA_MAC_VER_14:
+ case RTL_GIGA_MAC_VER_15:
+ case RTL_GIGA_MAC_VER_16:
+ case RTL_GIGA_MAC_VER_17:
+ ops->write = NULL;
+ ops->read = NULL;
+ break;
+
+ case RTL_GIGA_MAC_VER_37:
+ case RTL_GIGA_MAC_VER_38:
+ ops->write = r8402_csi_write;
+ ops->read = r8402_csi_read;
+ break;
+
+ default:
+ ops->write = r8169_csi_write;
+ ops->read = r8169_csi_read;
+ break;
+ }
}
struct ephy_info {
@@ -4257,8 +4539,11 @@ static void rtl_enable_clock_request(struct pci_dev *pdev)
PktCntrDisable | \
Mac_dbgo_sel)
-static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
@@ -4267,17 +4552,22 @@ static void rtl_hw_start_8168bb(void __iomem *ioaddr, struct pci_dev *pdev)
(0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
}
-static void rtl_hw_start_8168bef(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168bef(struct rtl8169_private *tp)
{
- rtl_hw_start_8168bb(ioaddr, pdev);
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ rtl_hw_start_8168bb(tp);
RTL_W8(MaxTxPacketSize, TxPacketMax);
RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
}
-static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev)
+static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
@@ -4289,8 +4579,9 @@ static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev)
RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
}
-static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
static const struct ephy_info e_info_8168cp[] = {
{ 0x01, 0, 0x0001 },
{ 0x02, 0x0800, 0x1000 },
@@ -4299,16 +4590,19 @@ static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev)
{ 0x07, 0, 0x2000 }
};
- rtl_csi_access_enable_2(ioaddr);
+ rtl_csi_access_enable_2(tp);
rtl_ephy_init(ioaddr, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
- __rtl_hw_start_8168cp(ioaddr, pdev);
+ __rtl_hw_start_8168cp(tp);
}
-static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
{
- rtl_csi_access_enable_2(ioaddr);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ rtl_csi_access_enable_2(tp);
RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
@@ -4317,9 +4611,12 @@ static void rtl_hw_start_8168cp_2(void __iomem *ioaddr, struct pci_dev *pdev)
RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
}
-static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
{
- rtl_csi_access_enable_2(ioaddr);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ rtl_csi_access_enable_2(tp);
RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
@@ -4333,52 +4630,57 @@ static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev)
RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
}
-static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
static const struct ephy_info e_info_8168c_1[] = {
{ 0x02, 0x0800, 0x1000 },
{ 0x03, 0, 0x0002 },
{ 0x06, 0x0080, 0x0000 }
};
- rtl_csi_access_enable_2(ioaddr);
+ rtl_csi_access_enable_2(tp);
RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
rtl_ephy_init(ioaddr, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
- __rtl_hw_start_8168cp(ioaddr, pdev);
+ __rtl_hw_start_8168cp(tp);
}
-static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
static const struct ephy_info e_info_8168c_2[] = {
{ 0x01, 0, 0x0001 },
{ 0x03, 0x0400, 0x0220 }
};
- rtl_csi_access_enable_2(ioaddr);
+ rtl_csi_access_enable_2(tp);
rtl_ephy_init(ioaddr, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
- __rtl_hw_start_8168cp(ioaddr, pdev);
+ __rtl_hw_start_8168cp(tp);
}
-static void rtl_hw_start_8168c_3(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168c_3(struct rtl8169_private *tp)
{
- rtl_hw_start_8168c_2(ioaddr, pdev);
+ rtl_hw_start_8168c_2(tp);
}
-static void rtl_hw_start_8168c_4(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
{
- rtl_csi_access_enable_2(ioaddr);
+ rtl_csi_access_enable_2(tp);
- __rtl_hw_start_8168cp(ioaddr, pdev);
+ __rtl_hw_start_8168cp(tp);
}
-static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168d(struct rtl8169_private *tp)
{
- rtl_csi_access_enable_2(ioaddr);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ rtl_csi_access_enable_2(tp);
rtl_disable_clock_request(pdev);
@@ -4389,9 +4691,12 @@ static void rtl_hw_start_8168d(void __iomem *ioaddr, struct pci_dev *pdev)
RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
}
-static void rtl_hw_start_8168dp(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
{
- rtl_csi_access_enable_1(ioaddr);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ rtl_csi_access_enable_1(tp);
rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
@@ -4400,8 +4705,10 @@ static void rtl_hw_start_8168dp(void __iomem *ioaddr, struct pci_dev *pdev)
rtl_disable_clock_request(pdev);
}
-static void rtl_hw_start_8168d_4(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
static const struct ephy_info e_info_8168d_4[] = {
{ 0x0b, ~0, 0x48 },
{ 0x19, 0x20, 0x50 },
@@ -4409,7 +4716,7 @@ static void rtl_hw_start_8168d_4(void __iomem *ioaddr, struct pci_dev *pdev)
};
int i;
- rtl_csi_access_enable_1(ioaddr);
+ rtl_csi_access_enable_1(tp);
rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
@@ -4426,8 +4733,10 @@ static void rtl_hw_start_8168d_4(void __iomem *ioaddr, struct pci_dev *pdev)
rtl_enable_clock_request(pdev);
}
-static void rtl_hw_start_8168e_1(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
static const struct ephy_info e_info_8168e_1[] = {
{ 0x00, 0x0200, 0x0100 },
{ 0x00, 0x0000, 0x0004 },
@@ -4444,7 +4753,7 @@ static void rtl_hw_start_8168e_1(void __iomem *ioaddr, struct pci_dev *pdev)
{ 0x0a, 0x0000, 0x0040 }
};
- rtl_csi_access_enable_2(ioaddr);
+ rtl_csi_access_enable_2(tp);
rtl_ephy_init(ioaddr, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
@@ -4461,14 +4770,16 @@ static void rtl_hw_start_8168e_1(void __iomem *ioaddr, struct pci_dev *pdev)
RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
}
-static void rtl_hw_start_8168e_2(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
static const struct ephy_info e_info_8168e_2[] = {
{ 0x09, 0x0000, 0x0080 },
{ 0x19, 0x0000, 0x0224 }
};
- rtl_csi_access_enable_1(ioaddr);
+ rtl_csi_access_enable_1(tp);
rtl_ephy_init(ioaddr, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
@@ -4499,18 +4810,12 @@ static void rtl_hw_start_8168e_2(void __iomem *ioaddr, struct pci_dev *pdev)
RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
}
-static void rtl_hw_start_8168f_1(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8168f(struct rtl8169_private *tp)
{
- static const struct ephy_info e_info_8168f_1[] = {
- { 0x06, 0x00c0, 0x0020 },
- { 0x08, 0x0001, 0x0002 },
- { 0x09, 0x0000, 0x0080 },
- { 0x19, 0x0000, 0x0224 }
- };
-
- rtl_csi_access_enable_1(ioaddr);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
- rtl_ephy_init(ioaddr, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
+ rtl_csi_access_enable_2(tp);
rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
@@ -4524,8 +4829,6 @@ static void rtl_hw_start_8168f_1(void __iomem *ioaddr, struct pci_dev *pdev)
rtl_w1w0_eri(ioaddr, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
rtl_eri_write(ioaddr, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
rtl_eri_write(ioaddr, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
- rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00,
- ERIAR_EXGMAC);
RTL_W8(MaxTxPacketSize, EarlySize);
@@ -4533,20 +4836,54 @@ static void rtl_hw_start_8168f_1(void __iomem *ioaddr, struct pci_dev *pdev)
RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
+ RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
+ RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
+ RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+}
+
+static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ static const struct ephy_info e_info_8168f_1[] = {
+ { 0x06, 0x00c0, 0x0020 },
+ { 0x08, 0x0001, 0x0002 },
+ { 0x09, 0x0000, 0x0080 },
+ { 0x19, 0x0000, 0x0224 }
+ };
+
+ rtl_hw_start_8168f(tp);
+
+ rtl_ephy_init(ioaddr, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
+
+ rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00,
+ ERIAR_EXGMAC);
/* Adjust EEE LED frequency */
RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
+}
- RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
- RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
- RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+static void rtl_hw_start_8411(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ static const struct ephy_info e_info_8168f_1[] = {
+ { 0x06, 0x00c0, 0x0020 },
+ { 0x0f, 0xffff, 0x5200 },
+ { 0x1e, 0x0000, 0x4000 },
+ { 0x19, 0x0000, 0x0224 }
+ };
+
+ rtl_hw_start_8168f(tp);
+
+ rtl_ephy_init(ioaddr, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
+
+ rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000,
+ ERIAR_EXGMAC);
}
static void rtl_hw_start_8168(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- struct pci_dev *pdev = tp->pci_dev;
RTL_W8(Cfg9346, Cfg9346_Unlock);
@@ -4577,67 +4914,71 @@ static void rtl_hw_start_8168(struct net_device *dev)
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_11:
- rtl_hw_start_8168bb(ioaddr, pdev);
+ rtl_hw_start_8168bb(tp);
break;
case RTL_GIGA_MAC_VER_12:
case RTL_GIGA_MAC_VER_17:
- rtl_hw_start_8168bef(ioaddr, pdev);
+ rtl_hw_start_8168bef(tp);
break;
case RTL_GIGA_MAC_VER_18:
- rtl_hw_start_8168cp_1(ioaddr, pdev);
+ rtl_hw_start_8168cp_1(tp);
break;
case RTL_GIGA_MAC_VER_19:
- rtl_hw_start_8168c_1(ioaddr, pdev);
+ rtl_hw_start_8168c_1(tp);
break;
case RTL_GIGA_MAC_VER_20:
- rtl_hw_start_8168c_2(ioaddr, pdev);
+ rtl_hw_start_8168c_2(tp);
break;
case RTL_GIGA_MAC_VER_21:
- rtl_hw_start_8168c_3(ioaddr, pdev);
+ rtl_hw_start_8168c_3(tp);
break;
case RTL_GIGA_MAC_VER_22:
- rtl_hw_start_8168c_4(ioaddr, pdev);
+ rtl_hw_start_8168c_4(tp);
break;
case RTL_GIGA_MAC_VER_23:
- rtl_hw_start_8168cp_2(ioaddr, pdev);
+ rtl_hw_start_8168cp_2(tp);
break;
case RTL_GIGA_MAC_VER_24:
- rtl_hw_start_8168cp_3(ioaddr, pdev);
+ rtl_hw_start_8168cp_3(tp);
break;
case RTL_GIGA_MAC_VER_25:
case RTL_GIGA_MAC_VER_26:
case RTL_GIGA_MAC_VER_27:
- rtl_hw_start_8168d(ioaddr, pdev);
+ rtl_hw_start_8168d(tp);
break;
case RTL_GIGA_MAC_VER_28:
- rtl_hw_start_8168d_4(ioaddr, pdev);
+ rtl_hw_start_8168d_4(tp);
break;
case RTL_GIGA_MAC_VER_31:
- rtl_hw_start_8168dp(ioaddr, pdev);
+ rtl_hw_start_8168dp(tp);
break;
case RTL_GIGA_MAC_VER_32:
case RTL_GIGA_MAC_VER_33:
- rtl_hw_start_8168e_1(ioaddr, pdev);
+ rtl_hw_start_8168e_1(tp);
break;
case RTL_GIGA_MAC_VER_34:
- rtl_hw_start_8168e_2(ioaddr, pdev);
+ rtl_hw_start_8168e_2(tp);
break;
case RTL_GIGA_MAC_VER_35:
case RTL_GIGA_MAC_VER_36:
- rtl_hw_start_8168f_1(ioaddr, pdev);
+ rtl_hw_start_8168f_1(tp);
+ break;
+
+ case RTL_GIGA_MAC_VER_38:
+ rtl_hw_start_8411(tp);
break;
default:
@@ -4664,8 +5005,10 @@ static void rtl_hw_start_8168(struct net_device *dev)
PktCntrDisable | \
Mac_dbgo_sel)
-static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
static const struct ephy_info e_info_8102e_1[] = {
{ 0x01, 0, 0x6e65 },
{ 0x02, 0, 0x091f },
@@ -4678,7 +5021,7 @@ static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev)
};
u8 cfg1;
- rtl_csi_access_enable_2(ioaddr);
+ rtl_csi_access_enable_2(tp);
RTL_W8(DBG_REG, FIX_NAK_1);
@@ -4695,9 +5038,12 @@ static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev)
rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
}
-static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
{
- rtl_csi_access_enable_2(ioaddr);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ rtl_csi_access_enable_2(tp);
rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
@@ -4705,15 +5051,16 @@ static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev)
RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
}
-static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
{
- rtl_hw_start_8102e_2(ioaddr, pdev);
+ rtl_hw_start_8102e_2(tp);
- rtl_ephy_write(ioaddr, 0x03, 0xc2f9);
+ rtl_ephy_write(tp->mmio_addr, 0x03, 0xc2f9);
}
-static void rtl_hw_start_8105e_1(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
static const struct ephy_info e_info_8105e_1[] = {
{ 0x07, 0, 0x4000 },
{ 0x19, 0, 0x0200 },
@@ -4737,12 +5084,44 @@ static void rtl_hw_start_8105e_1(void __iomem *ioaddr, struct pci_dev *pdev)
rtl_ephy_init(ioaddr, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
}
-static void rtl_hw_start_8105e_2(void __iomem *ioaddr, struct pci_dev *pdev)
+static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
{
- rtl_hw_start_8105e_1(ioaddr, pdev);
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ rtl_hw_start_8105e_1(tp);
rtl_ephy_write(ioaddr, 0x1e, rtl_ephy_read(ioaddr, 0x1e) | 0x8000);
}
+static void rtl_hw_start_8402(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ static const struct ephy_info e_info_8402[] = {
+ { 0x19, 0xffff, 0xff64 },
+ { 0x1e, 0, 0x4000 }
+ };
+
+ rtl_csi_access_enable_2(tp);
+
+ /* Force LAN exit from ASPM if Rx/Tx are not idle */
+ RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
+
+ RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
+ RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
+
+ rtl_ephy_init(ioaddr, e_info_8402, ARRAY_SIZE(e_info_8402));
+
+ rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+ rtl_eri_write(ioaddr, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC);
+ rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
+ rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+ rtl_eri_write(ioaddr, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+ rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00,
+ ERIAR_EXGMAC);
+}
+
static void rtl_hw_start_8101(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -4766,22 +5145,26 @@ static void rtl_hw_start_8101(struct net_device *dev)
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_07:
- rtl_hw_start_8102e_1(ioaddr, pdev);
+ rtl_hw_start_8102e_1(tp);
break;
case RTL_GIGA_MAC_VER_08:
- rtl_hw_start_8102e_3(ioaddr, pdev);
+ rtl_hw_start_8102e_3(tp);
break;
case RTL_GIGA_MAC_VER_09:
- rtl_hw_start_8102e_2(ioaddr, pdev);
+ rtl_hw_start_8102e_2(tp);
break;
case RTL_GIGA_MAC_VER_29:
- rtl_hw_start_8105e_1(ioaddr, pdev);
+ rtl_hw_start_8105e_1(tp);
break;
case RTL_GIGA_MAC_VER_30:
- rtl_hw_start_8105e_2(ioaddr, pdev);
+ rtl_hw_start_8105e_2(tp);
+ break;
+
+ case RTL_GIGA_MAC_VER_37:
+ rtl_hw_start_8402(tp);
break;
}
@@ -5115,7 +5498,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
u32 opts[2];
int frags;
- if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
+ if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) {
netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
goto err_stop_0;
}
@@ -5169,7 +5552,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
mmiowb();
- if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) {
+ if (!TX_FRAGS_READY_FOR(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.
*/
@@ -5183,7 +5566,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
* can't.
*/
smp_mb();
- if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)
+ if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS))
netif_wake_queue(dev);
}
@@ -5306,7 +5689,7 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
*/
smp_mb();
if (netif_queue_stopped(dev) &&
- (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) {
+ TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
netif_wake_queue(dev);
}
/*
@@ -5668,7 +6051,7 @@ static int rtl_open(struct net_device *dev)
pm_runtime_get_sync(&pdev->dev);
/*
- * Rx and Tx desscriptors needs 256 bytes alignment.
+ * Rx and Tx descriptors needs 256 bytes alignment.
* dma_alloc_coherent provides more.
*/
tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
@@ -6178,6 +6561,7 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rtl_init_mdio_ops(tp);
rtl_init_pll_power_ops(tp);
rtl_init_jumbo_ops(tp);
+ rtl_init_csi_ops(tp);
rtl8169_print_mac_version(tp);
diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
index 3fb2355af37e..46df3a04030c 100644
--- a/drivers/net/ethernet/renesas/Kconfig
+++ b/drivers/net/ethernet/renesas/Kconfig
@@ -4,11 +4,11 @@
config SH_ETH
tristate "Renesas SuperH Ethernet support"
- depends on SUPERH && \
+ depends on (SUPERH || ARCH_SHMOBILE) && \
(CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \
- CPU_SUBTYPE_SH7757)
+ CPU_SUBTYPE_SH7757 || ARCH_R8A7740)
select CRC32
select NET_CORE
select MII
@@ -17,4 +17,5 @@ config SH_ETH
---help---
Renesas SuperH Ethernet device driver.
This driver supporting CPUs are:
- - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763 and SH7757.
+ - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757,
+ and R8A7740.
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index d63e09b29a96..be3c22179161 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -386,6 +386,114 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev)
sh_eth_write(ndev, 0x0, CSMR);
}
+#elif defined(CONFIG_ARCH_R8A7740)
+#define SH_ETH_HAS_TSU 1
+static void sh_eth_chip_reset(struct net_device *ndev)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+ unsigned long mii;
+
+ /* reset device */
+ sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
+ mdelay(1);
+
+ switch (mdp->phy_interface) {
+ case PHY_INTERFACE_MODE_GMII:
+ mii = 2;
+ break;
+ case PHY_INTERFACE_MODE_MII:
+ mii = 1;
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ default:
+ mii = 0;
+ break;
+ }
+ sh_eth_write(ndev, mii, RMII_MII);
+}
+
+static void sh_eth_reset(struct net_device *ndev)
+{
+ int cnt = 100;
+
+ sh_eth_write(ndev, EDSR_ENALL, EDSR);
+ sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
+ while (cnt > 0) {
+ if (!(sh_eth_read(ndev, EDMR) & 0x3))
+ break;
+ mdelay(1);
+ cnt--;
+ }
+ if (cnt == 0)
+ printk(KERN_ERR "Device reset fail\n");
+
+ /* Table Init */
+ sh_eth_write(ndev, 0x0, TDLAR);
+ sh_eth_write(ndev, 0x0, TDFAR);
+ sh_eth_write(ndev, 0x0, TDFXR);
+ sh_eth_write(ndev, 0x0, TDFFR);
+ sh_eth_write(ndev, 0x0, RDLAR);
+ sh_eth_write(ndev, 0x0, RDFAR);
+ sh_eth_write(ndev, 0x0, RDFXR);
+ sh_eth_write(ndev, 0x0, RDFFR);
+}
+
+static void sh_eth_set_duplex(struct net_device *ndev)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+
+ if (mdp->duplex) /* Full */
+ sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
+ else /* Half */
+ sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
+}
+
+static void sh_eth_set_rate(struct net_device *ndev)
+{
+ struct sh_eth_private *mdp = netdev_priv(ndev);
+
+ switch (mdp->speed) {
+ case 10: /* 10BASE */
+ sh_eth_write(ndev, GECMR_10, GECMR);
+ break;
+ case 100:/* 100BASE */
+ sh_eth_write(ndev, GECMR_100, GECMR);
+ break;
+ case 1000: /* 1000BASE */
+ sh_eth_write(ndev, GECMR_1000, GECMR);
+ break;
+ default:
+ break;
+ }
+}
+
+/* R8A7740 */
+static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+ .chip_reset = sh_eth_chip_reset,
+ .set_duplex = sh_eth_set_duplex,
+ .set_rate = sh_eth_set_rate,
+
+ .ecsr_value = ECSR_ICD | ECSR_MPD,
+ .ecsipr_value = ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
+ .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
+
+ .tx_check = EESR_TC1 | EESR_FTC,
+ .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
+ EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
+ EESR_ECI,
+ .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
+ EESR_TFE,
+
+ .apr = 1,
+ .mpr = 1,
+ .tpauser = 1,
+ .bculr = 1,
+ .hw_swap = 1,
+ .no_trimd = 1,
+ .no_ade = 1,
+ .tsu = 1,
+};
+
#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
#define SH_ETH_RESET_DEFAULT 1
static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
@@ -443,7 +551,7 @@ static void sh_eth_reset(struct net_device *ndev)
}
#endif
-#if defined(CONFIG_CPU_SH4)
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
static void sh_eth_set_receive_align(struct sk_buff *skb)
{
int reserve;
@@ -919,6 +1027,10 @@ static int sh_eth_rx(struct net_device *ndev)
desc_status = edmac_to_cpu(mdp, rxdesc->status);
pkt_len = rxdesc->frame_length;
+#if defined(CONFIG_ARCH_R8A7740)
+ desc_status >>= 16;
+#endif
+
if (--boguscnt < 0)
break;
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 0fa14afce23d..57b8e1fc5d15 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -372,7 +372,7 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
};
/* Driver's parameters */
-#if defined(CONFIG_CPU_SH4)
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
#define SH4_SKB_RX_ALIGN 32
#else
#define SH2_SH3_SKB_RX_ALIGN 2
@@ -381,7 +381,8 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
/*
* Register's bits
*/
-#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
+#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) ||\
+ defined(CONFIG_ARCH_R8A7740)
/* EDSR */
enum EDSR_BIT {
EDSR_ENT = 0x01, EDSR_ENR = 0x02,
diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c
index 1895605abb35..2ed3ab4b3c2d 100644
--- a/drivers/net/ethernet/s6gmac.c
+++ b/drivers/net/ethernet/s6gmac.c
@@ -1,7 +1,7 @@
/*
* Ethernet driver for S6105 on chip network device
* (c)2008 emlix GmbH http://www.emlix.com
- * Authors: Oskar Schirmer <os@emlix.com>
+ * Authors: Oskar Schirmer <oskar@scara.com>
* Daniel Gloeckner <dg@emlix.com>
*
* This program is free software; you can redistribute it and/or
@@ -937,7 +937,7 @@ static struct net_device_stats *s6gmac_stats(struct net_device *dev)
do {
unsigned long flags;
spin_lock_irqsave(&pd->lock, flags);
- for (i = 0; i < sizeof(pd->stats) / sizeof(unsigned long); i++)
+ for (i = 0; i < ARRAY_SIZE(pd->stats); i++)
pd->stats[i] =
pd->carry[i] << (S6_GMAC_STAT_SIZE_MIN - 1);
s6gmac_stats_collect(pd, &statinf[0][0]);
@@ -1070,4 +1070,4 @@ module_exit(s6gmac_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("S6105 on chip Ethernet driver");
-MODULE_AUTHOR("Oskar Schirmer <os@emlix.com>");
+MODULE_AUTHOR("Oskar Schirmer <oskar@scara.com>");
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 3cbfbffe3f00..b95f2e1b33f0 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -656,25 +656,30 @@ static void efx_stop_datapath(struct efx_nic *efx)
struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
+ struct pci_dev *dev = efx->pci_dev;
int rc;
EFX_ASSERT_RESET_SERIALISED(efx);
BUG_ON(efx->port_enabled);
- rc = efx_nic_flush_queues(efx);
- if (rc && EFX_WORKAROUND_7803(efx)) {
- /* Schedule a reset to recover from the flush failure. The
- * descriptor caches reference memory we're about to free,
- * but falcon_reconfigure_mac_wrapper() won't reconnect
- * the MACs because of the pending reset. */
- netif_err(efx, drv, efx->net_dev,
- "Resetting to recover from flush failure\n");
- efx_schedule_reset(efx, RESET_TYPE_ALL);
- } else if (rc) {
- netif_err(efx, drv, efx->net_dev, "failed to flush queues\n");
- } else {
- netif_dbg(efx, drv, efx->net_dev,
- "successfully flushed all queues\n");
+ /* Only perform flush if dma is enabled */
+ if (dev->is_busmaster) {
+ rc = efx_nic_flush_queues(efx);
+
+ if (rc && EFX_WORKAROUND_7803(efx)) {
+ /* Schedule a reset to recover from the flush failure. The
+ * descriptor caches reference memory we're about to free,
+ * but falcon_reconfigure_mac_wrapper() won't reconnect
+ * the MACs because of the pending reset. */
+ netif_err(efx, drv, efx->net_dev,
+ "Resetting to recover from flush failure\n");
+ efx_schedule_reset(efx, RESET_TYPE_ALL);
+ } else if (rc) {
+ netif_err(efx, drv, efx->net_dev, "failed to flush queues\n");
+ } else {
+ netif_dbg(efx, drv, efx->net_dev,
+ "successfully flushed all queues\n");
+ }
}
efx_for_each_channel(channel, efx) {
@@ -1349,7 +1354,7 @@ static int efx_probe_interrupts(struct efx_nic *efx)
}
/* RSS might be usable on VFs even if it is disabled on the PF */
- efx->rss_spread = (efx->n_rx_channels > 1 ?
+ efx->rss_spread = ((efx->n_rx_channels > 1 || !efx_sriov_wanted(efx)) ?
efx->n_rx_channels : efx_vf_size(efx));
return 0;
@@ -2492,8 +2497,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
efx_fini_io(efx);
netif_dbg(efx, drv, efx->net_dev, "shutdown successful\n");
- pci_set_drvdata(pci_dev, NULL);
efx_fini_struct(efx);
+ pci_set_drvdata(pci_dev, NULL);
free_netdev(efx->net_dev);
};
@@ -2695,6 +2700,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
fail2:
efx_fini_struct(efx);
fail1:
+ pci_set_drvdata(pci_dev, NULL);
WARN_ON(rc > 0);
netif_dbg(efx, drv, efx->net_dev, "initialisation failed. rc=%d\n", rc);
free_netdev(net_dev);
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index f22f45f515a8..03ded364c8da 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -1023,7 +1023,7 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
return -EINVAL;
/* Is it a default UC or MC filter? */
- if (!compare_ether_addr(mac_mask->h_dest, mac_addr_mc_mask) &&
+ if (ether_addr_equal(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);
@@ -1108,6 +1108,39 @@ static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev,
return 0;
}
+static int efx_ethtool_get_module_eeprom(struct net_device *net_dev,
+ struct ethtool_eeprom *ee,
+ u8 *data)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ int ret;
+
+ if (!efx->phy_op || !efx->phy_op->get_module_eeprom)
+ return -EOPNOTSUPP;
+
+ mutex_lock(&efx->mac_lock);
+ ret = efx->phy_op->get_module_eeprom(efx, ee, data);
+ mutex_unlock(&efx->mac_lock);
+
+ return ret;
+}
+
+static int efx_ethtool_get_module_info(struct net_device *net_dev,
+ struct ethtool_modinfo *modinfo)
+{
+ struct efx_nic *efx = netdev_priv(net_dev);
+ int ret;
+
+ if (!efx->phy_op || !efx->phy_op->get_module_info)
+ return -EOPNOTSUPP;
+
+ mutex_lock(&efx->mac_lock);
+ ret = efx->phy_op->get_module_info(efx, modinfo);
+ mutex_unlock(&efx->mac_lock);
+
+ return ret;
+}
+
const struct ethtool_ops efx_ethtool_ops = {
.get_settings = efx_ethtool_get_settings,
.set_settings = efx_ethtool_set_settings,
@@ -1137,4 +1170,6 @@ const struct ethtool_ops efx_ethtool_ops = {
.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
.get_rxfh_indir = efx_ethtool_get_rxfh_indir,
.set_rxfh_indir = efx_ethtool_set_rxfh_indir,
+ .get_module_info = efx_ethtool_get_module_info,
+ .get_module_eeprom = efx_ethtool_get_module_eeprom,
};
diff --git a/drivers/net/ethernet/sfc/mcdi_phy.c b/drivers/net/ethernet/sfc/mcdi_phy.c
index 7bcad899a936..13cb40fe90c1 100644
--- a/drivers/net/ethernet/sfc/mcdi_phy.c
+++ b/drivers/net/ethernet/sfc/mcdi_phy.c
@@ -739,6 +739,80 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic *efx,
return NULL;
}
+#define SFP_PAGE_SIZE 128
+#define SFP_NUM_PAGES 2
+static int efx_mcdi_phy_get_module_eeprom(struct efx_nic *efx,
+ struct ethtool_eeprom *ee, u8 *data)
+{
+ u8 outbuf[MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX];
+ u8 inbuf[MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN];
+ size_t outlen;
+ int rc;
+ unsigned int payload_len;
+ unsigned int space_remaining = ee->len;
+ unsigned int page;
+ unsigned int page_off;
+ unsigned int to_copy;
+ u8 *user_data = data;
+
+ BUILD_BUG_ON(SFP_PAGE_SIZE * SFP_NUM_PAGES != ETH_MODULE_SFF_8079_LEN);
+
+ page_off = ee->offset % SFP_PAGE_SIZE;
+ page = ee->offset / SFP_PAGE_SIZE;
+
+ while (space_remaining && (page < SFP_NUM_PAGES)) {
+ MCDI_SET_DWORD(inbuf, GET_PHY_MEDIA_INFO_IN_PAGE, page);
+
+ rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_MEDIA_INFO,
+ inbuf, sizeof(inbuf),
+ outbuf, sizeof(outbuf),
+ &outlen);
+ if (rc)
+ return rc;
+
+ if (outlen < (MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST +
+ SFP_PAGE_SIZE))
+ return -EIO;
+
+ payload_len = MCDI_DWORD(outbuf,
+ GET_PHY_MEDIA_INFO_OUT_DATALEN);
+ if (payload_len != SFP_PAGE_SIZE)
+ return -EIO;
+
+ /* Copy as much as we can into data */
+ payload_len -= page_off;
+ to_copy = (space_remaining < payload_len) ?
+ space_remaining : payload_len;
+
+ memcpy(user_data,
+ outbuf + page_off +
+ MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST,
+ to_copy);
+
+ space_remaining -= to_copy;
+ user_data += to_copy;
+ page_off = 0;
+ page++;
+ }
+
+ return 0;
+}
+
+static int efx_mcdi_phy_get_module_info(struct efx_nic *efx,
+ struct ethtool_modinfo *modinfo)
+{
+ struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
+
+ switch (phy_cfg->media) {
+ case MC_CMD_MEDIA_SFP_PLUS:
+ modinfo->type = ETH_MODULE_SFF_8079;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
const struct efx_phy_operations efx_mcdi_phy_ops = {
.probe = efx_mcdi_phy_probe,
.init = efx_port_dummy_op_int,
@@ -751,4 +825,6 @@ const struct efx_phy_operations efx_mcdi_phy_ops = {
.test_alive = efx_mcdi_phy_test_alive,
.run_tests = efx_mcdi_phy_run_tests,
.test_name = efx_mcdi_phy_test_name,
+ .get_module_eeprom = efx_mcdi_phy_get_module_eeprom,
+ .get_module_info = efx_mcdi_phy_get_module_info,
};
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index f0385e1fb2d8..0e575359af17 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -252,8 +252,6 @@ struct efx_rx_page_state {
* @max_fill: RX descriptor maximum fill level (<= ring size)
* @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill
* (<= @max_fill)
- * @fast_fill_limit: The level to which a fast fill will fill
- * (@fast_fill_trigger <= @fast_fill_limit <= @max_fill)
* @min_fill: RX descriptor minimum non-zero fill level.
* This records the minimum fill level observed when a ring
* refill was triggered.
@@ -274,7 +272,6 @@ struct efx_rx_queue {
int removed_count;
unsigned int max_fill;
unsigned int fast_fill_trigger;
- unsigned int fast_fill_limit;
unsigned int min_fill;
unsigned int min_overfill;
unsigned int alloc_page_count;
@@ -522,6 +519,11 @@ struct efx_phy_operations {
int (*test_alive) (struct efx_nic *efx);
const char *(*test_name) (struct efx_nic *efx, unsigned int index);
int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags);
+ int (*get_module_eeprom) (struct efx_nic *efx,
+ struct ethtool_eeprom *ee,
+ u8 *data);
+ int (*get_module_info) (struct efx_nic *efx,
+ struct ethtool_modinfo *modinfo);
};
/**
diff --git a/drivers/net/ethernet/sfc/qt202x_phy.c b/drivers/net/ethernet/sfc/qt202x_phy.c
index 8a7caf88ffb6..326a28637f3c 100644
--- a/drivers/net/ethernet/sfc/qt202x_phy.c
+++ b/drivers/net/ethernet/sfc/qt202x_phy.c
@@ -449,6 +449,37 @@ static void qt202x_phy_remove(struct efx_nic *efx)
efx->phy_data = NULL;
}
+static int qt202x_phy_get_module_info(struct efx_nic *efx,
+ struct ethtool_modinfo *modinfo)
+{
+ modinfo->type = ETH_MODULE_SFF_8079;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
+ return 0;
+}
+
+static int qt202x_phy_get_module_eeprom(struct efx_nic *efx,
+ struct ethtool_eeprom *ee, u8 *data)
+{
+ int mmd, reg_base, rc, i;
+
+ if (efx->phy_type == PHY_TYPE_QT2025C) {
+ mmd = MDIO_MMD_PCS;
+ reg_base = 0xd000;
+ } else {
+ mmd = MDIO_MMD_PMAPMD;
+ reg_base = 0x8007;
+ }
+
+ for (i = 0; i < ee->len; i++) {
+ rc = efx_mdio_read(efx, mmd, reg_base + ee->offset + i);
+ if (rc < 0)
+ return rc;
+ data[i] = rc;
+ }
+
+ return 0;
+}
+
const struct efx_phy_operations falcon_qt202x_phy_ops = {
.probe = qt202x_phy_probe,
.init = qt202x_phy_init,
@@ -459,4 +490,6 @@ const struct efx_phy_operations falcon_qt202x_phy_ops = {
.get_settings = qt202x_phy_get_settings,
.set_settings = efx_mdio_set_settings,
.test_alive = efx_mdio_test_alive,
+ .get_module_eeprom = qt202x_phy_get_module_eeprom,
+ .get_module_info = qt202x_phy_get_module_info,
};
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 763fa2fe1a38..243e91f3dff9 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -76,12 +76,7 @@ static int rx_alloc_method = RX_ALLOC_METHOD_AUTO;
/* This is the percentage fill level below which new RX descriptors
* will be added to the RX descriptor ring.
*/
-static unsigned int rx_refill_threshold = 90;
-
-/* This is the percentage fill level to which an RX queue will be refilled
- * when the "RX refill threshold" is reached.
- */
-static unsigned int rx_refill_limit = 95;
+static unsigned int rx_refill_threshold;
/*
* RX maximum head room required.
@@ -342,7 +337,7 @@ static void efx_recycle_rx_buffer(struct efx_channel *channel,
* efx_fast_push_rx_descriptors - push new RX descriptors quickly
* @rx_queue: RX descriptor queue
* This will aim to fill the RX descriptor queue up to
- * @rx_queue->@fast_fill_limit. If there is insufficient atomic
+ * @rx_queue->@max_fill. If there is insufficient atomic
* memory to do so, a slow fill will be scheduled.
*
* The caller must provide serialisation (none is used here). In practise,
@@ -367,15 +362,14 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
rx_queue->min_fill = fill_level;
}
- space = rx_queue->fast_fill_limit - fill_level;
- if (space < EFX_RX_BATCH)
- goto out;
+ space = rx_queue->max_fill - fill_level;
+ EFX_BUG_ON_PARANOID(space < EFX_RX_BATCH);
netif_vdbg(rx_queue->efx, rx_status, rx_queue->efx->net_dev,
"RX queue %d fast-filling descriptor ring from"
" level %d to level %d using %s allocation\n",
efx_rx_queue_index(rx_queue), fill_level,
- rx_queue->fast_fill_limit,
+ rx_queue->max_fill,
channel->rx_alloc_push_pages ? "page" : "skb");
do {
@@ -681,7 +675,7 @@ int efx_probe_rx_queue(struct efx_rx_queue *rx_queue)
void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
{
struct efx_nic *efx = rx_queue->efx;
- unsigned int max_fill, trigger, limit;
+ unsigned int max_fill, trigger, max_trigger;
netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
"initialising RX queue %d\n", efx_rx_queue_index(rx_queue));
@@ -694,12 +688,17 @@ void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
/* Initialise limit fields */
max_fill = efx->rxq_entries - EFX_RXD_HEAD_ROOM;
- trigger = max_fill * min(rx_refill_threshold, 100U) / 100U;
- limit = max_fill * min(rx_refill_limit, 100U) / 100U;
+ max_trigger = max_fill - EFX_RX_BATCH;
+ if (rx_refill_threshold != 0) {
+ trigger = max_fill * min(rx_refill_threshold, 100U) / 100U;
+ if (trigger > max_trigger)
+ trigger = max_trigger;
+ } else {
+ trigger = max_trigger;
+ }
rx_queue->max_fill = max_fill;
rx_queue->fast_fill_trigger = trigger;
- rx_queue->fast_fill_limit = limit;
/* Set up RX descriptor ring */
rx_queue->enabled = true;
@@ -746,5 +745,5 @@ MODULE_PARM_DESC(rx_alloc_method, "Allocation method used for RX buffers");
module_param(rx_refill_threshold, uint, 0444);
MODULE_PARM_DESC(rx_refill_threshold,
- "RX descriptor ring fast/slow fill threshold (%)");
+ "RX descriptor ring refill threshold (%)");
diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c
index a284d6440538..32e55664df6e 100644
--- a/drivers/net/ethernet/silan/sc92031.c
+++ b/drivers/net/ethernet/silan/sc92031.c
@@ -39,9 +39,7 @@
#define SC92031_NAME "sc92031"
/* BAR 0 is MMIO, BAR 1 is PIO */
-#ifndef SC92031_USE_BAR
-#define SC92031_USE_BAR 0
-#endif
+#define SC92031_USE_PIO 0
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). */
static int multicast_filter_limit = 64;
@@ -366,7 +364,7 @@ static void sc92031_disable_interrupts(struct net_device *dev)
mmiowb();
/* wait for any concurrent interrupt/tasklet to finish */
- synchronize_irq(dev->irq);
+ synchronize_irq(priv->pdev->irq);
tasklet_disable(&priv->tasklet);
}
@@ -1114,10 +1112,13 @@ static void sc92031_tx_timeout(struct net_device *dev)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void sc92031_poll_controller(struct net_device *dev)
{
- disable_irq(dev->irq);
- if (sc92031_interrupt(dev->irq, dev) != IRQ_NONE)
+ struct sc92031_priv *priv = netdev_priv(dev);
+ const int irq = priv->pdev->irq;
+
+ disable_irq(irq);
+ if (sc92031_interrupt(irq, dev) != IRQ_NONE)
sc92031_tasklet((unsigned long)dev);
- enable_irq(dev->irq);
+ enable_irq(irq);
}
#endif
@@ -1402,7 +1403,6 @@ static int __devinit sc92031_probe(struct pci_dev *pdev,
struct net_device *dev;
struct sc92031_priv *priv;
u32 mac0, mac1;
- unsigned long base_addr;
err = pci_enable_device(pdev);
if (unlikely(err < 0))
@@ -1422,7 +1422,7 @@ static int __devinit sc92031_probe(struct pci_dev *pdev,
if (unlikely(err < 0))
goto out_request_regions;
- port_base = pci_iomap(pdev, SC92031_USE_BAR, 0);
+ port_base = pci_iomap(pdev, SC92031_USE_PIO, 0);
if (unlikely(!port_base)) {
err = -EIO;
goto out_iomap;
@@ -1437,14 +1437,6 @@ static int __devinit sc92031_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
-#if SC92031_USE_BAR == 0
- dev->mem_start = pci_resource_start(pdev, SC92031_USE_BAR);
- dev->mem_end = pci_resource_end(pdev, SC92031_USE_BAR);
-#elif SC92031_USE_BAR == 1
- dev->base_addr = pci_resource_start(pdev, SC92031_USE_BAR);
-#endif
- dev->irq = pdev->irq;
-
/* faked with skb_copy_and_csum_dev */
dev->features = NETIF_F_SG | NETIF_F_HIGHDMA |
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
@@ -1478,13 +1470,9 @@ static int __devinit sc92031_probe(struct pci_dev *pdev,
if (err < 0)
goto out_register_netdev;
-#if SC92031_USE_BAR == 0
- base_addr = dev->mem_start;
-#elif SC92031_USE_BAR == 1
- base_addr = dev->base_addr;
-#endif
printk(KERN_INFO "%s: SC92031 at 0x%lx, %pM, IRQ %d\n", dev->name,
- base_addr, dev->dev_addr, dev->irq);
+ (long)pci_resource_start(pdev, SC92031_USE_PIO), dev->dev_addr,
+ pdev->irq);
return 0;
diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c
index a9deda8eaf63..4613591b43e7 100644
--- a/drivers/net/ethernet/sis/sis190.c
+++ b/drivers/net/ethernet/sis/sis190.c
@@ -729,7 +729,7 @@ static void sis190_tx_interrupt(struct net_device *dev,
* The interrupt handler does all of the Rx thread work and cleans up after
* the Tx thread.
*/
-static irqreturn_t sis190_interrupt(int irq, void *__dev)
+static irqreturn_t sis190_irq(int irq, void *__dev)
{
struct net_device *dev = __dev;
struct sis190_private *tp = netdev_priv(dev);
@@ -772,11 +772,11 @@ out:
static void sis190_netpoll(struct net_device *dev)
{
struct sis190_private *tp = netdev_priv(dev);
- struct pci_dev *pdev = tp->pci_dev;
+ const int irq = tp->pci_dev->irq;
- disable_irq(pdev->irq);
- sis190_interrupt(pdev->irq, dev);
- enable_irq(pdev->irq);
+ disable_irq(irq);
+ sis190_irq(irq, dev);
+ enable_irq(irq);
}
#endif
@@ -1085,7 +1085,7 @@ static int sis190_open(struct net_device *dev)
sis190_request_timer(dev);
- rc = request_irq(dev->irq, sis190_interrupt, IRQF_SHARED, dev->name, dev);
+ rc = request_irq(pdev->irq, sis190_irq, IRQF_SHARED, dev->name, dev);
if (rc < 0)
goto err_release_timer_2;
@@ -1097,11 +1097,9 @@ err_release_timer_2:
sis190_delete_timer(dev);
sis190_rx_clear(tp);
err_free_rx_1:
- pci_free_consistent(tp->pci_dev, RX_RING_BYTES, tp->RxDescRing,
- tp->rx_dma);
+ pci_free_consistent(pdev, RX_RING_BYTES, tp->RxDescRing, tp->rx_dma);
err_free_tx_0:
- pci_free_consistent(tp->pci_dev, TX_RING_BYTES, tp->TxDescRing,
- tp->tx_dma);
+ pci_free_consistent(pdev, TX_RING_BYTES, tp->TxDescRing, tp->tx_dma);
goto out;
}
@@ -1141,7 +1139,7 @@ static void sis190_down(struct net_device *dev)
spin_unlock_irq(&tp->lock);
- synchronize_irq(dev->irq);
+ synchronize_irq(tp->pci_dev->irq);
if (!poll_locked)
poll_locked++;
@@ -1161,7 +1159,7 @@ static int sis190_close(struct net_device *dev)
sis190_down(dev);
- free_irq(dev->irq, dev);
+ free_irq(pdev->irq, dev);
pci_free_consistent(pdev, TX_RING_BYTES, tp->TxDescRing, tp->tx_dma);
pci_free_consistent(pdev, RX_RING_BYTES, tp->RxDescRing, tp->rx_dma);
@@ -1884,8 +1882,6 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
dev->netdev_ops = &sis190_netdev_ops;
SET_ETHTOOL_OPS(dev, &sis190_ethtool_ops);
- dev->irq = pdev->irq;
- dev->base_addr = (unsigned long) 0xdead;
dev->watchdog_timeo = SIS190_TX_TIMEOUT;
spin_lock_init(&tp->lock);
@@ -1902,7 +1898,7 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
netdev_info(dev, "%s: %s at %p (IRQ: %d), %pM\n",
pci_name(pdev),
sis_chip_info[ent->driver_data].name,
- ioaddr, dev->irq, dev->dev_addr);
+ ioaddr, pdev->irq, dev->dev_addr);
netdev_info(dev, "%s mode.\n",
(tp->features & F_HAS_RGMII) ? "RGMII" : "GMII");
}
diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c
index 5ccf02e7e3ad..203d9c6ec23a 100644
--- a/drivers/net/ethernet/sis/sis900.c
+++ b/drivers/net/ethernet/sis/sis900.c
@@ -168,6 +168,8 @@ struct sis900_private {
unsigned int cur_phy;
struct mii_if_info mii_info;
+ void __iomem *ioaddr;
+
struct timer_list timer; /* Link status detection timer. */
u8 autong_complete; /* 1: auto-negotiate complete */
@@ -201,13 +203,18 @@ MODULE_PARM_DESC(multicast_filter_limit, "SiS 900/7016 maximum number of filtere
MODULE_PARM_DESC(max_interrupt_work, "SiS 900/7016 maximum events handled per interrupt");
MODULE_PARM_DESC(sis900_debug, "SiS 900/7016 bitmapped debugging message level");
+#define sw32(reg, val) iowrite32(val, ioaddr + (reg))
+#define sw8(reg, val) iowrite8(val, ioaddr + (reg))
+#define sr32(reg) ioread32(ioaddr + (reg))
+#define sr16(reg) ioread16(ioaddr + (reg))
+
#ifdef CONFIG_NET_POLL_CONTROLLER
static void sis900_poll(struct net_device *dev);
#endif
static int sis900_open(struct net_device *net_dev);
static int sis900_mii_probe (struct net_device * net_dev);
static void sis900_init_rxfilter (struct net_device * net_dev);
-static u16 read_eeprom(long ioaddr, int location);
+static u16 read_eeprom(void __iomem *ioaddr, int location);
static int mdio_read(struct net_device *net_dev, int phy_id, int location);
static void mdio_write(struct net_device *net_dev, int phy_id, int location, int val);
static void sis900_timer(unsigned long data);
@@ -231,7 +238,7 @@ static u16 sis900_default_phy(struct net_device * net_dev);
static void sis900_set_capability( struct net_device *net_dev ,struct mii_phy *phy);
static u16 sis900_reset_phy(struct net_device *net_dev, int phy_addr);
static void sis900_auto_negotiate(struct net_device *net_dev, int phy_addr);
-static void sis900_set_mode (long ioaddr, int speed, int duplex);
+static void sis900_set_mode(struct sis900_private *, int speed, int duplex);
static const struct ethtool_ops sis900_ethtool_ops;
/**
@@ -246,7 +253,8 @@ static const struct ethtool_ops sis900_ethtool_ops;
static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
{
- long ioaddr = pci_resource_start(pci_dev, 0);
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
+ void __iomem *ioaddr = sis_priv->ioaddr;
u16 signature;
int i;
@@ -325,29 +333,30 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
struct net_device *net_dev)
{
- long ioaddr = net_dev->base_addr;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
+ void __iomem *ioaddr = sis_priv->ioaddr;
u32 rfcrSave;
u32 i;
- rfcrSave = inl(rfcr + ioaddr);
+ rfcrSave = sr32(rfcr);
- outl(rfcrSave | RELOAD, ioaddr + cr);
- outl(0, ioaddr + cr);
+ sw32(cr, rfcrSave | RELOAD);
+ sw32(cr, 0);
/* disable packet filtering before setting filter */
- outl(rfcrSave & ~RFEN, rfcr + ioaddr);
+ sw32(rfcr, rfcrSave & ~RFEN);
/* load MAC addr to filter data register */
for (i = 0 ; i < 3 ; i++) {
- outl((i << RFADDR_shift), ioaddr + rfcr);
- *( ((u16 *)net_dev->dev_addr) + i) = inw(ioaddr + rfdr);
+ sw32(rfcr, (i << RFADDR_shift));
+ *( ((u16 *)net_dev->dev_addr) + i) = sr16(rfdr);
}
/* Store MAC Address in perm_addr */
memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
/* enable packet filtering */
- outl(rfcrSave | RFEN, rfcr + ioaddr);
+ sw32(rfcr, rfcrSave | RFEN);
return 1;
}
@@ -371,31 +380,30 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
struct net_device *net_dev)
{
- long ioaddr = net_dev->base_addr;
- long ee_addr = ioaddr + mear;
- u32 waittime = 0;
- int i;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
+ void __iomem *ioaddr = sis_priv->ioaddr;
+ int wait, rc = 0;
- outl(EEREQ, ee_addr);
- while(waittime < 2000) {
- if(inl(ee_addr) & EEGNT) {
+ sw32(mear, EEREQ);
+ for (wait = 0; wait < 2000; wait++) {
+ if (sr32(mear) & EEGNT) {
+ u16 *mac = (u16 *)net_dev->dev_addr;
+ int i;
/* get MAC address from EEPROM */
for (i = 0; i < 3; i++)
- ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
+ mac[i] = read_eeprom(ioaddr, i + EEPROMMACAddr);
/* Store MAC Address in perm_addr */
memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
- outl(EEDONE, ee_addr);
- return 1;
- } else {
- udelay(1);
- waittime ++;
+ rc = 1;
+ break;
}
+ udelay(1);
}
- outl(EEDONE, ee_addr);
- return 0;
+ sw32(mear, EEDONE);
+ return rc;
}
static const struct net_device_ops sis900_netdev_ops = {
@@ -433,7 +441,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
struct pci_dev *dev;
dma_addr_t ring_dma;
void *ring_space;
- long ioaddr;
+ void __iomem *ioaddr;
int i, ret;
const char *card_name = card_names[pci_id->driver_data];
const char *dev_name = pci_name(pci_dev);
@@ -464,14 +472,17 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
SET_NETDEV_DEV(net_dev, &pci_dev->dev);
/* We do a request_region() to register /proc/ioports info. */
- ioaddr = pci_resource_start(pci_dev, 0);
ret = pci_request_regions(pci_dev, "sis900");
if (ret)
goto err_out;
+ /* IO region. */
+ ioaddr = pci_iomap(pci_dev, 0, 0);
+ if (!ioaddr)
+ goto err_out_cleardev;
+
sis_priv = netdev_priv(net_dev);
- net_dev->base_addr = ioaddr;
- net_dev->irq = pci_dev->irq;
+ sis_priv->ioaddr = ioaddr;
sis_priv->pci_dev = pci_dev;
spin_lock_init(&sis_priv->lock);
@@ -480,7 +491,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
ring_space = pci_alloc_consistent(pci_dev, TX_TOTAL_SIZE, &ring_dma);
if (!ring_space) {
ret = -ENOMEM;
- goto err_out_cleardev;
+ goto err_out_unmap;
}
sis_priv->tx_ring = ring_space;
sis_priv->tx_ring_dma = ring_dma;
@@ -534,7 +545,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
/* 630ET : set the mii access mode as software-mode */
if (sis_priv->chipset_rev == SIS630ET_900_REV)
- outl(ACCESSMODE | inl(ioaddr + cr), ioaddr + cr);
+ sw32(cr, ACCESSMODE | sr32(cr));
/* probe for mii transceiver */
if (sis900_mii_probe(net_dev) == 0) {
@@ -556,25 +567,27 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
goto err_unmap_rx;
/* print some information about our NIC */
- printk(KERN_INFO "%s: %s at %#lx, IRQ %d, %pM\n",
- net_dev->name, card_name, ioaddr, net_dev->irq,
+ printk(KERN_INFO "%s: %s at 0x%p, IRQ %d, %pM\n",
+ net_dev->name, card_name, ioaddr, pci_dev->irq,
net_dev->dev_addr);
/* Detect Wake on Lan support */
- ret = (inl(net_dev->base_addr + CFGPMC) & PMESP) >> 27;
+ ret = (sr32(CFGPMC) & PMESP) >> 27;
if (netif_msg_probe(sis_priv) && (ret & PME_D3C) == 0)
printk(KERN_INFO "%s: Wake on LAN only available from suspend to RAM.", net_dev->name);
return 0;
- err_unmap_rx:
+err_unmap_rx:
pci_free_consistent(pci_dev, RX_TOTAL_SIZE, sis_priv->rx_ring,
sis_priv->rx_ring_dma);
- err_unmap_tx:
+err_unmap_tx:
pci_free_consistent(pci_dev, TX_TOTAL_SIZE, sis_priv->tx_ring,
sis_priv->tx_ring_dma);
- err_out_cleardev:
- pci_set_drvdata(pci_dev, NULL);
+err_out_unmap:
+ pci_iounmap(pci_dev, ioaddr);
+err_out_cleardev:
+ pci_set_drvdata(pci_dev, NULL);
pci_release_regions(pci_dev);
err_out:
free_netdev(net_dev);
@@ -798,7 +811,7 @@ static void sis900_set_capability(struct net_device *net_dev, struct mii_phy *ph
/* Delay between EEPROM clock transitions. */
-#define eeprom_delay() inl(ee_addr)
+#define eeprom_delay() sr32(mear)
/**
* read_eeprom - Read Serial EEPROM
@@ -809,41 +822,41 @@ static void sis900_set_capability(struct net_device *net_dev, struct mii_phy *ph
* Note that location is in word (16 bits) unit
*/
-static u16 __devinit read_eeprom(long ioaddr, int location)
+static u16 __devinit read_eeprom(void __iomem *ioaddr, int location)
{
+ u32 read_cmd = location | EEread;
int i;
u16 retval = 0;
- long ee_addr = ioaddr + mear;
- u32 read_cmd = location | EEread;
- outl(0, ee_addr);
+ sw32(mear, 0);
eeprom_delay();
- outl(EECS, ee_addr);
+ sw32(mear, EECS);
eeprom_delay();
/* Shift the read command (9) bits out. */
for (i = 8; i >= 0; i--) {
u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
- outl(dataval, ee_addr);
+
+ sw32(mear, dataval);
eeprom_delay();
- outl(dataval | EECLK, ee_addr);
+ sw32(mear, dataval | EECLK);
eeprom_delay();
}
- outl(EECS, ee_addr);
+ sw32(mear, EECS);
eeprom_delay();
/* read the 16-bits data in */
for (i = 16; i > 0; i--) {
- outl(EECS, ee_addr);
+ sw32(mear, EECS);
eeprom_delay();
- outl(EECS | EECLK, ee_addr);
+ sw32(mear, EECS | EECLK);
eeprom_delay();
- retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);
+ retval = (retval << 1) | ((sr32(mear) & EEDO) ? 1 : 0);
eeprom_delay();
}
/* Terminate the EEPROM access. */
- outl(0, ee_addr);
+ sw32(mear, 0);
eeprom_delay();
return retval;
@@ -852,24 +865,27 @@ static u16 __devinit read_eeprom(long ioaddr, int location)
/* Read and write the MII management registers using software-generated
serial MDIO protocol. Note that the command bits and data bits are
send out separately */
-#define mdio_delay() inl(mdio_addr)
+#define mdio_delay() sr32(mear)
-static void mdio_idle(long mdio_addr)
+static void mdio_idle(struct sis900_private *sp)
{
- outl(MDIO | MDDIR, mdio_addr);
+ void __iomem *ioaddr = sp->ioaddr;
+
+ sw32(mear, MDIO | MDDIR);
mdio_delay();
- outl(MDIO | MDDIR | MDC, mdio_addr);
+ sw32(mear, MDIO | MDDIR | MDC);
}
-/* Syncronize the MII management interface by shifting 32 one bits out. */
-static void mdio_reset(long mdio_addr)
+/* Synchronize the MII management interface by shifting 32 one bits out. */
+static void mdio_reset(struct sis900_private *sp)
{
+ void __iomem *ioaddr = sp->ioaddr;
int i;
for (i = 31; i >= 0; i--) {
- outl(MDDIR | MDIO, mdio_addr);
+ sw32(mear, MDDIR | MDIO);
mdio_delay();
- outl(MDDIR | MDIO | MDC, mdio_addr);
+ sw32(mear, MDDIR | MDIO | MDC);
mdio_delay();
}
}
@@ -887,31 +903,33 @@ static void mdio_reset(long mdio_addr)
static int mdio_read(struct net_device *net_dev, int phy_id, int location)
{
- long mdio_addr = net_dev->base_addr + mear;
int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
+ struct sis900_private *sp = netdev_priv(net_dev);
+ void __iomem *ioaddr = sp->ioaddr;
u16 retval = 0;
int i;
- mdio_reset(mdio_addr);
- mdio_idle(mdio_addr);
+ mdio_reset(sp);
+ mdio_idle(sp);
for (i = 15; i >= 0; i--) {
int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
- outl(dataval, mdio_addr);
+
+ sw32(mear, dataval);
mdio_delay();
- outl(dataval | MDC, mdio_addr);
+ sw32(mear, dataval | MDC);
mdio_delay();
}
/* Read the 16 data bits. */
for (i = 16; i > 0; i--) {
- outl(0, mdio_addr);
+ sw32(mear, 0);
mdio_delay();
- retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0);
- outl(MDC, mdio_addr);
+ retval = (retval << 1) | ((sr32(mear) & MDIO) ? 1 : 0);
+ sw32(mear, MDC);
mdio_delay();
}
- outl(0x00, mdio_addr);
+ sw32(mear, 0x00);
return retval;
}
@@ -931,19 +949,21 @@ static int mdio_read(struct net_device *net_dev, int phy_id, int location)
static void mdio_write(struct net_device *net_dev, int phy_id, int location,
int value)
{
- long mdio_addr = net_dev->base_addr + mear;
int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
+ struct sis900_private *sp = netdev_priv(net_dev);
+ void __iomem *ioaddr = sp->ioaddr;
int i;
- mdio_reset(mdio_addr);
- mdio_idle(mdio_addr);
+ mdio_reset(sp);
+ mdio_idle(sp);
/* Shift the command bits out. */
for (i = 15; i >= 0; i--) {
int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
- outb(dataval, mdio_addr);
+
+ sw8(mear, dataval);
mdio_delay();
- outb(dataval | MDC, mdio_addr);
+ sw8(mear, dataval | MDC);
mdio_delay();
}
mdio_delay();
@@ -951,21 +971,22 @@ static void mdio_write(struct net_device *net_dev, int phy_id, int location,
/* Shift the value bits out. */
for (i = 15; i >= 0; i--) {
int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;
- outl(dataval, mdio_addr);
+
+ sw32(mear, dataval);
mdio_delay();
- outl(dataval | MDC, mdio_addr);
+ sw32(mear, dataval | MDC);
mdio_delay();
}
mdio_delay();
/* Clear out extra bits. */
for (i = 2; i > 0; i--) {
- outb(0, mdio_addr);
+ sw8(mear, 0);
mdio_delay();
- outb(MDC, mdio_addr);
+ sw8(mear, MDC);
mdio_delay();
}
- outl(0x00, mdio_addr);
+ sw32(mear, 0x00);
}
@@ -1000,9 +1021,12 @@ static u16 sis900_reset_phy(struct net_device *net_dev, int phy_addr)
*/
static void sis900_poll(struct net_device *dev)
{
- disable_irq(dev->irq);
- sis900_interrupt(dev->irq, dev);
- enable_irq(dev->irq);
+ struct sis900_private *sp = netdev_priv(dev);
+ const int irq = sp->pci_dev->irq;
+
+ disable_irq(irq);
+ sis900_interrupt(irq, dev);
+ enable_irq(irq);
}
#endif
@@ -1018,7 +1042,7 @@ static int
sis900_open(struct net_device *net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
- long ioaddr = net_dev->base_addr;
+ void __iomem *ioaddr = sis_priv->ioaddr;
int ret;
/* Soft reset the chip. */
@@ -1027,8 +1051,8 @@ sis900_open(struct net_device *net_dev)
/* Equalizer workaround Rule */
sis630_set_eq(net_dev, sis_priv->chipset_rev);
- ret = request_irq(net_dev->irq, sis900_interrupt, IRQF_SHARED,
- net_dev->name, net_dev);
+ ret = request_irq(sis_priv->pci_dev->irq, sis900_interrupt, IRQF_SHARED,
+ net_dev->name, net_dev);
if (ret)
return ret;
@@ -1042,12 +1066,12 @@ sis900_open(struct net_device *net_dev)
netif_start_queue(net_dev);
/* Workaround for EDB */
- sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
+ sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
/* Enable all known interrupts by setting the interrupt mask. */
- outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
- outl(RxENA | inl(ioaddr + cr), ioaddr + cr);
- outl(IE, ioaddr + ier);
+ sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE);
+ sw32(cr, RxENA | sr32(cr));
+ sw32(ier, IE);
sis900_check_mode(net_dev, sis_priv->mii);
@@ -1074,31 +1098,30 @@ static void
sis900_init_rxfilter (struct net_device * net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
- long ioaddr = net_dev->base_addr;
+ void __iomem *ioaddr = sis_priv->ioaddr;
u32 rfcrSave;
u32 i;
- rfcrSave = inl(rfcr + ioaddr);
+ rfcrSave = sr32(rfcr);
/* disable packet filtering before setting filter */
- outl(rfcrSave & ~RFEN, rfcr + ioaddr);
+ sw32(rfcr, rfcrSave & ~RFEN);
/* load MAC addr to filter data register */
for (i = 0 ; i < 3 ; i++) {
- u32 w;
+ u32 w = (u32) *((u16 *)(net_dev->dev_addr)+i);
- w = (u32) *((u16 *)(net_dev->dev_addr)+i);
- outl((i << RFADDR_shift), ioaddr + rfcr);
- outl(w, ioaddr + rfdr);
+ sw32(rfcr, i << RFADDR_shift);
+ sw32(rfdr, w);
if (netif_msg_hw(sis_priv)) {
printk(KERN_DEBUG "%s: Receive Filter Addrss[%d]=%x\n",
- net_dev->name, i, inl(ioaddr + rfdr));
+ net_dev->name, i, sr32(rfdr));
}
}
/* enable packet filtering */
- outl(rfcrSave | RFEN, rfcr + ioaddr);
+ sw32(rfcr, rfcrSave | RFEN);
}
/**
@@ -1112,7 +1135,7 @@ static void
sis900_init_tx_ring(struct net_device *net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
- long ioaddr = net_dev->base_addr;
+ void __iomem *ioaddr = sis_priv->ioaddr;
int i;
sis_priv->tx_full = 0;
@@ -1128,10 +1151,10 @@ sis900_init_tx_ring(struct net_device *net_dev)
}
/* load Transmit Descriptor Register */
- outl(sis_priv->tx_ring_dma, ioaddr + txdp);
+ sw32(txdp, sis_priv->tx_ring_dma);
if (netif_msg_hw(sis_priv))
printk(KERN_DEBUG "%s: TX descriptor register loaded with: %8.8x\n",
- net_dev->name, inl(ioaddr + txdp));
+ net_dev->name, sr32(txdp));
}
/**
@@ -1146,7 +1169,7 @@ static void
sis900_init_rx_ring(struct net_device *net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
- long ioaddr = net_dev->base_addr;
+ void __iomem *ioaddr = sis_priv->ioaddr;
int i;
sis_priv->cur_rx = 0;
@@ -1181,10 +1204,10 @@ sis900_init_rx_ring(struct net_device *net_dev)
sis_priv->dirty_rx = (unsigned int) (i - NUM_RX_DESC);
/* load Receive Descriptor Register */
- outl(sis_priv->rx_ring_dma, ioaddr + rxdp);
+ sw32(rxdp, sis_priv->rx_ring_dma);
if (netif_msg_hw(sis_priv))
printk(KERN_DEBUG "%s: RX descriptor register loaded with: %8.8x\n",
- net_dev->name, inl(ioaddr + rxdp));
+ net_dev->name, sr32(rxdp));
}
/**
@@ -1298,7 +1321,7 @@ static void sis900_timer(unsigned long data)
sis900_read_mode(net_dev, &speed, &duplex);
if (duplex){
- sis900_set_mode(net_dev->base_addr, speed, duplex);
+ sis900_set_mode(sis_priv, speed, duplex);
sis630_set_eq(net_dev, sis_priv->chipset_rev);
netif_start_queue(net_dev);
}
@@ -1359,25 +1382,25 @@ static void sis900_timer(unsigned long data)
static void sis900_check_mode(struct net_device *net_dev, struct mii_phy *mii_phy)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
- long ioaddr = net_dev->base_addr;
+ void __iomem *ioaddr = sis_priv->ioaddr;
int speed, duplex;
if (mii_phy->phy_types == LAN) {
- outl(~EXD & inl(ioaddr + cfg), ioaddr + cfg);
+ sw32(cfg, ~EXD & sr32(cfg));
sis900_set_capability(net_dev , mii_phy);
sis900_auto_negotiate(net_dev, sis_priv->cur_phy);
} else {
- outl(EXD | inl(ioaddr + cfg), ioaddr + cfg);
+ sw32(cfg, EXD | sr32(cfg));
speed = HW_SPEED_HOME;
duplex = FDX_CAPABLE_HALF_SELECTED;
- sis900_set_mode(ioaddr, speed, duplex);
+ sis900_set_mode(sis_priv, speed, duplex);
sis_priv->autong_complete = 1;
}
}
/**
* sis900_set_mode - Set the media mode of mac register.
- * @ioaddr: the address of the device
+ * @sp: the device private data
* @speed : the transmit speed to be determined
* @duplex: the duplex mode to be determined
*
@@ -1388,11 +1411,12 @@ static void sis900_check_mode(struct net_device *net_dev, struct mii_phy *mii_ph
* double words.
*/
-static void sis900_set_mode (long ioaddr, int speed, int duplex)
+static void sis900_set_mode(struct sis900_private *sp, int speed, int duplex)
{
+ void __iomem *ioaddr = sp->ioaddr;
u32 tx_flags = 0, rx_flags = 0;
- if (inl(ioaddr + cfg) & EDB_MASTER_EN) {
+ if (sr32( cfg) & EDB_MASTER_EN) {
tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) |
(TX_FILL_THRESH << TxFILLT_shift);
rx_flags = DMA_BURST_64 << RxMXDMA_shift;
@@ -1420,8 +1444,8 @@ static void sis900_set_mode (long ioaddr, int speed, int duplex)
rx_flags |= RxAJAB;
#endif
- outl (tx_flags, ioaddr + txcfg);
- outl (rx_flags, ioaddr + rxcfg);
+ sw32(txcfg, tx_flags);
+ sw32(rxcfg, rx_flags);
}
/**
@@ -1528,16 +1552,17 @@ static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex
static void sis900_tx_timeout(struct net_device *net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
- long ioaddr = net_dev->base_addr;
+ void __iomem *ioaddr = sis_priv->ioaddr;
unsigned long flags;
int i;
- if(netif_msg_tx_err(sis_priv))
+ if (netif_msg_tx_err(sis_priv)) {
printk(KERN_INFO "%s: Transmit timeout, status %8.8x %8.8x\n",
- net_dev->name, inl(ioaddr + cr), inl(ioaddr + isr));
+ net_dev->name, sr32(cr), sr32(isr));
+ }
/* Disable interrupts by clearing the interrupt mask. */
- outl(0x0000, ioaddr + imr);
+ sw32(imr, 0x0000);
/* use spinlock to prevent interrupt handler accessing buffer ring */
spin_lock_irqsave(&sis_priv->lock, flags);
@@ -1566,10 +1591,10 @@ static void sis900_tx_timeout(struct net_device *net_dev)
net_dev->trans_start = jiffies; /* prevent tx timeout */
/* load Transmit Descriptor Register */
- outl(sis_priv->tx_ring_dma, ioaddr + txdp);
+ sw32(txdp, sis_priv->tx_ring_dma);
/* Enable all known interrupts by setting the interrupt mask. */
- outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
+ sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE);
}
/**
@@ -1586,7 +1611,7 @@ static netdev_tx_t
sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
- long ioaddr = net_dev->base_addr;
+ void __iomem *ioaddr = sis_priv->ioaddr;
unsigned int entry;
unsigned long flags;
unsigned int index_cur_tx, index_dirty_tx;
@@ -1608,7 +1633,7 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
sis_priv->tx_ring[entry].bufptr = pci_map_single(sis_priv->pci_dev,
skb->data, skb->len, PCI_DMA_TODEVICE);
sis_priv->tx_ring[entry].cmdsts = (OWN | skb->len);
- outl(TxENA | inl(ioaddr + cr), ioaddr + cr);
+ sw32(cr, TxENA | sr32(cr));
sis_priv->cur_tx ++;
index_cur_tx = sis_priv->cur_tx;
@@ -1654,14 +1679,14 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
struct net_device *net_dev = dev_instance;
struct sis900_private *sis_priv = netdev_priv(net_dev);
int boguscnt = max_interrupt_work;
- long ioaddr = net_dev->base_addr;
+ void __iomem *ioaddr = sis_priv->ioaddr;
u32 status;
unsigned int handled = 0;
spin_lock (&sis_priv->lock);
do {
- status = inl(ioaddr + isr);
+ status = sr32(isr);
if ((status & (HIBERR|TxURN|TxERR|TxIDLE|RxORN|RxERR|RxOK)) == 0)
/* nothing intresting happened */
@@ -1696,7 +1721,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
if(netif_msg_intr(sis_priv))
printk(KERN_DEBUG "%s: exiting interrupt, "
"interrupt status = 0x%#8.8x.\n",
- net_dev->name, inl(ioaddr + isr));
+ net_dev->name, sr32(isr));
spin_unlock (&sis_priv->lock);
return IRQ_RETVAL(handled);
@@ -1715,7 +1740,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
static int sis900_rx(struct net_device *net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
- long ioaddr = net_dev->base_addr;
+ void __iomem *ioaddr = sis_priv->ioaddr;
unsigned int entry = sis_priv->cur_rx % NUM_RX_DESC;
u32 rx_status = sis_priv->rx_ring[entry].cmdsts;
int rx_work_limit;
@@ -1847,7 +1872,7 @@ refill_rx_ring:
}
}
/* re-enable the potentially idle receive state matchine */
- outl(RxENA | inl(ioaddr + cr), ioaddr + cr );
+ sw32(cr , RxENA | sr32(cr));
return 0;
}
@@ -1932,31 +1957,31 @@ static void sis900_finish_xmit (struct net_device *net_dev)
static int sis900_close(struct net_device *net_dev)
{
- long ioaddr = net_dev->base_addr;
struct sis900_private *sis_priv = netdev_priv(net_dev);
+ struct pci_dev *pdev = sis_priv->pci_dev;
+ void __iomem *ioaddr = sis_priv->ioaddr;
struct sk_buff *skb;
int i;
netif_stop_queue(net_dev);
/* Disable interrupts by clearing the interrupt mask. */
- outl(0x0000, ioaddr + imr);
- outl(0x0000, ioaddr + ier);
+ sw32(imr, 0x0000);
+ sw32(ier, 0x0000);
/* Stop the chip's Tx and Rx Status Machine */
- outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
+ sw32(cr, RxDIS | TxDIS | sr32(cr));
del_timer(&sis_priv->timer);
- free_irq(net_dev->irq, net_dev);
+ free_irq(pdev->irq, net_dev);
/* Free Tx and RX skbuff */
for (i = 0; i < NUM_RX_DESC; i++) {
skb = sis_priv->rx_skbuff[i];
if (skb) {
- pci_unmap_single(sis_priv->pci_dev,
- sis_priv->rx_ring[i].bufptr,
- RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(pdev, sis_priv->rx_ring[i].bufptr,
+ RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
dev_kfree_skb(skb);
sis_priv->rx_skbuff[i] = NULL;
}
@@ -1964,9 +1989,8 @@ static int sis900_close(struct net_device *net_dev)
for (i = 0; i < NUM_TX_DESC; i++) {
skb = sis_priv->tx_skbuff[i];
if (skb) {
- pci_unmap_single(sis_priv->pci_dev,
- sis_priv->tx_ring[i].bufptr, skb->len,
- PCI_DMA_TODEVICE);
+ pci_unmap_single(pdev, sis_priv->tx_ring[i].bufptr,
+ skb->len, PCI_DMA_TODEVICE);
dev_kfree_skb(skb);
sis_priv->tx_skbuff[i] = NULL;
}
@@ -2055,14 +2079,14 @@ static int sis900_nway_reset(struct net_device *net_dev)
static int sis900_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
- long pmctrl_addr = net_dev->base_addr + pmctrl;
+ void __iomem *ioaddr = sis_priv->ioaddr;
u32 cfgpmcsr = 0, pmctrl_bits = 0;
if (wol->wolopts == 0) {
pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr);
cfgpmcsr &= ~PME_EN;
pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr);
- outl(pmctrl_bits, pmctrl_addr);
+ sw32(pmctrl, pmctrl_bits);
if (netif_msg_wol(sis_priv))
printk(KERN_DEBUG "%s: Wake on LAN disabled\n", net_dev->name);
return 0;
@@ -2077,7 +2101,7 @@ static int sis900_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wo
if (wol->wolopts & WAKE_PHY)
pmctrl_bits |= LINKON;
- outl(pmctrl_bits, pmctrl_addr);
+ sw32(pmctrl, pmctrl_bits);
pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr);
cfgpmcsr |= PME_EN;
@@ -2090,10 +2114,11 @@ static int sis900_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wo
static void sis900_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
{
- long pmctrl_addr = net_dev->base_addr + pmctrl;
+ struct sis900_private *sp = netdev_priv(net_dev);
+ void __iomem *ioaddr = sp->ioaddr;
u32 pmctrl_bits;
- pmctrl_bits = inl(pmctrl_addr);
+ pmctrl_bits = sr32(pmctrl);
if (pmctrl_bits & MAGICPKT)
wol->wolopts |= WAKE_MAGIC;
if (pmctrl_bits & LINKON)
@@ -2279,8 +2304,8 @@ static inline u16 sis900_mcast_bitnr(u8 *addr, u8 revision)
static void set_rx_mode(struct net_device *net_dev)
{
- long ioaddr = net_dev->base_addr;
struct sis900_private *sis_priv = netdev_priv(net_dev);
+ void __iomem *ioaddr = sis_priv->ioaddr;
u16 mc_filter[16] = {0}; /* 256/128 bits multicast hash table */
int i, table_entries;
u32 rx_mode;
@@ -2322,24 +2347,24 @@ static void set_rx_mode(struct net_device *net_dev)
/* update Multicast Hash Table in Receive Filter */
for (i = 0; i < table_entries; i++) {
/* why plus 0x04 ??, That makes the correct value for hash table. */
- outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);
- outl(mc_filter[i], ioaddr + rfdr);
+ sw32(rfcr, (u32)(0x00000004 + i) << RFADDR_shift);
+ sw32(rfdr, mc_filter[i]);
}
- outl(RFEN | rx_mode, ioaddr + rfcr);
+ sw32(rfcr, RFEN | rx_mode);
/* sis900 is capable of looping back packets at MAC level for
* debugging purpose */
if (net_dev->flags & IFF_LOOPBACK) {
u32 cr_saved;
/* We must disable Tx/Rx before setting loopback mode */
- cr_saved = inl(ioaddr + cr);
- outl(cr_saved | TxDIS | RxDIS, ioaddr + cr);
+ cr_saved = sr32(cr);
+ sw32(cr, cr_saved | TxDIS | RxDIS);
/* enable loopback */
- outl(inl(ioaddr + txcfg) | TxMLB, ioaddr + txcfg);
- outl(inl(ioaddr + rxcfg) | RxATX, ioaddr + rxcfg);
+ sw32(txcfg, sr32(txcfg) | TxMLB);
+ sw32(rxcfg, sr32(rxcfg) | RxATX);
/* restore cr */
- outl(cr_saved, ioaddr + cr);
+ sw32(cr, cr_saved);
}
}
@@ -2355,26 +2380,25 @@ static void set_rx_mode(struct net_device *net_dev)
static void sis900_reset(struct net_device *net_dev)
{
struct sis900_private *sis_priv = netdev_priv(net_dev);
- long ioaddr = net_dev->base_addr;
- int i = 0;
+ void __iomem *ioaddr = sis_priv->ioaddr;
u32 status = TxRCMP | RxRCMP;
+ int i;
- outl(0, ioaddr + ier);
- outl(0, ioaddr + imr);
- outl(0, ioaddr + rfcr);
+ sw32(ier, 0);
+ sw32(imr, 0);
+ sw32(rfcr, 0);
- outl(RxRESET | TxRESET | RESET | inl(ioaddr + cr), ioaddr + cr);
+ sw32(cr, RxRESET | TxRESET | RESET | sr32(cr));
/* Check that the chip has finished the reset. */
- while (status && (i++ < 1000)) {
- status ^= (inl(isr + ioaddr) & status);
- }
+ for (i = 0; status && (i < 1000); i++)
+ status ^= sr32(isr) & status;
- if( (sis_priv->chipset_rev >= SIS635A_900_REV) ||
- (sis_priv->chipset_rev == SIS900B_900_REV) )
- outl(PESEL | RND_CNT, ioaddr + cfg);
+ if (sis_priv->chipset_rev >= SIS635A_900_REV ||
+ sis_priv->chipset_rev == SIS900B_900_REV)
+ sw32(cfg, PESEL | RND_CNT);
else
- outl(PESEL, ioaddr + cfg);
+ sw32(cfg, PESEL);
}
/**
@@ -2388,10 +2412,12 @@ static void __devexit sis900_remove(struct pci_dev *pci_dev)
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
struct sis900_private *sis_priv = netdev_priv(net_dev);
- struct mii_phy *phy = NULL;
+
+ unregister_netdev(net_dev);
while (sis_priv->first_mii) {
- phy = sis_priv->first_mii;
+ struct mii_phy *phy = sis_priv->first_mii;
+
sis_priv->first_mii = phy->next;
kfree(phy);
}
@@ -2400,7 +2426,7 @@ static void __devexit sis900_remove(struct pci_dev *pci_dev)
sis_priv->rx_ring_dma);
pci_free_consistent(pci_dev, TX_TOTAL_SIZE, sis_priv->tx_ring,
sis_priv->tx_ring_dma);
- unregister_netdev(net_dev);
+ pci_iounmap(pci_dev, sis_priv->ioaddr);
free_netdev(net_dev);
pci_release_regions(pci_dev);
pci_set_drvdata(pci_dev, NULL);
@@ -2411,7 +2437,8 @@ static void __devexit sis900_remove(struct pci_dev *pci_dev)
static int sis900_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
- long ioaddr = net_dev->base_addr;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
+ void __iomem *ioaddr = sis_priv->ioaddr;
if(!netif_running(net_dev))
return 0;
@@ -2420,7 +2447,7 @@ static int sis900_suspend(struct pci_dev *pci_dev, pm_message_t state)
netif_device_detach(net_dev);
/* Stop the chip's Tx and Rx Status Machine */
- outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
+ sw32(cr, RxDIS | TxDIS | sr32(cr));
pci_set_power_state(pci_dev, PCI_D3hot);
pci_save_state(pci_dev);
@@ -2432,7 +2459,7 @@ static int sis900_resume(struct pci_dev *pci_dev)
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
struct sis900_private *sis_priv = netdev_priv(net_dev);
- long ioaddr = net_dev->base_addr;
+ void __iomem *ioaddr = sis_priv->ioaddr;
if(!netif_running(net_dev))
return 0;
@@ -2453,9 +2480,9 @@ static int sis900_resume(struct pci_dev *pci_dev)
sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
/* Enable all known interrupts by setting the interrupt mask. */
- outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
- outl(RxENA | inl(ioaddr + cr), ioaddr + cr);
- outl(IE, ioaddr + ier);
+ sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE);
+ sw32(cr, RxENA | sr32(cr));
+ sw32(ier, IE);
sis900_check_mode(net_dev, sis_priv->mii);
diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c
index 2a662e6112e9..d01e59c348ad 100644
--- a/drivers/net/ethernet/smsc/epic100.c
+++ b/drivers/net/ethernet/smsc/epic100.c
@@ -146,6 +146,12 @@ enum chip_capability_flags { MII_PWRDWN=1, TYPE2_INTR=2, NO_MII=4 };
#define EPIC_TOTAL_SIZE 0x100
#define USE_IO_OPS 1
+#ifdef USE_IO_OPS
+#define EPIC_BAR 0
+#else
+#define EPIC_BAR 1
+#endif
+
typedef enum {
SMSC_83C170_0,
SMSC_83C170,
@@ -176,21 +182,11 @@ static DEFINE_PCI_DEVICE_TABLE(epic_pci_tbl) = {
};
MODULE_DEVICE_TABLE (pci, epic_pci_tbl);
-
-#ifndef USE_IO_OPS
-#undef inb
-#undef inw
-#undef inl
-#undef outb
-#undef outw
-#undef outl
-#define inb readb
-#define inw readw
-#define inl readl
-#define outb writeb
-#define outw writew
-#define outl writel
-#endif
+#define ew16(reg, val) iowrite16(val, ioaddr + (reg))
+#define ew32(reg, val) iowrite32(val, ioaddr + (reg))
+#define er8(reg) ioread8(ioaddr + (reg))
+#define er16(reg) ioread16(ioaddr + (reg))
+#define er32(reg) ioread32(ioaddr + (reg))
/* Offsets to registers, using the (ugh) SMC names. */
enum epic_registers {
@@ -275,6 +271,7 @@ struct epic_private {
u32 irq_mask;
unsigned int rx_buf_sz; /* Based on MTU+slack. */
+ void __iomem *ioaddr;
struct pci_dev *pci_dev; /* PCI bus location. */
int chip_id, chip_flags;
@@ -290,7 +287,7 @@ struct epic_private {
};
static int epic_open(struct net_device *dev);
-static int read_eeprom(long ioaddr, int location);
+static int read_eeprom(struct epic_private *, int);
static int mdio_read(struct net_device *dev, int phy_id, int location);
static void mdio_write(struct net_device *dev, int phy_id, int loc, int val);
static void epic_restart(struct net_device *dev);
@@ -321,11 +318,11 @@ static const struct net_device_ops epic_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static int __devinit epic_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __devinit epic_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
static int card_idx = -1;
- long ioaddr;
+ void __iomem *ioaddr;
int chip_idx = (int) ent->driver_data;
int irq;
struct net_device *dev;
@@ -368,19 +365,15 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
SET_NETDEV_DEV(dev, &pdev->dev);
-#ifdef USE_IO_OPS
- ioaddr = pci_resource_start (pdev, 0);
-#else
- ioaddr = pci_resource_start (pdev, 1);
- ioaddr = (long) pci_ioremap_bar(pdev, 1);
+ ioaddr = pci_iomap(pdev, EPIC_BAR, 0);
if (!ioaddr) {
dev_err(&pdev->dev, "ioremap failed\n");
goto err_out_free_netdev;
}
-#endif
pci_set_drvdata(pdev, dev);
ep = netdev_priv(dev);
+ ep->ioaddr = ioaddr;
ep->mii.dev = dev;
ep->mii.mdio_read = mdio_read;
ep->mii.mdio_write = mdio_write;
@@ -409,34 +402,31 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
duplex = full_duplex[card_idx];
}
- dev->base_addr = ioaddr;
- dev->irq = irq;
-
spin_lock_init(&ep->lock);
spin_lock_init(&ep->napi_lock);
ep->reschedule_in_poll = 0;
/* Bring the chip out of low-power mode. */
- outl(0x4200, ioaddr + GENCTL);
+ ew32(GENCTL, 0x4200);
/* Magic?! If we don't set this bit the MII interface won't work. */
/* This magic is documented in SMSC app note 7.15 */
for (i = 16; i > 0; i--)
- outl(0x0008, ioaddr + TEST1);
+ ew32(TEST1, 0x0008);
/* Turn on the MII transceiver. */
- outl(0x12, ioaddr + MIICfg);
+ ew32(MIICfg, 0x12);
if (chip_idx == 1)
- outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
- outl(0x0200, ioaddr + GENCTL);
+ ew32(NVCTL, (er32(NVCTL) & ~0x003c) | 0x4800);
+ ew32(GENCTL, 0x0200);
/* Note: the '175 does not have a serial EEPROM. */
for (i = 0; i < 3; i++)
- ((__le16 *)dev->dev_addr)[i] = cpu_to_le16(inw(ioaddr + LAN0 + i*4));
+ ((__le16 *)dev->dev_addr)[i] = cpu_to_le16(er16(LAN0 + i*4));
if (debug > 2) {
dev_printk(KERN_DEBUG, &pdev->dev, "EEPROM contents:\n");
for (i = 0; i < 64; i++)
- printk(" %4.4x%s", read_eeprom(ioaddr, i),
+ printk(" %4.4x%s", read_eeprom(ep, i),
i % 16 == 15 ? "\n" : "");
}
@@ -481,8 +471,8 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
/* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
if (ep->chip_flags & MII_PWRDWN)
- outl(inl(ioaddr + NVCTL) & ~0x483C, ioaddr + NVCTL);
- outl(0x0008, ioaddr + GENCTL);
+ ew32(NVCTL, er32(NVCTL) & ~0x483c);
+ ew32(GENCTL, 0x0008);
/* The lower four bits are the media type. */
if (duplex) {
@@ -501,8 +491,9 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
if (ret < 0)
goto err_out_unmap_rx;
- printk(KERN_INFO "%s: %s at %#lx, IRQ %d, %pM\n",
- dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq,
+ printk(KERN_INFO "%s: %s at %lx, IRQ %d, %pM\n",
+ dev->name, pci_id_tbl[chip_idx].name,
+ (long)pci_resource_start(pdev, EPIC_BAR), pdev->irq,
dev->dev_addr);
out:
@@ -513,10 +504,8 @@ err_out_unmap_rx:
err_out_unmap_tx:
pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
err_out_iounmap:
-#ifndef USE_IO_OPS
- iounmap(ioaddr);
+ pci_iounmap(pdev, ioaddr);
err_out_free_netdev:
-#endif
free_netdev(dev);
err_out_free_res:
pci_release_regions(pdev);
@@ -540,7 +529,7 @@ err_out_disable:
This serves to flush the operation to the PCI bus.
*/
-#define eeprom_delay() inl(ee_addr)
+#define eeprom_delay() er32(EECTL)
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5 << 6)
@@ -550,67 +539,67 @@ err_out_disable:
static void epic_disable_int(struct net_device *dev, struct epic_private *ep)
{
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = ep->ioaddr;
- outl(0x00000000, ioaddr + INTMASK);
+ ew32(INTMASK, 0x00000000);
}
-static inline void __epic_pci_commit(long ioaddr)
+static inline void __epic_pci_commit(void __iomem *ioaddr)
{
#ifndef USE_IO_OPS
- inl(ioaddr + INTMASK);
+ er32(INTMASK);
#endif
}
static inline void epic_napi_irq_off(struct net_device *dev,
struct epic_private *ep)
{
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = ep->ioaddr;
- outl(ep->irq_mask & ~EpicNapiEvent, ioaddr + INTMASK);
+ ew32(INTMASK, ep->irq_mask & ~EpicNapiEvent);
__epic_pci_commit(ioaddr);
}
static inline void epic_napi_irq_on(struct net_device *dev,
struct epic_private *ep)
{
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = ep->ioaddr;
/* No need to commit possible posted write */
- outl(ep->irq_mask | EpicNapiEvent, ioaddr + INTMASK);
+ ew32(INTMASK, ep->irq_mask | EpicNapiEvent);
}
-static int __devinit read_eeprom(long ioaddr, int location)
+static int __devinit read_eeprom(struct epic_private *ep, int location)
{
+ void __iomem *ioaddr = ep->ioaddr;
int i;
int retval = 0;
- long ee_addr = ioaddr + EECTL;
int read_cmd = location |
- (inl(ee_addr) & 0x40 ? EE_READ64_CMD : EE_READ256_CMD);
+ (er32(EECTL) & 0x40 ? EE_READ64_CMD : EE_READ256_CMD);
- outl(EE_ENB & ~EE_CS, ee_addr);
- outl(EE_ENB, ee_addr);
+ ew32(EECTL, EE_ENB & ~EE_CS);
+ ew32(EECTL, EE_ENB);
/* Shift the read command bits out. */
for (i = 12; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_WRITE_1 : EE_WRITE_0;
- outl(EE_ENB | dataval, ee_addr);
+ ew32(EECTL, EE_ENB | dataval);
eeprom_delay();
- outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+ ew32(EECTL, EE_ENB | dataval | EE_SHIFT_CLK);
eeprom_delay();
}
- outl(EE_ENB, ee_addr);
+ ew32(EECTL, EE_ENB);
for (i = 16; i > 0; i--) {
- outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
+ ew32(EECTL, EE_ENB | EE_SHIFT_CLK);
eeprom_delay();
- retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
- outl(EE_ENB, ee_addr);
+ retval = (retval << 1) | ((er32(EECTL) & EE_DATA_READ) ? 1 : 0);
+ ew32(EECTL, EE_ENB);
eeprom_delay();
}
/* Terminate the EEPROM access. */
- outl(EE_ENB & ~EE_CS, ee_addr);
+ ew32(EECTL, EE_ENB & ~EE_CS);
return retval;
}
@@ -618,22 +607,23 @@ static int __devinit read_eeprom(long ioaddr, int location)
#define MII_WRITEOP 2
static int mdio_read(struct net_device *dev, int phy_id, int location)
{
- long ioaddr = dev->base_addr;
+ struct epic_private *ep = netdev_priv(dev);
+ void __iomem *ioaddr = ep->ioaddr;
int read_cmd = (phy_id << 9) | (location << 4) | MII_READOP;
int i;
- outl(read_cmd, ioaddr + MIICtrl);
+ ew32(MIICtrl, read_cmd);
/* Typical operation takes 25 loops. */
for (i = 400; i > 0; i--) {
barrier();
- if ((inl(ioaddr + MIICtrl) & MII_READOP) == 0) {
+ if ((er32(MIICtrl) & MII_READOP) == 0) {
/* Work around read failure bug. */
if (phy_id == 1 && location < 6 &&
- inw(ioaddr + MIIData) == 0xffff) {
- outl(read_cmd, ioaddr + MIICtrl);
+ er16(MIIData) == 0xffff) {
+ ew32(MIICtrl, read_cmd);
continue;
}
- return inw(ioaddr + MIIData);
+ return er16(MIIData);
}
}
return 0xffff;
@@ -641,14 +631,15 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
{
- long ioaddr = dev->base_addr;
+ struct epic_private *ep = netdev_priv(dev);
+ void __iomem *ioaddr = ep->ioaddr;
int i;
- outw(value, ioaddr + MIIData);
- outl((phy_id << 9) | (loc << 4) | MII_WRITEOP, ioaddr + MIICtrl);
+ ew16(MIIData, value);
+ ew32(MIICtrl, (phy_id << 9) | (loc << 4) | MII_WRITEOP);
for (i = 10000; i > 0; i--) {
barrier();
- if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0)
+ if ((er32(MIICtrl) & MII_WRITEOP) == 0)
break;
}
}
@@ -657,25 +648,26 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
static int epic_open(struct net_device *dev)
{
struct epic_private *ep = netdev_priv(dev);
- long ioaddr = dev->base_addr;
- int i;
- int retval;
+ void __iomem *ioaddr = ep->ioaddr;
+ const int irq = ep->pci_dev->irq;
+ int rc, i;
/* Soft reset the chip. */
- outl(0x4001, ioaddr + GENCTL);
+ ew32(GENCTL, 0x4001);
napi_enable(&ep->napi);
- if ((retval = request_irq(dev->irq, epic_interrupt, IRQF_SHARED, dev->name, dev))) {
+ rc = request_irq(irq, epic_interrupt, IRQF_SHARED, dev->name, dev);
+ if (rc) {
napi_disable(&ep->napi);
- return retval;
+ return rc;
}
epic_init_ring(dev);
- outl(0x4000, ioaddr + GENCTL);
+ ew32(GENCTL, 0x4000);
/* This magic is documented in SMSC app note 7.15 */
for (i = 16; i > 0; i--)
- outl(0x0008, ioaddr + TEST1);
+ ew32(TEST1, 0x0008);
/* Pull the chip out of low-power mode, enable interrupts, and set for
PCI read multiple. The MIIcfg setting and strange write order are
@@ -683,29 +675,29 @@ static int epic_open(struct net_device *dev)
wiring on the Ositech CardBus card.
*/
#if 0
- outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
+ ew32(MIICfg, dev->if_port == 1 ? 0x13 : 0x12);
#endif
if (ep->chip_flags & MII_PWRDWN)
- outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+ ew32(NVCTL, (er32(NVCTL) & ~0x003c) | 0x4800);
/* Tell the chip to byteswap descriptors on big-endian hosts */
#ifdef __BIG_ENDIAN
- outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
- inl(ioaddr + GENCTL);
- outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+ ew32(GENCTL, 0x4432 | (RX_FIFO_THRESH << 8));
+ er32(GENCTL);
+ ew32(GENCTL, 0x0432 | (RX_FIFO_THRESH << 8));
#else
- outl(0x4412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
- inl(ioaddr + GENCTL);
- outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+ ew32(GENCTL, 0x4412 | (RX_FIFO_THRESH << 8));
+ er32(GENCTL);
+ ew32(GENCTL, 0x0412 | (RX_FIFO_THRESH << 8));
#endif
udelay(20); /* Looks like EPII needs that if you want reliable RX init. FIXME: pci posting bug? */
for (i = 0; i < 3; i++)
- outl(le16_to_cpu(((__le16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
+ ew32(LAN0 + i*4, le16_to_cpu(((__le16*)dev->dev_addr)[i]));
ep->tx_threshold = TX_FIFO_THRESH;
- outl(ep->tx_threshold, ioaddr + TxThresh);
+ ew32(TxThresh, ep->tx_threshold);
if (media2miictl[dev->if_port & 15]) {
if (ep->mii_phy_cnt)
@@ -731,26 +723,27 @@ static int epic_open(struct net_device *dev)
}
}
- outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
- outl(ep->rx_ring_dma, ioaddr + PRxCDAR);
- outl(ep->tx_ring_dma, ioaddr + PTxCDAR);
+ ew32(TxCtrl, ep->mii.full_duplex ? 0x7f : 0x79);
+ ew32(PRxCDAR, ep->rx_ring_dma);
+ ew32(PTxCDAR, ep->tx_ring_dma);
/* Start the chip's Rx process. */
set_rx_mode(dev);
- outl(StartRx | RxQueued, ioaddr + COMMAND);
+ ew32(COMMAND, StartRx | RxQueued);
netif_start_queue(dev);
/* Enable interrupts by setting the interrupt mask. */
- outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
- | CntFull | TxUnderrun
- | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
-
- if (debug > 1)
- printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
- "%s-duplex.\n",
- dev->name, ioaddr, dev->irq, (int)inl(ioaddr + GENCTL),
- ep->mii.full_duplex ? "full" : "half");
+ ew32(INTMASK, RxError | RxHeader | EpicNapiEvent | CntFull |
+ ((ep->chip_flags & TYPE2_INTR) ? PCIBusErr175 : PCIBusErr170) |
+ TxUnderrun);
+
+ if (debug > 1) {
+ printk(KERN_DEBUG "%s: epic_open() ioaddr %p IRQ %d "
+ "status %4.4x %s-duplex.\n",
+ dev->name, ioaddr, irq, er32(GENCTL),
+ ep->mii.full_duplex ? "full" : "half");
+ }
/* Set the timer to switch to check for link beat and perhaps switch
to an alternate media type. */
@@ -760,27 +753,29 @@ static int epic_open(struct net_device *dev)
ep->timer.function = epic_timer; /* timer handler */
add_timer(&ep->timer);
- return 0;
+ return rc;
}
/* Reset the chip to recover from a PCI transaction error.
This may occur at interrupt time. */
static void epic_pause(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ struct net_device_stats *stats = &dev->stats;
+ struct epic_private *ep = netdev_priv(dev);
+ void __iomem *ioaddr = ep->ioaddr;
netif_stop_queue (dev);
/* Disable interrupts by clearing the interrupt mask. */
- outl(0x00000000, ioaddr + INTMASK);
+ ew32(INTMASK, 0x00000000);
/* Stop the chip's Tx and Rx DMA processes. */
- outw(StopRx | StopTxDMA | StopRxDMA, ioaddr + COMMAND);
+ ew16(COMMAND, StopRx | StopTxDMA | StopRxDMA);
/* Update the error counts. */
- if (inw(ioaddr + COMMAND) != 0xffff) {
- dev->stats.rx_missed_errors += inb(ioaddr + MPCNT);
- dev->stats.rx_frame_errors += inb(ioaddr + ALICNT);
- dev->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ if (er16(COMMAND) != 0xffff) {
+ stats->rx_missed_errors += er8(MPCNT);
+ stats->rx_frame_errors += er8(ALICNT);
+ stats->rx_crc_errors += er8(CRCCNT);
}
/* Remove the packets on the Rx queue. */
@@ -789,12 +784,12 @@ static void epic_pause(struct net_device *dev)
static void epic_restart(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
struct epic_private *ep = netdev_priv(dev);
+ void __iomem *ioaddr = ep->ioaddr;
int i;
/* Soft reset the chip. */
- outl(0x4001, ioaddr + GENCTL);
+ ew32(GENCTL, 0x4001);
printk(KERN_DEBUG "%s: Restarting the EPIC chip, Rx %d/%d Tx %d/%d.\n",
dev->name, ep->cur_rx, ep->dirty_rx, ep->dirty_tx, ep->cur_tx);
@@ -802,47 +797,46 @@ static void epic_restart(struct net_device *dev)
/* This magic is documented in SMSC app note 7.15 */
for (i = 16; i > 0; i--)
- outl(0x0008, ioaddr + TEST1);
+ ew32(TEST1, 0x0008);
#ifdef __BIG_ENDIAN
- outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+ ew32(GENCTL, 0x0432 | (RX_FIFO_THRESH << 8));
#else
- outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+ ew32(GENCTL, 0x0412 | (RX_FIFO_THRESH << 8));
#endif
- outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
+ ew32(MIICfg, dev->if_port == 1 ? 0x13 : 0x12);
if (ep->chip_flags & MII_PWRDWN)
- outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+ ew32(NVCTL, (er32(NVCTL) & ~0x003c) | 0x4800);
for (i = 0; i < 3; i++)
- outl(le16_to_cpu(((__le16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
+ ew32(LAN0 + i*4, le16_to_cpu(((__le16*)dev->dev_addr)[i]));
ep->tx_threshold = TX_FIFO_THRESH;
- outl(ep->tx_threshold, ioaddr + TxThresh);
- outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
- outl(ep->rx_ring_dma + (ep->cur_rx%RX_RING_SIZE)*
- sizeof(struct epic_rx_desc), ioaddr + PRxCDAR);
- outl(ep->tx_ring_dma + (ep->dirty_tx%TX_RING_SIZE)*
- sizeof(struct epic_tx_desc), ioaddr + PTxCDAR);
+ ew32(TxThresh, ep->tx_threshold);
+ ew32(TxCtrl, ep->mii.full_duplex ? 0x7f : 0x79);
+ ew32(PRxCDAR, ep->rx_ring_dma +
+ (ep->cur_rx % RX_RING_SIZE) * sizeof(struct epic_rx_desc));
+ ew32(PTxCDAR, ep->tx_ring_dma +
+ (ep->dirty_tx % TX_RING_SIZE) * sizeof(struct epic_tx_desc));
/* Start the chip's Rx process. */
set_rx_mode(dev);
- outl(StartRx | RxQueued, ioaddr + COMMAND);
+ ew32(COMMAND, StartRx | RxQueued);
/* Enable interrupts by setting the interrupt mask. */
- outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
- | CntFull | TxUnderrun
- | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
+ ew32(INTMASK, RxError | RxHeader | EpicNapiEvent | CntFull |
+ ((ep->chip_flags & TYPE2_INTR) ? PCIBusErr175 : PCIBusErr170) |
+ TxUnderrun);
printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
" interrupt %4.4x.\n",
- dev->name, (int)inl(ioaddr + COMMAND), (int)inl(ioaddr + GENCTL),
- (int)inl(ioaddr + INTSTAT));
+ dev->name, er32(COMMAND), er32(GENCTL), er32(INTSTAT));
}
static void check_media(struct net_device *dev)
{
struct epic_private *ep = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = ep->ioaddr;
int mii_lpa = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], MII_LPA) : 0;
int negotiated = mii_lpa & ep->mii.advertising;
int duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
@@ -856,7 +850,7 @@ static void check_media(struct net_device *dev)
printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
" partner capability of %4.4x.\n", dev->name,
ep->mii.full_duplex ? "full" : "half", ep->phys[0], mii_lpa);
- outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+ ew32(TxCtrl, ep->mii.full_duplex ? 0x7F : 0x79);
}
}
@@ -864,16 +858,15 @@ static void epic_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct epic_private *ep = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = ep->ioaddr;
int next_tick = 5*HZ;
if (debug > 3) {
printk(KERN_DEBUG "%s: Media monitor tick, Tx status %8.8x.\n",
- dev->name, (int)inl(ioaddr + TxSTAT));
+ dev->name, er32(TxSTAT));
printk(KERN_DEBUG "%s: Other registers are IntMask %4.4x "
- "IntStatus %4.4x RxStatus %4.4x.\n",
- dev->name, (int)inl(ioaddr + INTMASK),
- (int)inl(ioaddr + INTSTAT), (int)inl(ioaddr + RxSTAT));
+ "IntStatus %4.4x RxStatus %4.4x.\n", dev->name,
+ er32(INTMASK), er32(INTSTAT), er32(RxSTAT));
}
check_media(dev);
@@ -885,23 +878,22 @@ static void epic_timer(unsigned long data)
static void epic_tx_timeout(struct net_device *dev)
{
struct epic_private *ep = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = ep->ioaddr;
if (debug > 0) {
printk(KERN_WARNING "%s: Transmit timeout using MII device, "
- "Tx status %4.4x.\n",
- dev->name, (int)inw(ioaddr + TxSTAT));
+ "Tx status %4.4x.\n", dev->name, er16(TxSTAT));
if (debug > 1) {
printk(KERN_DEBUG "%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
dev->name, ep->dirty_tx, ep->cur_tx);
}
}
- if (inw(ioaddr + TxSTAT) & 0x10) { /* Tx FIFO underflow. */
+ if (er16(TxSTAT) & 0x10) { /* Tx FIFO underflow. */
dev->stats.tx_fifo_errors++;
- outl(RestartTx, ioaddr + COMMAND);
+ ew32(COMMAND, RestartTx);
} else {
epic_restart(dev);
- outl(TxQueued, dev->base_addr + COMMAND);
+ ew32(COMMAND, TxQueued);
}
dev->trans_start = jiffies; /* prevent tx timeout */
@@ -959,6 +951,7 @@ static void epic_init_ring(struct net_device *dev)
static netdev_tx_t epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct epic_private *ep = netdev_priv(dev);
+ void __iomem *ioaddr = ep->ioaddr;
int entry, free_count;
u32 ctrl_word;
unsigned long flags;
@@ -999,13 +992,12 @@ static netdev_tx_t epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&ep->lock, flags);
/* Trigger an immediate transmit demand. */
- outl(TxQueued, dev->base_addr + COMMAND);
+ ew32(COMMAND, TxQueued);
if (debug > 4)
printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, "
- "flag %2.2x Tx status %8.8x.\n",
- dev->name, (int)skb->len, entry, ctrl_word,
- (int)inl(dev->base_addr + TxSTAT));
+ "flag %2.2x Tx status %8.8x.\n", dev->name, skb->len,
+ entry, ctrl_word, er32(TxSTAT));
return NETDEV_TX_OK;
}
@@ -1086,18 +1078,17 @@ static irqreturn_t epic_interrupt(int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
struct epic_private *ep = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = ep->ioaddr;
unsigned int handled = 0;
int status;
- status = inl(ioaddr + INTSTAT);
+ status = er32(INTSTAT);
/* Acknowledge all of the current interrupt sources ASAP. */
- outl(status & EpicNormalEvent, ioaddr + INTSTAT);
+ ew32(INTSTAT, status & EpicNormalEvent);
if (debug > 4) {
printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new "
- "intstat=%#8.8x.\n", dev->name, status,
- (int)inl(ioaddr + INTSTAT));
+ "intstat=%#8.8x.\n", dev->name, status, er32(INTSTAT));
}
if ((status & IntrSummary) == 0)
@@ -1118,19 +1109,21 @@ static irqreturn_t epic_interrupt(int irq, void *dev_instance)
/* Check uncommon events all at once. */
if (status & (CntFull | TxUnderrun | PCIBusErr170 | PCIBusErr175)) {
+ struct net_device_stats *stats = &dev->stats;
+
if (status == EpicRemoved)
goto out;
/* Always update the error counts to avoid overhead later. */
- dev->stats.rx_missed_errors += inb(ioaddr + MPCNT);
- dev->stats.rx_frame_errors += inb(ioaddr + ALICNT);
- dev->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ stats->rx_missed_errors += er8(MPCNT);
+ stats->rx_frame_errors += er8(ALICNT);
+ stats->rx_crc_errors += er8(CRCCNT);
if (status & TxUnderrun) { /* Tx FIFO underflow. */
- dev->stats.tx_fifo_errors++;
- outl(ep->tx_threshold += 128, ioaddr + TxThresh);
+ stats->tx_fifo_errors++;
+ ew32(TxThresh, ep->tx_threshold += 128);
/* Restart the transmit process. */
- outl(RestartTx, ioaddr + COMMAND);
+ ew32(COMMAND, RestartTx);
}
if (status & PCIBusErr170) {
printk(KERN_ERR "%s: PCI Bus Error! status %4.4x.\n",
@@ -1139,7 +1132,7 @@ static irqreturn_t epic_interrupt(int irq, void *dev_instance)
epic_restart(dev);
}
/* Clear all error sources. */
- outl(status & 0x7f18, ioaddr + INTSTAT);
+ ew32(INTSTAT, status & 0x7f18);
}
out:
@@ -1248,17 +1241,17 @@ static int epic_rx(struct net_device *dev, int budget)
static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
{
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = ep->ioaddr;
int status;
- status = inl(ioaddr + INTSTAT);
+ status = er32(INTSTAT);
if (status == EpicRemoved)
return;
if (status & RxOverflow) /* Missed a Rx frame. */
dev->stats.rx_errors++;
if (status & (RxOverflow | RxFull))
- outw(RxQueued, ioaddr + COMMAND);
+ ew16(COMMAND, RxQueued);
}
static int epic_poll(struct napi_struct *napi, int budget)
@@ -1266,7 +1259,7 @@ static int epic_poll(struct napi_struct *napi, int budget)
struct epic_private *ep = container_of(napi, struct epic_private, napi);
struct net_device *dev = ep->mii.dev;
int work_done = 0;
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = ep->ioaddr;
rx_action:
@@ -1287,7 +1280,7 @@ rx_action:
more = ep->reschedule_in_poll;
if (!more) {
__napi_complete(napi);
- outl(EpicNapiEvent, ioaddr + INTSTAT);
+ ew32(INTSTAT, EpicNapiEvent);
epic_napi_irq_on(dev, ep);
} else
ep->reschedule_in_poll--;
@@ -1303,8 +1296,9 @@ rx_action:
static int epic_close(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
struct epic_private *ep = netdev_priv(dev);
+ struct pci_dev *pdev = ep->pci_dev;
+ void __iomem *ioaddr = ep->ioaddr;
struct sk_buff *skb;
int i;
@@ -1313,13 +1307,13 @@ static int epic_close(struct net_device *dev)
if (debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
- dev->name, (int)inl(ioaddr + INTSTAT));
+ dev->name, er32(INTSTAT));
del_timer_sync(&ep->timer);
epic_disable_int(dev, ep);
- free_irq(dev->irq, dev);
+ free_irq(pdev->irq, dev);
epic_pause(dev);
@@ -1330,7 +1324,7 @@ static int epic_close(struct net_device *dev)
ep->rx_ring[i].rxstatus = 0; /* Not owned by Epic chip. */
ep->rx_ring[i].buflength = 0;
if (skb) {
- pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr,
+ pci_unmap_single(pdev, ep->rx_ring[i].bufaddr,
ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
dev_kfree_skb(skb);
}
@@ -1341,26 +1335,28 @@ static int epic_close(struct net_device *dev)
ep->tx_skbuff[i] = NULL;
if (!skb)
continue;
- pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr,
- skb->len, PCI_DMA_TODEVICE);
+ pci_unmap_single(pdev, ep->tx_ring[i].bufaddr, skb->len,
+ PCI_DMA_TODEVICE);
dev_kfree_skb(skb);
}
/* Green! Leave the chip in low-power mode. */
- outl(0x0008, ioaddr + GENCTL);
+ ew32(GENCTL, 0x0008);
return 0;
}
static struct net_device_stats *epic_get_stats(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ struct epic_private *ep = netdev_priv(dev);
+ void __iomem *ioaddr = ep->ioaddr;
if (netif_running(dev)) {
- /* Update the error counts. */
- dev->stats.rx_missed_errors += inb(ioaddr + MPCNT);
- dev->stats.rx_frame_errors += inb(ioaddr + ALICNT);
- dev->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ struct net_device_stats *stats = &dev->stats;
+
+ stats->rx_missed_errors += er8(MPCNT);
+ stats->rx_frame_errors += er8(ALICNT);
+ stats->rx_crc_errors += er8(CRCCNT);
}
return &dev->stats;
@@ -1373,13 +1369,13 @@ static struct net_device_stats *epic_get_stats(struct net_device *dev)
static void set_rx_mode(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
struct epic_private *ep = netdev_priv(dev);
+ void __iomem *ioaddr = ep->ioaddr;
unsigned char mc_filter[8]; /* Multicast hash filter */
int i;
if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
- outl(0x002C, ioaddr + RxCtrl);
+ ew32(RxCtrl, 0x002c);
/* Unconditionally log net taps. */
memset(mc_filter, 0xff, sizeof(mc_filter));
} else if ((!netdev_mc_empty(dev)) || (dev->flags & IFF_ALLMULTI)) {
@@ -1387,9 +1383,9 @@ static void set_rx_mode(struct net_device *dev)
is never enabled. */
/* Too many to filter perfectly -- accept all multicasts. */
memset(mc_filter, 0xff, sizeof(mc_filter));
- outl(0x000C, ioaddr + RxCtrl);
+ ew32(RxCtrl, 0x000c);
} else if (netdev_mc_empty(dev)) {
- outl(0x0004, ioaddr + RxCtrl);
+ ew32(RxCtrl, 0x0004);
return;
} else { /* Never executed, for now. */
struct netdev_hw_addr *ha;
@@ -1404,7 +1400,7 @@ static void set_rx_mode(struct net_device *dev)
/* ToDo: perhaps we need to stop the Tx and Rx process here? */
if (memcmp(mc_filter, ep->mc_filter, sizeof(mc_filter))) {
for (i = 0; i < 4; i++)
- outw(((u16 *)mc_filter)[i], ioaddr + MC0 + i*4);
+ ew16(MC0 + i*4, ((u16 *)mc_filter)[i]);
memcpy(ep->mc_filter, mc_filter, sizeof(mc_filter));
}
}
@@ -1466,22 +1462,26 @@ static void netdev_set_msglevel(struct net_device *dev, u32 value)
static int ethtool_begin(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
+ struct epic_private *ep = netdev_priv(dev);
+ void __iomem *ioaddr = ep->ioaddr;
+
/* power-up, if interface is down */
- if (! netif_running(dev)) {
- outl(0x0200, ioaddr + GENCTL);
- outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+ if (!netif_running(dev)) {
+ ew32(GENCTL, 0x0200);
+ ew32(NVCTL, (er32(NVCTL) & ~0x003c) | 0x4800);
}
return 0;
}
static void ethtool_complete(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
+ struct epic_private *ep = netdev_priv(dev);
+ void __iomem *ioaddr = ep->ioaddr;
+
/* power-down, if interface is down */
- if (! netif_running(dev)) {
- outl(0x0008, ioaddr + GENCTL);
- outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
+ if (!netif_running(dev)) {
+ ew32(GENCTL, 0x0008);
+ ew32(NVCTL, (er32(NVCTL) & ~0x483c) | 0x0000);
}
}
@@ -1500,14 +1500,14 @@ static const struct ethtool_ops netdev_ethtool_ops = {
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct epic_private *np = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = np->ioaddr;
struct mii_ioctl_data *data = if_mii(rq);
int rc;
/* power-up, if interface is down */
if (! netif_running(dev)) {
- outl(0x0200, ioaddr + GENCTL);
- outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+ ew32(GENCTL, 0x0200);
+ ew32(NVCTL, (er32(NVCTL) & ~0x003c) | 0x4800);
}
/* all non-ethtool ioctls (the SIOC[GS]MIIxxx ioctls) */
@@ -1517,14 +1517,14 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
/* power-down, if interface is down */
if (! netif_running(dev)) {
- outl(0x0008, ioaddr + GENCTL);
- outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
+ ew32(GENCTL, 0x0008);
+ ew32(NVCTL, (er32(NVCTL) & ~0x483c) | 0x0000);
}
return rc;
}
-static void __devexit epic_remove_one (struct pci_dev *pdev)
+static void __devexit epic_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct epic_private *ep = netdev_priv(dev);
@@ -1532,9 +1532,7 @@ static void __devexit epic_remove_one (struct pci_dev *pdev)
pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma);
unregister_netdev(dev);
-#ifndef USE_IO_OPS
- iounmap((void*) dev->base_addr);
-#endif
+ pci_iounmap(pdev, ep->ioaddr);
pci_release_regions(pdev);
free_netdev(dev);
pci_disable_device(pdev);
@@ -1548,13 +1546,14 @@ static void __devexit epic_remove_one (struct pci_dev *pdev)
static int epic_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
- long ioaddr = dev->base_addr;
+ struct epic_private *ep = netdev_priv(dev);
+ void __iomem *ioaddr = ep->ioaddr;
if (!netif_running(dev))
return 0;
epic_pause(dev);
/* Put the chip into low-power mode. */
- outl(0x0008, ioaddr + GENCTL);
+ ew32(GENCTL, 0x0008);
/* pci_power_off(pdev, -1); */
return 0;
}
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index cd3defb11ffb..dab9c6f671ec 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -2066,6 +2066,7 @@ static const struct ethtool_ops smsc911x_ethtool_ops = {
.get_eeprom_len = smsc911x_ethtool_get_eeprom_len,
.get_eeprom = smsc911x_ethtool_get_eeprom,
.set_eeprom = smsc911x_ethtool_set_eeprom,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static const struct net_device_ops smsc911x_netdev_ops = {
diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
index 38386478532b..fd33b21f6c96 100644
--- a/drivers/net/ethernet/smsc/smsc9420.c
+++ b/drivers/net/ethernet/smsc/smsc9420.c
@@ -54,7 +54,7 @@ struct smsc9420_ring_info {
};
struct smsc9420_pdata {
- void __iomem *base_addr;
+ void __iomem *ioaddr;
struct pci_dev *pdev;
struct net_device *dev;
@@ -114,13 +114,13 @@ do { if ((pd)->msg_enable & NETIF_MSG_##TYPE) \
static inline u32 smsc9420_reg_read(struct smsc9420_pdata *pd, u32 offset)
{
- return ioread32(pd->base_addr + offset);
+ return ioread32(pd->ioaddr + offset);
}
static inline void
smsc9420_reg_write(struct smsc9420_pdata *pd, u32 offset, u32 value)
{
- iowrite32(value, pd->base_addr + offset);
+ iowrite32(value, pd->ioaddr + offset);
}
static inline void smsc9420_pci_flush_write(struct smsc9420_pdata *pd)
@@ -469,6 +469,7 @@ static const struct ethtool_ops smsc9420_ethtool_ops = {
.set_eeprom = smsc9420_ethtool_set_eeprom,
.get_regs_len = smsc9420_ethtool_getregslen,
.get_regs = smsc9420_ethtool_getregs,
+ .get_ts_info = ethtool_op_get_ts_info,
};
/* Sets the device MAC address to dev_addr */
@@ -659,7 +660,7 @@ static irqreturn_t smsc9420_isr(int irq, void *dev_id)
ulong flags;
BUG_ON(!pd);
- BUG_ON(!pd->base_addr);
+ BUG_ON(!pd->ioaddr);
int_cfg = smsc9420_reg_read(pd, INT_CFG);
@@ -720,9 +721,12 @@ static irqreturn_t smsc9420_isr(int irq, void *dev_id)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void smsc9420_poll_controller(struct net_device *dev)
{
- disable_irq(dev->irq);
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ const int irq = pd->pdev->irq;
+
+ disable_irq(irq);
smsc9420_isr(0, dev);
- enable_irq(dev->irq);
+ enable_irq(irq);
}
#endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -759,7 +763,7 @@ static int smsc9420_stop(struct net_device *dev)
smsc9420_stop_rx(pd);
smsc9420_free_rx_ring(pd);
- free_irq(dev->irq, pd);
+ free_irq(pd->pdev->irq, pd);
smsc9420_dmac_soft_reset(pd);
@@ -1331,15 +1335,12 @@ out:
static int smsc9420_open(struct net_device *dev)
{
- struct smsc9420_pdata *pd;
+ struct smsc9420_pdata *pd = netdev_priv(dev);
u32 bus_mode, mac_cr, dmac_control, int_cfg, dma_intr_ena, int_ctl;
+ const int irq = pd->pdev->irq;
unsigned long flags;
int result = 0, timeout;
- BUG_ON(!dev);
- pd = netdev_priv(dev);
- BUG_ON(!pd);
-
if (!is_valid_ether_addr(dev->dev_addr)) {
smsc_warn(IFUP, "dev_addr is not a valid MAC address");
result = -EADDRNOTAVAIL;
@@ -1358,9 +1359,10 @@ static int smsc9420_open(struct net_device *dev)
smsc9420_reg_write(pd, INT_STAT, 0xFFFFFFFF);
smsc9420_pci_flush_write(pd);
- if (request_irq(dev->irq, smsc9420_isr, IRQF_SHARED | IRQF_DISABLED,
- DRV_NAME, pd)) {
- smsc_warn(IFUP, "Unable to use IRQ = %d", dev->irq);
+ result = request_irq(irq, smsc9420_isr, IRQF_SHARED | IRQF_DISABLED,
+ DRV_NAME, pd);
+ if (result) {
+ smsc_warn(IFUP, "Unable to use IRQ = %d", irq);
result = -ENODEV;
goto out_0;
}
@@ -1395,7 +1397,7 @@ static int smsc9420_open(struct net_device *dev)
smsc9420_pci_flush_write(pd);
/* test the IRQ connection to the ISR */
- smsc_dbg(IFUP, "Testing ISR using IRQ %d", dev->irq);
+ smsc_dbg(IFUP, "Testing ISR using IRQ %d", irq);
pd->software_irq_signal = false;
spin_lock_irqsave(&pd->int_lock, flags);
@@ -1430,7 +1432,7 @@ static int smsc9420_open(struct net_device *dev)
goto out_free_irq_1;
}
- smsc_dbg(IFUP, "ISR passed test using IRQ %d", dev->irq);
+ smsc_dbg(IFUP, "ISR passed test using IRQ %d", irq);
result = smsc9420_alloc_tx_ring(pd);
if (result) {
@@ -1490,7 +1492,7 @@ out_free_rx_ring_3:
out_free_tx_ring_2:
smsc9420_free_tx_ring(pd);
out_free_irq_1:
- free_irq(dev->irq, pd);
+ free_irq(irq, pd);
out_0:
return result;
}
@@ -1519,7 +1521,7 @@ static int smsc9420_suspend(struct pci_dev *pdev, pm_message_t state)
smsc9420_stop_rx(pd);
smsc9420_free_rx_ring(pd);
- free_irq(dev->irq, pd);
+ free_irq(pd->pdev->irq, pd);
netif_device_detach(dev);
}
@@ -1552,6 +1554,7 @@ static int smsc9420_resume(struct pci_dev *pdev)
smsc_warn(IFUP, "pci_enable_wake failed: %d", err);
if (netif_running(dev)) {
+ /* FIXME: gross. It looks like ancient PM relic.*/
err = smsc9420_open(dev);
netif_device_attach(dev);
}
@@ -1625,8 +1628,6 @@ smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* registers are double mapped with 0 offset for LE and 0x200 for BE */
virt_addr += LAN9420_CPSR_ENDIAN_OFFSET;
- dev->base_addr = (ulong)virt_addr;
-
pd = netdev_priv(dev);
/* pci descriptors are created in the PCI consistent area */
@@ -1646,7 +1647,7 @@ smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pd->pdev = pdev;
pd->dev = dev;
- pd->base_addr = virt_addr;
+ pd->ioaddr = virt_addr;
pd->msg_enable = smsc_debug;
pd->rx_csum = true;
@@ -1669,7 +1670,6 @@ smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev->netdev_ops = &smsc9420_netdev_ops;
dev->ethtool_ops = &smsc9420_ethtool_ops;
- dev->irq = pdev->irq;
netif_napi_add(dev, &pd->napi, smsc9420_rx_poll, NAPI_WEIGHT);
@@ -1727,7 +1727,7 @@ static void __devexit smsc9420_remove(struct pci_dev *pdev)
pci_free_consistent(pdev, sizeof(struct smsc9420_dma_desc) *
(RX_RING_SIZE + TX_RING_SIZE), pd->rx_ring, pd->rx_dma_addr);
- iounmap(pd->base_addr - LAN9420_CPSR_ENDIAN_OFFSET);
+ iounmap(pd->ioaddr - LAN9420_CPSR_ENDIAN_OFFSET);
pci_release_regions(pdev);
free_netdev(dev);
pci_disable_device(pdev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 0319d640f728..bcd54d6e94fd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -97,6 +97,16 @@ struct stmmac_extra_stats {
unsigned long normal_irq_n;
};
+/* CSR Frequency Access Defines*/
+#define CSR_F_35M 35000000
+#define CSR_F_60M 60000000
+#define CSR_F_100M 100000000
+#define CSR_F_150M 150000000
+#define CSR_F_250M 250000000
+#define CSR_F_300M 300000000
+
+#define MAC_CSR_H_FRQ_MASK 0x20
+
#define HASH_TABLE_SIZE 64
#define PAUSE_TIME 0x200
@@ -137,6 +147,7 @@ struct stmmac_extra_stats {
#define DMA_HW_FEAT_FLEXIPPSEN 0x04000000 /* Flexible PPS Output */
#define DMA_HW_FEAT_SAVLANINS 0x08000000 /* Source Addr or VLAN Insertion */
#define DMA_HW_FEAT_ACTPHYIF 0x70000000 /* Active/selected PHY interface */
+#define DEFAULT_DMA_PBL 8
enum rx_frame_status { /* IPC status */
good_frame = 0,
@@ -228,7 +239,7 @@ struct stmmac_desc_ops {
int (*get_rx_owner) (struct dma_desc *p);
void (*set_rx_owner) (struct dma_desc *p);
/* Get the receive frame size */
- int (*get_rx_frame_len) (struct dma_desc *p);
+ int (*get_rx_frame_len) (struct dma_desc *p, int rx_coe_type);
/* Return the reception status looking at the RDES1 */
int (*rx_status) (void *data, struct stmmac_extra_stats *x,
struct dma_desc *p);
@@ -236,7 +247,8 @@ struct stmmac_desc_ops {
struct stmmac_dma_ops {
/* DMA core initialization */
- int (*init) (void __iomem *ioaddr, int pbl, u32 dma_tx, u32 dma_rx);
+ int (*init) (void __iomem *ioaddr, int pbl, int fb, int mb,
+ int burst_len, u32 dma_tx, u32 dma_rx);
/* Dump DMA registers */
void (*dump_regs) (void __iomem *ioaddr);
/* Set tx/rx threshold in the csr6 register
@@ -261,14 +273,14 @@ struct stmmac_dma_ops {
struct stmmac_ops {
/* MAC core initialization */
void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned;
- /* Support checksum offload engine */
- int (*rx_coe) (void __iomem *ioaddr);
+ /* Enable and verify that the IPC module is supported */
+ int (*rx_ipc) (void __iomem *ioaddr);
/* Dump MAC registers */
void (*dump_regs) (void __iomem *ioaddr);
/* Handle extra events on specific interrupts hw dependent */
void (*host_irq_status) (void __iomem *ioaddr);
/* Multicast filter setting */
- void (*set_filter) (struct net_device *dev);
+ void (*set_filter) (struct net_device *dev, int id);
/* Flow control setting */
void (*flow_ctrl) (void __iomem *ioaddr, unsigned int duplex,
unsigned int fc, unsigned int pause_time);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index cfcef0ea0fa5..23478bf4ed7a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -61,9 +61,11 @@ enum power_event {
};
/* GMAC HW ADDR regs */
-#define GMAC_ADDR_HIGH(reg) (0x00000040+(reg * 8))
-#define GMAC_ADDR_LOW(reg) (0x00000044+(reg * 8))
-#define GMAC_MAX_UNICAST_ADDRESSES 16
+#define GMAC_ADDR_HIGH(reg) (((reg > 15) ? 0x00000800 : 0x00000040) + \
+ (reg * 8))
+#define GMAC_ADDR_LOW(reg) (((reg > 15) ? 0x00000804 : 0x00000044) + \
+ (reg * 8))
+#define GMAC_MAX_PERFECT_ADDRESSES 32
#define GMAC_AN_CTRL 0x000000c0 /* AN control */
#define GMAC_AN_STATUS 0x000000c4 /* AN status */
@@ -139,10 +141,11 @@ enum rx_tx_priority_ratio {
};
#define DMA_BUS_MODE_FB 0x00010000 /* Fixed burst */
+#define DMA_BUS_MODE_MB 0x04000000 /* Mixed burst */
#define DMA_BUS_MODE_RPBL_MASK 0x003e0000 /* Rx-Programmable Burst Len */
#define DMA_BUS_MODE_RPBL_SHIFT 17
#define DMA_BUS_MODE_USP 0x00800000
-#define DMA_BUS_MODE_4PBL 0x01000000
+#define DMA_BUS_MODE_PBL 0x01000000
#define DMA_BUS_MODE_AAL 0x02000000
/* DMA CRS Control and Status Register Mapping */
@@ -205,4 +208,7 @@ enum rtc_control {
#define GMAC_MMC_TX_INTR 0x108
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
+/* Synopsys Core versions */
+#define DWMAC_CORE_3_40 34
+
extern const struct stmmac_dma_ops dwmac1000_dma_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index b1c48b975945..b5e4d02f15c9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -46,7 +46,7 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
#endif
}
-static int dwmac1000_rx_coe_supported(void __iomem *ioaddr)
+static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr)
{
u32 value = readl(ioaddr + GMAC_CONTROL);
@@ -84,10 +84,11 @@ static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
GMAC_ADDR_LOW(reg_n));
}
-static void dwmac1000_set_filter(struct net_device *dev)
+static void dwmac1000_set_filter(struct net_device *dev, int id)
{
void __iomem *ioaddr = (void __iomem *) dev->base_addr;
unsigned int value = 0;
+ unsigned int perfect_addr_number;
CHIP_DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n",
__func__, netdev_mc_count(dev), netdev_uc_count(dev));
@@ -121,8 +122,14 @@ static void dwmac1000_set_filter(struct net_device *dev)
writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH);
}
+ /* Extra 16 regs are available in cores newer than the 3.40. */
+ if (id > DWMAC_CORE_3_40)
+ perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES;
+ else
+ perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES / 2;
+
/* Handle multiple unicast addresses (perfect filtering)*/
- if (netdev_uc_count(dev) > GMAC_MAX_UNICAST_ADDRESSES)
+ if (netdev_uc_count(dev) > perfect_addr_number)
/* Switch to promiscuous mode is more than 16 addrs
are required */
value |= GMAC_FRAME_FILTER_PR;
@@ -211,7 +218,7 @@ static void dwmac1000_irq_status(void __iomem *ioaddr)
static const struct stmmac_ops dwmac1000_ops = {
.core_init = dwmac1000_core_init,
- .rx_coe = dwmac1000_rx_coe_supported,
+ .rx_ipc = dwmac1000_rx_ipc_enable,
.dump_regs = dwmac1000_dump_regs,
.host_irq_status = dwmac1000_irq_status,
.set_filter = dwmac1000_set_filter,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 4d5402a1d262..033500090f55 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -30,8 +30,8 @@
#include "dwmac1000.h"
#include "dwmac_dma.h"
-static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
- u32 dma_rx)
+static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb,
+ int mb, int burst_len, u32 dma_tx, u32 dma_rx)
{
u32 value = readl(ioaddr + DMA_BUS_MODE);
int limit;
@@ -48,15 +48,51 @@ static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
if (limit < 0)
return -EBUSY;
- value = /* DMA_BUS_MODE_FB | */ DMA_BUS_MODE_4PBL |
- ((pbl << DMA_BUS_MODE_PBL_SHIFT) |
- (pbl << DMA_BUS_MODE_RPBL_SHIFT));
+ /*
+ * Set the DMA PBL (Programmable Burst Length) mode
+ * Before stmmac core 3.50 this mode bit was 4xPBL, and
+ * post 3.5 mode bit acts as 8*PBL.
+ * For core rev < 3.5, when the core is set for 4xPBL mode, the
+ * DMA transfers the data in 4, 8, 16, 32, 64 & 128 beats
+ * depending on pbl value.
+ * For core rev > 3.5, when the core is set for 8xPBL mode, the
+ * DMA transfers the data in 8, 16, 32, 64, 128 & 256 beats
+ * depending on pbl value.
+ */
+ value = DMA_BUS_MODE_PBL | ((pbl << DMA_BUS_MODE_PBL_SHIFT) |
+ (pbl << DMA_BUS_MODE_RPBL_SHIFT));
+
+ /* Set the Fixed burst mode */
+ if (fb)
+ value |= DMA_BUS_MODE_FB;
+
+ /* Mixed Burst has no effect when fb is set */
+ if (mb)
+ value |= DMA_BUS_MODE_MB;
#ifdef CONFIG_STMMAC_DA
value |= DMA_BUS_MODE_DA; /* Rx has priority over tx */
#endif
writel(value, ioaddr + DMA_BUS_MODE);
+ /* In case of GMAC AXI configuration, program the DMA_AXI_BUS_MODE
+ * for supported bursts.
+ *
+ * Note: This is applicable only for revision GMACv3.61a. For
+ * older version this register is reserved and shall have no
+ * effect.
+ *
+ * Note:
+ * For Fixed Burst Mode: if we directly write 0xFF to this
+ * register using the configurations pass from platform code,
+ * this would ensure that all bursts supported by core are set
+ * and those which are not supported would remain ineffective.
+ *
+ * For Non Fixed Burst Mode: provide the maximum value of the
+ * burst length. Any burst equal or below the provided burst
+ * length would be allowed to perform. */
+ writel(burst_len, ioaddr + DMA_AXI_BUS_MODE);
+
/* Mask interrupts by writing to CSR7 */
writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 138fb8dd1e87..19e0f4eed2bc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -43,11 +43,6 @@ static void dwmac100_core_init(void __iomem *ioaddr)
#endif
}
-static int dwmac100_rx_coe_supported(void __iomem *ioaddr)
-{
- return 0;
-}
-
static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
{
pr_info("\t----------------------------------------------\n"
@@ -72,6 +67,11 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
readl(ioaddr + MAC_VLAN2));
}
+static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
+{
+ return 0;
+}
+
static void dwmac100_irq_status(void __iomem *ioaddr)
{
return;
@@ -89,7 +89,7 @@ static void dwmac100_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
}
-static void dwmac100_set_filter(struct net_device *dev)
+static void dwmac100_set_filter(struct net_device *dev, int id)
{
void __iomem *ioaddr = (void __iomem *) dev->base_addr;
u32 value = readl(ioaddr + MAC_CONTROL);
@@ -160,7 +160,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
static const struct stmmac_ops dwmac100_ops = {
.core_init = dwmac100_core_init,
- .rx_coe = dwmac100_rx_coe_supported,
+ .rx_ipc = dwmac100_rx_ipc_enable,
.dump_regs = dwmac100_dump_mac_regs,
.host_irq_status = dwmac100_irq_status,
.set_filter = dwmac100_set_filter,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
index bc17fd08b55d..c2b4d55a79b6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
@@ -32,8 +32,8 @@
#include "dwmac100.h"
#include "dwmac_dma.h"
-static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
- u32 dma_rx)
+static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, int fb,
+ int mb, int burst_len, u32 dma_tx, u32 dma_rx)
{
u32 value = readl(ioaddr + DMA_BUS_MODE);
int limit;
@@ -52,7 +52,7 @@ static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
/* Enable Application Access by writing to DMA CSR0 */
writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT),
- ioaddr + DMA_BUS_MODE);
+ ioaddr + DMA_BUS_MODE);
/* Mask interrupts by writing to CSR7 */
writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 437edacd602e..6e0360f9cfde 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -32,6 +32,7 @@
#define DMA_CONTROL 0x00001018 /* Ctrl (Operational Mode) */
#define DMA_INTR_ENA 0x0000101c /* Interrupt Enable */
#define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */
+#define DMA_AXI_BUS_MODE 0x00001028 /* AXI Bus Mode */
#define DMA_CUR_TX_BUF_ADDR 0x00001050 /* Current Host Tx Buffer */
#define DMA_CUR_RX_BUF_ADDR 0x00001054 /* Current Host Rx Buffer */
#define DMA_HW_FEATURE 0x00001058 /* HW Feature Register */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index f20aa12931d0..4e0e18a44fcc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -31,6 +31,8 @@
#define DWMAC_LIB_DBG(fmt, args...) do { } while (0)
#endif
+#define GMAC_HI_REG_AE 0x80000000
+
/* CSR1 enables the transmit DMA to check for new descriptor */
void dwmac_enable_dma_transmission(void __iomem *ioaddr)
{
@@ -233,7 +235,11 @@ void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
unsigned long data;
data = (addr[5] << 8) | addr[4];
- writel(data, ioaddr + high);
+ /* For MAC Addr registers se have to set the Address Enable (AE)
+ * bit that has no effect on the High Reg 0 where the bit 31 (MO)
+ * is RO.
+ */
+ writel(data | GMAC_HI_REG_AE, ioaddr + high);
data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
writel(data, ioaddr + low);
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index ad1b627f8ec2..2fc8ef95f97a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -22,6 +22,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#include <linux/stmmac.h>
#include "common.h"
#include "descs_com.h"
@@ -309,9 +310,17 @@ static void enh_desc_close_tx_desc(struct dma_desc *p)
p->des01.etx.interrupt = 1;
}
-static int enh_desc_get_rx_frame_len(struct dma_desc *p)
+static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
{
- return p->des01.erx.frame_length;
+ /* The type-1 checksum offload engines append the checksum at
+ * the end of frame and the two bytes of checksum are added in
+ * the length.
+ * Adjust for that in the framelen for type-1 checksum offload
+ * engines. */
+ if (rx_coe_type == STMMAC_RX_COE_TYPE1)
+ return p->des01.erx.frame_length - 2;
+ else
+ return p->des01.erx.frame_length;
}
const struct stmmac_desc_ops enh_desc_ops = {
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 25953bb45a73..68962c549a2d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -22,6 +22,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#include <linux/stmmac.h>
#include "common.h"
#include "descs_com.h"
@@ -201,9 +202,17 @@ static void ndesc_close_tx_desc(struct dma_desc *p)
p->des01.tx.interrupt = 1;
}
-static int ndesc_get_rx_frame_len(struct dma_desc *p)
+static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
{
- return p->des01.rx.frame_length;
+ /* The type-1 checksum offload engines append the checksum at
+ * the end of frame and the two bytes of checksum are added in
+ * the length.
+ * Adjust for that in the framelen for type-1 checksum offload
+ * engines. */
+ if (rx_coe_type == STMMAC_RX_COE_TYPE1)
+ return p->des01.rx.frame_length - 2;
+ else
+ return p->des01.rx.frame_length;
}
const struct stmmac_desc_ops ndesc_ops = {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index b4b095fdcf29..6b5d060ee9de 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -21,7 +21,9 @@
*******************************************************************************/
#define STMMAC_RESOURCE_NAME "stmmaceth"
-#define DRV_MODULE_VERSION "Feb_2012"
+#define DRV_MODULE_VERSION "March_2012"
+
+#include <linux/clk.h>
#include <linux/stmmac.h>
#include <linux/phy.h>
#include "common.h"
@@ -56,8 +58,6 @@ struct stmmac_priv {
struct stmmac_extra_stats xstats;
struct napi_struct napi;
-
- int rx_coe;
int no_csum_insertion;
struct phy_device *phydev;
@@ -81,6 +81,11 @@ struct stmmac_priv {
struct stmmac_counters mmc;
struct dma_features dma_cap;
int hw_cap_support;
+#ifdef CONFIG_HAVE_CLK
+ struct clk *stmmac_clk;
+#endif
+ int clk_csr;
+ int synopsys_id;
};
extern int phyaddr;
@@ -99,3 +104,42 @@ int stmmac_dvr_remove(struct net_device *ndev);
struct stmmac_priv *stmmac_dvr_probe(struct device *device,
struct plat_stmmacenet_data *plat_dat,
void __iomem *addr);
+
+#ifdef CONFIG_HAVE_CLK
+static inline int stmmac_clk_enable(struct stmmac_priv *priv)
+{
+ if (!IS_ERR(priv->stmmac_clk))
+ return clk_enable(priv->stmmac_clk);
+
+ return 0;
+}
+
+static inline void stmmac_clk_disable(struct stmmac_priv *priv)
+{
+ if (IS_ERR(priv->stmmac_clk))
+ return;
+
+ clk_disable(priv->stmmac_clk);
+}
+static inline int stmmac_clk_get(struct stmmac_priv *priv)
+{
+ priv->stmmac_clk = clk_get(priv->device, NULL);
+
+ if (IS_ERR(priv->stmmac_clk))
+ return PTR_ERR(priv->stmmac_clk);
+
+ return 0;
+}
+#else
+static inline int stmmac_clk_enable(struct stmmac_priv *priv)
+{
+ return 0;
+}
+static inline void stmmac_clk_disable(struct stmmac_priv *priv)
+{
+}
+static inline int stmmac_clk_get(struct stmmac_priv *priv)
+{
+ return 0;
+}
+#endif /* CONFIG_HAVE_CLK */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index f98e1511660f..ce431846fc6f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -481,6 +481,7 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
.get_wol = stmmac_get_wol,
.set_wol = stmmac_set_wol,
.get_sset_count = stmmac_get_sset_count,
+ .get_ts_info = ethtool_op_get_ts_info,
};
void stmmac_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 48d56da62f08..70966330f44e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -163,6 +163,38 @@ static void stmmac_verify_args(void)
pause = PAUSE_TIME;
}
+static void stmmac_clk_csr_set(struct stmmac_priv *priv)
+{
+#ifdef CONFIG_HAVE_CLK
+ u32 clk_rate;
+
+ if (IS_ERR(priv->stmmac_clk))
+ return;
+
+ clk_rate = clk_get_rate(priv->stmmac_clk);
+
+ /* Platform provided default clk_csr would be assumed valid
+ * for all other cases except for the below mentioned ones. */
+ if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) {
+ if (clk_rate < CSR_F_35M)
+ priv->clk_csr = STMMAC_CSR_20_35M;
+ else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M))
+ priv->clk_csr = STMMAC_CSR_35_60M;
+ else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M))
+ priv->clk_csr = STMMAC_CSR_60_100M;
+ else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M))
+ priv->clk_csr = STMMAC_CSR_100_150M;
+ else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
+ priv->clk_csr = STMMAC_CSR_150_250M;
+ else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
+ priv->clk_csr = STMMAC_CSR_250_300M;
+ } /* For values higher than the IEEE 802.3 specified frequency
+ * we can not estimate the proper divider as it is not known
+ * the frequency of clk_csr_i. So we do not change the default
+ * divider. */
+#endif
+}
+
#if defined(STMMAC_XMIT_DEBUG) || defined(STMMAC_RX_DEBUG)
static void print_pkt(unsigned char *buf, int len)
{
@@ -307,7 +339,13 @@ static int stmmac_init_phy(struct net_device *dev)
priv->speed = 0;
priv->oldduplex = -1;
- snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", priv->plat->bus_id);
+ if (priv->plat->phy_bus_name)
+ snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
+ priv->plat->phy_bus_name, priv->plat->bus_id);
+ else
+ snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
+ priv->plat->bus_id);
+
snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
priv->plat->phy_addr);
pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id);
@@ -884,6 +922,26 @@ static void stmmac_check_ether_addr(struct stmmac_priv *priv)
priv->dev->dev_addr);
}
+static int stmmac_init_dma_engine(struct stmmac_priv *priv)
+{
+ int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0;
+ int mixed_burst = 0;
+
+ /* Some DMA parameters can be passed from the platform;
+ * in case of these are not passed we keep a default
+ * (good for all the chips) and init the DMA! */
+ if (priv->plat->dma_cfg) {
+ pbl = priv->plat->dma_cfg->pbl;
+ fixed_burst = priv->plat->dma_cfg->fixed_burst;
+ mixed_burst = priv->plat->dma_cfg->mixed_burst;
+ burst_len = priv->plat->dma_cfg->burst_len;
+ }
+
+ return priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst,
+ burst_len, priv->dma_tx_phy,
+ priv->dma_rx_phy);
+}
+
/**
* stmmac_open - open entry point of the driver
* @dev : pointer to the device structure.
@@ -898,16 +956,6 @@ static int stmmac_open(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev);
int ret;
- stmmac_check_ether_addr(priv);
-
- /* MDIO bus Registration */
- ret = stmmac_mdio_register(dev);
- if (ret < 0) {
- pr_debug("%s: MDIO bus (id: %d) registration failed",
- __func__, priv->plat->bus_id);
- return ret;
- }
-
#ifdef CONFIG_STMMAC_TIMER
priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
if (unlikely(priv->tm == NULL))
@@ -925,6 +973,10 @@ static int stmmac_open(struct net_device *dev)
} else
priv->tm->enable = 1;
#endif
+ stmmac_clk_enable(priv);
+
+ stmmac_check_ether_addr(priv);
+
ret = stmmac_init_phy(dev);
if (unlikely(ret)) {
pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
@@ -938,8 +990,7 @@ static int stmmac_open(struct net_device *dev)
init_dma_desc_rings(dev);
/* DMA initialization and SW reset */
- ret = priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
- priv->dma_tx_phy, priv->dma_rx_phy);
+ ret = stmmac_init_dma_engine(priv);
if (ret < 0) {
pr_err("%s: DMA initialization failed\n", __func__);
goto open_error;
@@ -1026,6 +1077,8 @@ open_error:
if (priv->phydev)
phy_disconnect(priv->phydev);
+ stmmac_clk_disable(priv);
+
return ret;
}
@@ -1077,7 +1130,7 @@ static int stmmac_release(struct net_device *dev)
#ifdef CONFIG_STMMAC_DEBUG_FS
stmmac_exit_fs();
#endif
- stmmac_mdio_unregister(dev);
+ stmmac_clk_disable(priv);
return 0;
}
@@ -1276,7 +1329,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
struct sk_buff *skb;
int frame_len;
- frame_len = priv->hw->desc->get_rx_frame_len(p);
+ frame_len = priv->hw->desc->get_rx_frame_len(p,
+ priv->plat->rx_coe);
/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
* Type frames (LLC/LLC-SNAP) */
if (unlikely(status != llc_snap))
@@ -1312,7 +1366,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
#endif
skb->protocol = eth_type_trans(skb, priv->dev);
- if (unlikely(!priv->rx_coe)) {
+ if (unlikely(!priv->plat->rx_coe)) {
/* No RX COE for old mac10/100 devices */
skb_checksum_none_assert(skb);
netif_receive_skb(skb);
@@ -1413,7 +1467,7 @@ static void stmmac_set_rx_mode(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev);
spin_lock(&priv->lock);
- priv->hw->mac->set_filter(dev);
+ priv->hw->mac->set_filter(dev, priv->synopsys_id);
spin_unlock(&priv->lock);
}
@@ -1459,8 +1513,10 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev,
{
struct stmmac_priv *priv = netdev_priv(dev);
- if (!priv->rx_coe)
+ if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
features &= ~NETIF_F_RXCSUM;
+ else if (priv->plat->rx_coe == STMMAC_RX_COE_TYPE1)
+ features &= ~NETIF_F_IPV6_CSUM;
if (!priv->plat->tx_coe)
features &= ~NETIF_F_ALL_CSUM;
@@ -1584,7 +1640,7 @@ static const struct file_operations stmmac_rings_status_fops = {
.open = stmmac_sysfs_ring_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = single_release,
};
static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
@@ -1656,7 +1712,7 @@ static const struct file_operations stmmac_dma_cap_fops = {
.open = stmmac_sysfs_dma_cap_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = single_release,
};
static int stmmac_init_fs(struct net_device *dev)
@@ -1752,7 +1808,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
priv->hw->ring = &ring_mode_ops;
/* Get and dump the chip ID */
- stmmac_get_synopsys_id(priv);
+ priv->synopsys_id = stmmac_get_synopsys_id(priv);
/* Get the HW capability (new GMAC newer than 3.50a) */
priv->hw_cap_support = stmmac_get_hw_features(priv);
@@ -1765,17 +1821,32 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
* register (if supported).
*/
priv->plat->enh_desc = priv->dma_cap.enh_desc;
- priv->plat->tx_coe = priv->dma_cap.tx_coe;
priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
+
+ priv->plat->tx_coe = priv->dma_cap.tx_coe;
+
+ if (priv->dma_cap.rx_coe_type2)
+ priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
+ else if (priv->dma_cap.rx_coe_type1)
+ priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
+
} else
pr_info(" No HW DMA feature register supported");
/* Select the enhnaced/normal descriptor structures */
stmmac_selec_desc_mode(priv);
- priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
- if (priv->rx_coe)
- pr_info(" RX Checksum Offload Engine supported\n");
+ /* Enable the IPC (Checksum Offload) and check if the feature has been
+ * enabled during the core configuration. */
+ ret = priv->hw->mac->rx_ipc(priv->ioaddr);
+ if (!ret) {
+ pr_warning(" RX IPC Checksum Offload not configured.\n");
+ priv->plat->rx_coe = STMMAC_RX_COE_NONE;
+ }
+
+ if (priv->plat->rx_coe)
+ pr_info(" RX Checksum Offload Engine supported (type %d)\n",
+ priv->plat->rx_coe);
if (priv->plat->tx_coe)
pr_info(" TX Checksum insertion supported\n");
@@ -1856,6 +1927,28 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
goto error;
}
+ if (stmmac_clk_get(priv))
+ pr_warning("%s: warning: cannot get CSR clock\n", __func__);
+
+ /* If a specific clk_csr value is passed from the platform
+ * this means that the CSR Clock Range selection cannot be
+ * changed at run-time and it is fixed. Viceversa the driver'll try to
+ * set the MDC clock dynamically according to the csr actual
+ * clock input.
+ */
+ if (!priv->plat->clk_csr)
+ stmmac_clk_csr_set(priv);
+ else
+ priv->clk_csr = priv->plat->clk_csr;
+
+ /* MDIO bus Registration */
+ ret = stmmac_mdio_register(ndev);
+ if (ret < 0) {
+ pr_debug("%s: MDIO bus (id: %d) registration failed",
+ __func__, priv->plat->bus_id);
+ goto error;
+ }
+
return priv;
error:
@@ -1883,6 +1976,7 @@ int stmmac_dvr_remove(struct net_device *ndev)
priv->hw->dma->stop_tx(priv->ioaddr);
stmmac_set_mac(priv->ioaddr, false);
+ stmmac_mdio_unregister(ndev);
netif_carrier_off(ndev);
unregister_netdev(ndev);
free_netdev(ndev);
@@ -1895,6 +1989,7 @@ int stmmac_suspend(struct net_device *ndev)
{
struct stmmac_priv *priv = netdev_priv(ndev);
int dis_ic = 0;
+ unsigned long flags;
if (!ndev || !netif_running(ndev))
return 0;
@@ -1902,7 +1997,7 @@ int stmmac_suspend(struct net_device *ndev)
if (priv->phydev)
phy_stop(priv->phydev);
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->lock, flags);
netif_device_detach(ndev);
netif_stop_queue(ndev);
@@ -1925,21 +2020,24 @@ int stmmac_suspend(struct net_device *ndev)
/* Enable Power down mode by programming the PMT regs */
if (device_may_wakeup(priv->device))
priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
- else
+ else {
stmmac_set_mac(priv->ioaddr, false);
-
- spin_unlock(&priv->lock);
+ /* Disable clock in case of PWM is off */
+ stmmac_clk_disable(priv);
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
int stmmac_resume(struct net_device *ndev)
{
struct stmmac_priv *priv = netdev_priv(ndev);
+ unsigned long flags;
if (!netif_running(ndev))
return 0;
- spin_lock(&priv->lock);
+ spin_lock_irqsave(&priv->lock, flags);
/* Power Down bit, into the PM register, is cleared
* automatically as soon as a magic packet or a Wake-up frame
@@ -1948,6 +2046,9 @@ int stmmac_resume(struct net_device *ndev)
* from another devices (e.g. serial console). */
if (device_may_wakeup(priv->device))
priv->hw->mac->pmt(priv->ioaddr, 0);
+ else
+ /* enable the clk prevously disabled */
+ stmmac_clk_enable(priv);
netif_device_attach(ndev);
@@ -1964,7 +2065,7 @@ int stmmac_resume(struct net_device *ndev)
netif_start_queue(ndev);
- spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&priv->lock, flags);
if (priv->phydev)
phy_start(priv->phydev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 73195329aa46..ade108232048 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -34,6 +34,22 @@
#define MII_BUSY 0x00000001
#define MII_WRITE 0x00000002
+static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr)
+{
+ unsigned long curr;
+ unsigned long finish = jiffies + 3 * HZ;
+
+ do {
+ curr = jiffies;
+ if (readl(ioaddr + mii_addr) & MII_BUSY)
+ cpu_relax();
+ else
+ return 0;
+ } while (!time_after_eq(curr, finish));
+
+ return -EBUSY;
+}
+
/**
* stmmac_mdio_read
* @bus: points to the mii_bus structure
@@ -54,11 +70,15 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
int data;
u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
((phyreg << 6) & (0x000007C0)));
- regValue |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2);
+ regValue |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
+
+ if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
+ return -EBUSY;
- do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
writel(regValue, priv->ioaddr + mii_address);
- do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
+
+ if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
+ return -EBUSY;
/* Read the data from the MII data register */
data = (int)readl(priv->ioaddr + mii_data);
@@ -86,20 +106,18 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
(((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
| MII_WRITE;
- value |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2);
-
+ value |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
/* Wait until any existing MII operation is complete */
- do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
+ if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
+ return -EBUSY;
/* Set the MII address register to write */
writel(phydata, priv->ioaddr + mii_data);
writel(value, priv->ioaddr + mii_address);
/* Wait until any existing MII operation is complete */
- do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
-
- return 0;
+ return stmmac_mdio_busy_wait(priv->ioaddr, mii_address);
}
/**
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index da66ed7c3c5d..58fab5303e9c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -28,6 +28,7 @@
struct plat_stmmacenet_data plat_dat;
struct stmmac_mdio_bus_data mdio_data;
+struct stmmac_dma_cfg dma_cfg;
static void stmmac_default_data(void)
{
@@ -35,7 +36,6 @@ static void stmmac_default_data(void)
plat_dat.bus_id = 1;
plat_dat.phy_addr = 0;
plat_dat.interface = PHY_INTERFACE_MODE_GMII;
- plat_dat.pbl = 32;
plat_dat.clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
plat_dat.has_gmac = 1;
plat_dat.force_sf_dma_mode = 1;
@@ -44,6 +44,10 @@ static void stmmac_default_data(void)
mdio_data.phy_reset = NULL;
mdio_data.phy_mask = 0;
plat_dat.mdio_bus_data = &mdio_data;
+
+ dma_cfg.pbl = 32;
+ dma_cfg.burst_len = DMA_AXI_BLEN_256;
+ plat_dat.dma_cfg = &dma_cfg;
}
/**
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 116529a366b2..3dd8f0803808 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -50,7 +50,6 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
* once needed on other platforms.
*/
if (of_device_is_compatible(np, "st,spear600-gmac")) {
- plat->pbl = 8;
plat->has_gmac = 1;
plat->pmt = 1;
}
@@ -189,9 +188,6 @@ static int stmmac_pltfr_remove(struct platform_device *pdev)
if (priv->plat->exit)
priv->plat->exit(pdev);
- if (priv->plat->exit)
- priv->plat->exit(pdev);
-
platform_set_drvdata(pdev, NULL);
iounmap((void *)priv->ioaddr);
@@ -218,14 +214,26 @@ static int stmmac_pltfr_resume(struct device *dev)
int stmmac_pltfr_freeze(struct device *dev)
{
+ int ret;
+ struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev);
struct net_device *ndev = dev_get_drvdata(dev);
+ struct platform_device *pdev = to_platform_device(dev);
- return stmmac_freeze(ndev);
+ ret = stmmac_freeze(ndev);
+ if (plat_dat->exit)
+ plat_dat->exit(pdev);
+
+ return ret;
}
int stmmac_pltfr_restore(struct device *dev)
{
+ struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev);
struct net_device *ndev = dev_get_drvdata(dev);
+ struct platform_device *pdev = to_platform_device(dev);
+
+ if (plat_dat->init)
+ plat_dat->init(pdev);
return stmmac_restore(ndev);
}
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index c99b3b0e2eae..703c8cce2a2c 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -9838,7 +9838,7 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
goto err_out_release_parent;
}
}
- if (err || dma_mask == DMA_BIT_MASK(32)) {
+ if (err) {
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (err) {
dev_err(&pdev->dev, "No usable DMA configuration, aborting\n");
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index 4ba969096717..3cf4ab755838 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -401,7 +401,7 @@ static int gem_rxmac_reset(struct gem *gp)
return 1;
}
- udelay(5000);
+ mdelay(5);
/* Execute RX reset command. */
writel(gp->swrst_base | GREG_SWRST_RXRST,
@@ -2898,7 +2898,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
}
gp->pdev = pdev;
- dev->base_addr = (long) pdev;
gp->dev = dev;
gp->msg_enable = DEFAULT_MSG;
@@ -2972,7 +2971,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
netif_napi_add(dev, &gp->napi, gem_poll, 64);
dev->ethtool_ops = &gem_ethtool_ops;
dev->watchdog_timeo = 5 * HZ;
- dev->irq = pdev->irq;
dev->dma = 0;
/* Set that now, in case PM kicks in now */
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index b95e7e681b38..dfc00c4683e5 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -2182,11 +2182,12 @@ static int happy_meal_open(struct net_device *dev)
* into a single source which we register handling at probe time.
*/
if ((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO) {
- if (request_irq(dev->irq, happy_meal_interrupt,
- IRQF_SHARED, dev->name, (void *)dev)) {
+ res = request_irq(hp->irq, happy_meal_interrupt, IRQF_SHARED,
+ dev->name, dev);
+ if (res) {
HMD(("EAGAIN\n"));
printk(KERN_ERR "happy_meal(SBUS): Can't order irq %d to go.\n",
- dev->irq);
+ hp->irq);
return -EAGAIN;
}
@@ -2199,7 +2200,7 @@ static int happy_meal_open(struct net_device *dev)
spin_unlock_irq(&hp->happy_lock);
if (res && ((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO))
- free_irq(dev->irq, dev);
+ free_irq(hp->irq, dev);
return res;
}
@@ -2221,7 +2222,7 @@ static int happy_meal_close(struct net_device *dev)
* time and never unregister.
*/
if ((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO)
- free_irq(dev->irq, dev);
+ free_irq(hp->irq, dev);
return 0;
}
@@ -2777,7 +2778,7 @@ static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int i
dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
dev->features |= dev->hw_features | NETIF_F_RXCSUM;
- dev->irq = op->archdata.irqs[0];
+ hp->irq = op->archdata.irqs[0];
#if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
/* Hook up SBUS register/descriptor accessors. */
@@ -2981,8 +2982,6 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
if (hme_version_printed++ == 0)
printk(KERN_INFO "%s", version);
- dev->base_addr = (long) pdev;
-
hp = netdev_priv(dev);
hp->happy_dev = pdev;
@@ -3087,12 +3086,11 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
init_timer(&hp->happy_timer);
+ hp->irq = pdev->irq;
hp->dev = dev;
dev->netdev_ops = &hme_netdev_ops;
dev->watchdog_timeo = 5*HZ;
dev->ethtool_ops = &hme_ethtool_ops;
- dev->irq = pdev->irq;
- dev->dma = 0;
/* Happy Meal can do it all... */
dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
diff --git a/drivers/net/ethernet/sun/sunhme.h b/drivers/net/ethernet/sun/sunhme.h
index 64f278360d89..f4307654e4ae 100644
--- a/drivers/net/ethernet/sun/sunhme.h
+++ b/drivers/net/ethernet/sun/sunhme.h
@@ -432,6 +432,7 @@ struct happy_meal {
dma_addr_t hblock_dvma; /* DVMA visible address happy block */
unsigned int happy_flags; /* Driver state flags */
+ int irq;
enum happy_transceiver tcvr_type; /* Kind of transceiver in use */
unsigned int happy_bursts; /* Get your mind out of the gutter */
unsigned int paddr; /* PHY address for transceiver */
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index 38e3ae9155b7..a108db35924e 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -618,7 +618,7 @@ struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb)
struct vnet_port *port;
hlist_for_each_entry(port, n, hp, hash) {
- if (!compare_ether_addr(port->raddr, skb->data))
+ if (ether_addr_equal(port->raddr, skb->data))
return port;
}
port = NULL;
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index ad973ffc9ff3..447a6932cab3 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -341,8 +341,8 @@ static int bdx_fw_load(struct bdx_priv *priv)
out:
if (master)
WRITE_REG(priv, regINIT_SEMAPHORE, 1);
- if (fw)
- release_firmware(fw);
+
+ release_firmware(fw);
if (rc) {
netdev_err(priv->ndev, "firmware loading failed\n");
@@ -1317,7 +1317,7 @@ static void print_rxdd(struct rxd_desc *rxdd, u32 rxd_val1, u16 len,
static void print_rxfd(struct rxf_desc *rxfd)
{
- DBG("=== RxF desc CHIP ORDER/ENDIANESS =============\n"
+ DBG("=== RxF desc CHIP ORDER/ENDIANNESS =============\n"
"info 0x%x va_lo %u pa_lo 0x%x pa_hi 0x%x len 0x%x\n",
rxfd->info, rxfd->va_lo, rxfd->pa_lo, rxfd->pa_hi, rxfd->len);
}
@@ -1988,10 +1988,6 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* these fields are used for info purposes only
* so we can have them same for all ports of the board */
ndev->if_port = port;
- ndev->base_addr = pciaddr;
- ndev->mem_start = pciaddr;
- ndev->mem_end = pciaddr + regionSize;
- ndev->irq = pdev->irq;
ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO
| NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER | NETIF_F_RXCSUM
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index b42252c4bec8..1b173a6145d6 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -51,7 +51,7 @@ config TI_DAVINCI_CPDMA
config TI_CPSW
tristate "TI CPSW Switch Support"
- depends on ARM && (ARCH_DAVINCI || SOC_OMAPAM33XX)
+ depends on ARM && (ARCH_DAVINCI || SOC_AM33XX)
select TI_DAVINCI_CPDMA
select TI_DAVINCI_MDIO
---help---
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index 34558766cbf0..d614c374ed9d 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -92,7 +92,7 @@ enum cpdma_state {
CPDMA_STATE_TEARDOWN,
};
-const char *cpdma_state_str[] = { "idle", "active", "teardown" };
+static const char *cpdma_state_str[] = { "idle", "active", "teardown" };
struct cpdma_ctlr {
enum cpdma_state state;
@@ -276,6 +276,7 @@ struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params)
ctlr->num_chan = CPDMA_MAX_CHANNELS;
return ctlr;
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_create);
int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
{
@@ -321,6 +322,7 @@ int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
spin_unlock_irqrestore(&ctlr->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_start);
int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
{
@@ -351,6 +353,7 @@ int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
spin_unlock_irqrestore(&ctlr->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_stop);
int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr)
{
@@ -421,6 +424,7 @@ int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr)
spin_unlock_irqrestore(&ctlr->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_dump);
int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
{
@@ -444,6 +448,7 @@ int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
kfree(ctlr);
return ret;
}
+EXPORT_SYMBOL_GPL(cpdma_ctlr_destroy);
int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
{
@@ -528,6 +533,7 @@ err_chan_busy:
err_chan_alloc:
return ERR_PTR(ret);
}
+EXPORT_SYMBOL_GPL(cpdma_chan_create);
int cpdma_chan_destroy(struct cpdma_chan *chan)
{
@@ -545,6 +551,7 @@ int cpdma_chan_destroy(struct cpdma_chan *chan)
kfree(chan);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_destroy);
int cpdma_chan_get_stats(struct cpdma_chan *chan,
struct cpdma_chan_stats *stats)
@@ -693,6 +700,7 @@ unlock_ret:
spin_unlock_irqrestore(&chan->lock, flags);
return ret;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_submit);
static void __cpdma_chan_free(struct cpdma_chan *chan,
struct cpdma_desc __iomem *desc,
@@ -776,6 +784,7 @@ int cpdma_chan_process(struct cpdma_chan *chan, int quota)
}
return used;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_process);
int cpdma_chan_start(struct cpdma_chan *chan)
{
@@ -803,6 +812,7 @@ int cpdma_chan_start(struct cpdma_chan *chan)
spin_unlock_irqrestore(&chan->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_start);
int cpdma_chan_stop(struct cpdma_chan *chan)
{
@@ -863,6 +873,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan)
spin_unlock_irqrestore(&chan->lock, flags);
return 0;
}
+EXPORT_SYMBOL_GPL(cpdma_chan_stop);
int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable)
{
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 08aff1a2087c..4da93a5d7ec6 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -627,6 +627,7 @@ static const struct ethtool_ops ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_coalesce = emac_get_coalesce,
.set_coalesce = emac_set_coalesce,
+ .get_ts_info = ethtool_op_get_ts_info,
};
/**
diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c
index efd36691ce54..3e6abf0f2771 100644
--- a/drivers/net/ethernet/ti/tlan.c
+++ b/drivers/net/ethernet/ti/tlan.c
@@ -2545,7 +2545,7 @@ static void tlan_phy_reset(struct net_device *dev)
phy = priv->phy[priv->phy_num];
- TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Reseting PHY.\n", dev->name);
+ TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Resetting PHY.\n", dev->name);
tlan_mii_sync(dev->base_addr);
value = MII_GC_LOOPBK | MII_GC_RESET;
tlan_mii_write_reg(dev, phy, MII_GEN_CTL, value);
diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c
index 3d501ec7fad7..96070e9b50dc 100644
--- a/drivers/net/ethernet/tile/tilepro.c
+++ b/drivers/net/ethernet/tile/tilepro.c
@@ -843,7 +843,7 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
if (!is_multicast_ether_addr(buf)) {
/* Filter packets not for our address. */
const u8 *mine = dev->dev_addr;
- filter = compare_ether_addr(mine, buf);
+ filter = !ether_addr_equal(mine, buf);
}
}
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
index 5c14f82c4954..961c8321451f 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
@@ -1590,8 +1590,8 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
found = 0;
oldest = NULL;
list_for_each_entry(target, &wl->network_list, list) {
- if (!compare_ether_addr(&target->hwinfo->bssid[2],
- &scan_info->bssid[2])) {
+ if (ether_addr_equal(&target->hwinfo->bssid[2],
+ &scan_info->bssid[2])) {
found = 1;
pr_debug("%s: same BBS found scanned list\n",
__func__);
@@ -1691,8 +1691,8 @@ struct gelic_wl_scan_info *gelic_wl_find_best_bss(struct gelic_wl_info *wl)
/* If bss specified, check it only */
if (test_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat)) {
- if (!compare_ether_addr(&scan_info->hwinfo->bssid[2],
- wl->bssid)) {
+ if (ether_addr_equal(&scan_info->hwinfo->bssid[2],
+ wl->bssid)) {
best_bss = scan_info;
pr_debug("%s: bssid matched\n", __func__);
break;
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index fcfa01f7ceb6..0459c096629f 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -689,9 +689,12 @@ static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void rhine_poll(struct net_device *dev)
{
- disable_irq(dev->irq);
- rhine_interrupt(dev->irq, (void *)dev);
- enable_irq(dev->irq);
+ struct rhine_private *rp = netdev_priv(dev);
+ const int irq = rp->pdev->irq;
+
+ disable_irq(irq);
+ rhine_interrupt(irq, dev);
+ enable_irq(irq);
}
#endif
@@ -972,7 +975,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
}
#endif /* USE_MMIO */
- dev->base_addr = (unsigned long)ioaddr;
rp->base = ioaddr;
/* Get chip registers into a sane state */
@@ -995,8 +997,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
if (!phy_id)
phy_id = ioread8(ioaddr + 0x6C);
- dev->irq = pdev->irq;
-
spin_lock_init(&rp->lock);
mutex_init(&rp->task_lock);
INIT_WORK(&rp->reset_task, rhine_reset_task);
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index 8a5d7c100a5e..ea3e0a21ba74 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -2488,8 +2488,8 @@ static int velocity_close(struct net_device *dev)
if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED)
velocity_get_ip(vptr);
- if (dev->irq != 0)
- free_irq(dev->irq, dev);
+
+ free_irq(vptr->pdev->irq, dev);
velocity_free_rings(vptr);
@@ -2755,8 +2755,6 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
if (ret < 0)
goto err_free_dev;
- dev->irq = pdev->irq;
-
ret = velocity_get_pci_info(vptr, pdev);
if (ret < 0) {
/* error message already printed */
@@ -2779,8 +2777,6 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
mac_wol_reset(regs);
- dev->base_addr = vptr->ioaddr;
-
for (i = 0; i < 6; i++)
dev->dev_addr[i] = readb(&regs->PAR[i]);
@@ -2806,7 +2802,6 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs);
- dev->irq = pdev->irq;
dev->netdev_ops = &velocity_netdev_ops;
dev->ethtool_ops = &velocity_ethtool_ops;
netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT);
diff --git a/drivers/net/ethernet/wiznet/Kconfig b/drivers/net/ethernet/wiznet/Kconfig
new file mode 100644
index 000000000000..cb18043f5830
--- /dev/null
+++ b/drivers/net/ethernet/wiznet/Kconfig
@@ -0,0 +1,73 @@
+#
+# WIZnet devices configuration
+#
+
+config NET_VENDOR_WIZNET
+ bool "WIZnet devices"
+ default y
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about WIZnet devices. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_WIZNET
+
+config WIZNET_W5100
+ tristate "WIZnet W5100 Ethernet support"
+ depends on HAS_IOMEM
+ ---help---
+ Support for WIZnet W5100 chips.
+
+ W5100 is a single chip with integrated 10/100 Ethernet MAC,
+ PHY and hardware TCP/IP stack, but this driver is limited to
+ the MAC and PHY functions only, onchip TCP/IP is unused.
+
+ To compile this driver as a module, choose M here: the module
+ will be called w5100.
+
+config WIZNET_W5300
+ tristate "WIZnet W5300 Ethernet support"
+ depends on HAS_IOMEM
+ ---help---
+ Support for WIZnet W5300 chips.
+
+ W5300 is a single chip with integrated 10/100 Ethernet MAC,
+ PHY and hardware TCP/IP stack, but this driver is limited to
+ the MAC and PHY functions only, onchip TCP/IP is unused.
+
+ To compile this driver as a module, choose M here: the module
+ will be called w5300.
+
+choice
+ prompt "WIZnet interface mode"
+ depends on WIZNET_W5100 || WIZNET_W5300
+ default WIZNET_BUS_ANY
+
+config WIZNET_BUS_DIRECT
+ bool "Direct address bus mode"
+ ---help---
+ In direct address mode host system can directly access all registers
+ after mapping to Memory-Mapped I/O space.
+
+config WIZNET_BUS_INDIRECT
+ bool "Indirect address bus mode"
+ ---help---
+ In indirect address mode host system indirectly accesses registers
+ using Indirect Mode Address Register and Indirect Mode Data Register,
+ which are directly mapped to Memory-Mapped I/O space.
+
+config WIZNET_BUS_ANY
+ bool "Select interface mode in runtime"
+ ---help---
+ If interface mode is unknown in compile time, it can be selected
+ in runtime from board/platform resources configuration.
+
+ Performance may decrease compared to explicitly selected bus mode.
+endchoice
+
+endif # NET_VENDOR_WIZNET
diff --git a/drivers/net/ethernet/wiznet/Makefile b/drivers/net/ethernet/wiznet/Makefile
new file mode 100644
index 000000000000..c614535227e8
--- /dev/null
+++ b/drivers/net/ethernet/wiznet/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_WIZNET_W5100) += w5100.o
+obj-$(CONFIG_WIZNET_W5300) += w5300.o
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
new file mode 100644
index 000000000000..a75e9ef5a4ce
--- /dev/null
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -0,0 +1,808 @@
+/*
+ * Ethernet driver for the WIZnet W5100 chip.
+ *
+ * Copyright (C) 2006-2008 WIZnet Co.,Ltd.
+ * Copyright (C) 2012 Mike Sinkovsky <msink@permonline.ru>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kconfig.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/wiznet.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+
+#define DRV_NAME "w5100"
+#define DRV_VERSION "2012-04-04"
+
+MODULE_DESCRIPTION("WIZnet W5100 Ethernet driver v"DRV_VERSION);
+MODULE_AUTHOR("Mike Sinkovsky <msink@permonline.ru>");
+MODULE_ALIAS("platform:"DRV_NAME);
+MODULE_LICENSE("GPL");
+
+/*
+ * Registers
+ */
+#define W5100_COMMON_REGS 0x0000
+#define W5100_MR 0x0000 /* Mode Register */
+#define MR_RST 0x80 /* S/W reset */
+#define MR_PB 0x10 /* Ping block */
+#define MR_AI 0x02 /* Address Auto-Increment */
+#define MR_IND 0x01 /* Indirect mode */
+#define W5100_SHAR 0x0009 /* Source MAC address */
+#define W5100_IR 0x0015 /* Interrupt Register */
+#define W5100_IMR 0x0016 /* Interrupt Mask Register */
+#define IR_S0 0x01 /* S0 interrupt */
+#define W5100_RTR 0x0017 /* Retry Time-value Register */
+#define RTR_DEFAULT 2000 /* =0x07d0 (2000) */
+#define W5100_RMSR 0x001a /* Receive Memory Size */
+#define W5100_TMSR 0x001b /* Transmit Memory Size */
+#define W5100_COMMON_REGS_LEN 0x0040
+
+#define W5100_S0_REGS 0x0400
+#define W5100_S0_MR 0x0400 /* S0 Mode Register */
+#define S0_MR_MACRAW 0x04 /* MAC RAW mode (promiscous) */
+#define S0_MR_MACRAW_MF 0x44 /* MAC RAW mode (filtered) */
+#define W5100_S0_CR 0x0401 /* S0 Command Register */
+#define S0_CR_OPEN 0x01 /* OPEN command */
+#define S0_CR_CLOSE 0x10 /* CLOSE command */
+#define S0_CR_SEND 0x20 /* SEND command */
+#define S0_CR_RECV 0x40 /* RECV command */
+#define W5100_S0_IR 0x0402 /* S0 Interrupt Register */
+#define S0_IR_SENDOK 0x10 /* complete sending */
+#define S0_IR_RECV 0x04 /* receiving data */
+#define W5100_S0_SR 0x0403 /* S0 Status Register */
+#define S0_SR_MACRAW 0x42 /* mac raw mode */
+#define W5100_S0_TX_FSR 0x0420 /* S0 Transmit free memory size */
+#define W5100_S0_TX_RD 0x0422 /* S0 Transmit memory read pointer */
+#define W5100_S0_TX_WR 0x0424 /* S0 Transmit memory write pointer */
+#define W5100_S0_RX_RSR 0x0426 /* S0 Receive free memory size */
+#define W5100_S0_RX_RD 0x0428 /* S0 Receive memory read pointer */
+#define W5100_S0_REGS_LEN 0x0040
+
+#define W5100_TX_MEM_START 0x4000
+#define W5100_TX_MEM_END 0x5fff
+#define W5100_TX_MEM_MASK 0x1fff
+#define W5100_RX_MEM_START 0x6000
+#define W5100_RX_MEM_END 0x7fff
+#define W5100_RX_MEM_MASK 0x1fff
+
+/*
+ * Device driver private data structure
+ */
+struct w5100_priv {
+ void __iomem *base;
+ spinlock_t reg_lock;
+ bool indirect;
+ u8 (*read)(struct w5100_priv *priv, u16 addr);
+ void (*write)(struct w5100_priv *priv, u16 addr, u8 data);
+ u16 (*read16)(struct w5100_priv *priv, u16 addr);
+ void (*write16)(struct w5100_priv *priv, u16 addr, u16 data);
+ void (*readbuf)(struct w5100_priv *priv, u16 addr, u8 *buf, int len);
+ void (*writebuf)(struct w5100_priv *priv, u16 addr, u8 *buf, int len);
+ int irq;
+ int link_irq;
+ int link_gpio;
+
+ struct napi_struct napi;
+ struct net_device *ndev;
+ bool promisc;
+ u32 msg_enable;
+};
+
+/************************************************************************
+ *
+ * Lowlevel I/O functions
+ *
+ ***********************************************************************/
+
+/*
+ * In direct address mode host system can directly access W5100 registers
+ * after mapping to Memory-Mapped I/O space.
+ *
+ * 0x8000 bytes are required for memory space.
+ */
+static inline u8 w5100_read_direct(struct w5100_priv *priv, u16 addr)
+{
+ return ioread8(priv->base + (addr << CONFIG_WIZNET_BUS_SHIFT));
+}
+
+static inline void w5100_write_direct(struct w5100_priv *priv,
+ u16 addr, u8 data)
+{
+ iowrite8(data, priv->base + (addr << CONFIG_WIZNET_BUS_SHIFT));
+}
+
+static u16 w5100_read16_direct(struct w5100_priv *priv, u16 addr)
+{
+ u16 data;
+ data = w5100_read_direct(priv, addr) << 8;
+ data |= w5100_read_direct(priv, addr + 1);
+ return data;
+}
+
+static void w5100_write16_direct(struct w5100_priv *priv, u16 addr, u16 data)
+{
+ w5100_write_direct(priv, addr, data >> 8);
+ w5100_write_direct(priv, addr + 1, data);
+}
+
+static void w5100_readbuf_direct(struct w5100_priv *priv,
+ u16 offset, u8 *buf, int len)
+{
+ u16 addr = W5100_RX_MEM_START + (offset & W5100_RX_MEM_MASK);
+ int i;
+
+ for (i = 0; i < len; i++, addr++) {
+ if (unlikely(addr > W5100_RX_MEM_END))
+ addr = W5100_RX_MEM_START;
+ *buf++ = w5100_read_direct(priv, addr);
+ }
+}
+
+static void w5100_writebuf_direct(struct w5100_priv *priv,
+ u16 offset, u8 *buf, int len)
+{
+ u16 addr = W5100_TX_MEM_START + (offset & W5100_TX_MEM_MASK);
+ int i;
+
+ for (i = 0; i < len; i++, addr++) {
+ if (unlikely(addr > W5100_TX_MEM_END))
+ addr = W5100_TX_MEM_START;
+ w5100_write_direct(priv, addr, *buf++);
+ }
+}
+
+/*
+ * In indirect address mode host system indirectly accesses registers by
+ * using Indirect Mode Address Register (IDM_AR) and Indirect Mode Data
+ * Register (IDM_DR), which are directly mapped to Memory-Mapped I/O space.
+ * Mode Register (MR) is directly accessible.
+ *
+ * Only 0x04 bytes are required for memory space.
+ */
+#define W5100_IDM_AR 0x01 /* Indirect Mode Address Register */
+#define W5100_IDM_DR 0x03 /* Indirect Mode Data Register */
+
+static u8 w5100_read_indirect(struct w5100_priv *priv, u16 addr)
+{
+ unsigned long flags;
+ u8 data;
+
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ w5100_write16_direct(priv, W5100_IDM_AR, addr);
+ mmiowb();
+ data = w5100_read_direct(priv, W5100_IDM_DR);
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+
+ return data;
+}
+
+static void w5100_write_indirect(struct w5100_priv *priv, u16 addr, u8 data)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ w5100_write16_direct(priv, W5100_IDM_AR, addr);
+ mmiowb();
+ w5100_write_direct(priv, W5100_IDM_DR, data);
+ mmiowb();
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+}
+
+static u16 w5100_read16_indirect(struct w5100_priv *priv, u16 addr)
+{
+ unsigned long flags;
+ u16 data;
+
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ w5100_write16_direct(priv, W5100_IDM_AR, addr);
+ mmiowb();
+ data = w5100_read_direct(priv, W5100_IDM_DR) << 8;
+ data |= w5100_read_direct(priv, W5100_IDM_DR);
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+
+ return data;
+}
+
+static void w5100_write16_indirect(struct w5100_priv *priv, u16 addr, u16 data)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ w5100_write16_direct(priv, W5100_IDM_AR, addr);
+ mmiowb();
+ w5100_write_direct(priv, W5100_IDM_DR, data >> 8);
+ w5100_write_direct(priv, W5100_IDM_DR, data);
+ mmiowb();
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+}
+
+static void w5100_readbuf_indirect(struct w5100_priv *priv,
+ u16 offset, u8 *buf, int len)
+{
+ u16 addr = W5100_RX_MEM_START + (offset & W5100_RX_MEM_MASK);
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ w5100_write16_direct(priv, W5100_IDM_AR, addr);
+ mmiowb();
+
+ for (i = 0; i < len; i++, addr++) {
+ if (unlikely(addr > W5100_RX_MEM_END)) {
+ addr = W5100_RX_MEM_START;
+ w5100_write16_direct(priv, W5100_IDM_AR, addr);
+ mmiowb();
+ }
+ *buf++ = w5100_read_direct(priv, W5100_IDM_DR);
+ }
+ mmiowb();
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+}
+
+static void w5100_writebuf_indirect(struct w5100_priv *priv,
+ u16 offset, u8 *buf, int len)
+{
+ u16 addr = W5100_TX_MEM_START + (offset & W5100_TX_MEM_MASK);
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ w5100_write16_direct(priv, W5100_IDM_AR, addr);
+ mmiowb();
+
+ for (i = 0; i < len; i++, addr++) {
+ if (unlikely(addr > W5100_TX_MEM_END)) {
+ addr = W5100_TX_MEM_START;
+ w5100_write16_direct(priv, W5100_IDM_AR, addr);
+ mmiowb();
+ }
+ w5100_write_direct(priv, W5100_IDM_DR, *buf++);
+ }
+ mmiowb();
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+}
+
+#if defined(CONFIG_WIZNET_BUS_DIRECT)
+#define w5100_read w5100_read_direct
+#define w5100_write w5100_write_direct
+#define w5100_read16 w5100_read16_direct
+#define w5100_write16 w5100_write16_direct
+#define w5100_readbuf w5100_readbuf_direct
+#define w5100_writebuf w5100_writebuf_direct
+
+#elif defined(CONFIG_WIZNET_BUS_INDIRECT)
+#define w5100_read w5100_read_indirect
+#define w5100_write w5100_write_indirect
+#define w5100_read16 w5100_read16_indirect
+#define w5100_write16 w5100_write16_indirect
+#define w5100_readbuf w5100_readbuf_indirect
+#define w5100_writebuf w5100_writebuf_indirect
+
+#else /* CONFIG_WIZNET_BUS_ANY */
+#define w5100_read priv->read
+#define w5100_write priv->write
+#define w5100_read16 priv->read16
+#define w5100_write16 priv->write16
+#define w5100_readbuf priv->readbuf
+#define w5100_writebuf priv->writebuf
+#endif
+
+static int w5100_command(struct w5100_priv *priv, u16 cmd)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(100);
+
+ w5100_write(priv, W5100_S0_CR, cmd);
+ mmiowb();
+
+ while (w5100_read(priv, W5100_S0_CR) != 0) {
+ if (time_after(jiffies, timeout))
+ return -EIO;
+ cpu_relax();
+ }
+
+ return 0;
+}
+
+static void w5100_write_macaddr(struct w5100_priv *priv)
+{
+ struct net_device *ndev = priv->ndev;
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ w5100_write(priv, W5100_SHAR + i, ndev->dev_addr[i]);
+ mmiowb();
+}
+
+static void w5100_hw_reset(struct w5100_priv *priv)
+{
+ w5100_write_direct(priv, W5100_MR, MR_RST);
+ mmiowb();
+ mdelay(5);
+ w5100_write_direct(priv, W5100_MR, priv->indirect ?
+ MR_PB | MR_AI | MR_IND :
+ MR_PB);
+ mmiowb();
+ w5100_write(priv, W5100_IMR, 0);
+ w5100_write_macaddr(priv);
+
+ /* Configure 16K of internal memory
+ * as 8K RX buffer and 8K TX buffer
+ */
+ w5100_write(priv, W5100_RMSR, 0x03);
+ w5100_write(priv, W5100_TMSR, 0x03);
+ mmiowb();
+}
+
+static void w5100_hw_start(struct w5100_priv *priv)
+{
+ w5100_write(priv, W5100_S0_MR, priv->promisc ?
+ S0_MR_MACRAW : S0_MR_MACRAW_MF);
+ mmiowb();
+ w5100_command(priv, S0_CR_OPEN);
+ w5100_write(priv, W5100_IMR, IR_S0);
+ mmiowb();
+}
+
+static void w5100_hw_close(struct w5100_priv *priv)
+{
+ w5100_write(priv, W5100_IMR, 0);
+ mmiowb();
+ w5100_command(priv, S0_CR_CLOSE);
+}
+
+/***********************************************************************
+ *
+ * Device driver functions / callbacks
+ *
+ ***********************************************************************/
+
+static void w5100_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+ strlcpy(info->bus_info, dev_name(ndev->dev.parent),
+ sizeof(info->bus_info));
+}
+
+static u32 w5100_get_link(struct net_device *ndev)
+{
+ struct w5100_priv *priv = netdev_priv(ndev);
+
+ if (gpio_is_valid(priv->link_gpio))
+ return !!gpio_get_value(priv->link_gpio);
+
+ return 1;
+}
+
+static u32 w5100_get_msglevel(struct net_device *ndev)
+{
+ struct w5100_priv *priv = netdev_priv(ndev);
+
+ return priv->msg_enable;
+}
+
+static void w5100_set_msglevel(struct net_device *ndev, u32 value)
+{
+ struct w5100_priv *priv = netdev_priv(ndev);
+
+ priv->msg_enable = value;
+}
+
+static int w5100_get_regs_len(struct net_device *ndev)
+{
+ return W5100_COMMON_REGS_LEN + W5100_S0_REGS_LEN;
+}
+
+static void w5100_get_regs(struct net_device *ndev,
+ struct ethtool_regs *regs, void *_buf)
+{
+ struct w5100_priv *priv = netdev_priv(ndev);
+ u8 *buf = _buf;
+ u16 i;
+
+ regs->version = 1;
+ for (i = 0; i < W5100_COMMON_REGS_LEN; i++)
+ *buf++ = w5100_read(priv, W5100_COMMON_REGS + i);
+ for (i = 0; i < W5100_S0_REGS_LEN; i++)
+ *buf++ = w5100_read(priv, W5100_S0_REGS + i);
+}
+
+static void w5100_tx_timeout(struct net_device *ndev)
+{
+ struct w5100_priv *priv = netdev_priv(ndev);
+
+ netif_stop_queue(ndev);
+ w5100_hw_reset(priv);
+ w5100_hw_start(priv);
+ ndev->stats.tx_errors++;
+ ndev->trans_start = jiffies;
+ netif_wake_queue(ndev);
+}
+
+static int w5100_start_tx(struct sk_buff *skb, struct net_device *ndev)
+{
+ struct w5100_priv *priv = netdev_priv(ndev);
+ u16 offset;
+
+ netif_stop_queue(ndev);
+
+ offset = w5100_read16(priv, W5100_S0_TX_WR);
+ w5100_writebuf(priv, offset, skb->data, skb->len);
+ w5100_write16(priv, W5100_S0_TX_WR, offset + skb->len);
+ mmiowb();
+ ndev->stats.tx_bytes += skb->len;
+ ndev->stats.tx_packets++;
+ dev_kfree_skb(skb);
+
+ w5100_command(priv, S0_CR_SEND);
+
+ return NETDEV_TX_OK;
+}
+
+static int w5100_napi_poll(struct napi_struct *napi, int budget)
+{
+ struct w5100_priv *priv = container_of(napi, struct w5100_priv, napi);
+ struct net_device *ndev = priv->ndev;
+ struct sk_buff *skb;
+ int rx_count;
+ u16 rx_len;
+ u16 offset;
+ u8 header[2];
+
+ for (rx_count = 0; rx_count < budget; rx_count++) {
+ u16 rx_buf_len = w5100_read16(priv, W5100_S0_RX_RSR);
+ if (rx_buf_len == 0)
+ break;
+
+ offset = w5100_read16(priv, W5100_S0_RX_RD);
+ w5100_readbuf(priv, offset, header, 2);
+ rx_len = get_unaligned_be16(header) - 2;
+
+ skb = netdev_alloc_skb_ip_align(ndev, rx_len);
+ if (unlikely(!skb)) {
+ w5100_write16(priv, W5100_S0_RX_RD,
+ offset + rx_buf_len);
+ w5100_command(priv, S0_CR_RECV);
+ ndev->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ skb_put(skb, rx_len);
+ w5100_readbuf(priv, offset + 2, skb->data, rx_len);
+ w5100_write16(priv, W5100_S0_RX_RD, offset + 2 + rx_len);
+ mmiowb();
+ w5100_command(priv, S0_CR_RECV);
+ skb->protocol = eth_type_trans(skb, ndev);
+
+ netif_receive_skb(skb);
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += rx_len;
+ }
+
+ if (rx_count < budget) {
+ w5100_write(priv, W5100_IMR, IR_S0);
+ mmiowb();
+ napi_complete(napi);
+ }
+
+ return rx_count;
+}
+
+static irqreturn_t w5100_interrupt(int irq, void *ndev_instance)
+{
+ struct net_device *ndev = ndev_instance;
+ struct w5100_priv *priv = netdev_priv(ndev);
+
+ int ir = w5100_read(priv, W5100_S0_IR);
+ if (!ir)
+ return IRQ_NONE;
+ w5100_write(priv, W5100_S0_IR, ir);
+ mmiowb();
+
+ if (ir & S0_IR_SENDOK) {
+ netif_dbg(priv, tx_done, ndev, "tx done\n");
+ netif_wake_queue(ndev);
+ }
+
+ if (ir & S0_IR_RECV) {
+ if (napi_schedule_prep(&priv->napi)) {
+ w5100_write(priv, W5100_IMR, 0);
+ mmiowb();
+ __napi_schedule(&priv->napi);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t w5100_detect_link(int irq, void *ndev_instance)
+{
+ struct net_device *ndev = ndev_instance;
+ struct w5100_priv *priv = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ if (gpio_get_value(priv->link_gpio) != 0) {
+ netif_info(priv, link, ndev, "link is up\n");
+ netif_carrier_on(ndev);
+ } else {
+ netif_info(priv, link, ndev, "link is down\n");
+ netif_carrier_off(ndev);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void w5100_set_rx_mode(struct net_device *ndev)
+{
+ struct w5100_priv *priv = netdev_priv(ndev);
+ bool set_promisc = (ndev->flags & IFF_PROMISC) != 0;
+
+ if (priv->promisc != set_promisc) {
+ priv->promisc = set_promisc;
+ w5100_hw_start(priv);
+ }
+}
+
+static int w5100_set_macaddr(struct net_device *ndev, void *addr)
+{
+ struct w5100_priv *priv = netdev_priv(ndev);
+ struct sockaddr *sock_addr = addr;
+
+ if (!is_valid_ether_addr(sock_addr->sa_data))
+ return -EADDRNOTAVAIL;
+ memcpy(ndev->dev_addr, sock_addr->sa_data, ETH_ALEN);
+ ndev->addr_assign_type &= ~NET_ADDR_RANDOM;
+ w5100_write_macaddr(priv);
+ return 0;
+}
+
+static int w5100_open(struct net_device *ndev)
+{
+ struct w5100_priv *priv = netdev_priv(ndev);
+
+ netif_info(priv, ifup, ndev, "enabling\n");
+ if (!is_valid_ether_addr(ndev->dev_addr))
+ return -EINVAL;
+ w5100_hw_start(priv);
+ napi_enable(&priv->napi);
+ netif_start_queue(ndev);
+ if (!gpio_is_valid(priv->link_gpio) ||
+ gpio_get_value(priv->link_gpio) != 0)
+ netif_carrier_on(ndev);
+ return 0;
+}
+
+static int w5100_stop(struct net_device *ndev)
+{
+ struct w5100_priv *priv = netdev_priv(ndev);
+
+ netif_info(priv, ifdown, ndev, "shutting down\n");
+ w5100_hw_close(priv);
+ netif_carrier_off(ndev);
+ netif_stop_queue(ndev);
+ napi_disable(&priv->napi);
+ return 0;
+}
+
+static const struct ethtool_ops w5100_ethtool_ops = {
+ .get_drvinfo = w5100_get_drvinfo,
+ .get_msglevel = w5100_get_msglevel,
+ .set_msglevel = w5100_set_msglevel,
+ .get_link = w5100_get_link,
+ .get_regs_len = w5100_get_regs_len,
+ .get_regs = w5100_get_regs,
+};
+
+static const struct net_device_ops w5100_netdev_ops = {
+ .ndo_open = w5100_open,
+ .ndo_stop = w5100_stop,
+ .ndo_start_xmit = w5100_start_tx,
+ .ndo_tx_timeout = w5100_tx_timeout,
+ .ndo_set_rx_mode = w5100_set_rx_mode,
+ .ndo_set_mac_address = w5100_set_macaddr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+};
+
+static int __devinit w5100_hw_probe(struct platform_device *pdev)
+{
+ struct wiznet_platform_data *data = pdev->dev.platform_data;
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct w5100_priv *priv = netdev_priv(ndev);
+ const char *name = netdev_name(ndev);
+ struct resource *mem;
+ int mem_size;
+ int irq;
+ int ret;
+
+ if (data && is_valid_ether_addr(data->mac_addr)) {
+ memcpy(ndev->dev_addr, data->mac_addr, ETH_ALEN);
+ } else {
+ random_ether_addr(ndev->dev_addr);
+ ndev->addr_assign_type |= NET_ADDR_RANDOM;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem)
+ return -ENXIO;
+ mem_size = resource_size(mem);
+ if (!devm_request_mem_region(&pdev->dev, mem->start, mem_size, name))
+ return -EBUSY;
+ priv->base = devm_ioremap(&pdev->dev, mem->start, mem_size);
+ if (!priv->base)
+ return -EBUSY;
+
+ spin_lock_init(&priv->reg_lock);
+ priv->indirect = mem_size < W5100_BUS_DIRECT_SIZE;
+ if (priv->indirect) {
+ priv->read = w5100_read_indirect;
+ priv->write = w5100_write_indirect;
+ priv->read16 = w5100_read16_indirect;
+ priv->write16 = w5100_write16_indirect;
+ priv->readbuf = w5100_readbuf_indirect;
+ priv->writebuf = w5100_writebuf_indirect;
+ } else {
+ priv->read = w5100_read_direct;
+ priv->write = w5100_write_direct;
+ priv->read16 = w5100_read16_direct;
+ priv->write16 = w5100_write16_direct;
+ priv->readbuf = w5100_readbuf_direct;
+ priv->writebuf = w5100_writebuf_direct;
+ }
+
+ w5100_hw_reset(priv);
+ if (w5100_read16(priv, W5100_RTR) != RTR_DEFAULT)
+ return -ENODEV;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+ ret = request_irq(irq, w5100_interrupt,
+ IRQ_TYPE_LEVEL_LOW, name, ndev);
+ if (ret < 0)
+ return ret;
+ priv->irq = irq;
+
+ priv->link_gpio = data ? data->link_gpio : -EINVAL;
+ if (gpio_is_valid(priv->link_gpio)) {
+ char *link_name = devm_kzalloc(&pdev->dev, 16, GFP_KERNEL);
+ if (!link_name)
+ return -ENOMEM;
+ snprintf(link_name, 16, "%s-link", name);
+ priv->link_irq = gpio_to_irq(priv->link_gpio);
+ if (request_any_context_irq(priv->link_irq, w5100_detect_link,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ link_name, priv->ndev) < 0)
+ priv->link_gpio = -EINVAL;
+ }
+
+ netdev_info(ndev, "at 0x%llx irq %d\n", (u64)mem->start, irq);
+ return 0;
+}
+
+static int __devinit w5100_probe(struct platform_device *pdev)
+{
+ struct w5100_priv *priv;
+ struct net_device *ndev;
+ int err;
+
+ ndev = alloc_etherdev(sizeof(*priv));
+ if (!ndev)
+ return -ENOMEM;
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+ platform_set_drvdata(pdev, ndev);
+ priv = netdev_priv(ndev);
+ priv->ndev = ndev;
+
+ ether_setup(ndev);
+ ndev->netdev_ops = &w5100_netdev_ops;
+ ndev->ethtool_ops = &w5100_ethtool_ops;
+ ndev->watchdog_timeo = HZ;
+ netif_napi_add(ndev, &priv->napi, w5100_napi_poll, 16);
+
+ /* This chip doesn't support VLAN packets with normal MTU,
+ * so disable VLAN for this device.
+ */
+ ndev->features |= NETIF_F_VLAN_CHALLENGED;
+
+ err = register_netdev(ndev);
+ if (err < 0)
+ goto err_register;
+
+ err = w5100_hw_probe(pdev);
+ if (err < 0)
+ goto err_hw_probe;
+
+ return 0;
+
+err_hw_probe:
+ unregister_netdev(ndev);
+err_register:
+ free_netdev(ndev);
+ platform_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static int __devexit w5100_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct w5100_priv *priv = netdev_priv(ndev);
+
+ w5100_hw_reset(priv);
+ free_irq(priv->irq, ndev);
+ if (gpio_is_valid(priv->link_gpio))
+ free_irq(priv->link_irq, ndev);
+
+ unregister_netdev(ndev);
+ free_netdev(ndev);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int w5100_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct w5100_priv *priv = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ netif_carrier_off(ndev);
+ netif_device_detach(ndev);
+
+ w5100_hw_close(priv);
+ }
+ return 0;
+}
+
+static int w5100_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct w5100_priv *priv = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ w5100_hw_reset(priv);
+ w5100_hw_start(priv);
+
+ netif_device_attach(ndev);
+ if (!gpio_is_valid(priv->link_gpio) ||
+ gpio_get_value(priv->link_gpio) != 0)
+ netif_carrier_on(ndev);
+ }
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static SIMPLE_DEV_PM_OPS(w5100_pm_ops, w5100_suspend, w5100_resume);
+
+static struct platform_driver w5100_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &w5100_pm_ops,
+ },
+ .probe = w5100_probe,
+ .remove = __devexit_p(w5100_remove),
+};
+
+module_platform_driver(w5100_driver);
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
new file mode 100644
index 000000000000..3306a20ec211
--- /dev/null
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -0,0 +1,720 @@
+/*
+ * Ethernet driver for the WIZnet W5300 chip.
+ *
+ * Copyright (C) 2008-2009 WIZnet Co.,Ltd.
+ * Copyright (C) 2011 Taehun Kim <kth3321 <at> gmail.com>
+ * Copyright (C) 2012 Mike Sinkovsky <msink@permonline.ru>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kconfig.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/wiznet.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+
+#define DRV_NAME "w5300"
+#define DRV_VERSION "2012-04-04"
+
+MODULE_DESCRIPTION("WIZnet W5300 Ethernet driver v"DRV_VERSION);
+MODULE_AUTHOR("Mike Sinkovsky <msink@permonline.ru>");
+MODULE_ALIAS("platform:"DRV_NAME);
+MODULE_LICENSE("GPL");
+
+/*
+ * Registers
+ */
+#define W5300_MR 0x0000 /* Mode Register */
+#define MR_DBW (1 << 15) /* Data bus width */
+#define MR_MPF (1 << 14) /* Mac layer pause frame */
+#define MR_WDF(n) (((n)&7)<<11) /* Write data fetch time */
+#define MR_RDH (1 << 10) /* Read data hold time */
+#define MR_FS (1 << 8) /* FIFO swap */
+#define MR_RST (1 << 7) /* S/W reset */
+#define MR_PB (1 << 4) /* Ping block */
+#define MR_DBS (1 << 2) /* Data bus swap */
+#define MR_IND (1 << 0) /* Indirect mode */
+#define W5300_IR 0x0002 /* Interrupt Register */
+#define W5300_IMR 0x0004 /* Interrupt Mask Register */
+#define IR_S0 0x0001 /* S0 interrupt */
+#define W5300_SHARL 0x0008 /* Source MAC address (0123) */
+#define W5300_SHARH 0x000c /* Source MAC address (45) */
+#define W5300_TMSRL 0x0020 /* Transmit Memory Size (0123) */
+#define W5300_TMSRH 0x0024 /* Transmit Memory Size (4567) */
+#define W5300_RMSRL 0x0028 /* Receive Memory Size (0123) */
+#define W5300_RMSRH 0x002c /* Receive Memory Size (4567) */
+#define W5300_MTYPE 0x0030 /* Memory Type */
+#define W5300_IDR 0x00fe /* Chip ID register */
+#define IDR_W5300 0x5300 /* =0x5300 for WIZnet W5300 */
+#define W5300_S0_MR 0x0200 /* S0 Mode Register */
+#define S0_MR_CLOSED 0x0000 /* Close mode */
+#define S0_MR_MACRAW 0x0004 /* MAC RAW mode (promiscous) */
+#define S0_MR_MACRAW_MF 0x0044 /* MAC RAW mode (filtered) */
+#define W5300_S0_CR 0x0202 /* S0 Command Register */
+#define S0_CR_OPEN 0x0001 /* OPEN command */
+#define S0_CR_CLOSE 0x0010 /* CLOSE command */
+#define S0_CR_SEND 0x0020 /* SEND command */
+#define S0_CR_RECV 0x0040 /* RECV command */
+#define W5300_S0_IMR 0x0204 /* S0 Interrupt Mask Register */
+#define W5300_S0_IR 0x0206 /* S0 Interrupt Register */
+#define S0_IR_RECV 0x0004 /* Receive interrupt */
+#define S0_IR_SENDOK 0x0010 /* Send OK interrupt */
+#define W5300_S0_SSR 0x0208 /* S0 Socket Status Register */
+#define W5300_S0_TX_WRSR 0x0220 /* S0 TX Write Size Register */
+#define W5300_S0_TX_FSR 0x0224 /* S0 TX Free Size Register */
+#define W5300_S0_RX_RSR 0x0228 /* S0 Received data Size */
+#define W5300_S0_TX_FIFO 0x022e /* S0 Transmit FIFO */
+#define W5300_S0_RX_FIFO 0x0230 /* S0 Receive FIFO */
+#define W5300_REGS_LEN 0x0400
+
+/*
+ * Device driver private data structure
+ */
+struct w5300_priv {
+ void __iomem *base;
+ spinlock_t reg_lock;
+ bool indirect;
+ u16 (*read) (struct w5300_priv *priv, u16 addr);
+ void (*write)(struct w5300_priv *priv, u16 addr, u16 data);
+ int irq;
+ int link_irq;
+ int link_gpio;
+
+ struct napi_struct napi;
+ struct net_device *ndev;
+ bool promisc;
+ u32 msg_enable;
+};
+
+/************************************************************************
+ *
+ * Lowlevel I/O functions
+ *
+ ***********************************************************************/
+
+/*
+ * In direct address mode host system can directly access W5300 registers
+ * after mapping to Memory-Mapped I/O space.
+ *
+ * 0x400 bytes are required for memory space.
+ */
+static inline u16 w5300_read_direct(struct w5300_priv *priv, u16 addr)
+{
+ return ioread16(priv->base + (addr << CONFIG_WIZNET_BUS_SHIFT));
+}
+
+static inline void w5300_write_direct(struct w5300_priv *priv,
+ u16 addr, u16 data)
+{
+ iowrite16(data, priv->base + (addr << CONFIG_WIZNET_BUS_SHIFT));
+}
+
+/*
+ * In indirect address mode host system indirectly accesses registers by
+ * using Indirect Mode Address Register (IDM_AR) and Indirect Mode Data
+ * Register (IDM_DR), which are directly mapped to Memory-Mapped I/O space.
+ * Mode Register (MR) is directly accessible.
+ *
+ * Only 0x06 bytes are required for memory space.
+ */
+#define W5300_IDM_AR 0x0002 /* Indirect Mode Address */
+#define W5300_IDM_DR 0x0004 /* Indirect Mode Data */
+
+static u16 w5300_read_indirect(struct w5300_priv *priv, u16 addr)
+{
+ unsigned long flags;
+ u16 data;
+
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ w5300_write_direct(priv, W5300_IDM_AR, addr);
+ mmiowb();
+ data = w5300_read_direct(priv, W5300_IDM_DR);
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+
+ return data;
+}
+
+static void w5300_write_indirect(struct w5300_priv *priv, u16 addr, u16 data)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ w5300_write_direct(priv, W5300_IDM_AR, addr);
+ mmiowb();
+ w5300_write_direct(priv, W5300_IDM_DR, data);
+ mmiowb();
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+}
+
+#if defined(CONFIG_WIZNET_BUS_DIRECT)
+#define w5300_read w5300_read_direct
+#define w5300_write w5300_write_direct
+
+#elif defined(CONFIG_WIZNET_BUS_INDIRECT)
+#define w5300_read w5300_read_indirect
+#define w5300_write w5300_write_indirect
+
+#else /* CONFIG_WIZNET_BUS_ANY */
+#define w5300_read priv->read
+#define w5300_write priv->write
+#endif
+
+static u32 w5300_read32(struct w5300_priv *priv, u16 addr)
+{
+ u32 data;
+ data = w5300_read(priv, addr) << 16;
+ data |= w5300_read(priv, addr + 2);
+ return data;
+}
+
+static void w5300_write32(struct w5300_priv *priv, u16 addr, u32 data)
+{
+ w5300_write(priv, addr, data >> 16);
+ w5300_write(priv, addr + 2, data);
+}
+
+static int w5300_command(struct w5300_priv *priv, u16 cmd)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(100);
+
+ w5300_write(priv, W5300_S0_CR, cmd);
+ mmiowb();
+
+ while (w5300_read(priv, W5300_S0_CR) != 0) {
+ if (time_after(jiffies, timeout))
+ return -EIO;
+ cpu_relax();
+ }
+
+ return 0;
+}
+
+static void w5300_read_frame(struct w5300_priv *priv, u8 *buf, int len)
+{
+ u16 fifo;
+ int i;
+
+ for (i = 0; i < len; i += 2) {
+ fifo = w5300_read(priv, W5300_S0_RX_FIFO);
+ *buf++ = fifo >> 8;
+ *buf++ = fifo;
+ }
+ fifo = w5300_read(priv, W5300_S0_RX_FIFO);
+ fifo = w5300_read(priv, W5300_S0_RX_FIFO);
+}
+
+static void w5300_write_frame(struct w5300_priv *priv, u8 *buf, int len)
+{
+ u16 fifo;
+ int i;
+
+ for (i = 0; i < len; i += 2) {
+ fifo = *buf++ << 8;
+ fifo |= *buf++;
+ w5300_write(priv, W5300_S0_TX_FIFO, fifo);
+ }
+ w5300_write32(priv, W5300_S0_TX_WRSR, len);
+}
+
+static void w5300_write_macaddr(struct w5300_priv *priv)
+{
+ struct net_device *ndev = priv->ndev;
+ w5300_write32(priv, W5300_SHARL,
+ ndev->dev_addr[0] << 24 |
+ ndev->dev_addr[1] << 16 |
+ ndev->dev_addr[2] << 8 |
+ ndev->dev_addr[3]);
+ w5300_write(priv, W5300_SHARH,
+ ndev->dev_addr[4] << 8 |
+ ndev->dev_addr[5]);
+ mmiowb();
+}
+
+static void w5300_hw_reset(struct w5300_priv *priv)
+{
+ w5300_write_direct(priv, W5300_MR, MR_RST);
+ mmiowb();
+ mdelay(5);
+ w5300_write_direct(priv, W5300_MR, priv->indirect ?
+ MR_WDF(7) | MR_PB | MR_IND :
+ MR_WDF(7) | MR_PB);
+ mmiowb();
+ w5300_write(priv, W5300_IMR, 0);
+ w5300_write_macaddr(priv);
+
+ /* Configure 128K of internal memory
+ * as 64K RX fifo and 64K TX fifo
+ */
+ w5300_write32(priv, W5300_RMSRL, 64 << 24);
+ w5300_write32(priv, W5300_RMSRH, 0);
+ w5300_write32(priv, W5300_TMSRL, 64 << 24);
+ w5300_write32(priv, W5300_TMSRH, 0);
+ w5300_write(priv, W5300_MTYPE, 0x00ff);
+ mmiowb();
+}
+
+static void w5300_hw_start(struct w5300_priv *priv)
+{
+ w5300_write(priv, W5300_S0_MR, priv->promisc ?
+ S0_MR_MACRAW : S0_MR_MACRAW_MF);
+ mmiowb();
+ w5300_command(priv, S0_CR_OPEN);
+ w5300_write(priv, W5300_S0_IMR, S0_IR_RECV | S0_IR_SENDOK);
+ w5300_write(priv, W5300_IMR, IR_S0);
+ mmiowb();
+}
+
+static void w5300_hw_close(struct w5300_priv *priv)
+{
+ w5300_write(priv, W5300_IMR, 0);
+ mmiowb();
+ w5300_command(priv, S0_CR_CLOSE);
+}
+
+/***********************************************************************
+ *
+ * Device driver functions / callbacks
+ *
+ ***********************************************************************/
+
+static void w5300_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+ strlcpy(info->bus_info, dev_name(ndev->dev.parent),
+ sizeof(info->bus_info));
+}
+
+static u32 w5300_get_link(struct net_device *ndev)
+{
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ if (gpio_is_valid(priv->link_gpio))
+ return !!gpio_get_value(priv->link_gpio);
+
+ return 1;
+}
+
+static u32 w5300_get_msglevel(struct net_device *ndev)
+{
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ return priv->msg_enable;
+}
+
+static void w5300_set_msglevel(struct net_device *ndev, u32 value)
+{
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ priv->msg_enable = value;
+}
+
+static int w5300_get_regs_len(struct net_device *ndev)
+{
+ return W5300_REGS_LEN;
+}
+
+static void w5300_get_regs(struct net_device *ndev,
+ struct ethtool_regs *regs, void *_buf)
+{
+ struct w5300_priv *priv = netdev_priv(ndev);
+ u8 *buf = _buf;
+ u16 addr;
+ u16 data;
+
+ regs->version = 1;
+ for (addr = 0; addr < W5300_REGS_LEN; addr += 2) {
+ switch (addr & 0x23f) {
+ case W5300_S0_TX_FIFO: /* cannot read TX_FIFO */
+ case W5300_S0_RX_FIFO: /* cannot read RX_FIFO */
+ data = 0xffff;
+ break;
+ default:
+ data = w5300_read(priv, addr);
+ break;
+ }
+ *buf++ = data >> 8;
+ *buf++ = data;
+ }
+}
+
+static void w5300_tx_timeout(struct net_device *ndev)
+{
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ netif_stop_queue(ndev);
+ w5300_hw_reset(priv);
+ w5300_hw_start(priv);
+ ndev->stats.tx_errors++;
+ ndev->trans_start = jiffies;
+ netif_wake_queue(ndev);
+}
+
+static int w5300_start_tx(struct sk_buff *skb, struct net_device *ndev)
+{
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ netif_stop_queue(ndev);
+
+ w5300_write_frame(priv, skb->data, skb->len);
+ mmiowb();
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += skb->len;
+ dev_kfree_skb(skb);
+ netif_dbg(priv, tx_queued, ndev, "tx queued\n");
+
+ w5300_command(priv, S0_CR_SEND);
+
+ return NETDEV_TX_OK;
+}
+
+static int w5300_napi_poll(struct napi_struct *napi, int budget)
+{
+ struct w5300_priv *priv = container_of(napi, struct w5300_priv, napi);
+ struct net_device *ndev = priv->ndev;
+ struct sk_buff *skb;
+ int rx_count;
+ u16 rx_len;
+
+ for (rx_count = 0; rx_count < budget; rx_count++) {
+ u32 rx_fifo_len = w5300_read32(priv, W5300_S0_RX_RSR);
+ if (rx_fifo_len == 0)
+ break;
+
+ rx_len = w5300_read(priv, W5300_S0_RX_FIFO);
+
+ skb = netdev_alloc_skb_ip_align(ndev, roundup(rx_len, 2));
+ if (unlikely(!skb)) {
+ u32 i;
+ for (i = 0; i < rx_fifo_len; i += 2)
+ w5300_read(priv, W5300_S0_RX_FIFO);
+ ndev->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ skb_put(skb, rx_len);
+ w5300_read_frame(priv, skb->data, rx_len);
+ skb->protocol = eth_type_trans(skb, ndev);
+
+ netif_receive_skb(skb);
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += rx_len;
+ }
+
+ if (rx_count < budget) {
+ w5300_write(priv, W5300_IMR, IR_S0);
+ mmiowb();
+ napi_complete(napi);
+ }
+
+ return rx_count;
+}
+
+static irqreturn_t w5300_interrupt(int irq, void *ndev_instance)
+{
+ struct net_device *ndev = ndev_instance;
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ int ir = w5300_read(priv, W5300_S0_IR);
+ if (!ir)
+ return IRQ_NONE;
+ w5300_write(priv, W5300_S0_IR, ir);
+ mmiowb();
+
+ if (ir & S0_IR_SENDOK) {
+ netif_dbg(priv, tx_done, ndev, "tx done\n");
+ netif_wake_queue(ndev);
+ }
+
+ if (ir & S0_IR_RECV) {
+ if (napi_schedule_prep(&priv->napi)) {
+ w5300_write(priv, W5300_IMR, 0);
+ mmiowb();
+ __napi_schedule(&priv->napi);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t w5300_detect_link(int irq, void *ndev_instance)
+{
+ struct net_device *ndev = ndev_instance;
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ if (gpio_get_value(priv->link_gpio) != 0) {
+ netif_info(priv, link, ndev, "link is up\n");
+ netif_carrier_on(ndev);
+ } else {
+ netif_info(priv, link, ndev, "link is down\n");
+ netif_carrier_off(ndev);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void w5300_set_rx_mode(struct net_device *ndev)
+{
+ struct w5300_priv *priv = netdev_priv(ndev);
+ bool set_promisc = (ndev->flags & IFF_PROMISC) != 0;
+
+ if (priv->promisc != set_promisc) {
+ priv->promisc = set_promisc;
+ w5300_hw_start(priv);
+ }
+}
+
+static int w5300_set_macaddr(struct net_device *ndev, void *addr)
+{
+ struct w5300_priv *priv = netdev_priv(ndev);
+ struct sockaddr *sock_addr = addr;
+
+ if (!is_valid_ether_addr(sock_addr->sa_data))
+ return -EADDRNOTAVAIL;
+ memcpy(ndev->dev_addr, sock_addr->sa_data, ETH_ALEN);
+ ndev->addr_assign_type &= ~NET_ADDR_RANDOM;
+ w5300_write_macaddr(priv);
+ return 0;
+}
+
+static int w5300_open(struct net_device *ndev)
+{
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ netif_info(priv, ifup, ndev, "enabling\n");
+ if (!is_valid_ether_addr(ndev->dev_addr))
+ return -EINVAL;
+ w5300_hw_start(priv);
+ napi_enable(&priv->napi);
+ netif_start_queue(ndev);
+ if (!gpio_is_valid(priv->link_gpio) ||
+ gpio_get_value(priv->link_gpio) != 0)
+ netif_carrier_on(ndev);
+ return 0;
+}
+
+static int w5300_stop(struct net_device *ndev)
+{
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ netif_info(priv, ifdown, ndev, "shutting down\n");
+ w5300_hw_close(priv);
+ netif_carrier_off(ndev);
+ netif_stop_queue(ndev);
+ napi_disable(&priv->napi);
+ return 0;
+}
+
+static const struct ethtool_ops w5300_ethtool_ops = {
+ .get_drvinfo = w5300_get_drvinfo,
+ .get_msglevel = w5300_get_msglevel,
+ .set_msglevel = w5300_set_msglevel,
+ .get_link = w5300_get_link,
+ .get_regs_len = w5300_get_regs_len,
+ .get_regs = w5300_get_regs,
+};
+
+static const struct net_device_ops w5300_netdev_ops = {
+ .ndo_open = w5300_open,
+ .ndo_stop = w5300_stop,
+ .ndo_start_xmit = w5300_start_tx,
+ .ndo_tx_timeout = w5300_tx_timeout,
+ .ndo_set_rx_mode = w5300_set_rx_mode,
+ .ndo_set_mac_address = w5300_set_macaddr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+};
+
+static int __devinit w5300_hw_probe(struct platform_device *pdev)
+{
+ struct wiznet_platform_data *data = pdev->dev.platform_data;
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct w5300_priv *priv = netdev_priv(ndev);
+ const char *name = netdev_name(ndev);
+ struct resource *mem;
+ int mem_size;
+ int irq;
+ int ret;
+
+ if (data && is_valid_ether_addr(data->mac_addr)) {
+ memcpy(ndev->dev_addr, data->mac_addr, ETH_ALEN);
+ } else {
+ random_ether_addr(ndev->dev_addr);
+ ndev->addr_assign_type |= NET_ADDR_RANDOM;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem)
+ return -ENXIO;
+ mem_size = resource_size(mem);
+ if (!devm_request_mem_region(&pdev->dev, mem->start, mem_size, name))
+ return -EBUSY;
+ priv->base = devm_ioremap(&pdev->dev, mem->start, mem_size);
+ if (!priv->base)
+ return -EBUSY;
+
+ spin_lock_init(&priv->reg_lock);
+ priv->indirect = mem_size < W5300_BUS_DIRECT_SIZE;
+ if (priv->indirect) {
+ priv->read = w5300_read_indirect;
+ priv->write = w5300_write_indirect;
+ } else {
+ priv->read = w5300_read_direct;
+ priv->write = w5300_write_direct;
+ }
+
+ w5300_hw_reset(priv);
+ if (w5300_read(priv, W5300_IDR) != IDR_W5300)
+ return -ENODEV;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+ ret = request_irq(irq, w5300_interrupt,
+ IRQ_TYPE_LEVEL_LOW, name, ndev);
+ if (ret < 0)
+ return ret;
+ priv->irq = irq;
+
+ priv->link_gpio = data ? data->link_gpio : -EINVAL;
+ if (gpio_is_valid(priv->link_gpio)) {
+ char *link_name = devm_kzalloc(&pdev->dev, 16, GFP_KERNEL);
+ if (!link_name)
+ return -ENOMEM;
+ snprintf(link_name, 16, "%s-link", name);
+ priv->link_irq = gpio_to_irq(priv->link_gpio);
+ if (request_any_context_irq(priv->link_irq, w5300_detect_link,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ link_name, priv->ndev) < 0)
+ priv->link_gpio = -EINVAL;
+ }
+
+ netdev_info(ndev, "at 0x%llx irq %d\n", (u64)mem->start, irq);
+ return 0;
+}
+
+static int __devinit w5300_probe(struct platform_device *pdev)
+{
+ struct w5300_priv *priv;
+ struct net_device *ndev;
+ int err;
+
+ ndev = alloc_etherdev(sizeof(*priv));
+ if (!ndev)
+ return -ENOMEM;
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+ platform_set_drvdata(pdev, ndev);
+ priv = netdev_priv(ndev);
+ priv->ndev = ndev;
+
+ ether_setup(ndev);
+ ndev->netdev_ops = &w5300_netdev_ops;
+ ndev->ethtool_ops = &w5300_ethtool_ops;
+ ndev->watchdog_timeo = HZ;
+ netif_napi_add(ndev, &priv->napi, w5300_napi_poll, 16);
+
+ /* This chip doesn't support VLAN packets with normal MTU,
+ * so disable VLAN for this device.
+ */
+ ndev->features |= NETIF_F_VLAN_CHALLENGED;
+
+ err = register_netdev(ndev);
+ if (err < 0)
+ goto err_register;
+
+ err = w5300_hw_probe(pdev);
+ if (err < 0)
+ goto err_hw_probe;
+
+ return 0;
+
+err_hw_probe:
+ unregister_netdev(ndev);
+err_register:
+ free_netdev(ndev);
+ platform_set_drvdata(pdev, NULL);
+ return err;
+}
+
+static int __devexit w5300_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ w5300_hw_reset(priv);
+ free_irq(priv->irq, ndev);
+ if (gpio_is_valid(priv->link_gpio))
+ free_irq(priv->link_irq, ndev);
+
+ unregister_netdev(ndev);
+ free_netdev(ndev);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int w5300_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ netif_carrier_off(ndev);
+ netif_device_detach(ndev);
+
+ w5300_hw_close(priv);
+ }
+ return 0;
+}
+
+static int w5300_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct w5300_priv *priv = netdev_priv(ndev);
+
+ if (!netif_running(ndev)) {
+ w5300_hw_reset(priv);
+ w5300_hw_start(priv);
+
+ netif_device_attach(ndev);
+ if (!gpio_is_valid(priv->link_gpio) ||
+ gpio_get_value(priv->link_gpio) != 0)
+ netif_carrier_on(ndev);
+ }
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static SIMPLE_DEV_PM_OPS(w5300_pm_ops, w5300_suspend, w5300_resume);
+
+static struct platform_driver w5300_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &w5300_pm_ops,
+ },
+ .probe = w5300_probe,
+ .remove = __devexit_p(w5300_remove),
+};
+
+module_platform_driver(w5300_driver);
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index d21591a2c593..1eaf7128afee 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -1000,6 +1000,7 @@ static const struct ethtool_ops temac_ethtool_ops = {
.set_settings = temac_set_settings,
.nway_reset = temac_nway_reset,
.get_link = ethtool_op_get_link,
+ .get_ts_info = ethtool_op_get_ts_info,
};
static int __devinit temac_of_probe(struct platform_device *op)
diff --git a/drivers/net/ethernet/xscale/Kconfig b/drivers/net/ethernet/xscale/Kconfig
index cf67352cea14..3f431019e615 100644
--- a/drivers/net/ethernet/xscale/Kconfig
+++ b/drivers/net/ethernet/xscale/Kconfig
@@ -5,8 +5,8 @@
config NET_VENDOR_XSCALE
bool "Intel XScale IXP devices"
default y
- depends on NET_VENDOR_INTEL && ((ARM && ARCH_IXP4XX && \
- IXP4XX_NPE && IXP4XX_QMGR) || ARCH_ENP2611)
+ depends on NET_VENDOR_INTEL && (ARM && ARCH_IXP4XX && \
+ IXP4XX_NPE && IXP4XX_QMGR)
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -27,6 +27,4 @@ config IXP4XX_ETH
Say Y here if you want to use built-in Ethernet ports
on IXP4xx processor.
-source "drivers/net/ethernet/xscale/ixp2000/Kconfig"
-
endif # NET_VENDOR_XSCALE
diff --git a/drivers/net/ethernet/xscale/Makefile b/drivers/net/ethernet/xscale/Makefile
index b195b9d7fe81..abc3b031fba7 100644
--- a/drivers/net/ethernet/xscale/Makefile
+++ b/drivers/net/ethernet/xscale/Makefile
@@ -2,5 +2,4 @@
# Makefile for the Intel XScale IXP device drivers.
#
-obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o
diff --git a/drivers/net/ethernet/xscale/ixp2000/Kconfig b/drivers/net/ethernet/xscale/ixp2000/Kconfig
deleted file mode 100644
index 58dbc5b876bc..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/Kconfig
+++ /dev/null
@@ -1,6 +0,0 @@
-config ENP2611_MSF_NET
- tristate "Radisys ENP2611 MSF network interface support"
- depends on ARCH_ENP2611
- ---help---
- This is a driver for the MSF network interface unit in
- the IXP2400 on the Radisys ENP2611 platform.
diff --git a/drivers/net/ethernet/xscale/ixp2000/Makefile b/drivers/net/ethernet/xscale/ixp2000/Makefile
deleted file mode 100644
index fd38351ceaa7..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_ENP2611_MSF_NET) += enp2611_mod.o
-
-enp2611_mod-objs := caleb.o enp2611.o ixp2400-msf.o ixpdev.o pm3386.o
diff --git a/drivers/net/ethernet/xscale/ixp2000/caleb.c b/drivers/net/ethernet/xscale/ixp2000/caleb.c
deleted file mode 100644
index 7dea5b95012c..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/caleb.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Helper functions for the SPI-3 bridge FPGA on the Radisys ENP2611
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include "caleb.h"
-
-#define CALEB_IDLO 0x00
-#define CALEB_IDHI 0x01
-#define CALEB_RID 0x02
-#define CALEB_RESET 0x03
-#define CALEB_INTREN0 0x04
-#define CALEB_INTREN1 0x05
-#define CALEB_INTRSTAT0 0x06
-#define CALEB_INTRSTAT1 0x07
-#define CALEB_PORTEN 0x08
-#define CALEB_BURST 0x09
-#define CALEB_PORTPAUS 0x0A
-#define CALEB_PORTPAUSD 0x0B
-#define CALEB_PHY0RX 0x10
-#define CALEB_PHY1RX 0x11
-#define CALEB_PHY0TX 0x12
-#define CALEB_PHY1TX 0x13
-#define CALEB_IXPRX_HI_CNTR 0x15
-#define CALEB_PHY0RX_HI_CNTR 0x16
-#define CALEB_PHY1RX_HI_CNTR 0x17
-#define CALEB_IXPRX_CNTR 0x18
-#define CALEB_PHY0RX_CNTR 0x19
-#define CALEB_PHY1RX_CNTR 0x1A
-#define CALEB_IXPTX_CNTR 0x1B
-#define CALEB_PHY0TX_CNTR 0x1C
-#define CALEB_PHY1TX_CNTR 0x1D
-#define CALEB_DEBUG0 0x1E
-#define CALEB_DEBUG1 0x1F
-
-
-static u8 caleb_reg_read(int reg)
-{
- u8 value;
-
- value = *((volatile u8 *)(ENP2611_CALEB_VIRT_BASE + reg));
-
-// printk(KERN_INFO "caleb_reg_read(%d) = %.2x\n", reg, value);
-
- return value;
-}
-
-static void caleb_reg_write(int reg, u8 value)
-{
- u8 dummy;
-
-// printk(KERN_INFO "caleb_reg_write(%d, %.2x)\n", reg, value);
-
- *((volatile u8 *)(ENP2611_CALEB_VIRT_BASE + reg)) = value;
-
- dummy = *((volatile u8 *)ENP2611_CALEB_VIRT_BASE);
- __asm__ __volatile__("mov %0, %0" : "+r" (dummy));
-}
-
-
-void caleb_reset(void)
-{
- /*
- * Perform a chip reset.
- */
- caleb_reg_write(CALEB_RESET, 0x02);
- udelay(1);
-
- /*
- * Enable all interrupt sources. This is needed to get
- * meaningful results out of the status bits (register 6
- * and 7.)
- */
- caleb_reg_write(CALEB_INTREN0, 0xff);
- caleb_reg_write(CALEB_INTREN1, 0x07);
-
- /*
- * Set RX and TX FIFO thresholds to 1.5kb.
- */
- caleb_reg_write(CALEB_PHY0RX, 0x11);
- caleb_reg_write(CALEB_PHY1RX, 0x11);
- caleb_reg_write(CALEB_PHY0TX, 0x11);
- caleb_reg_write(CALEB_PHY1TX, 0x11);
-
- /*
- * Program SPI-3 burst size.
- */
- caleb_reg_write(CALEB_BURST, 0); // 64-byte RBUF mpackets
-// caleb_reg_write(CALEB_BURST, 1); // 128-byte RBUF mpackets
-// caleb_reg_write(CALEB_BURST, 2); // 256-byte RBUF mpackets
-}
-
-void caleb_enable_rx(int port)
-{
- u8 temp;
-
- temp = caleb_reg_read(CALEB_PORTEN);
- temp |= 1 << port;
- caleb_reg_write(CALEB_PORTEN, temp);
-}
-
-void caleb_disable_rx(int port)
-{
- u8 temp;
-
- temp = caleb_reg_read(CALEB_PORTEN);
- temp &= ~(1 << port);
- caleb_reg_write(CALEB_PORTEN, temp);
-}
-
-void caleb_enable_tx(int port)
-{
- u8 temp;
-
- temp = caleb_reg_read(CALEB_PORTEN);
- temp |= 1 << (port + 4);
- caleb_reg_write(CALEB_PORTEN, temp);
-}
-
-void caleb_disable_tx(int port)
-{
- u8 temp;
-
- temp = caleb_reg_read(CALEB_PORTEN);
- temp &= ~(1 << (port + 4));
- caleb_reg_write(CALEB_PORTEN, temp);
-}
diff --git a/drivers/net/ethernet/xscale/ixp2000/caleb.h b/drivers/net/ethernet/xscale/ixp2000/caleb.h
deleted file mode 100644
index e93a1ef5b8a3..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/caleb.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Helper functions for the SPI-3 bridge FPGA on the Radisys ENP2611
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __CALEB_H
-#define __CALEB_H
-
-void caleb_reset(void);
-void caleb_enable_rx(int port);
-void caleb_disable_rx(int port);
-void caleb_enable_tx(int port);
-void caleb_disable_tx(int port);
-
-
-#endif
diff --git a/drivers/net/ethernet/xscale/ixp2000/enp2611.c b/drivers/net/ethernet/xscale/ixp2000/enp2611.c
deleted file mode 100644
index 34a6cfd17930..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/enp2611.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * IXP2400 MSF network device driver for the Radisys ENP2611
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/moduleparam.h>
-#include <asm/hardware/uengine.h>
-#include <asm/mach-types.h>
-#include <asm/io.h>
-#include "ixpdev.h"
-#include "caleb.h"
-#include "ixp2400-msf.h"
-#include "pm3386.h"
-
-/***********************************************************************
- * The Radisys ENP2611 is a PCI form factor board with three SFP GBIC
- * slots, connected via two PMC/Sierra 3386s and an SPI-3 bridge FPGA
- * to the IXP2400.
- *
- * +-------------+
- * SFP GBIC #0 ---+ | +---------+
- * | PM3386 #0 +-------+ |
- * SFP GBIC #1 ---+ | | "Caleb" | +---------+
- * +-------------+ | | | |
- * | SPI-3 +---------+ IXP2400 |
- * +-------------+ | bridge | | |
- * SFP GBIC #2 ---+ | | FPGA | +---------+
- * | PM3386 #1 +-------+ |
- * | | +---------+
- * +-------------+
- * ^ ^ ^
- * | 1.25Gbaud | 104MHz | 104MHz
- * | SERDES ea. | SPI-3 ea. | SPI-3
- *
- ***********************************************************************/
-static struct ixp2400_msf_parameters enp2611_msf_parameters =
-{
- .rx_mode = IXP2400_RX_MODE_UTOPIA_POS |
- IXP2400_RX_MODE_1x32 |
- IXP2400_RX_MODE_MPHY |
- IXP2400_RX_MODE_MPHY_32 |
- IXP2400_RX_MODE_MPHY_POLLED_STATUS |
- IXP2400_RX_MODE_MPHY_LEVEL3 |
- IXP2400_RX_MODE_RBUF_SIZE_64,
-
- .rxclk01_multiplier = IXP2400_PLL_MULTIPLIER_16,
-
- .rx_poll_ports = 3,
-
- .rx_channel_mode = {
- IXP2400_PORT_RX_MODE_MASTER |
- IXP2400_PORT_RX_MODE_POS_PHY |
- IXP2400_PORT_RX_MODE_POS_PHY_L3 |
- IXP2400_PORT_RX_MODE_ODD_PARITY |
- IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
-
- IXP2400_PORT_RX_MODE_MASTER |
- IXP2400_PORT_RX_MODE_POS_PHY |
- IXP2400_PORT_RX_MODE_POS_PHY_L3 |
- IXP2400_PORT_RX_MODE_ODD_PARITY |
- IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
-
- IXP2400_PORT_RX_MODE_MASTER |
- IXP2400_PORT_RX_MODE_POS_PHY |
- IXP2400_PORT_RX_MODE_POS_PHY_L3 |
- IXP2400_PORT_RX_MODE_ODD_PARITY |
- IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
-
- IXP2400_PORT_RX_MODE_MASTER |
- IXP2400_PORT_RX_MODE_POS_PHY |
- IXP2400_PORT_RX_MODE_POS_PHY_L3 |
- IXP2400_PORT_RX_MODE_ODD_PARITY |
- IXP2400_PORT_RX_MODE_2_CYCLE_DECODE
- },
-
- .tx_mode = IXP2400_TX_MODE_UTOPIA_POS |
- IXP2400_TX_MODE_1x32 |
- IXP2400_TX_MODE_MPHY |
- IXP2400_TX_MODE_MPHY_32 |
- IXP2400_TX_MODE_MPHY_POLLED_STATUS |
- IXP2400_TX_MODE_MPHY_LEVEL3 |
- IXP2400_TX_MODE_TBUF_SIZE_64,
-
- .txclk01_multiplier = IXP2400_PLL_MULTIPLIER_16,
-
- .tx_poll_ports = 3,
-
- .tx_channel_mode = {
- IXP2400_PORT_TX_MODE_MASTER |
- IXP2400_PORT_TX_MODE_POS_PHY |
- IXP2400_PORT_TX_MODE_ODD_PARITY |
- IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
-
- IXP2400_PORT_TX_MODE_MASTER |
- IXP2400_PORT_TX_MODE_POS_PHY |
- IXP2400_PORT_TX_MODE_ODD_PARITY |
- IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
-
- IXP2400_PORT_TX_MODE_MASTER |
- IXP2400_PORT_TX_MODE_POS_PHY |
- IXP2400_PORT_TX_MODE_ODD_PARITY |
- IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
-
- IXP2400_PORT_TX_MODE_MASTER |
- IXP2400_PORT_TX_MODE_POS_PHY |
- IXP2400_PORT_TX_MODE_ODD_PARITY |
- IXP2400_PORT_TX_MODE_2_CYCLE_DECODE
- }
-};
-
-static struct net_device *nds[3];
-static struct timer_list link_check_timer;
-
-/* @@@ Poll the SFP moddef0 line too. */
-/* @@@ Try to use the pm3386 DOOL interrupt as well. */
-static void enp2611_check_link_status(unsigned long __dummy)
-{
- int i;
-
- for (i = 0; i < 3; i++) {
- struct net_device *dev;
- int status;
-
- dev = nds[i];
- if (dev == NULL)
- continue;
-
- status = pm3386_is_link_up(i);
- if (status && !netif_carrier_ok(dev)) {
- /* @@@ Should report autonegotiation status. */
- printk(KERN_INFO "%s: NIC Link is Up\n", dev->name);
-
- pm3386_enable_tx(i);
- caleb_enable_tx(i);
- netif_carrier_on(dev);
- } else if (!status && netif_carrier_ok(dev)) {
- printk(KERN_INFO "%s: NIC Link is Down\n", dev->name);
-
- netif_carrier_off(dev);
- caleb_disable_tx(i);
- pm3386_disable_tx(i);
- }
- }
-
- link_check_timer.expires = jiffies + HZ / 10;
- add_timer(&link_check_timer);
-}
-
-static void enp2611_set_port_admin_status(int port, int up)
-{
- if (up) {
- caleb_enable_rx(port);
-
- pm3386_set_carrier(port, 1);
- pm3386_enable_rx(port);
- } else {
- caleb_disable_tx(port);
- pm3386_disable_tx(port);
- /* @@@ Flush out pending packets. */
- pm3386_set_carrier(port, 0);
-
- pm3386_disable_rx(port);
- caleb_disable_rx(port);
- }
-}
-
-static int __init enp2611_init_module(void)
-{
- int ports;
- int i;
-
- if (!machine_is_enp2611())
- return -ENODEV;
-
- caleb_reset();
- pm3386_reset();
-
- ports = pm3386_port_count();
- for (i = 0; i < ports; i++) {
- nds[i] = ixpdev_alloc(i, sizeof(struct ixpdev_priv));
- if (nds[i] == NULL) {
- while (--i >= 0)
- free_netdev(nds[i]);
- return -ENOMEM;
- }
-
- pm3386_init_port(i);
- pm3386_get_mac(i, nds[i]->dev_addr);
- }
-
- ixp2400_msf_init(&enp2611_msf_parameters);
-
- if (ixpdev_init(ports, nds, enp2611_set_port_admin_status)) {
- for (i = 0; i < ports; i++)
- if (nds[i])
- free_netdev(nds[i]);
- return -EINVAL;
- }
-
- init_timer(&link_check_timer);
- link_check_timer.function = enp2611_check_link_status;
- link_check_timer.expires = jiffies;
- add_timer(&link_check_timer);
-
- return 0;
-}
-
-static void __exit enp2611_cleanup_module(void)
-{
- int i;
-
- del_timer_sync(&link_check_timer);
-
- ixpdev_deinit();
- for (i = 0; i < 3; i++)
- free_netdev(nds[i]);
-}
-
-module_init(enp2611_init_module);
-module_exit(enp2611_cleanup_module);
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.c b/drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.c
deleted file mode 100644
index f5ffd7e05d26..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Generic library functions for the MSF (Media and Switch Fabric) unit
- * found on the Intel IXP2400 network processor.
- *
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <mach/hardware.h>
-#include <mach/ixp2000-regs.h>
-#include <asm/delay.h>
-#include <asm/io.h>
-#include "ixp2400-msf.h"
-
-/*
- * This is the Intel recommended PLL init procedure as described on
- * page 340 of the IXP2400/IXP2800 Programmer's Reference Manual.
- */
-static void ixp2400_pll_init(struct ixp2400_msf_parameters *mp)
-{
- int rx_dual_clock;
- int tx_dual_clock;
- u32 value;
-
- /*
- * If the RX mode is not 1x32, we have to enable both RX PLLs
- * (#0 and #1.) The same thing for the TX direction.
- */
- rx_dual_clock = !!(mp->rx_mode & IXP2400_RX_MODE_WIDTH_MASK);
- tx_dual_clock = !!(mp->tx_mode & IXP2400_TX_MODE_WIDTH_MASK);
-
- /*
- * Read initial value.
- */
- value = ixp2000_reg_read(IXP2000_MSF_CLK_CNTRL);
-
- /*
- * Put PLLs in powerdown and bypass mode.
- */
- value |= 0x0000f0f0;
- ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
-
- /*
- * Set single or dual clock mode bits.
- */
- value &= ~0x03000000;
- value |= (rx_dual_clock << 24) | (tx_dual_clock << 25);
-
- /*
- * Set multipliers.
- */
- value &= ~0x00ff0000;
- value |= mp->rxclk01_multiplier << 16;
- value |= mp->rxclk23_multiplier << 18;
- value |= mp->txclk01_multiplier << 20;
- value |= mp->txclk23_multiplier << 22;
-
- /*
- * And write value.
- */
- ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
-
- /*
- * Disable PLL bypass mode.
- */
- value &= ~(0x00005000 | rx_dual_clock << 13 | tx_dual_clock << 15);
- ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
-
- /*
- * Turn on PLLs.
- */
- value &= ~(0x00000050 | rx_dual_clock << 5 | tx_dual_clock << 7);
- ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
-
- /*
- * Wait for PLLs to lock. There are lock status bits, but IXP2400
- * erratum #65 says that these lock bits should not be relied upon
- * as they might not accurately reflect the true state of the PLLs.
- */
- udelay(100);
-}
-
-/*
- * Needed according to p480 of Programmer's Reference Manual.
- */
-static void ixp2400_msf_free_rbuf_entries(struct ixp2400_msf_parameters *mp)
-{
- int size_bits;
- int i;
-
- /*
- * Work around IXP2400 erratum #69 (silent RBUF-to-DRAM transfer
- * corruption) in the Intel-recommended way: do not add the RBUF
- * elements susceptible to corruption to the freelist.
- */
- size_bits = mp->rx_mode & IXP2400_RX_MODE_RBUF_SIZE_MASK;
- if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_64) {
- for (i = 1; i < 128; i++) {
- if (i == 9 || i == 18 || i == 27)
- continue;
- ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
- }
- } else if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_128) {
- for (i = 1; i < 64; i++) {
- if (i == 4 || i == 9 || i == 13)
- continue;
- ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
- }
- } else if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_256) {
- for (i = 1; i < 32; i++) {
- if (i == 2 || i == 4 || i == 6)
- continue;
- ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
- }
- }
-}
-
-static u32 ixp2400_msf_valid_channels(u32 reg)
-{
- u32 channels;
-
- channels = 0;
- switch (reg & IXP2400_RX_MODE_WIDTH_MASK) {
- case IXP2400_RX_MODE_1x32:
- channels = 0x1;
- if (reg & IXP2400_RX_MODE_MPHY &&
- !(reg & IXP2400_RX_MODE_MPHY_32))
- channels = 0xf;
- break;
-
- case IXP2400_RX_MODE_2x16:
- channels = 0x5;
- break;
-
- case IXP2400_RX_MODE_4x8:
- channels = 0xf;
- break;
-
- case IXP2400_RX_MODE_1x16_2x8:
- channels = 0xd;
- break;
- }
-
- return channels;
-}
-
-static void ixp2400_msf_enable_rx(struct ixp2400_msf_parameters *mp)
-{
- u32 value;
-
- value = ixp2000_reg_read(IXP2000_MSF_RX_CONTROL) & 0x0fffffff;
- value |= ixp2400_msf_valid_channels(mp->rx_mode) << 28;
- ixp2000_reg_write(IXP2000_MSF_RX_CONTROL, value);
-}
-
-static void ixp2400_msf_enable_tx(struct ixp2400_msf_parameters *mp)
-{
- u32 value;
-
- value = ixp2000_reg_read(IXP2000_MSF_TX_CONTROL) & 0x0fffffff;
- value |= ixp2400_msf_valid_channels(mp->tx_mode) << 28;
- ixp2000_reg_write(IXP2000_MSF_TX_CONTROL, value);
-}
-
-
-void ixp2400_msf_init(struct ixp2400_msf_parameters *mp)
-{
- u32 value;
- int i;
-
- /*
- * Init the RX/TX PLLs based on the passed parameter block.
- */
- ixp2400_pll_init(mp);
-
- /*
- * Reset MSF. Bit 7 in IXP_RESET_0 resets the MSF.
- */
- value = ixp2000_reg_read(IXP2000_RESET0);
- ixp2000_reg_write(IXP2000_RESET0, value | 0x80);
- ixp2000_reg_write(IXP2000_RESET0, value & ~0x80);
-
- /*
- * Initialise the RX section.
- */
- ixp2000_reg_write(IXP2000_MSF_RX_MPHY_POLL_LIMIT, mp->rx_poll_ports - 1);
- ixp2000_reg_write(IXP2000_MSF_RX_CONTROL, mp->rx_mode);
- for (i = 0; i < 4; i++) {
- ixp2000_reg_write(IXP2000_MSF_RX_UP_CONTROL_0 + i,
- mp->rx_channel_mode[i]);
- }
- ixp2400_msf_free_rbuf_entries(mp);
- ixp2400_msf_enable_rx(mp);
-
- /*
- * Initialise the TX section.
- */
- ixp2000_reg_write(IXP2000_MSF_TX_MPHY_POLL_LIMIT, mp->tx_poll_ports - 1);
- ixp2000_reg_write(IXP2000_MSF_TX_CONTROL, mp->tx_mode);
- for (i = 0; i < 4; i++) {
- ixp2000_reg_write(IXP2000_MSF_TX_UP_CONTROL_0 + i,
- mp->tx_channel_mode[i]);
- }
- ixp2400_msf_enable_tx(mp);
-}
diff --git a/drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.h b/drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.h
deleted file mode 100644
index 3ac1af2771da..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/ixp2400-msf.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Generic library functions for the MSF (Media and Switch Fabric) unit
- * found on the Intel IXP2400 network processor.
- *
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the
- * License, or (at your option) any later version.
- */
-
-#ifndef __IXP2400_MSF_H
-#define __IXP2400_MSF_H
-
-struct ixp2400_msf_parameters
-{
- u32 rx_mode;
- unsigned rxclk01_multiplier:2;
- unsigned rxclk23_multiplier:2;
- unsigned rx_poll_ports:6;
- u32 rx_channel_mode[4];
-
- u32 tx_mode;
- unsigned txclk01_multiplier:2;
- unsigned txclk23_multiplier:2;
- unsigned tx_poll_ports:6;
- u32 tx_channel_mode[4];
-};
-
-void ixp2400_msf_init(struct ixp2400_msf_parameters *mp);
-
-#define IXP2400_PLL_MULTIPLIER_48 0x00
-#define IXP2400_PLL_MULTIPLIER_24 0x01
-#define IXP2400_PLL_MULTIPLIER_16 0x02
-#define IXP2400_PLL_MULTIPLIER_12 0x03
-
-#define IXP2400_RX_MODE_CSIX 0x00400000
-#define IXP2400_RX_MODE_UTOPIA_POS 0x00000000
-#define IXP2400_RX_MODE_WIDTH_MASK 0x00300000
-#define IXP2400_RX_MODE_1x16_2x8 0x00300000
-#define IXP2400_RX_MODE_4x8 0x00200000
-#define IXP2400_RX_MODE_2x16 0x00100000
-#define IXP2400_RX_MODE_1x32 0x00000000
-#define IXP2400_RX_MODE_MPHY 0x00080000
-#define IXP2400_RX_MODE_SPHY 0x00000000
-#define IXP2400_RX_MODE_MPHY_32 0x00040000
-#define IXP2400_RX_MODE_MPHY_4 0x00000000
-#define IXP2400_RX_MODE_MPHY_POLLED_STATUS 0x00020000
-#define IXP2400_RX_MODE_MPHY_DIRECT_STATUS 0x00000000
-#define IXP2400_RX_MODE_CBUS_FULL_DUPLEX 0x00010000
-#define IXP2400_RX_MODE_CBUS_SIMPLEX 0x00000000
-#define IXP2400_RX_MODE_MPHY_LEVEL2 0x00004000
-#define IXP2400_RX_MODE_MPHY_LEVEL3 0x00000000
-#define IXP2400_RX_MODE_CBUS_8BIT 0x00002000
-#define IXP2400_RX_MODE_CBUS_4BIT 0x00000000
-#define IXP2400_RX_MODE_CSIX_SINGLE_FREELIST 0x00000200
-#define IXP2400_RX_MODE_CSIX_SPLIT_FREELISTS 0x00000000
-#define IXP2400_RX_MODE_RBUF_SIZE_MASK 0x0000000c
-#define IXP2400_RX_MODE_RBUF_SIZE_256 0x00000008
-#define IXP2400_RX_MODE_RBUF_SIZE_128 0x00000004
-#define IXP2400_RX_MODE_RBUF_SIZE_64 0x00000000
-
-#define IXP2400_PORT_RX_MODE_SLAVE 0x00000040
-#define IXP2400_PORT_RX_MODE_MASTER 0x00000000
-#define IXP2400_PORT_RX_MODE_POS_PHY_L3 0x00000020
-#define IXP2400_PORT_RX_MODE_POS_PHY_L2 0x00000000
-#define IXP2400_PORT_RX_MODE_POS_PHY 0x00000010
-#define IXP2400_PORT_RX_MODE_UTOPIA 0x00000000
-#define IXP2400_PORT_RX_MODE_EVEN_PARITY 0x0000000c
-#define IXP2400_PORT_RX_MODE_ODD_PARITY 0x00000008
-#define IXP2400_PORT_RX_MODE_NO_PARITY 0x00000000
-#define IXP2400_PORT_RX_MODE_UTOPIA_BIG_CELLS 0x00000002
-#define IXP2400_PORT_RX_MODE_UTOPIA_NORMAL_CELLS 0x00000000
-#define IXP2400_PORT_RX_MODE_2_CYCLE_DECODE 0x00000001
-#define IXP2400_PORT_RX_MODE_1_CYCLE_DECODE 0x00000000
-
-#define IXP2400_TX_MODE_CSIX 0x00400000
-#define IXP2400_TX_MODE_UTOPIA_POS 0x00000000
-#define IXP2400_TX_MODE_WIDTH_MASK 0x00300000
-#define IXP2400_TX_MODE_1x16_2x8 0x00300000
-#define IXP2400_TX_MODE_4x8 0x00200000
-#define IXP2400_TX_MODE_2x16 0x00100000
-#define IXP2400_TX_MODE_1x32 0x00000000
-#define IXP2400_TX_MODE_MPHY 0x00080000
-#define IXP2400_TX_MODE_SPHY 0x00000000
-#define IXP2400_TX_MODE_MPHY_32 0x00040000
-#define IXP2400_TX_MODE_MPHY_4 0x00000000
-#define IXP2400_TX_MODE_MPHY_POLLED_STATUS 0x00020000
-#define IXP2400_TX_MODE_MPHY_DIRECT_STATUS 0x00000000
-#define IXP2400_TX_MODE_CBUS_FULL_DUPLEX 0x00010000
-#define IXP2400_TX_MODE_CBUS_SIMPLEX 0x00000000
-#define IXP2400_TX_MODE_MPHY_LEVEL2 0x00004000
-#define IXP2400_TX_MODE_MPHY_LEVEL3 0x00000000
-#define IXP2400_TX_MODE_CBUS_8BIT 0x00002000
-#define IXP2400_TX_MODE_CBUS_4BIT 0x00000000
-#define IXP2400_TX_MODE_TBUF_SIZE_MASK 0x0000000c
-#define IXP2400_TX_MODE_TBUF_SIZE_256 0x00000008
-#define IXP2400_TX_MODE_TBUF_SIZE_128 0x00000004
-#define IXP2400_TX_MODE_TBUF_SIZE_64 0x00000000
-
-#define IXP2400_PORT_TX_MODE_SLAVE 0x00000040
-#define IXP2400_PORT_TX_MODE_MASTER 0x00000000
-#define IXP2400_PORT_TX_MODE_POS_PHY 0x00000010
-#define IXP2400_PORT_TX_MODE_UTOPIA 0x00000000
-#define IXP2400_PORT_TX_MODE_EVEN_PARITY 0x0000000c
-#define IXP2400_PORT_TX_MODE_ODD_PARITY 0x00000008
-#define IXP2400_PORT_TX_MODE_NO_PARITY 0x00000000
-#define IXP2400_PORT_TX_MODE_UTOPIA_BIG_CELLS 0x00000002
-#define IXP2400_PORT_TX_MODE_2_CYCLE_DECODE 0x00000001
-#define IXP2400_PORT_TX_MODE_1_CYCLE_DECODE 0x00000000
-
-
-#endif
diff --git a/drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.uc b/drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.uc
deleted file mode 100644
index 42a73e357afa..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.uc
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * RX ucode for the Intel IXP2400 in POS-PHY mode.
- * Copyright (C) 2004, 2005 Lennert Buytenhek
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Assumptions made in this code:
- * - The IXP2400 MSF is configured for POS-PHY mode, in a mode where
- * only one full element list is used. This includes, for example,
- * 1x32 SPHY and 1x32 MPHY32, but not 4x8 SPHY or 1x32 MPHY4. (This
- * is not an exhaustive list.)
- * - The RBUF uses 64-byte mpackets.
- * - RX descriptors reside in SRAM, and have the following format:
- * struct rx_desc
- * {
- * // to uengine
- * u32 buf_phys_addr;
- * u32 buf_length;
- *
- * // from uengine
- * u32 channel;
- * u32 pkt_length;
- * };
- * - Packet data resides in DRAM.
- * - Packet buffer addresses are 8-byte aligned.
- * - Scratch ring 0 is rx_pending.
- * - Scratch ring 1 is rx_done, and has status condition 'full'.
- * - The host triggers rx_done flush and rx_pending refill on seeing INTA.
- * - This code is run on all eight threads of the microengine it runs on.
- *
- * Local memory is used for per-channel RX state.
- */
-
-#define RX_THREAD_FREELIST_0 0x0030
-#define RBUF_ELEMENT_DONE 0x0044
-
-#define CHANNEL_FLAGS *l$index0[0]
-#define CHANNEL_FLAG_RECEIVING 1
-#define PACKET_LENGTH *l$index0[1]
-#define PACKET_CHECKSUM *l$index0[2]
-#define BUFFER_HANDLE *l$index0[3]
-#define BUFFER_START *l$index0[4]
-#define BUFFER_LENGTH *l$index0[5]
-
-#define CHANNEL_STATE_SIZE 24 // in bytes
-#define CHANNEL_STATE_SHIFT 5 // ceil(log2(state size))
-
-
- .sig volatile sig1
- .sig volatile sig2
- .sig volatile sig3
-
- .sig mpacket_arrived
- .reg add_to_rx_freelist
- .reg read $rsw0, $rsw1
- .xfer_order $rsw0 $rsw1
-
- .reg zero
-
- /*
- * Initialise add_to_rx_freelist.
- */
- .begin
- .reg temp
- .reg temp2
-
- immed[add_to_rx_freelist, RX_THREAD_FREELIST_0]
- immed_w1[add_to_rx_freelist, (&$rsw0 | (&mpacket_arrived << 12))]
-
- local_csr_rd[ACTIVE_CTX_STS]
- immed[temp, 0]
- alu[temp2, temp, and, 0x1f]
- alu_shf[add_to_rx_freelist, add_to_rx_freelist, or, temp2, <<20]
- alu[temp2, temp, and, 0x80]
- alu_shf[add_to_rx_freelist, add_to_rx_freelist, or, temp2, <<18]
- .end
-
- immed[zero, 0]
-
- /*
- * Skip context 0 initialisation?
- */
- .begin
- br!=ctx[0, mpacket_receive_loop#]
- .end
-
- /*
- * Initialise local memory.
- */
- .begin
- .reg addr
- .reg temp
-
- immed[temp, 0]
- init_local_mem_loop#:
- alu_shf[addr, --, b, temp, <<CHANNEL_STATE_SHIFT]
- local_csr_wr[ACTIVE_LM_ADDR_0, addr]
- nop
- nop
- nop
-
- immed[CHANNEL_FLAGS, 0]
-
- alu[temp, temp, +, 1]
- alu[--, temp, and, 0x20]
- beq[init_local_mem_loop#]
- .end
-
- /*
- * Initialise signal pipeline.
- */
- .begin
- local_csr_wr[SAME_ME_SIGNAL, (&sig1 << 3)]
- .set_sig sig1
-
- local_csr_wr[SAME_ME_SIGNAL, (&sig2 << 3)]
- .set_sig sig2
-
- local_csr_wr[SAME_ME_SIGNAL, (&sig3 << 3)]
- .set_sig sig3
- .end
-
-mpacket_receive_loop#:
- /*
- * Synchronise and wait for mpacket.
- */
- .begin
- ctx_arb[sig1]
- local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig1 << 3))]
-
- msf[fast_wr, --, add_to_rx_freelist, 0]
- .set_sig mpacket_arrived
- ctx_arb[mpacket_arrived]
- .set $rsw0 $rsw1
- .end
-
- /*
- * We halt if we see {inbparerr,parerr,null,soperror}.
- */
- .begin
- alu_shf[--, 0x1b, and, $rsw0, >>8]
- bne[abort_rswerr#]
- .end
-
- /*
- * Point local memory pointer to this channel's state area.
- */
- .begin
- .reg chanaddr
-
- alu[chanaddr, $rsw0, and, 0x1f]
- alu_shf[chanaddr, --, b, chanaddr, <<CHANNEL_STATE_SHIFT]
- local_csr_wr[ACTIVE_LM_ADDR_0, chanaddr]
- nop
- nop
- nop
- .end
-
- /*
- * Check whether we received a SOP mpacket while we were already
- * working on a packet, or a non-SOP mpacket while there was no
- * packet pending. (SOP == RECEIVING -> abort) If everything's
- * okay, update the RECEIVING flag to reflect our new state.
- */
- .begin
- .reg temp
- .reg eop
-
- #if CHANNEL_FLAG_RECEIVING != 1
- #error CHANNEL_FLAG_RECEIVING is not 1
- #endif
-
- alu_shf[temp, 1, and, $rsw0, >>15]
- alu[temp, temp, xor, CHANNEL_FLAGS]
- alu[--, temp, and, CHANNEL_FLAG_RECEIVING]
- beq[abort_proterr#]
-
- alu_shf[eop, 1, and, $rsw0, >>14]
- alu[CHANNEL_FLAGS, temp, xor, eop]
- .end
-
- /*
- * Copy the mpacket into the right spot, and in case of EOP,
- * write back the descriptor and pass the packet on.
- */
- .begin
- .reg buffer_offset
- .reg _packet_length
- .reg _packet_checksum
- .reg _buffer_handle
- .reg _buffer_start
- .reg _buffer_length
-
- /*
- * Determine buffer_offset, _packet_length and
- * _packet_checksum.
- */
- .begin
- .reg temp
-
- alu[--, 1, and, $rsw0, >>15]
- beq[not_sop#]
-
- immed[PACKET_LENGTH, 0]
- immed[PACKET_CHECKSUM, 0]
-
- not_sop#:
- alu[buffer_offset, --, b, PACKET_LENGTH]
- alu_shf[temp, 0xff, and, $rsw0, >>16]
- alu[_packet_length, buffer_offset, +, temp]
- alu[PACKET_LENGTH, --, b, _packet_length]
-
- immed[temp, 0xffff]
- alu[temp, $rsw1, and, temp]
- alu[_packet_checksum, PACKET_CHECKSUM, +, temp]
- alu[PACKET_CHECKSUM, --, b, _packet_checksum]
- .end
-
- /*
- * Allocate buffer in case of SOP.
- */
- .begin
- .reg temp
-
- alu[temp, 1, and, $rsw0, >>15]
- beq[skip_buffer_alloc#]
-
- .begin
- .sig zzz
- .reg read $stemp $stemp2
- .xfer_order $stemp $stemp2
-
- rx_nobufs#:
- scratch[get, $stemp, zero, 0, 1], ctx_swap[zzz]
- alu[_buffer_handle, --, b, $stemp]
- beq[rx_nobufs#]
-
- sram[read, $stemp, _buffer_handle, 0, 2],
- ctx_swap[zzz]
- alu[_buffer_start, --, b, $stemp]
- alu[_buffer_length, --, b, $stemp2]
- .end
-
- skip_buffer_alloc#:
- .end
-
- /*
- * Resynchronise.
- */
- .begin
- ctx_arb[sig2]
- local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig2 << 3))]
- .end
-
- /*
- * Synchronise buffer state.
- */
- .begin
- .reg temp
-
- alu[temp, 1, and, $rsw0, >>15]
- beq[copy_from_local_mem#]
-
- alu[BUFFER_HANDLE, --, b, _buffer_handle]
- alu[BUFFER_START, --, b, _buffer_start]
- alu[BUFFER_LENGTH, --, b, _buffer_length]
- br[sync_state_done#]
-
- copy_from_local_mem#:
- alu[_buffer_handle, --, b, BUFFER_HANDLE]
- alu[_buffer_start, --, b, BUFFER_START]
- alu[_buffer_length, --, b, BUFFER_LENGTH]
-
- sync_state_done#:
- .end
-
-#if 0
- /*
- * Debug buffer state management.
- */
- .begin
- .reg temp
-
- alu[temp, 1, and, $rsw0, >>14]
- beq[no_poison#]
- immed[BUFFER_HANDLE, 0xdead]
- immed[BUFFER_START, 0xdead]
- immed[BUFFER_LENGTH, 0xdead]
- no_poison#:
-
- immed[temp, 0xdead]
- alu[--, _buffer_handle, -, temp]
- beq[state_corrupted#]
- alu[--, _buffer_start, -, temp]
- beq[state_corrupted#]
- alu[--, _buffer_length, -, temp]
- beq[state_corrupted#]
- .end
-#endif
-
- /*
- * Check buffer length.
- */
- .begin
- alu[--, _buffer_length, -, _packet_length]
- blo[buffer_overflow#]
- .end
-
- /*
- * Copy the mpacket and give back the RBUF element.
- */
- .begin
- .reg element
- .reg xfer_size
- .reg temp
- .sig copy_sig
-
- alu_shf[element, 0x7f, and, $rsw0, >>24]
- alu_shf[xfer_size, 0xff, and, $rsw0, >>16]
-
- alu[xfer_size, xfer_size, -, 1]
- alu_shf[xfer_size, 0x10, or, xfer_size, >>3]
- alu_shf[temp, 0x10, or, xfer_size, <<21]
- alu_shf[temp, temp, or, element, <<11]
- alu_shf[--, temp, or, 1, <<18]
-
- dram[rbuf_rd, --, _buffer_start, buffer_offset, max_8],
- indirect_ref, sig_done[copy_sig]
- ctx_arb[copy_sig]
-
- alu[temp, RBUF_ELEMENT_DONE, or, element, <<16]
- msf[fast_wr, --, temp, 0]
- .end
-
- /*
- * If EOP, write back the packet descriptor.
- */
- .begin
- .reg write $stemp $stemp2
- .xfer_order $stemp $stemp2
- .sig zzz
-
- alu_shf[--, 1, and, $rsw0, >>14]
- beq[no_writeback#]
-
- alu[$stemp, $rsw0, and, 0x1f]
- alu[$stemp2, --, b, _packet_length]
- sram[write, $stemp, _buffer_handle, 8, 2], ctx_swap[zzz]
-
- no_writeback#:
- .end
-
- /*
- * Resynchronise.
- */
- .begin
- ctx_arb[sig3]
- local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig3 << 3))]
- .end
-
- /*
- * If EOP, put the buffer back onto the scratch ring.
- */
- .begin
- .reg write $stemp
- .sig zzz
-
- br_inp_state[SCR_Ring1_Status, rx_done_ring_overflow#]
-
- alu_shf[--, 1, and, $rsw0, >>14]
- beq[mpacket_receive_loop#]
-
- alu[--, 1, and, $rsw0, >>10]
- bne[rxerr#]
-
- alu[$stemp, --, b, _buffer_handle]
- scratch[put, $stemp, zero, 4, 1], ctx_swap[zzz]
- cap[fast_wr, 0, XSCALE_INT_A]
- br[mpacket_receive_loop#]
-
- rxerr#:
- alu[$stemp, --, b, _buffer_handle]
- scratch[put, $stemp, zero, 0, 1], ctx_swap[zzz]
- br[mpacket_receive_loop#]
- .end
- .end
-
-
-abort_rswerr#:
- halt
-
-abort_proterr#:
- halt
-
-state_corrupted#:
- halt
-
-buffer_overflow#:
- halt
-
-rx_done_ring_overflow#:
- halt
-
-
diff --git a/drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.ucode b/drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.ucode
deleted file mode 100644
index e8aee2f81aad..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/ixp2400_rx.ucode
+++ /dev/null
@@ -1,130 +0,0 @@
-static struct ixp2000_uengine_code ixp2400_rx =
-{
- .cpu_model_bitmask = 0x000003fe,
- .cpu_min_revision = 0,
- .cpu_max_revision = 255,
-
- .uengine_parameters = IXP2000_UENGINE_8_CONTEXTS |
- IXP2000_UENGINE_PRN_UPDATE_EVERY |
- IXP2000_UENGINE_NN_FROM_PREVIOUS |
- IXP2000_UENGINE_ASSERT_EMPTY_AT_0 |
- IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT |
- IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT,
-
- .initial_reg_values = (struct ixp2000_reg_value []) {
- { -1, -1 }
- },
-
- .num_insns = 109,
- .insns = (u8 []) {
- 0xf0, 0x00, 0x0c, 0xc0, 0x05,
- 0xf4, 0x44, 0x0c, 0x00, 0x05,
- 0xfc, 0x04, 0x4c, 0x00, 0x00,
- 0xf0, 0x00, 0x00, 0x3b, 0x00,
- 0xb4, 0x40, 0xf0, 0x3b, 0x1f,
- 0x8a, 0xc0, 0x50, 0x3e, 0x05,
- 0xb4, 0x40, 0xf0, 0x3b, 0x80,
- 0x9a, 0xe0, 0x00, 0x3e, 0x05,
- 0xf0, 0x00, 0x00, 0x07, 0x00,
- 0xd8, 0x05, 0xc0, 0x00, 0x11,
- 0xf0, 0x00, 0x00, 0x0f, 0x00,
- 0x91, 0xb0, 0x20, 0x0e, 0x00,
- 0xfc, 0x06, 0x60, 0x0b, 0x00,
- 0xf0, 0x00, 0x0c, 0x03, 0x00,
- 0xf0, 0x00, 0x0c, 0x03, 0x00,
- 0xf0, 0x00, 0x0c, 0x03, 0x00,
- 0xf0, 0x00, 0x0c, 0x02, 0x00,
- 0xb0, 0xc0, 0x30, 0x0f, 0x01,
- 0xa4, 0x70, 0x00, 0x0f, 0x20,
- 0xd8, 0x02, 0xc0, 0x01, 0x00,
- 0xfc, 0x10, 0xac, 0x23, 0x08,
- 0xfc, 0x10, 0xac, 0x43, 0x10,
- 0xfc, 0x10, 0xac, 0x63, 0x18,
- 0xe0, 0x00, 0x00, 0x00, 0x02,
- 0xfc, 0x10, 0xae, 0x23, 0x88,
- 0x3d, 0x00, 0x04, 0x03, 0x20,
- 0xe0, 0x00, 0x00, 0x00, 0x10,
- 0x84, 0x82, 0x02, 0x01, 0x3b,
- 0xd8, 0x1a, 0x00, 0x01, 0x01,
- 0xb4, 0x00, 0x8c, 0x7d, 0x80,
- 0x91, 0xb0, 0x80, 0x22, 0x00,
- 0xfc, 0x06, 0x60, 0x23, 0x00,
- 0xf0, 0x00, 0x0c, 0x03, 0x00,
- 0xf0, 0x00, 0x0c, 0x03, 0x00,
- 0xf0, 0x00, 0x0c, 0x03, 0x00,
- 0x94, 0xf0, 0x92, 0x01, 0x21,
- 0xac, 0x40, 0x60, 0x26, 0x00,
- 0xa4, 0x30, 0x0c, 0x04, 0x06,
- 0xd8, 0x1a, 0x40, 0x01, 0x00,
- 0x94, 0xe0, 0xa2, 0x01, 0x21,
- 0xac, 0x20, 0x00, 0x28, 0x06,
- 0x84, 0xf2, 0x02, 0x01, 0x21,
- 0xd8, 0x0b, 0x40, 0x01, 0x00,
- 0xf0, 0x00, 0x0c, 0x02, 0x01,
- 0xf0, 0x00, 0x0c, 0x02, 0x02,
- 0xa0, 0x00, 0x08, 0x04, 0x00,
- 0x95, 0x00, 0xc6, 0x01, 0xff,
- 0xa0, 0x80, 0x10, 0x30, 0x00,
- 0xa0, 0x60, 0x1c, 0x00, 0x01,
- 0xf0, 0x0f, 0xf0, 0x33, 0xff,
- 0xb4, 0x00, 0xc0, 0x31, 0x81,
- 0xb0, 0x80, 0xb0, 0x32, 0x02,
- 0xa0, 0x20, 0x20, 0x2c, 0x00,
- 0x94, 0xf0, 0xd2, 0x01, 0x21,
- 0xd8, 0x0f, 0x40, 0x01, 0x00,
- 0x19, 0x40, 0x10, 0x04, 0x20,
- 0xa0, 0x00, 0x26, 0x04, 0x00,
- 0xd8, 0x0d, 0xc0, 0x01, 0x00,
- 0x00, 0x42, 0x10, 0x80, 0x02,
- 0xb0, 0x00, 0x46, 0x04, 0x00,
- 0xb0, 0x00, 0x56, 0x08, 0x00,
- 0xe0, 0x00, 0x00, 0x00, 0x04,
- 0xfc, 0x10, 0xae, 0x43, 0x90,
- 0x84, 0xf0, 0x32, 0x01, 0x21,
- 0xd8, 0x11, 0x40, 0x01, 0x00,
- 0xa0, 0x60, 0x3c, 0x00, 0x02,
- 0xa0, 0x20, 0x40, 0x10, 0x00,
- 0xa0, 0x20, 0x50, 0x14, 0x00,
- 0xd8, 0x12, 0x00, 0x00, 0x18,
- 0xa0, 0x00, 0x28, 0x0c, 0x00,
- 0xb0, 0x00, 0x48, 0x10, 0x00,
- 0xb0, 0x00, 0x58, 0x14, 0x00,
- 0xaa, 0xf0, 0x00, 0x14, 0x01,
- 0xd8, 0x1a, 0xc0, 0x01, 0x05,
- 0x85, 0x80, 0x42, 0x01, 0xff,
- 0x95, 0x00, 0x66, 0x01, 0xff,
- 0xba, 0xc0, 0x60, 0x1b, 0x01,
- 0x9a, 0x30, 0x60, 0x19, 0x30,
- 0x9a, 0xb0, 0x70, 0x1a, 0x30,
- 0x9b, 0x50, 0x78, 0x1e, 0x04,
- 0x8a, 0xe2, 0x08, 0x1e, 0x21,
- 0x6a, 0x4e, 0x00, 0x13, 0x00,
- 0xe0, 0x00, 0x00, 0x00, 0x30,
- 0x9b, 0x00, 0x7a, 0x92, 0x04,
- 0x3d, 0x00, 0x04, 0x1f, 0x20,
- 0x84, 0xe2, 0x02, 0x01, 0x21,
- 0xd8, 0x16, 0x80, 0x01, 0x00,
- 0xa4, 0x18, 0x0c, 0x7d, 0x80,
- 0xa0, 0x58, 0x1c, 0x00, 0x01,
- 0x01, 0x42, 0x00, 0xa0, 0x02,
- 0xe0, 0x00, 0x00, 0x00, 0x08,
- 0xfc, 0x10, 0xae, 0x63, 0x98,
- 0xd8, 0x1b, 0x00, 0xc2, 0x14,
- 0x84, 0xe2, 0x02, 0x01, 0x21,
- 0xd8, 0x05, 0xc0, 0x01, 0x00,
- 0x84, 0xa2, 0x02, 0x01, 0x21,
- 0xd8, 0x19, 0x40, 0x01, 0x01,
- 0xa0, 0x58, 0x0c, 0x00, 0x02,
- 0x1a, 0x40, 0x00, 0x04, 0x24,
- 0x33, 0x00, 0x01, 0x2f, 0x20,
- 0xd8, 0x05, 0xc0, 0x00, 0x18,
- 0xa0, 0x58, 0x0c, 0x00, 0x02,
- 0x1a, 0x40, 0x00, 0x04, 0x20,
- 0xd8, 0x05, 0xc0, 0x00, 0x18,
- 0xe0, 0x00, 0x02, 0x00, 0x00,
- 0xe0, 0x00, 0x02, 0x00, 0x00,
- 0xe0, 0x00, 0x02, 0x00, 0x00,
- 0xe0, 0x00, 0x02, 0x00, 0x00,
- 0xe0, 0x00, 0x02, 0x00, 0x00,
- }
-};
diff --git a/drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.uc b/drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.uc
deleted file mode 100644
index d090d1884fb7..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.uc
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * TX ucode for the Intel IXP2400 in POS-PHY mode.
- * Copyright (C) 2004, 2005 Lennert Buytenhek
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Assumptions made in this code:
- * - The IXP2400 MSF is configured for POS-PHY mode, in a mode where
- * only one TBUF partition is used. This includes, for example,
- * 1x32 SPHY and 1x32 MPHY32, but not 4x8 SPHY or 1x32 MPHY4. (This
- * is not an exhaustive list.)
- * - The TBUF uses 64-byte mpackets.
- * - TX descriptors reside in SRAM, and have the following format:
- * struct tx_desc
- * {
- * // to uengine
- * u32 buf_phys_addr;
- * u32 pkt_length;
- * u32 channel;
- * };
- * - Packet data resides in DRAM.
- * - Packet buffer addresses are 8-byte aligned.
- * - Scratch ring 2 is tx_pending.
- * - Scratch ring 3 is tx_done, and has status condition 'full'.
- * - This code is run on all eight threads of the microengine it runs on.
- */
-
-#define TX_SEQUENCE_0 0x0060
-#define TBUF_CTRL 0x1800
-
-#define PARTITION_SIZE 128
-#define PARTITION_THRESH 96
-
-
- .sig volatile sig1
- .sig volatile sig2
- .sig volatile sig3
-
- .reg @old_tx_seq_0
- .reg @mpkts_in_flight
- .reg @next_tbuf_mpacket
-
- .reg @buffer_handle
- .reg @buffer_start
- .reg @packet_length
- .reg @channel
- .reg @packet_offset
-
- .reg zero
-
- immed[zero, 0]
-
- /*
- * Skip context 0 initialisation?
- */
- .begin
- br!=ctx[0, mpacket_tx_loop#]
- .end
-
- /*
- * Wait until all pending TBUF elements have been transmitted.
- */
- .begin
- .reg read $tx
- .sig zzz
-
- loop_empty#:
- msf[read, $tx, zero, TX_SEQUENCE_0, 1], ctx_swap[zzz]
- alu_shf[--, --, b, $tx, >>31]
- beq[loop_empty#]
-
- alu[@old_tx_seq_0, --, b, $tx]
- .end
-
- immed[@mpkts_in_flight, 0]
- alu[@next_tbuf_mpacket, @old_tx_seq_0, and, (PARTITION_SIZE - 1)]
-
- immed[@buffer_handle, 0]
-
- /*
- * Initialise signal pipeline.
- */
- .begin
- local_csr_wr[SAME_ME_SIGNAL, (&sig1 << 3)]
- .set_sig sig1
-
- local_csr_wr[SAME_ME_SIGNAL, (&sig2 << 3)]
- .set_sig sig2
-
- local_csr_wr[SAME_ME_SIGNAL, (&sig3 << 3)]
- .set_sig sig3
- .end
-
-mpacket_tx_loop#:
- .begin
- .reg tbuf_element_index
- .reg buffer_handle
- .reg sop_eop
- .reg packet_data
- .reg channel
- .reg mpacket_size
-
- /*
- * If there is no packet currently being transmitted,
- * dequeue the next TX descriptor, and fetch the buffer
- * address, packet length and destination channel number.
- */
- .begin
- .reg read $stemp $stemp2 $stemp3
- .xfer_order $stemp $stemp2 $stemp3
- .sig zzz
-
- ctx_arb[sig1]
-
- alu[--, --, b, @buffer_handle]
- bne[already_got_packet#]
-
- tx_nobufs#:
- scratch[get, $stemp, zero, 8, 1], ctx_swap[zzz]
- alu[@buffer_handle, --, b, $stemp]
- beq[tx_nobufs#]
-
- sram[read, $stemp, $stemp, 0, 3], ctx_swap[zzz]
- alu[@buffer_start, --, b, $stemp]
- alu[@packet_length, --, b, $stemp2]
- beq[zero_byte_packet#]
- alu[@channel, --, b, $stemp3]
- immed[@packet_offset, 0]
-
- already_got_packet#:
- local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig1 << 3))]
- .end
-
- /*
- * Determine tbuf element index, SOP/EOP flags, mpacket
- * offset and mpacket size and cache buffer_handle and
- * channel number.
- */
- .begin
- alu[tbuf_element_index, --, b, @next_tbuf_mpacket]
- alu[@next_tbuf_mpacket, @next_tbuf_mpacket, +, 1]
- alu[@next_tbuf_mpacket, @next_tbuf_mpacket, and,
- (PARTITION_SIZE - 1)]
-
- alu[buffer_handle, --, b, @buffer_handle]
- immed[@buffer_handle, 0]
-
- immed[sop_eop, 1]
-
- alu[packet_data, --, b, @packet_offset]
- bne[no_sop#]
- alu[sop_eop, sop_eop, or, 2]
- no_sop#:
- alu[packet_data, packet_data, +, @buffer_start]
-
- alu[channel, --, b, @channel]
-
- alu[mpacket_size, @packet_length, -, @packet_offset]
- alu[--, 64, -, mpacket_size]
- bhs[eop#]
- alu[@buffer_handle, --, b, buffer_handle]
- immed[mpacket_size, 64]
- alu[sop_eop, sop_eop, and, 2]
- eop#:
-
- alu[@packet_offset, @packet_offset, +, mpacket_size]
- .end
-
- /*
- * Wait until there's enough space in the TBUF.
- */
- .begin
- .reg read $tx
- .reg temp
- .sig zzz
-
- ctx_arb[sig2]
-
- br[test_space#]
-
- loop_space#:
- msf[read, $tx, zero, TX_SEQUENCE_0, 1], ctx_swap[zzz]
-
- alu[temp, $tx, -, @old_tx_seq_0]
- alu[temp, temp, and, 0xff]
- alu[@mpkts_in_flight, @mpkts_in_flight, -, temp]
-
- alu[@old_tx_seq_0, --, b, $tx]
-
- test_space#:
- alu[--, PARTITION_THRESH, -, @mpkts_in_flight]
- blo[loop_space#]
-
- alu[@mpkts_in_flight, @mpkts_in_flight, +, 1]
-
- local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig2 << 3))]
- .end
-
- /*
- * Copy the packet data to the TBUF.
- */
- .begin
- .reg temp
- .sig copy_sig
-
- alu[temp, mpacket_size, -, 1]
- alu_shf[temp, 0x10, or, temp, >>3]
- alu_shf[temp, 0x10, or, temp, <<21]
- alu_shf[temp, temp, or, tbuf_element_index, <<11]
- alu_shf[--, temp, or, 1, <<18]
-
- dram[tbuf_wr, --, packet_data, 0, max_8],
- indirect_ref, sig_done[copy_sig]
- ctx_arb[copy_sig]
- .end
-
- /*
- * Mark TBUF element as ready-to-be-transmitted.
- */
- .begin
- .reg write $tsw $tsw2
- .xfer_order $tsw $tsw2
- .reg temp
- .sig zzz
-
- alu_shf[temp, channel, or, mpacket_size, <<24]
- alu_shf[$tsw, temp, or, sop_eop, <<8]
- immed[$tsw2, 0]
-
- immed[temp, TBUF_CTRL]
- alu_shf[temp, temp, or, tbuf_element_index, <<3]
- msf[write, $tsw, temp, 0, 2], ctx_swap[zzz]
- .end
-
- /*
- * Resynchronise.
- */
- .begin
- ctx_arb[sig3]
- local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig3 << 3))]
- .end
-
- /*
- * If this was an EOP mpacket, recycle the TX buffer
- * and signal the host.
- */
- .begin
- .reg write $stemp
- .sig zzz
-
- alu[--, sop_eop, and, 1]
- beq[mpacket_tx_loop#]
-
- tx_done_ring_full#:
- br_inp_state[SCR_Ring3_Status, tx_done_ring_full#]
-
- alu[$stemp, --, b, buffer_handle]
- scratch[put, $stemp, zero, 12, 1], ctx_swap[zzz]
- cap[fast_wr, 0, XSCALE_INT_A]
- br[mpacket_tx_loop#]
- .end
- .end
-
-
-zero_byte_packet#:
- halt
-
-
diff --git a/drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.ucode b/drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.ucode
deleted file mode 100644
index a433e24b0a51..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/ixp2400_tx.ucode
+++ /dev/null
@@ -1,98 +0,0 @@
-static struct ixp2000_uengine_code ixp2400_tx =
-{
- .cpu_model_bitmask = 0x000003fe,
- .cpu_min_revision = 0,
- .cpu_max_revision = 255,
-
- .uengine_parameters = IXP2000_UENGINE_8_CONTEXTS |
- IXP2000_UENGINE_PRN_UPDATE_EVERY |
- IXP2000_UENGINE_NN_FROM_PREVIOUS |
- IXP2000_UENGINE_ASSERT_EMPTY_AT_0 |
- IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT |
- IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT,
-
- .initial_reg_values = (struct ixp2000_reg_value []) {
- { -1, -1 }
- },
-
- .num_insns = 77,
- .insns = (u8 []) {
- 0xf0, 0x00, 0x00, 0x07, 0x00,
- 0xd8, 0x03, 0x00, 0x00, 0x11,
- 0x3c, 0x40, 0x00, 0x04, 0xe0,
- 0x81, 0xf2, 0x02, 0x01, 0x00,
- 0xd8, 0x00, 0x80, 0x01, 0x00,
- 0xb0, 0x08, 0x06, 0x00, 0x00,
- 0xf0, 0x00, 0x0c, 0x00, 0x80,
- 0xb4, 0x49, 0x02, 0x03, 0x7f,
- 0xf0, 0x00, 0x02, 0x83, 0x00,
- 0xfc, 0x10, 0xac, 0x23, 0x08,
- 0xfc, 0x10, 0xac, 0x43, 0x10,
- 0xfc, 0x10, 0xac, 0x63, 0x18,
- 0xe0, 0x00, 0x00, 0x00, 0x02,
- 0xa0, 0x30, 0x02, 0x80, 0x00,
- 0xd8, 0x06, 0x00, 0x01, 0x01,
- 0x19, 0x40, 0x00, 0x04, 0x28,
- 0xb0, 0x0a, 0x06, 0x00, 0x00,
- 0xd8, 0x03, 0xc0, 0x01, 0x00,
- 0x00, 0x44, 0x00, 0x80, 0x80,
- 0xa0, 0x09, 0x06, 0x00, 0x00,
- 0xb0, 0x0b, 0x06, 0x04, 0x00,
- 0xd8, 0x13, 0x00, 0x01, 0x00,
- 0xb0, 0x0c, 0x06, 0x08, 0x00,
- 0xf0, 0x00, 0x0c, 0x00, 0xa0,
- 0xfc, 0x10, 0xae, 0x23, 0x88,
- 0xa0, 0x00, 0x12, 0x40, 0x00,
- 0xb0, 0xc9, 0x02, 0x43, 0x01,
- 0xb4, 0x49, 0x02, 0x43, 0x7f,
- 0xb0, 0x00, 0x22, 0x80, 0x00,
- 0xf0, 0x00, 0x02, 0x83, 0x00,
- 0xf0, 0x00, 0x0c, 0x04, 0x02,
- 0xb0, 0x40, 0x6c, 0x00, 0xa0,
- 0xd8, 0x08, 0x80, 0x01, 0x01,
- 0xaa, 0x00, 0x2c, 0x08, 0x02,
- 0xa0, 0xc0, 0x30, 0x18, 0x90,
- 0xa0, 0x00, 0x43, 0x00, 0x00,
- 0xba, 0xc0, 0x32, 0xc0, 0xa0,
- 0xaa, 0xb0, 0x00, 0x0f, 0x40,
- 0xd8, 0x0a, 0x80, 0x01, 0x04,
- 0xb0, 0x0a, 0x00, 0x08, 0x00,
- 0xf0, 0x00, 0x00, 0x0f, 0x40,
- 0xa4, 0x00, 0x2c, 0x08, 0x02,
- 0xa0, 0x8a, 0x00, 0x0c, 0xa0,
- 0xe0, 0x00, 0x00, 0x00, 0x04,
- 0xd8, 0x0c, 0x80, 0x00, 0x18,
- 0x3c, 0x40, 0x00, 0x04, 0xe0,
- 0xba, 0x80, 0x42, 0x01, 0x80,
- 0xb4, 0x40, 0x40, 0x13, 0xff,
- 0xaa, 0x88, 0x00, 0x10, 0x80,
- 0xb0, 0x08, 0x06, 0x00, 0x00,
- 0xaa, 0xf0, 0x0d, 0x80, 0x80,
- 0xd8, 0x0b, 0x40, 0x01, 0x05,
- 0xa0, 0x88, 0x0c, 0x04, 0x80,
- 0xfc, 0x10, 0xae, 0x43, 0x90,
- 0xba, 0xc0, 0x50, 0x0f, 0x01,
- 0x9a, 0x30, 0x50, 0x15, 0x30,
- 0x9a, 0xb0, 0x50, 0x16, 0x30,
- 0x9b, 0x50, 0x58, 0x16, 0x01,
- 0x8a, 0xe2, 0x08, 0x16, 0x21,
- 0x6b, 0x4e, 0x00, 0x83, 0x03,
- 0xe0, 0x00, 0x00, 0x00, 0x30,
- 0x9a, 0x80, 0x70, 0x0e, 0x04,
- 0x8b, 0x88, 0x08, 0x1e, 0x02,
- 0xf0, 0x00, 0x0c, 0x01, 0x81,
- 0xf0, 0x01, 0x80, 0x1f, 0x00,
- 0x9b, 0xd0, 0x78, 0x1e, 0x01,
- 0x3d, 0x42, 0x00, 0x1c, 0x20,
- 0xe0, 0x00, 0x00, 0x00, 0x08,
- 0xfc, 0x10, 0xae, 0x63, 0x98,
- 0xa4, 0x30, 0x0c, 0x04, 0x02,
- 0xd8, 0x03, 0x00, 0x01, 0x00,
- 0xd8, 0x11, 0xc1, 0x42, 0x14,
- 0xa0, 0x18, 0x00, 0x08, 0x00,
- 0x1a, 0x40, 0x00, 0x04, 0x2c,
- 0x33, 0x00, 0x01, 0x2f, 0x20,
- 0xd8, 0x03, 0x00, 0x00, 0x18,
- 0xe0, 0x00, 0x02, 0x00, 0x00,
- }
-};
diff --git a/drivers/net/ethernet/xscale/ixp2000/ixpdev.c b/drivers/net/ethernet/xscale/ixp2000/ixpdev.c
deleted file mode 100644
index 45008377c8bf..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/ixpdev.c
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * IXP2000 MSF network device driver
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-#include <linux/gfp.h>
-#include <asm/hardware/uengine.h>
-#include <asm/io.h>
-#include "ixp2400_rx.ucode"
-#include "ixp2400_tx.ucode"
-#include "ixpdev_priv.h"
-#include "ixpdev.h"
-#include "pm3386.h"
-
-#define DRV_MODULE_VERSION "0.2"
-
-static int nds_count;
-static struct net_device **nds;
-static int nds_open;
-static void (*set_port_admin_status)(int port, int up);
-
-static struct ixpdev_rx_desc * const rx_desc =
- (struct ixpdev_rx_desc *)(IXP2000_SRAM0_VIRT_BASE + RX_BUF_DESC_BASE);
-static struct ixpdev_tx_desc * const tx_desc =
- (struct ixpdev_tx_desc *)(IXP2000_SRAM0_VIRT_BASE + TX_BUF_DESC_BASE);
-static int tx_pointer;
-
-
-static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct ixpdev_priv *ip = netdev_priv(dev);
- struct ixpdev_tx_desc *desc;
- int entry;
- unsigned long flags;
-
- if (unlikely(skb->len > PAGE_SIZE)) {
- /* @@@ Count drops. */
- dev_kfree_skb(skb);
- return NETDEV_TX_OK;
- }
-
- entry = tx_pointer;
- tx_pointer = (tx_pointer + 1) % TX_BUF_COUNT;
-
- desc = tx_desc + entry;
- desc->pkt_length = skb->len;
- desc->channel = ip->channel;
-
- skb_copy_and_csum_dev(skb, phys_to_virt(desc->buf_addr));
- dev_kfree_skb(skb);
-
- ixp2000_reg_write(RING_TX_PENDING,
- TX_BUF_DESC_BASE + (entry * sizeof(struct ixpdev_tx_desc)));
-
- local_irq_save(flags);
- ip->tx_queue_entries++;
- if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN)
- netif_stop_queue(dev);
- local_irq_restore(flags);
-
- return NETDEV_TX_OK;
-}
-
-
-static int ixpdev_rx(struct net_device *dev, int processed, int budget)
-{
- while (processed < budget) {
- struct ixpdev_rx_desc *desc;
- struct sk_buff *skb;
- void *buf;
- u32 _desc;
-
- _desc = ixp2000_reg_read(RING_RX_DONE);
- if (_desc == 0)
- return 0;
-
- desc = rx_desc +
- ((_desc - RX_BUF_DESC_BASE) / sizeof(struct ixpdev_rx_desc));
- buf = phys_to_virt(desc->buf_addr);
-
- if (desc->pkt_length < 4 || desc->pkt_length > PAGE_SIZE) {
- printk(KERN_ERR "ixp2000: rx err, length %d\n",
- desc->pkt_length);
- goto err;
- }
-
- if (desc->channel < 0 || desc->channel >= nds_count) {
- printk(KERN_ERR "ixp2000: rx err, channel %d\n",
- desc->channel);
- goto err;
- }
-
- /* @@@ Make FCS stripping configurable. */
- desc->pkt_length -= 4;
-
- if (unlikely(!netif_running(nds[desc->channel])))
- goto err;
-
- skb = netdev_alloc_skb_ip_align(dev, desc->pkt_length);
- if (likely(skb != NULL)) {
- skb_copy_to_linear_data(skb, buf, desc->pkt_length);
- skb_put(skb, desc->pkt_length);
- skb->protocol = eth_type_trans(skb, nds[desc->channel]);
-
- netif_receive_skb(skb);
- }
-
-err:
- ixp2000_reg_write(RING_RX_PENDING, _desc);
- processed++;
- }
-
- return processed;
-}
-
-/* dev always points to nds[0]. */
-static int ixpdev_poll(struct napi_struct *napi, int budget)
-{
- struct ixpdev_priv *ip = container_of(napi, struct ixpdev_priv, napi);
- struct net_device *dev = ip->dev;
- int rx;
-
- rx = 0;
- do {
- ixp2000_reg_write(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0x00ff);
-
- rx = ixpdev_rx(dev, rx, budget);
- if (rx >= budget)
- break;
- } while (ixp2000_reg_read(IXP2000_IRQ_THD_RAW_STATUS_A_0) & 0x00ff);
-
- napi_complete(napi);
- ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff);
-
- return rx;
-}
-
-static void ixpdev_tx_complete(void)
-{
- int channel;
- u32 wake;
-
- wake = 0;
- while (1) {
- struct ixpdev_priv *ip;
- u32 desc;
- int entry;
-
- desc = ixp2000_reg_read(RING_TX_DONE);
- if (desc == 0)
- break;
-
- /* @@@ Check whether entries come back in order. */
- entry = (desc - TX_BUF_DESC_BASE) / sizeof(struct ixpdev_tx_desc);
- channel = tx_desc[entry].channel;
-
- if (channel < 0 || channel >= nds_count) {
- printk(KERN_ERR "ixp2000: txcomp channel index "
- "out of bounds (%d, %.8i, %d)\n",
- channel, (unsigned int)desc, entry);
- continue;
- }
-
- ip = netdev_priv(nds[channel]);
- if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN)
- wake |= 1 << channel;
- ip->tx_queue_entries--;
- }
-
- for (channel = 0; wake != 0; channel++) {
- if (wake & (1 << channel)) {
- netif_wake_queue(nds[channel]);
- wake &= ~(1 << channel);
- }
- }
-}
-
-static irqreturn_t ixpdev_interrupt(int irq, void *dev_id)
-{
- u32 status;
-
- status = ixp2000_reg_read(IXP2000_IRQ_THD_STATUS_A_0);
- if (status == 0)
- return IRQ_NONE;
-
- /*
- * Any of the eight receive units signaled RX?
- */
- if (status & 0x00ff) {
- struct net_device *dev = nds[0];
- struct ixpdev_priv *ip = netdev_priv(dev);
-
- ixp2000_reg_wrb(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0x00ff);
- if (likely(napi_schedule_prep(&ip->napi))) {
- __napi_schedule(&ip->napi);
- } else {
- printk(KERN_CRIT "ixp2000: irq while polling!!\n");
- }
- }
-
- /*
- * Any of the eight transmit units signaled TXdone?
- */
- if (status & 0xff00) {
- ixp2000_reg_wrb(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0xff00);
- ixpdev_tx_complete();
- }
-
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void ixpdev_poll_controller(struct net_device *dev)
-{
- disable_irq(IRQ_IXP2000_THDA0);
- ixpdev_interrupt(IRQ_IXP2000_THDA0, dev);
- enable_irq(IRQ_IXP2000_THDA0);
-}
-#endif
-
-static int ixpdev_open(struct net_device *dev)
-{
- struct ixpdev_priv *ip = netdev_priv(dev);
- int err;
-
- napi_enable(&ip->napi);
- if (!nds_open++) {
- err = request_irq(IRQ_IXP2000_THDA0, ixpdev_interrupt,
- IRQF_SHARED, "ixp2000_eth", nds);
- if (err) {
- nds_open--;
- napi_disable(&ip->napi);
- return err;
- }
-
- ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0xffff);
- }
-
- set_port_admin_status(ip->channel, 1);
- netif_start_queue(dev);
-
- return 0;
-}
-
-static int ixpdev_close(struct net_device *dev)
-{
- struct ixpdev_priv *ip = netdev_priv(dev);
-
- netif_stop_queue(dev);
- napi_disable(&ip->napi);
- set_port_admin_status(ip->channel, 0);
-
- if (!--nds_open) {
- ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0xffff);
- free_irq(IRQ_IXP2000_THDA0, nds);
- }
-
- return 0;
-}
-
-static struct net_device_stats *ixpdev_get_stats(struct net_device *dev)
-{
- struct ixpdev_priv *ip = netdev_priv(dev);
-
- pm3386_get_stats(ip->channel, &(dev->stats));
-
- return &(dev->stats);
-}
-
-static const struct net_device_ops ixpdev_netdev_ops = {
- .ndo_open = ixpdev_open,
- .ndo_stop = ixpdev_close,
- .ndo_start_xmit = ixpdev_xmit,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_get_stats = ixpdev_get_stats,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = ixpdev_poll_controller,
-#endif
-};
-
-struct net_device *ixpdev_alloc(int channel, int sizeof_priv)
-{
- struct net_device *dev;
- struct ixpdev_priv *ip;
-
- dev = alloc_etherdev(sizeof_priv);
- if (dev == NULL)
- return NULL;
-
- dev->netdev_ops = &ixpdev_netdev_ops;
-
- dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
-
- ip = netdev_priv(dev);
- ip->dev = dev;
- netif_napi_add(dev, &ip->napi, ixpdev_poll, 64);
- ip->channel = channel;
- ip->tx_queue_entries = 0;
-
- return dev;
-}
-
-int ixpdev_init(int __nds_count, struct net_device **__nds,
- void (*__set_port_admin_status)(int port, int up))
-{
- int i;
- int err;
-
- BUILD_BUG_ON(RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192);
-
- printk(KERN_INFO "IXP2000 MSF ethernet driver %s\n", DRV_MODULE_VERSION);
-
- nds_count = __nds_count;
- nds = __nds;
- set_port_admin_status = __set_port_admin_status;
-
- for (i = 0; i < RX_BUF_COUNT; i++) {
- void *buf;
-
- buf = (void *)get_zeroed_page(GFP_KERNEL);
- if (buf == NULL) {
- err = -ENOMEM;
- while (--i >= 0)
- free_page((unsigned long)phys_to_virt(rx_desc[i].buf_addr));
- goto err_out;
- }
- rx_desc[i].buf_addr = virt_to_phys(buf);
- rx_desc[i].buf_length = PAGE_SIZE;
- }
-
- /* @@@ Maybe we shouldn't be preallocating TX buffers. */
- for (i = 0; i < TX_BUF_COUNT; i++) {
- void *buf;
-
- buf = (void *)get_zeroed_page(GFP_KERNEL);
- if (buf == NULL) {
- err = -ENOMEM;
- while (--i >= 0)
- free_page((unsigned long)phys_to_virt(tx_desc[i].buf_addr));
- goto err_free_rx;
- }
- tx_desc[i].buf_addr = virt_to_phys(buf);
- }
-
- /* 256 entries, ring status set means 'empty', base address 0x0000. */
- ixp2000_reg_write(RING_RX_PENDING_BASE, 0x44000000);
- ixp2000_reg_write(RING_RX_PENDING_HEAD, 0x00000000);
- ixp2000_reg_write(RING_RX_PENDING_TAIL, 0x00000000);
-
- /* 256 entries, ring status set means 'full', base address 0x0400. */
- ixp2000_reg_write(RING_RX_DONE_BASE, 0x40000400);
- ixp2000_reg_write(RING_RX_DONE_HEAD, 0x00000000);
- ixp2000_reg_write(RING_RX_DONE_TAIL, 0x00000000);
-
- for (i = 0; i < RX_BUF_COUNT; i++) {
- ixp2000_reg_write(RING_RX_PENDING,
- RX_BUF_DESC_BASE + (i * sizeof(struct ixpdev_rx_desc)));
- }
-
- ixp2000_uengine_load(0, &ixp2400_rx);
- ixp2000_uengine_start_contexts(0, 0xff);
-
- /* 256 entries, ring status set means 'empty', base address 0x0800. */
- ixp2000_reg_write(RING_TX_PENDING_BASE, 0x44000800);
- ixp2000_reg_write(RING_TX_PENDING_HEAD, 0x00000000);
- ixp2000_reg_write(RING_TX_PENDING_TAIL, 0x00000000);
-
- /* 256 entries, ring status set means 'full', base address 0x0c00. */
- ixp2000_reg_write(RING_TX_DONE_BASE, 0x40000c00);
- ixp2000_reg_write(RING_TX_DONE_HEAD, 0x00000000);
- ixp2000_reg_write(RING_TX_DONE_TAIL, 0x00000000);
-
- ixp2000_uengine_load(1, &ixp2400_tx);
- ixp2000_uengine_start_contexts(1, 0xff);
-
- for (i = 0; i < nds_count; i++) {
- err = register_netdev(nds[i]);
- if (err) {
- while (--i >= 0)
- unregister_netdev(nds[i]);
- goto err_free_tx;
- }
- }
-
- for (i = 0; i < nds_count; i++) {
- printk(KERN_INFO "%s: IXP2000 MSF ethernet (port %d), %pM.\n",
- nds[i]->name, i, nds[i]->dev_addr);
- }
-
- return 0;
-
-err_free_tx:
- for (i = 0; i < TX_BUF_COUNT; i++)
- free_page((unsigned long)phys_to_virt(tx_desc[i].buf_addr));
-
-err_free_rx:
- for (i = 0; i < RX_BUF_COUNT; i++)
- free_page((unsigned long)phys_to_virt(rx_desc[i].buf_addr));
-
-err_out:
- return err;
-}
-
-void ixpdev_deinit(void)
-{
- int i;
-
- /* @@@ Flush out pending packets. */
-
- for (i = 0; i < nds_count; i++)
- unregister_netdev(nds[i]);
-
- ixp2000_uengine_stop_contexts(1, 0xff);
- ixp2000_uengine_stop_contexts(0, 0xff);
- ixp2000_uengine_reset(0x3);
-
- for (i = 0; i < TX_BUF_COUNT; i++)
- free_page((unsigned long)phys_to_virt(tx_desc[i].buf_addr));
-
- for (i = 0; i < RX_BUF_COUNT; i++)
- free_page((unsigned long)phys_to_virt(rx_desc[i].buf_addr));
-}
diff --git a/drivers/net/ethernet/xscale/ixp2000/ixpdev.h b/drivers/net/ethernet/xscale/ixp2000/ixpdev.h
deleted file mode 100644
index 391ece623243..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/ixpdev.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * IXP2000 MSF network device driver
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __IXPDEV_H
-#define __IXPDEV_H
-
-struct ixpdev_priv
-{
- struct net_device *dev;
- struct napi_struct napi;
- int channel;
- int tx_queue_entries;
-};
-
-struct net_device *ixpdev_alloc(int channel, int sizeof_priv);
-int ixpdev_init(int num_ports, struct net_device **nds,
- void (*set_port_admin_status)(int port, int up));
-void ixpdev_deinit(void);
-
-
-#endif
diff --git a/drivers/net/ethernet/xscale/ixp2000/ixpdev_priv.h b/drivers/net/ethernet/xscale/ixp2000/ixpdev_priv.h
deleted file mode 100644
index 86aa08ea0c33..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/ixpdev_priv.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * IXP2000 MSF network device driver
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __IXPDEV_PRIV_H
-#define __IXPDEV_PRIV_H
-
-#define RX_BUF_DESC_BASE 0x00001000
-#define RX_BUF_COUNT ((3 * PAGE_SIZE) / (4 * sizeof(struct ixpdev_rx_desc)))
-#define TX_BUF_DESC_BASE 0x00002000
-#define TX_BUF_COUNT ((3 * PAGE_SIZE) / (4 * sizeof(struct ixpdev_tx_desc)))
-#define TX_BUF_COUNT_PER_CHAN (TX_BUF_COUNT / 4)
-
-#define RING_RX_PENDING ((u32 *)IXP2000_SCRATCH_RING_VIRT_BASE)
-#define RING_RX_DONE ((u32 *)(IXP2000_SCRATCH_RING_VIRT_BASE + 4))
-#define RING_TX_PENDING ((u32 *)(IXP2000_SCRATCH_RING_VIRT_BASE + 8))
-#define RING_TX_DONE ((u32 *)(IXP2000_SCRATCH_RING_VIRT_BASE + 12))
-
-#define SCRATCH_REG(x) ((u32 *)(IXP2000_GLOBAL_REG_VIRT_BASE | 0x0800 | (x)))
-#define RING_RX_PENDING_BASE SCRATCH_REG(0x00)
-#define RING_RX_PENDING_HEAD SCRATCH_REG(0x04)
-#define RING_RX_PENDING_TAIL SCRATCH_REG(0x08)
-#define RING_RX_DONE_BASE SCRATCH_REG(0x10)
-#define RING_RX_DONE_HEAD SCRATCH_REG(0x14)
-#define RING_RX_DONE_TAIL SCRATCH_REG(0x18)
-#define RING_TX_PENDING_BASE SCRATCH_REG(0x20)
-#define RING_TX_PENDING_HEAD SCRATCH_REG(0x24)
-#define RING_TX_PENDING_TAIL SCRATCH_REG(0x28)
-#define RING_TX_DONE_BASE SCRATCH_REG(0x30)
-#define RING_TX_DONE_HEAD SCRATCH_REG(0x34)
-#define RING_TX_DONE_TAIL SCRATCH_REG(0x38)
-
-struct ixpdev_rx_desc
-{
- u32 buf_addr;
- u32 buf_length;
- u32 channel;
- u32 pkt_length;
-};
-
-struct ixpdev_tx_desc
-{
- u32 buf_addr;
- u32 pkt_length;
- u32 channel;
- u32 unused;
-};
-
-
-#endif
diff --git a/drivers/net/ethernet/xscale/ixp2000/pm3386.c b/drivers/net/ethernet/xscale/ixp2000/pm3386.c
deleted file mode 100644
index e08d3f9863b8..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/pm3386.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Helper functions for the PM3386s on the Radisys ENP2611
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <asm/io.h>
-#include "pm3386.h"
-
-/*
- * Read from register 'reg' of PM3386 device 'pm'.
- */
-static u16 pm3386_reg_read(int pm, int reg)
-{
- void *_reg;
- u16 value;
-
- _reg = (void *)ENP2611_PM3386_0_VIRT_BASE;
- if (pm == 1)
- _reg = (void *)ENP2611_PM3386_1_VIRT_BASE;
-
- value = *((volatile u16 *)(_reg + (reg << 1)));
-
-// printk(KERN_INFO "pm3386_reg_read(%d, %.3x) = %.8x\n", pm, reg, value);
-
- return value;
-}
-
-/*
- * Write to register 'reg' of PM3386 device 'pm', and perform
- * a readback from the identification register.
- */
-static void pm3386_reg_write(int pm, int reg, u16 value)
-{
- void *_reg;
- u16 dummy;
-
-// printk(KERN_INFO "pm3386_reg_write(%d, %.3x, %.8x)\n", pm, reg, value);
-
- _reg = (void *)ENP2611_PM3386_0_VIRT_BASE;
- if (pm == 1)
- _reg = (void *)ENP2611_PM3386_1_VIRT_BASE;
-
- *((volatile u16 *)(_reg + (reg << 1))) = value;
-
- dummy = *((volatile u16 *)_reg);
- __asm__ __volatile__("mov %0, %0" : "+r" (dummy));
-}
-
-/*
- * Read from port 'port' register 'reg', where the registers
- * for the different ports are 'spacing' registers apart.
- */
-static u16 pm3386_port_reg_read(int port, int _reg, int spacing)
-{
- int reg;
-
- reg = _reg;
- if (port & 1)
- reg += spacing;
-
- return pm3386_reg_read(port >> 1, reg);
-}
-
-/*
- * Write to port 'port' register 'reg', where the registers
- * for the different ports are 'spacing' registers apart.
- */
-static void pm3386_port_reg_write(int port, int _reg, int spacing, u16 value)
-{
- int reg;
-
- reg = _reg;
- if (port & 1)
- reg += spacing;
-
- pm3386_reg_write(port >> 1, reg, value);
-}
-
-int pm3386_secondary_present(void)
-{
- return pm3386_reg_read(1, 0) == 0x3386;
-}
-
-void pm3386_reset(void)
-{
- u8 mac[3][6];
- int secondary;
-
- secondary = pm3386_secondary_present();
-
- /* Save programmed MAC addresses. */
- pm3386_get_mac(0, mac[0]);
- pm3386_get_mac(1, mac[1]);
- if (secondary)
- pm3386_get_mac(2, mac[2]);
-
- /* Assert analog and digital reset. */
- pm3386_reg_write(0, 0x002, 0x0060);
- if (secondary)
- pm3386_reg_write(1, 0x002, 0x0060);
- mdelay(1);
-
- /* Deassert analog reset. */
- pm3386_reg_write(0, 0x002, 0x0062);
- if (secondary)
- pm3386_reg_write(1, 0x002, 0x0062);
- mdelay(10);
-
- /* Deassert digital reset. */
- pm3386_reg_write(0, 0x002, 0x0063);
- if (secondary)
- pm3386_reg_write(1, 0x002, 0x0063);
- mdelay(10);
-
- /* Restore programmed MAC addresses. */
- pm3386_set_mac(0, mac[0]);
- pm3386_set_mac(1, mac[1]);
- if (secondary)
- pm3386_set_mac(2, mac[2]);
-
- /* Disable carrier on all ports. */
- pm3386_set_carrier(0, 0);
- pm3386_set_carrier(1, 0);
- if (secondary)
- pm3386_set_carrier(2, 0);
-}
-
-static u16 swaph(u16 x)
-{
- return ((x << 8) | (x >> 8)) & 0xffff;
-}
-
-int pm3386_port_count(void)
-{
- return 2 + pm3386_secondary_present();
-}
-
-void pm3386_init_port(int port)
-{
- int pm = port >> 1;
-
- /*
- * Work around ENP2611 bootloader programming MAC address
- * in reverse.
- */
- if (pm3386_port_reg_read(port, 0x30a, 0x100) == 0x0000 &&
- (pm3386_port_reg_read(port, 0x309, 0x100) & 0xff00) == 0x5000) {
- u16 temp[3];
-
- temp[0] = pm3386_port_reg_read(port, 0x308, 0x100);
- temp[1] = pm3386_port_reg_read(port, 0x309, 0x100);
- temp[2] = pm3386_port_reg_read(port, 0x30a, 0x100);
- pm3386_port_reg_write(port, 0x308, 0x100, swaph(temp[2]));
- pm3386_port_reg_write(port, 0x309, 0x100, swaph(temp[1]));
- pm3386_port_reg_write(port, 0x30a, 0x100, swaph(temp[0]));
- }
-
- /*
- * Initialise narrowbanding mode. See application note 2010486
- * for more information. (@@@ We also need to issue a reset
- * when ROOL or DOOL are detected.)
- */
- pm3386_port_reg_write(port, 0x708, 0x10, 0xd055);
- udelay(500);
- pm3386_port_reg_write(port, 0x708, 0x10, 0x5055);
-
- /*
- * SPI-3 ingress block. Set 64 bytes SPI-3 burst size
- * towards SPI-3 bridge.
- */
- pm3386_port_reg_write(port, 0x122, 0x20, 0x0002);
-
- /*
- * Enable ingress protocol checking, and soft reset the
- * SPI-3 ingress block.
- */
- pm3386_reg_write(pm, 0x103, 0x0003);
- while (!(pm3386_reg_read(pm, 0x103) & 0x80))
- ;
-
- /*
- * SPI-3 egress block. Gather 12288 bytes of the current
- * packet in the TX fifo before initiating transmit on the
- * SERDES interface. (Prevents TX underflows.)
- */
- pm3386_port_reg_write(port, 0x221, 0x20, 0x0007);
-
- /*
- * Enforce odd parity from the SPI-3 bridge, and soft reset
- * the SPI-3 egress block.
- */
- pm3386_reg_write(pm, 0x203, 0x000d & ~(4 << (port & 1)));
- while ((pm3386_reg_read(pm, 0x203) & 0x000c) != 0x000c)
- ;
-
- /*
- * EGMAC block. Set this channels to reject long preambles,
- * not send or transmit PAUSE frames, enable preamble checking,
- * disable frame length checking, enable FCS appending, enable
- * TX frame padding.
- */
- pm3386_port_reg_write(port, 0x302, 0x100, 0x0113);
-
- /*
- * Soft reset the EGMAC block.
- */
- pm3386_port_reg_write(port, 0x301, 0x100, 0x8000);
- pm3386_port_reg_write(port, 0x301, 0x100, 0x0000);
-
- /*
- * Auto-sense autonegotiation status.
- */
- pm3386_port_reg_write(port, 0x306, 0x100, 0x0100);
-
- /*
- * Allow reception of jumbo frames.
- */
- pm3386_port_reg_write(port, 0x310, 0x100, 9018);
-
- /*
- * Allow transmission of jumbo frames.
- */
- pm3386_port_reg_write(port, 0x336, 0x100, 9018);
-
- /* @@@ Should set 0x337/0x437 (RX forwarding threshold.) */
-
- /*
- * Set autonegotiation parameters to 'no PAUSE, full duplex.'
- */
- pm3386_port_reg_write(port, 0x31c, 0x100, 0x0020);
-
- /*
- * Enable and restart autonegotiation.
- */
- pm3386_port_reg_write(port, 0x318, 0x100, 0x0003);
- pm3386_port_reg_write(port, 0x318, 0x100, 0x0002);
-}
-
-void pm3386_get_mac(int port, u8 *mac)
-{
- u16 temp;
-
- temp = pm3386_port_reg_read(port, 0x308, 0x100);
- mac[0] = temp & 0xff;
- mac[1] = (temp >> 8) & 0xff;
-
- temp = pm3386_port_reg_read(port, 0x309, 0x100);
- mac[2] = temp & 0xff;
- mac[3] = (temp >> 8) & 0xff;
-
- temp = pm3386_port_reg_read(port, 0x30a, 0x100);
- mac[4] = temp & 0xff;
- mac[5] = (temp >> 8) & 0xff;
-}
-
-void pm3386_set_mac(int port, u8 *mac)
-{
- pm3386_port_reg_write(port, 0x308, 0x100, (mac[1] << 8) | mac[0]);
- pm3386_port_reg_write(port, 0x309, 0x100, (mac[3] << 8) | mac[2]);
- pm3386_port_reg_write(port, 0x30a, 0x100, (mac[5] << 8) | mac[4]);
-}
-
-static u32 pm3386_get_stat(int port, u16 base)
-{
- u32 value;
-
- value = pm3386_port_reg_read(port, base, 0x100);
- value |= pm3386_port_reg_read(port, base + 1, 0x100) << 16;
-
- return value;
-}
-
-void pm3386_get_stats(int port, struct net_device_stats *stats)
-{
- /*
- * Snapshot statistics counters.
- */
- pm3386_port_reg_write(port, 0x500, 0x100, 0x0001);
- while (pm3386_port_reg_read(port, 0x500, 0x100) & 0x0001)
- ;
-
- memset(stats, 0, sizeof(*stats));
-
- stats->rx_packets = pm3386_get_stat(port, 0x510);
- stats->tx_packets = pm3386_get_stat(port, 0x590);
- stats->rx_bytes = pm3386_get_stat(port, 0x514);
- stats->tx_bytes = pm3386_get_stat(port, 0x594);
- /* @@@ Add other stats. */
-}
-
-void pm3386_set_carrier(int port, int state)
-{
- pm3386_port_reg_write(port, 0x703, 0x10, state ? 0x1001 : 0x0000);
-}
-
-int pm3386_is_link_up(int port)
-{
- u16 temp;
-
- temp = pm3386_port_reg_read(port, 0x31a, 0x100);
- temp = pm3386_port_reg_read(port, 0x31a, 0x100);
-
- return !!(temp & 0x0002);
-}
-
-void pm3386_enable_rx(int port)
-{
- u16 temp;
-
- temp = pm3386_port_reg_read(port, 0x303, 0x100);
- temp |= 0x1000;
- pm3386_port_reg_write(port, 0x303, 0x100, temp);
-}
-
-void pm3386_disable_rx(int port)
-{
- u16 temp;
-
- temp = pm3386_port_reg_read(port, 0x303, 0x100);
- temp &= 0xefff;
- pm3386_port_reg_write(port, 0x303, 0x100, temp);
-}
-
-void pm3386_enable_tx(int port)
-{
- u16 temp;
-
- temp = pm3386_port_reg_read(port, 0x303, 0x100);
- temp |= 0x4000;
- pm3386_port_reg_write(port, 0x303, 0x100, temp);
-}
-
-void pm3386_disable_tx(int port)
-{
- u16 temp;
-
- temp = pm3386_port_reg_read(port, 0x303, 0x100);
- temp &= 0xbfff;
- pm3386_port_reg_write(port, 0x303, 0x100, temp);
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/xscale/ixp2000/pm3386.h b/drivers/net/ethernet/xscale/ixp2000/pm3386.h
deleted file mode 100644
index cc4183dca911..000000000000
--- a/drivers/net/ethernet/xscale/ixp2000/pm3386.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Helper functions for the PM3386s on the Radisys ENP2611
- * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
- * Dedicated to Marija Kulikova.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __PM3386_H
-#define __PM3386_H
-
-void pm3386_reset(void);
-int pm3386_port_count(void);
-void pm3386_init_port(int port);
-void pm3386_get_mac(int port, u8 *mac);
-void pm3386_set_mac(int port, u8 *mac);
-void pm3386_get_stats(int port, struct net_device_stats *stats);
-void pm3386_set_carrier(int port, int state);
-int pm3386_is_link_up(int port);
-void pm3386_enable_rx(int port);
-void pm3386_disable_rx(int port);
-void pm3386_enable_tx(int port);
-void pm3386_disable_tx(int port);
-
-
-#endif
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index 41a8b5a9849e..482648fcf0b6 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -1002,12 +1002,41 @@ static int ixp4xx_nway_reset(struct net_device *dev)
return phy_start_aneg(port->phydev);
}
+int ixp46x_phc_index = -1;
+
+static int ixp4xx_get_ts_info(struct net_device *dev,
+ struct ethtool_ts_info *info)
+{
+ if (!cpu_is_ixp46x()) {
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE;
+ info->phc_index = -1;
+ return 0;
+ }
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->phc_index = ixp46x_phc_index;
+ info->tx_types =
+ (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+ info->rx_filters =
+ (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ);
+ return 0;
+}
+
static const struct ethtool_ops ixp4xx_ethtool_ops = {
.get_drvinfo = ixp4xx_get_drvinfo,
.get_settings = ixp4xx_get_settings,
.set_settings = ixp4xx_set_settings,
.nway_reset = ixp4xx_nway_reset,
.get_link = ethtool_op_get_link,
+ .get_ts_info = ixp4xx_get_ts_info,
};